時間: 2016年8月11日
說明: 文檔主要描述微信公眾號支付開發(fā)過程中處理流程和一些遇到的問題桥嗤。
1 準備工作
- 微信公眾號申請副硅,類型選擇服務號或企業(yè)號芯急,訂閱號不支持微信支付功能
- 微信商戶帳號申請(需要審核)
- 選擇對應版本的 SDK 文件準備開發(fā)
2 支付原理
3 通知(同步、異步)
- 3.1 同步通知
商戶根據微信支付后返回的結果來處理自己的業(yè)務。
- 3.2 異步通知
微信支付完成后圆雁,會通過在下單時候設置的 notify_url 通知商戶支付結果,商戶通過返回的結果來處理內部訂單然后給微信返回處理結果帆谍,如果返回成功則說明商戶校驗信息正常通知微信不需要再次通知伪朽,否則微信會在一定時間內重復發(fā)通知給商戶。通知頻率為15/15/30/180/1800/1800/1800/1800/3600汛蝙,單位:秒烈涮。
4 開發(fā)流程
官方文檔: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
4.1 統一下單 unifiedorder
4.1.1 方法中需要參數都填寫,注意參數名大小寫和長度
4.1.2 統一下單時簽名問題
4.1.3 微信用戶 openid 獲取
4.1.4 加強下單時參數驗證
public static function unifiedOrder($wxpay_config = array(), $ssl_config = array(), $proxy_config = array())
{
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//檢測必填參數
if (!array_key_exists('out_trade_no', $wxpay_config)) {
throw new WxPayException("缺少統一支付接口必填參數 out_trade_no窖剑!");
}
if (!array_key_exists('body', $wxpay_config)) {
throw new WxPayException("缺少統一支付接口必填參數 body坚洽!");
}
if (!array_key_exists('total_fee', $wxpay_config)) {
throw new WxPayException("缺少統一支付接口必填參數 total_fee!");
}
if (!array_key_exists('trade_type', $wxpay_config)) {
throw new WxPayException("缺少統一支付接口必填參數 trade_type西土!");
}
//關聯參數
if ('JSAPI' == $wxpay_config['trade_type']) {
if (!array_key_exists('openid', $wxpay_config)) {
throw new WxPayException("統一支付接口中讶舰,缺少必填參數openid!trade_type為JSAPI時翠储,openid為必填參數绘雁!");
}
}
if ('NATIVE' == $wxpay_config['trade_type']) {
if (!array_key_exists('product_id', $wxpay_config)) {
throw new WxPayException("統一支付接口中,缺少必填參數product_id援所!trade_type為JSAPI時,product_id為必填參數欣除!");
}
}
if (!array_key_exists('notify_url', $wxpay_config)) {
throw new WxPayException("缺少統一支付接口必填參數住拭!notify_url");
}
$xml = WxPayCore::toXml($wxpay_config);
$startTimeStamp = WxPayCore::getMillisecond();//請求開始時間
$response = WxPayCore::postXmlCurl($xml, $url, $proxy_config['curl_proxy_host'], $proxy_config['curl_proxy_port'], $ssl_config['sslcert_path'], $ssl_config['sslkey_path'], true);
// 響應結果
$responseArr = WxPayCore::fromXml($response);
return $responseArr;
}
4.2 微信支付JSAPI
4.2.1 統一下單成功后返回數據
4.2.2 簽名驗證
public function getJSApiParameters($UnifiedOrderResult, $key)
{
if (!array_key_exists("appid", $UnifiedOrderResult)
|| !array_key_exists("prepay_id", $UnifiedOrderResult)
|| $UnifiedOrderResult['prepay_id'] == "") {
throw new WxPayException("參數錯誤");
}
$timemap = time();
// 生成隨機數
$o_ranchar = new Core\Utility\RandChar();
$s_ranchar = $o_ranchar->randChar('mix', 32);
// 生成簽名
$sign_config = array(
"appId" => $UnifiedOrderResult['appid'],
"timeStamp" => "$timemap",
"nonceStr" => $s_ranchar,
"package" => "prepay_id=" . $UnifiedOrderResult['prepay_id'],
"signType" => "MD5",
);
$o_sign = new Core\Utility\WxPay\WxPaySign($sign_config);
$s_sign = $o_sign->makeSign($key);
$params = array(
"appId" => $UnifiedOrderResult['appid'],
"timeStamp" => "$timemap",
"nonceStr" => $s_ranchar,
"package" => "prepay_id=" . $UnifiedOrderResult['prepay_id'],
"signType" => "MD5",
"paySign" => $s_sign
);
return $params;
}
4.3 微信公眾號內置支付功能
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "wx2421b1c4370ec43b", //公眾號名稱,由商戶傳入
"timeStamp":" 1395712654", //時間戳历帚,自1970年以來的秒數
"nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串
"package" : "prepay_id=u802345jgfjsdfgsdg888",
"signType" : "MD5", //微信簽名方式:
"paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {}
// 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功后返回 ok滔岳,但并不保證它絕對可靠。
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
將 微信支付 JSAPI 生成的數據作為微信內置函數 WeixinJSBridge.invoke() 發(fā)起 getBrandWCPayRequest 請求時的參數挽牢,如果參數正確當點擊支付時候可以在微信公眾號中調用微信客戶端支付功能谱煤。
4.4 同步通知流程處理
商戶根據微信內置函數調用支付結果來處理業(yè)務,例如:當支付返回 get_brand_wcpay_request:ok
說明支付成功禽拔,get_brand_wcpay_request:fail
或 get_brand_wcpay_request:cancle
說明支付失敗刘离,但是 返回數據不一定可靠。
4.5 異步通知處理
微信會通過統一下單時設置的 notify_url 向商戶發(fā)送支付結果通知睹栖,商戶應該根據返回的數據對訂單信息和商戶信息等重要信息驗證
避免訂單錯誤導致資金錯誤硫惕,然后更新內部訂單狀態(tài),最后將處理后的結果返回給微信,如果微信收到商戶的應答不是成功或超時野来,微信認為通知失敗恼除,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率曼氛,但微信不保證通知最終能成功豁辉。 (通知頻率為15/15/30/180/1800/1800/1800/1800/3600令野,單位:秒)
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
------------------------------------------------------------
<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[商戶返回失敗的原因]]></return_msg>
</xml>
5 常見問題
5.1 統一下單時簽名問題
5.2 支付時簽名驗證失敗
5.3 異步通知未響應
Q&A: 簽名錯誤
簽名問題大部分是因為生成簽名時參數不一致,例如:在統一下單時候需要傳遞簽名參數和其他參數徽级,個人感覺微信在調用生成預支付訂單時候內部也產生簽名并且
和傳遞過來的簽名進行對比驗證彩掐,當不一致時就會提示簽名錯誤,原因就是在下單時商戶主動生成的簽名參數和微信內部生成參數不一致灰追,當簽名不一致時建議將方
法所需的參數作為生成簽名的參數堵幽,然后再將生成簽名傳遞。
Q&A: 異步通知未響應
1. 統一下單時 notify_url 是否設置
2. notify_url 是否符合規(guī)范:1.不能帶有參數弹澎,例如:https://pay.weixin.qq.com/notify.php?wx=20160811 2.能夠訪問
3. 檢查接口是否有訪問權限設置
4. 通過 error_log 檢查是否有日志文件產生
6 總結
在微信公眾號支付開發(fā)過程中朴下,遇到很多問題有些官方文檔沒怎么描述清楚,導致后面花較長時間去測試原因苦蒿。然后是理解到同步和異步通知的區(qū)別并且學習到
error_log 日志功能的好處殴胧,通過生成的日志文件方便去解決問題和優(yōu)化,遠遠超過自己預測情況時沒有數據來對比分析佩迟。