微信小程序高级能力之一:微信支付

作者: 甚时跃马归来 | 来源:发表于2019-04-16 09:22 被阅读3次

    前言

    微信支付可以说是微信开放的所有能力中最重要的一个,在小程序中涉及微信支付的场景很多,而且微信支付也是面试环节中常常会问的一个问题。
    当然小程序中发起微信支付的代码非常简单,因为没什么好讲的,所以本文主要讲得是后台对接微信支付中所需要做的一些流程。(因为面试中,如果能说出后台对接微信支付过程中的几个主要的点来的话,是很加分的(o)/~)

    小程序中调用微信支付

    小程序中调用微信支付的代码很简单,如下:

    wx.requestPayment({
        timeStamp : '', // 时间戳,必填(后台传回)
        nonceStr : '', // 随机字符串,必填(后台传回)
        package : '', // 统一下单接口返回的 prepay_id 参数值,必填(后台传回)
        signType : 'MD5', // 签名算法,非必填,(预先约定或者后台传回)
        paySign  : '', // 签名 ,必填 (后台传回)
        success:function(res){ // 成功后的回调函数
            // do something
        }
    })
    

    这就讲完了?当然没有这么简单,而且这里面有什么好讲的,面试过程中有什么好问的?
    我们要讲的当然不是小程序的接口,事实上我们要讲得是后台对接微信支付过程中需要做的事情。

    完整的一次微信支付所经历的流程

    完整的一次微信支付所经历的的流程大概是这样子的:

    ①小程序请求后台提供的下单接口,申请支付参数(传递商品id,商品描述body,总金额total_fee等) ——>
    ②后台接收到请求参数,和原本准备好的参数进行一系列的处理,请求微信后台,获得相关支付参数,再返回给小程序端 ——>
    ③小程序得到支付的参数,发起支付(4个或5个,因为signType可以约定好也可以后台传回) ——>
    ④微信支付及其后台处理,请求我们后台预留的回调接口 ——>
    ⑤ 后台回调接口在接收到回调请求时,对订单进行后续处理(比如订单状态代付款改成已付款)。

    参数说明

    可以看到,上面流程中,1、2、5是在后台进行的,3是在小程序端进行的,4是微信方进行处理,这样就构成了1个完整的支付流程。
    而在后台的1、2、5中,1、5是没有任何难度的,因此主要看流程2。

    流程2主要用到的相关参数说明:
    appid ---> 小程序appid
    body ---> 商品描述
    mch_id ---> 商户号(商户开通了微信商户时拿到的id)
    nonce_str ---> 随机字符串(自己生成)
    notify_url ---> 后台提供的回调接口地址,用于后续处理订单(如改变订单状态等)
    openid ---> 用户的openid
    out_trade_no ---> 订单号,自己生成,保证唯一即可
    spbill_create_ip ---> 终端ip,其实填127.0.0.1也不会影响支付结果
    total_fee ---> 总金额,单位是 分
    trade_type ---> 交易类型,在小程序支付中为固定值 JSAPI
    key ---> 商户自定义秘钥key,在微信商户平台中定义的

    后台申请微信支付参数的过程

    在上面中,我们已经了解了微信支付所需要的参数。接下来主要是讲解流程2中所需要做的事情。
    在流程2中,主要分为4步:

    // 1 建立数组
    $arr = [
        'appid' => $appid,
        'body' => $body,
        'mch_id' => $mch_id,
        'nonce_str' => $nonce_str,
        'notify_url' => $notify_url,
        'openid' => $openid,
        'out_trade_no' => $out_trade_no,
        'spbill_create_ip' => $spbill_create_ip,
        'total_fee' => $total_fee,
        'trade_type' => 'JSAPI'
    ]
    
    
    // 2 对数组进行遍历,按照 key=value这个格式拼接字符串,并在最后加上 key='商户自定义秘钥key',
    // 然后md5该值,得到sign  示例如下:
    $str = 'appid=$appid&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_url=$notify_url&openid=$openid&out_trade_no=$out_trade_no&spbill_create=$spbill_create&total_fee=$total_fee&trade_type=JSAPI&key=$key'
    $sign = md5(str);
    
    
    
    
    // 3 拿到sign值,加入数组中,并将数组转成xml格式,用curl中的post方式请求微信接口
    https://api.mch.weixin.qq.com/pay/unifiedorder
    
    格式如下:
    <xml>
       <appid>wx2421b1c4370ec43b</appid>
       <attach>支付测试</attach>
       <body>JSAPI支付测试</body>
       <mch_id>10000100</mch_id>
       <detail><![CDATA[{ "goods_detail":[ { "goods_id":"iphone6s_16G", "wxpay_goods_id":"1001", "goods_name":"iPhone6s 16G", "quantity":1, "price":528800, "goods_category":"123456", "body":"苹果手机" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"苹果手机" } ] }]]></detail>
       <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
       <notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
       <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
       <out_trade_no>1415659990</out_trade_no>
       <spbill_create_ip>14.23.150.211</spbill_create_ip>
       <total_fee>1</total_fee>
       <trade_type>JSAPI</trade_type>
       <sign>0CB01533B8C1EF103065174F50BCA001</sign>
    </xml>
    
    
    // 4 第3步接收到的也是个xml数据,将其转成数组取出prepry_id字段,假设转换成的数组是$unifiedorder
    
    返回格式如下:
    <xml>
       <return_code><![CDATA[SUCCESS]]></return_code>
       <return_msg><![CDATA[OK]]></return_msg>
       <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
       <mch_id><![CDATA[10000100]]></mch_id>
       <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
       <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
       <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
       <result_code><![CDATA[SUCCESS]]></result_code>
       <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
       <trade_type><![CDATA[JSAPI]]></trade_type>
    </xml>
    
    
    新建以下数组
    $newarr = [
        'appId' => $this->appid,                  // 小程序ID
        'timeStamp' => '',                        // 新生成一个时间戳
        'nonceStr' => $this->createNoncestr(),     // 随机字符串
        'package' => 'prepay_id=' . $unifiedorder['prepay_id'], // 微信后台返回的数据包
        'signType' => 'MD5'      
    ]
    
    将其转成
    appid=appid&timestamp=timestamp&noncestr=noncestr&package=’prepay_id=xxxx’&signtype=signtype&key=key
    这种格式,再md5一次,得到paySign
    
    
    然后返回给小程序端的支付参数数据是 第4步中的
    
    timeStamp
    nonceStr
    package
    signType
    paySign
    
    
    至此,已经OJBK了。
    
    

    其他注意事项

    spbill_create_ip 终端ip 这个字段在文档中是必填的,但其实填个127.0.0.1也没什么影响
    total_fee 总金额 单位为 分
    notify_url 支付成功后的回调接口,但这个接口乱填,填错,在接口中没有响应或者是返回失败的结果,其实也不影响交易结果,但还是要填正确的地址(为了避免纠纷(o)/~)
    notify_url 这个接口中除了改订单状态,还可以做下订单校验什么的。(例如,我和后台曾经测试,后台返回1毛钱,实际支付2毛钱,结果 支付成功...)

    参考文章: 参考文章1

    相关文章

      网友评论

        本文标题:微信小程序高级能力之一:微信支付

        本文链接:https://www.haomeiwen.com/subject/gwmmwqtx.html