前言
微信支付可以說(shuō)是微信開(kāi)放的所有能力中最重要的一個(gè)酷愧,在小程序中涉及微信支付的場(chǎng)景很多寂殉,而且微信支付也是面試環(huán)節(jié)中常常會(huì)問(wèn)的一個(gè)問(wèn)題蹋盆。
當(dāng)然小程序中發(fā)起微信支付的代碼非常簡(jiǎn)單傀缩,因?yàn)闆](méi)什么好講的漆魔,所以本文主要講得是后臺(tái)對(duì)接微信支付中所需要做的一些流程坷檩。(因?yàn)槊嬖囍校绻苷f(shuō)出后臺(tái)對(duì)接微信支付過(guò)程中的幾個(gè)主要的點(diǎn)來(lái)的話(huà)改抡,是很加分的(o)/~)
小程序中調(diào)用微信支付
小程序中調(diào)用微信支付的代碼很簡(jiǎn)單矢炼,如下:
wx.requestPayment({
timeStamp : '', // 時(shí)間戳,必填(后臺(tái)傳回)
nonceStr : '', // 隨機(jī)字符串雀摘,必填(后臺(tái)傳回)
package : '', // 統(tǒng)一下單接口返回的 prepay_id 參數(shù)值裸删,必填(后臺(tái)傳回)
signType : 'MD5', // 簽名算法,非必填阵赠,(預(yù)先約定或者后臺(tái)傳回)
paySign : '', // 簽名 涯塔,必填 (后臺(tái)傳回)
success:function(res){ // 成功后的回調(diào)函數(shù)
// do something
}
})
這就講完了?當(dāng)然沒(méi)有這么簡(jiǎn)單清蚀,而且這里面有什么好講的匕荸,面試過(guò)程中有什么好問(wèn)的?
我們要講的當(dāng)然不是小程序的接口枷邪,事實(shí)上我們要講得是后臺(tái)對(duì)接微信支付過(guò)程中需要做的事情榛搔。
完整的一次微信支付所經(jīng)歷的流程
完整的一次微信支付所經(jīng)歷的的流程大概是這樣子的:
①小程序請(qǐng)求后臺(tái)提供的下單接口,申請(qǐng)支付參數(shù)(傳遞商品id,商品描述body,總金額total_fee等) ——>
②后臺(tái)接收到請(qǐng)求參數(shù)东揣,和原本準(zhǔn)備好的參數(shù)進(jìn)行一系列的處理践惑,請(qǐng)求微信后臺(tái),獲得相關(guān)支付參數(shù)嘶卧,再返回給小程序端 ——>
③小程序得到支付的參數(shù)尔觉,發(fā)起支付(4個(gè)或5個(gè),因?yàn)閟ignType可以約定好也可以后臺(tái)傳回) ——>
④微信支付及其后臺(tái)處理芥吟,請(qǐng)求我們后臺(tái)預(yù)留的回調(diào)接口 ——>
⑤ 后臺(tái)回調(diào)接口在接收到回調(diào)請(qǐng)求時(shí)侦铜,對(duì)訂單進(jìn)行后續(xù)處理(比如訂單狀態(tài)代付款改成已付款)专甩。
參數(shù)說(shuō)明
可以看到,上面流程中钉稍,1涤躲、2、5是在后臺(tái)進(jìn)行的贡未,3是在小程序端進(jìn)行的种樱,4是微信方進(jìn)行處理,這樣就構(gòu)成了1個(gè)完整的支付流程羞秤。
而在后臺(tái)的1缸托、2左敌、5中瘾蛋,1、5是沒(méi)有任何難度的矫限,因此主要看流程2哺哼。
流程2主要用到的相關(guān)參數(shù)說(shuō)明:
appid ---> 小程序appid
body ---> 商品描述
mch_id ---> 商戶(hù)號(hào)(商戶(hù)開(kāi)通了微信商戶(hù)時(shí)拿到的id)
nonce_str ---> 隨機(jī)字符串(自己生成)
notify_url ---> 后臺(tái)提供的回調(diào)接口地址,用于后續(xù)處理訂單(如改變訂單狀態(tài)等)
openid ---> 用戶(hù)的openid
out_trade_no ---> 訂單號(hào)叼风,自己生成取董,保證唯一即可
spbill_create_ip ---> 終端ip,其實(shí)填127.0.0.1也不會(huì)影響支付結(jié)果
total_fee ---> 總金額无宿,單位是 分
trade_type ---> 交易類(lèi)型茵汰,在小程序支付中為固定值 JSAPI
key ---> 商戶(hù)自定義秘鑰key,在微信商戶(hù)平臺(tái)中定義的
后臺(tái)申請(qǐng)微信支付參數(shù)的過(guò)程
在上面中孽鸡,我們已經(jīng)了解了微信支付所需要的參數(shù)蹂午。接下來(lái)主要是講解流程2中所需要做的事情。
在流程2中彬碱,主要分為4步:
// 1 建立數(shù)組
$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 對(duì)數(shù)組進(jìn)行遍歷豆胸,按照 key=value這個(gè)格式拼接字符串,并在最后加上 key='商戶(hù)自定義秘鑰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值,加入數(shù)組中嚼沿,并將數(shù)組轉(zhuǎn)成xml格式估盘,用curl中的post方式請(qǐng)求微信接口
https://api.mch.weixin.qq.com/pay/unifiedorder
格式如下:
<xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付測(cè)試</attach>
<body>JSAPI支付測(cè)試</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":"蘋(píng)果手機(jī)" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"蘋(píng)果手機(jī)" } ] }]]></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步接收到的也是個(gè)xml數(shù)據(jù),將其轉(zhuǎn)成數(shù)組取出prepry_id字段骡尽,假設(shè)轉(zhuǎn)換成的數(shù)組是$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>
新建以下數(shù)組
$newarr = [
'appId' => $this->appid, // 小程序ID
'timeStamp' => '', // 新生成一個(gè)時(shí)間戳
'nonceStr' => $this->createNoncestr(), // 隨機(jī)字符串
'package' => 'prepay_id=' . $unifiedorder['prepay_id'], // 微信后臺(tái)返回的數(shù)據(jù)包
'signType' => 'MD5'
]
將其轉(zhuǎn)成
appid=appid×tamp=timestamp&noncestr=noncestr&package=’prepay_id=xxxx’&signtype=signtype&key=key
這種格式遣妥,再md5一次,得到paySign
然后返回給小程序端的支付參數(shù)數(shù)據(jù)是 第4步中的
timeStamp
nonceStr
package
signType
paySign
至此爆阶,已經(jīng)OJBK了燥透。
其他注意事項(xiàng)
spbill_create_ip 終端ip 這個(gè)字段在文檔中是必填的沙咏,但其實(shí)填個(gè)127.0.0.1也沒(méi)什么影響
total_fee 總金額 單位為 分
notify_url 支付成功后的回調(diào)接口,但這個(gè)接口亂填班套,填錯(cuò)肢藐,在接口中沒(méi)有響應(yīng)或者是返回失敗的結(jié)果,其實(shí)也不影響交易結(jié)果吱韭,但還是要填正確的地址(為了避免糾紛(o)/~)
notify_url 這個(gè)接口中除了改訂單狀態(tài)吆豹,還可以做下訂單校驗(yàn)什么的。(例如理盆,我和后臺(tái)曾經(jīng)測(cè)試痘煤,后臺(tái)返回1毛錢(qián),實(shí)際支付2毛錢(qián)猿规,結(jié)果 支付成功...)
參考文章: 參考文章1