easywechat微信开发系列(2):公众号网页支付

准备工作:

1、已认证的服务号(apppid、appsecret、token、aes_key)

2、微信支付商户(商户号、密钥)

3、两者互相绑定

原理解析:

1、前台商品页面:点击支付按钮,js获取商品id和数量(价格和用户ID尽量在后台获取,防止用户恶意操作)

2、点击按钮后ajax把商品id和数量传递给后台(后台地址为  /wxPay)

3、后台根据商品id查找价格等信息,创建订单(订单价格,订单号,是否支付等信息)创建订单时是未支付状态。然后把总价×100和订单号通过easywechat的unify下单,拿到返回值(包含时间戳 prepayid等信息)

4、再把返回值传到前台,这个返回值就是支付配置,

5、前台根据这个返回值发起支付

6、用户进行支付操作(可能成功也可能失败)

7、支付结果由微信服务器异步通知到设定的回调地址,在回调方法里面,如果成功支付,则根据支付结果的订单id找到相应订单更新为已支付状态

代码演示

1、前台页面(对应原理1、2、5、6)

<button onclick="prePay()">支付</button>

<script>
const config; //定义全局变量
function prePay(){
    $.post('/wxPay',{product_id:***,count:***},function(res){//获取到后台返回的支付配置
        config = res; //将配置信息赋值给config
        callpay();
    });
}

function jsApiCall() {
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', config,    //此处使用配置发起jsapi支付
        function (res) {
            WeixinJSBridge.log(res.err_msg);
            if (res.err_msg == 'get_brand_wcpay_request:ok') {
                $.toast("充值成功");
            } else {
                 $.toast("您取消了充值",'text');
            }
        }
    );
}
function callpay() {
    if (typeof WeixinJSBridge == "undefined") {
        if (document.addEventListener) {
            document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
        } else if (document.attachEvent) {
            document.attachEvent('WeixinJSBridgeReady', jsApiCall);
            document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
        }
    } else {
        jsApiCall();
    }
}
</script>

2、后台逻辑1:接收product_id、count等信息(对应原理3、4)

function callWxPay(Request $request){
      $user = $this->getUserInfo(); 
      $app = app('wechat.official_account');
      $payment = Factory::payment(config('wechat.payment.default'));

      $billnum = date('YmdHis') . rand(100000,999999);
      Bill::create([
            'user_id'=>$user->id,
            'ispay' => 0,
            'money'=> $request->money,
            'billnum' => $billnum
        ]);

//(对应原理3)
        $result = $payment->order->unify([
                'body' => '微信支付',
                'out_trade_no' => $billnum,
                'total_fee' => $request->money * 100, //注意:微信支付单位是分
                'notify_url' => 'http://**.com/wx/notify', //回调地址,用于接收微信支付结果,如果用laravel,需要对/wx/notify路由去掉csrf验证
                'trade_type' => 'JSAPI',
                'openid' => $user->wxopenid,
        ]);
        
            if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
                $prepayId = $result['prepay_id'];
                $jssdk = $payment->jssdk;
                $config = $jssdk->sdkConfig($prepayId);
                $config['timeStamp'] = $config['timestamp'];//此处需要将小写s变为大写
                return $config;//(对应原理4)
            } else {
                return $result;
            }

    }
    

3、后台逻辑2:接收回调、更新订单信息(对应原理7)

 public function wxNotify()
    {
        $payment = \EasyWeChat::payment();
        $response = $payment->handlePaidNotify(function ($message, $fail) {
         if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') {
               
               // DB::beginTransaction(); 如果要更改余额表等信息,应该使用事务
                DB::table('bill')->where('billno',$message['out_trade_no'])->update([ 'updated_at' => date('Y-m-d H:i:s'),'ispay'=>1]);  
               // DB::commit();
                return true;
            } else {
                return $fail('失败');
            }
        });
        return $response;
    }

重要部分

1、获取prepayid

$result = $payment->order->unify([
                'body' => '微信支付',
                'out_trade_no' => $billnum,
                'total_fee' => $request->money * 100, //注意:微信支付单位是分
                'notify_url' => 'http://**.com/wx/notify', //回调地址,用于接收微信支付结果,如果用laravel,需要对/wx/notify路由去掉csrf验证
                'trade_type' => 'JSAPI',
                'openid' => $user->wxopenid,
        ]);

2、生成支付配置
$config = $jssdk->sdkConfig($prepayId);

猜你喜欢

转载自blog.csdn.net/sinat_37390744/article/details/107481014