作者 董瑞恩
1 个管道 的构建 通过 耗费 1 秒

cost

@@ -10,14 +10,26 @@ namespace app\portal\controller; @@ -10,14 +10,26 @@ namespace app\portal\controller;
10 10
11 11
12 use cmf\controller\HomeBaseController; 12 use cmf\controller\HomeBaseController;
  13 +use EasyWeChat\Foundation\Application;
13 use think\Db; 14 use think\Db;
  15 +use wxapp\pay\WeixinPay;
  16 +
14 /** 17 /**
15 * @title 用户相关接口 18 * @title 用户相关接口
16 * @description 用户相关接口 19 * @description 用户相关接口
17 * @group 用户相关接口 20 * @group 用户相关接口
18 */ 21 */
19 class UsersController extends HomeBaseController{ 22 class UsersController extends HomeBaseController{
20 - 23 + protected $options;
  24 + function _initialize()
  25 + {
  26 + parent::_initialize();
  27 + $this->options = [
  28 + 'app_id' => config('wechat_config.app_id'),
  29 + 'secret' => config('wechat_config.secret'),
  30 + 'payment' => config('wechat_config.payment'),
  31 + ];
  32 + }
21 /** 33 /**
22 * @title 状态验证 34 * @title 状态验证
23 * @description 开锁前判断是否有未支付订单与是否提交押金 35 * @description 开锁前判断是否有未支付订单与是否提交押金
@@ -54,6 +66,8 @@ class UsersController extends HomeBaseController{ @@ -54,6 +66,8 @@ class UsersController extends HomeBaseController{
54 * @method GET 66 * @method GET
55 * 67 *
56 * @param name:users_id type:String require:1 default:无 other: desc:用户id 68 * @param name:users_id type:String require:1 default:无 other: desc:用户id
  69 + *
  70 + *
57 */ 71 */
58 public function isUse(){ 72 public function isUse(){
59 $users_id=$this->request->param('users_id'); 73 $users_id=$this->request->param('users_id');
@@ -65,6 +79,119 @@ class UsersController extends HomeBaseController{ @@ -65,6 +79,119 @@ class UsersController extends HomeBaseController{
65 } 79 }
66 } 80 }
67 81
  82 + /**
  83 + * @title 用户交纳押金
  84 + * @description 交纳押金
  85 + * @author 董瑞恩
  86 + * @url /portal/users/payDeposit
  87 + * @method GET
  88 + *
  89 + * @param name:users_id type:String require:1 default:无 other: desc:用户id
  90 + *
  91 + * @return data:下单返回值
  92 + */
  93 + public function payDeposit(){
  94 + $users_id=$this->request->param('users_id');
  95 + $users=Db::name('users')->where('users_id',$users_id)->find();
  96 + $openId=$users['open_id'];
  97 + $order_no = cmf_get_order_sn();
  98 + $body="押金-支付";
  99 + $price=300*100;//数据库查询
  100 + $notify_url=url('users/notify','','',true);//回调地址
  101 + $wxPay=new WeixinPay($openId,$order_no,$body,$price,$notify_url);
  102 + $data=$wxPay->pay();
  103 + if (isset($data['package'])){
  104 + try{
  105 + Db::name('users')->where(['users_id'=>$users_id])->update(['deposit_order_no'=>$order_no]);
  106 + }catch (\Exception $exception){
  107 +
  108 + }
  109 + $this->apiResponse(200,'下单成功',$data);//微信支付下单成功,返回调用支付的参数
  110 + }
  111 + }
68 112
  113 + //支付回调接口
  114 + public function notify(){
  115 + $param = $this->request->param();
  116 + if ($param == null) {
  117 + $param = file_get_contents("php://input");
  118 + if ($param == null) {
  119 + $param = $GLOBALS['HTTP_RAW_POST_DATA'];
  120 + }
  121 + }
  122 + $wxPay=new WeixinPay();
  123 + $data = $wxPay->xmlToArray($param);
  124 + $Sign = $data['sign'];
  125 + //支付成功回调后变更订单状态
  126 + $mySign = $wxPay->getSign($data);
  127 + $order_no = $data['out_trade_no'];
  128 + if ($Sign===$mySign && $data['return_code'] == 'SUCCESS') {
  129 + $data=[
  130 + 'is_deposit' => 1,
  131 + 'deposit' => $data['total_fee'],
  132 + ];
  133 + try{
  134 + Db::name('order')->where(['order_no'=>$order_no])->update($data);
  135 + }catch (\Exception $exception){
  136 + $this->apiResponse(301,'error:'.$exception->getMessage());
  137 + }
  138 + return "<xml>
  139 + <return_code><![CDATA[SUCCESS]]></return_code>
  140 + <return_msg><![CDATA[OK]]></return_msg>
  141 + </xml>";
  142 + }
  143 + }
  144 +
  145 + /**
  146 + * @title 用户退回押金
  147 + * @description 用户退回押金
  148 + * @author 董瑞恩
  149 + * @url /portal/users/refundDeposit
  150 + * @method GET
  151 + *
  152 + * @param name:users_id type:String require:1 default:无 other: desc:用户id
  153 + *
  154 + * @return result:退款接口返回值
  155 + */
  156 + public function refundDeposit(){
  157 + $users_id=$this->request->param('users_id');
  158 + $users=Db::name('users')->where('users_id',$users_id)->find();
  159 + $orderNo=$users['deposit_order_no'];//需要退款的订单
  160 + $price=$users['deposit'];
  161 + Db::startTrans();
  162 + try{
  163 + Db::name('users')->where('users_id',$users_id)->update(['is_deposit'=>0,'deposit'=>null,'deposit_order_no'=>null]);
  164 + }catch (\Exception $exception){
  165 + $this->apiResponse(301,'数据库修改失败');
  166 + }
  167 + $app= new Application($this->options);
  168 + $payment = $app->payment;
  169 + //使用商户订单号退款 PS.其他形式参考文档
  170 + $refundNo =cmf_get_order_sn();//退款单号
  171 + $result = $payment->refund($orderNo, $refundNo, $price); // 总金额 100, 退款 80,refundFee可选(为空时全额退款)
  172 + if ($result['return_code']==='SUCCESS' && $result['result_code']==='SUCCESS'){
  173 + Db::commit();
  174 + }else{
  175 + Db::rollback();
  176 + }
  177 + return json_decode($result,true);
  178 + }
  179 +
  180 + /**
  181 + * 退款结果回调
  182 + */
  183 + public function refundNotify() {
  184 + $app = new Application($this->options);
  185 + $response = $app->payment->handleRefundNotify(function ($message, $reqInfo) {
  186 + cache('message',$message);
  187 + cache('reqInfo',$reqInfo);
  188 + // 其中 $message['req_info'] 获取到的是加密信息
  189 + // $reqInfo 为 message['req_info'] 解密后的信息
  190 + // 你的业务逻辑...
  191 + return true; // 返回 true 告诉微信“我已处理完成”
  192 + // 或返回错误原因 $fail('参数格式校验错误');
  193 + });
  194 + $response->send();
  195 + }
69 196
70 } 197 }
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: ruidiudiu
  5 + * Date: 2018/10/16
  6 + * Time: 16:34
  7 + */
  8 +
  9 +namespace wxapp\pay;
  10 +const APICLIENT_CERT=EXTEND_PATH."wxapp/pay/cert/apiclient_cert.pem";
  11 +const APICLIENT_KEY=EXTEND_PATH."wxapp/pay/cert/apiclient_key.pem";
  12 +class WecharGetCash{
  13 + protected $appid;//商户账号
  14 + protected $mch_id;//商户号
  15 + protected $key;
  16 + protected $partner_trade_no;//商户订单号
  17 + protected $openid;
  18 + protected $check_name;//校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
  19 + protected $amount;//金额
  20 + protected $desc;//企业付款备注
  21 + protected $spbill_create_ip;//Ip地址:该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP。
  22 +
  23 + function __construct($openid,$partner_trade_no,$desc,$amount) {
  24 + $this->appid = config('wechat_config.app_id');
  25 + $this->mch_id = config('wechat_config.payment')['merchant_id'];
  26 + $this->key = config('wechat_config.payment')['key'];
  27 + $this->partner_trade_no = $partner_trade_no;//商户订单号
  28 + $this->openid = $openid;
  29 + $this->check_name = "NO_CHECK";
  30 + $this->amount = $amount*100;//金额
  31 + $this->desc = $desc;//企业付款备注
  32 + $this->spbill_create_ip = "114.215.223.17";//Ip地址
  33 + }
  34 +
  35 + public function getCash() {
  36 + //提现接口
  37 + $return = $this->enterprisePayment();
  38 + return $return;
  39 + }
  40 + //企业付款接口
  41 + private function enterprisePayment() {
  42 + $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
  43 + $parameters = array(
  44 + 'mch_appid' => $this->appid,
  45 + 'mchid' => $this->mch_id,
  46 + 'nonce_str' => $this->createNoncestr(),
  47 + 'partner_trade_no' => $this->partner_trade_no,
  48 + 'openid' => $this->openid,
  49 + 'check_name' => $this->check_name,
  50 + 'amount' => $this->amount,
  51 + 'desc' => $this->desc,
  52 + 'spbill_create_ip' => $this->spbill_create_ip
  53 + );
  54 + //签名
  55 + $parameters['sign'] = $this->getSign($parameters);
  56 + $xmlData = $this->arrayToXml($parameters);
  57 + $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
  58 + return $return;
  59 + }
  60 +
  61 + private static function postXmlCurl($xml, $url, $second = 30)
  62 + {
  63 + $ch = curl_init();
  64 + //设置超时
  65 + curl_setopt($ch, CURLOPT_TIMEOUT, $second);
  66 + curl_setopt($ch, CURLOPT_URL, $url);
  67 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  68 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
  69 +
  70 + //第一种方法,cert 与 key 分别属于两个.pem文件
  71 + //默认格式为PEM,可以注释
  72 + curl_setopt($ch,CURLOPT_SSLCERT,APICLIENT_CERT);
  73 + curl_setopt($ch,CURLOPT_SSLKEY,APICLIENT_KEY);
  74 +
  75 + //设置header
  76 + curl_setopt($ch, CURLOPT_HEADER, FALSE);
  77 + //要求结果为字符串且输出到屏幕上
  78 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  79 + //post提交方式
  80 + curl_setopt($ch, CURLOPT_POST, TRUE);
  81 + curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  82 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
  83 + curl_setopt($ch, CURLOPT_TIMEOUT, 40);
  84 + set_time_limit(0);
  85 + //运行curl
  86 + $data = curl_exec($ch);
  87 + //返回结果
  88 + if ($data) {
  89 + curl_close($ch);
  90 + return $data;
  91 + } else {
  92 + $error = curl_errno($ch);
  93 + curl_close($ch);
  94 + throw new ErrorException("curl出错,错误码:$error");
  95 + }
  96 + }
  97 +
  98 + //数组转换成xml
  99 + private function arrayToXml($arr) {
  100 + $xml = "<root>";
  101 + foreach ($arr as $key => $val) {
  102 + if (is_array($val)) {
  103 + $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
  104 + } else {
  105 + $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  106 + }
  107 + }
  108 + $xml .= "</root>";
  109 + return $xml;
  110 + }
  111 + //xml转换成数组
  112 + public function xmlToArray($xml) {
  113 + //禁止引用外部xml实体
  114 + libxml_disable_entity_loader(true);
  115 + $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  116 + $val = json_decode(json_encode($xmlstring), true);
  117 + return $val;
  118 + }
  119 +
  120 + //作用:产生随机字符串,不长于32位
  121 + private function createNoncestr($length = 32) {
  122 + $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  123 + $str = "";
  124 + for ($i = 0; $i < $length; $i++) {
  125 + $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  126 + }
  127 + return $str;
  128 + }
  129 +
  130 + //作用:生成签名
  131 + public function getSign($Obj) {
  132 + foreach ($Obj as $k => $v) {
  133 + $Parameters[$k] = $v;
  134 + }
  135 + //签名步骤一:按字典序排序参数
  136 + ksort($Parameters);
  137 + $String = $this->formatBizQueryParaMap($Parameters, false);
  138 + //签名步骤二:在string后加入KEY
  139 + $String = $String . "&key=" . $this->key;
  140 + //签名步骤三:MD5加密
  141 + $String = md5($String);
  142 + //签名步骤四:所有字符转为大写
  143 + $result_ = strtoupper($String);
  144 + return $result_;
  145 + }
  146 +
  147 + ///作用:格式化参数,签名过程需要使用
  148 + private function formatBizQueryParaMap($paraMap, $urlencode) {
  149 + $buff = "";
  150 + ksort($paraMap);
  151 + foreach ($paraMap as $k => $v) {
  152 + if(null != $v && "null" != $v && "sign" != $k) {
  153 + if ($urlencode) {
  154 + $v = urlencode($v);
  155 + }
  156 + $buff .= $k . "=" . $v . "&";
  157 + }
  158 + }
  159 + $reqPar='';
  160 + if (strlen($buff) > 0) {
  161 + $reqPar = substr($buff, 0, strlen($buff) - 1);
  162 + }
  163 + return $reqPar;
  164 + }
  165 +}