周大胖子 发表于 2021-8-30 16:26:16

微信支付全部流程

本帖最后由 周大胖子 于 2021-8-30 16:40 编辑

先说下微信支付的本项目开发状况:
1.项目前后端分离.
2.项目前端采用 react umi; 后端采用 laravel-admin / easywechat ;
3.项目是网页,但是是在公众号中的网页; 所以对象目前是微信浏览器.
4.项目前后端 是我一个人开发.   
5.注意你支付的页面url 需要在商户号的配置中添加,也就是你在哪个页点支付按钮的页面url   , 后台返回的url 不需要注册 .6.商户 公众号 需要互相绑定

微信支付提前意识:
1. 本环境适合的支付模式是 jsapi [ 基本上都是使用这个 在网页上,小程序APP啥的 例外 ]
2. 支付的 具体流程:
      2.1客户选中商品 [前端]
      2.2[前端] 发送信息给后端 ,后端生成一条订单 ;
      2.3后端通过自己内部的订单号 -> 获取系统内部配置 ->生成一条微信订单 [ 传统说法叫做向微信下单]
      2.4后端把配置返回给 [前端]
      2.5[前端] 接收后台传回来的配置-> 使用 WeixinJSBridge 开启微信支付 . ( WeixinJSBridge 这是微信浏览器内置的一个东西,不需要引入,直接 就在前端项目里用 )
      2.6[前端] 展示成功或者失败的状态给客户, (这里有个知识点: 成功失败 是不需要传给后台的,后台是通过预留给微信的返回URL 来改变订单的状态 )到这[前端]就算是结束了.
      2.7后端,生成订单配置的时候留了一条完整的 URL 会写在配置里, 这个URL是接收微信返回值的 [ 客户支付成功或者失败后,微信会不断给你的预留接口发值,你得确认接收,并且告诉微信你处理完了,他就不发了 ].


好了 开始上代码 :先上后台的[也就是 2.3 / 2.4 步骤(2.1的下单,2.2的生成订单省略 就点一下 ,然后后台产生个单号) ] // 支付路由
    public function pay( Request $request)
    {

      $userinfo = $request->get('userinfo');
      
      $ord_id =$request->input('ord');

      $config = [
            // 必要配置
            'app_id'             => '公众号ID',
            'mch_id'             => '商户号',
            'key'                => '',   // API 密钥

            // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'          => 'we/apiclient_cert.pem', // XXX: 绝对路径!!!!
            'key_path'         => 'we/apiclient_key.pem',      // XXX: 绝对路径!!!!

            'notify_url'         => 'https://****/api/payback',   //回调地址 后面的 api/payback 不是固定格式你也可以在下单时单独设置来想覆盖它
      ];

      $app = Factory::payment($config);

      $result = $app->order->unify([
            'body' => '加油费用',
            'out_trade_no' => $ord_id,
            'total_fee' => 1,
            'spbill_create_ip' => '', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
            'notify_url' => 'https://you.qancloud.com/api/payback', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => '需要支付的用户的OPENID',
      ]);
      
      
      $payment = Factory::payment($config);

      $jssdk = $payment->jssdk;

      $json = $jssdk->bridgeConfig($result['prepay_id']);

    //   dd( json_decode($json) );

      return [
            'code'=>0,
            'message' =>'获取信息成功',
            'data' => json_decode($json)
      ];



    }









[ 前端 2.5/ 2.6步骤 ,前端 要做的 就这么多 ,大部分其实在后端]
WeixinJSBridge.invoke(
                        'getBrandWCPayRequest', 这个参数填上面返回的json,也就是 data 里的值 ,
                        function (res) {
                            if (res.err_msg === "get_brand_wcpay_request:ok") {
      history.push('/web/paybacksuccess');
                              // 支付成功
                            } else if (res.err_msg === "get_brand_wcpay_request:cancel") {
                              //用户取消支付
       history.push('/web/paybackfail');
                            } else if (res.err_msg === "get_brand_wcpay_request:fail") {
                              //支付失败
    history.push('/web/paybackfail');
                            }
                        }
                  )

[后端 2.7步骤处理微信后台 不断给我发来的返回值 ] // 支付回调路由
    public function payBack( Request $request )
    {
      $config = [
            // 必要配置

      ];

      $app = Factory::payment($config);
      $response = $app->handlePaidNotify(function($message, $fail){
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            // $order = 查询订单($message['out_trade_no']);
            $order = JyOrder::where('ord_id', $message['out_trade_no'])->first();
            
            
            Cache::put('paymessage', $message ,now()->addMinutes(60));
      
            if (!$order || $order->paid_at) { // 如果订单不存在 或者 订单已经支付过了
                return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
            }
      
            ///////////// <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况,确认是已经支付 /////////////
      
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
                // 用户是否支付成功
                if (array_get($message, 'result_code') === 'SUCCESS') {
                  $order->paid_at = date("Y-m-d H:i:s",time()) ; // 更新支付时间为当前时间
                  $order->payment_status = 3;
                  $this->addLogs( $message['out_trade_no'], 5, "客户已微信支付" );
                  
                // 用户支付失败
                } elseif (array_get($message, 'result_code') === 'FAIL') {
                  $order->payment_status = 7;
                }
            } else {
                return $fail('通信失败,请稍后再通知我');
            }
      
            $order->save(); // 保存订单
      
            return true; // 返回处理完成
      });
      
      $response->send(); // return $response;
      // Cache::put('wxpay',$request ,now()->addMinutes(60));

    }







完结









周大胖子 发表于 2021-8-30 16:38:55

贴一个微信返回的数据格式:
{
        "appid": "",
        "bank_type": "OTHERS",
        "cash_fee": "1",
        "fee_type": "CNY",
        "is_subscribe": "Y",
        "mch_id": "",
        "nonce_str": "",
        "openid": "",
        "out_trade_no": "20212068",
        "result_code": "SUCCESS",
        "return_code": "SUCCESS",
        "sign": "60B5F638DF7B2CB88F1BDD8F3947A074",
        "time_end": "20210830145512",
        "total_fee": "1",
        "trade_type": "JSAPI",
        "transaction_id": "4200001198202108302865001992"
}


参考链接: https://www.easywechat.com/docs/5.x/payment/notify

页: [1]
查看完整版本: 微信支付全部流程