前言
微信支付可以说是微信开放的所有能力中最重要的一个,在小程序中涉及微信支付的场景很多,而且微信支付也是面试环节中常常会问的一个问题。
当然小程序中发起微信支付的代码非常简单,因为没什么好讲的,所以本文主要讲得是后台对接微信支付中所需要做的一些流程。(因为面试中,如果能说出后台对接微信支付过程中的几个主要的点来的话,是很加分的(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¬ify_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×tamp=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
网友评论