微信公眾號支付v3總結(jié)

時間: 2016年8月11日

說明: 文檔主要描述微信公眾號支付開發(fā)過程中處理流程和一些遇到的問題。

1 準備工作

步驟
步驟
  • 微信公眾號申請,類型選擇服務(wù)號或企業(yè)號,訂閱號不支持微信支付功能
  • 微信商戶帳號申請(需要審核)
  • 選擇對應(yīng)版本的 SDK 文件準備開發(fā)

2 支付原理

業(yè)務(wù)流程
業(yè)務(wù)流程

3 通知(同步、異步)

  • 3.1 同步通知

商戶根據(jù)微信支付后返回的結(jié)果來處理自己的業(yè)務(wù)。

  • 3.2 異步通知

微信支付完成后,會通過在下單時候設(shè)置的 notify_url 通知商戶支付結(jié)果,商戶通過返回的結(jié)果來處理內(nèi)部訂單然后給微信返回處理結(jié)果,如果返回成功則說明商戶校驗信息正常通知微信不需要再次通知,否則微信會在一定時間內(nèi)重復(fù)發(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 統(tǒng)一下單 unifiedorder

  • 4.1.1 方法中需要參數(shù)都填寫,注意參數(shù)名大小寫和長度

  • 4.1.2 統(tǒng)一下單時簽名問題

  • 4.1.3 微信用戶 openid 獲取

  • 4.1.4 加強下單時參數(shù)驗證

    public static function unifiedOrder($wxpay_config = array(), $ssl_config = array(), $proxy_config = array())
    {
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        //檢測必填參數(shù)
        if (!array_key_exists('out_trade_no', $wxpay_config)) {
            throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù) out_trade_no!");
        }
        if (!array_key_exists('body', $wxpay_config)) {
            throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù) body!");
        }
        if (!array_key_exists('total_fee', $wxpay_config)) {
            throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù) total_fee!");
        }
        if (!array_key_exists('trade_type', $wxpay_config)) {
            throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù) trade_type!");
        }

        //關(guān)聯(lián)參數(shù)
        if ('JSAPI' == $wxpay_config['trade_type']) {
            if (!array_key_exists('openid', $wxpay_config)) {
                throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)openid!trade_type為JSAPI時,openid為必填參數(shù)!");
            }
        }
        if ('NATIVE' == $wxpay_config['trade_type']) {
            if (!array_key_exists('product_id', $wxpay_config)) {
                throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)product_id!trade_type為JSAPI時,product_id為必填參數(shù)!");
            }
        }
        if (!array_key_exists('notify_url', $wxpay_config)) {
            throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)!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);

        // 響應(yīng)結(jié)果
        $responseArr = WxPayCore::fromXml($response);

        return $responseArr;
    }

4.2 微信支付JSAPI

  • 4.2.1 統(tǒng)一下單成功后返回數(shù)據(jù)

  • 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("參數(shù)錯誤");
        }

        $timemap = time();

        // 生成隨機數(shù)
        $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 微信公眾號內(nèi)置支付功能

function onBridgeReady(){
   WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
           "appId" : "wx2421b1c4370ec43b",                        //公眾號名稱,由商戶傳入
           "timeStamp":" 1395712654",                             //時間戳,自1970年以來的秒數(shù)
           "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 生成的數(shù)據(jù)作為微信內(nèi)置函數(shù) WeixinJSBridge.invoke() 發(fā)起 getBrandWCPayRequest 請求時的參數(shù),如果參數(shù)正確當點擊支付時候可以在微信公眾號中調(diào)用微信客戶端支付功能。

4.4 同步通知流程處理
商戶根據(jù)微信內(nèi)置函數(shù)調(diào)用支付結(jié)果來處理業(yè)務(wù),例如:當支付返回 get_brand_wcpay_request:ok 說明支付成功,get_brand_wcpay_request:failget_brand_wcpay_request:cancle 說明支付失敗,但是 返回數(shù)據(jù)不一定可靠

4.5 異步通知處理
微信會通過統(tǒng)一下單時設(shè)置的 notify_url 向商戶發(fā)送支付結(jié)果通知,商戶應(yīng)該根據(jù)返回的數(shù)據(jù)對訂單信息和商戶信息等重要信息驗證
避免訂單錯誤導(dǎo)致資金錯誤,然后更新內(nèi)部訂單狀態(tài),最后將處理后的結(jié)果返回給微信,如果微信收到商戶的應(yīng)答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發(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 統(tǒng)一下單時簽名問題

  • 5.2 支付時簽名驗證失敗

  • 5.3 異步通知未響應(yīng)

Q&A: 簽名錯誤

簽名問題大部分是因為生成簽名時參數(shù)不一致,例如:在統(tǒng)一下單時候需要傳遞簽名參數(shù)和其他參數(shù),個人感覺微信在調(diào)用生成預(yù)支付訂單時候內(nèi)部也產(chǎn)生簽名并且
和傳遞過來的簽名進行對比驗證,當不一致時就會提示簽名錯誤,原因就是在下單時商戶主動生成的簽名參數(shù)和微信內(nèi)部生成參數(shù)不一致,當簽名不一致時建議將方
法所需的參數(shù)作為生成簽名的參數(shù),然后再將生成簽名傳遞。

Q&A: 異步通知未響應(yīng)

1. 統(tǒng)一下單時 notify_url 是否設(shè)置
2. notify_url 是否符合規(guī)范:1.不能帶有參數(shù),例如:https://pay.weixin.qq.com/notify.php?wx=20160811  2.能夠訪問
3. 檢查接口是否有訪問權(quán)限設(shè)置
4. 通過 error_log 檢查是否有日志文件產(chǎn)生

6 總結(jié)

    在微信公眾號支付開發(fā)過程中,遇到很多問題有些官方文檔沒怎么描述清楚,導(dǎo)致后面花較長時間去測試原因。然后是理解到同步和異步通知的區(qū)別并且學(xué)習到 
error_log 日志功能的好處,通過生成的日志文件方便去解決問題和優(yōu)化,遠遠超過自己預(yù)測情況時沒有數(shù)據(jù)來對比分析。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 引言 秋高氣爽,天氣轉(zhuǎn)涼,正是學(xué)習工作做的好時候。(~ ̄▽ ̄)~~(~ ̄▽ ̄)~ 我是個phper最近在寫微信支付...
    恩就是這個名閱讀 8,222評論 2 15
  • 該文僅對于中間這種支付方式有參考價值喲 一、開發(fā)背景 在微信公眾號中,需要進行微信支付且為微信公眾號網(wǎng)頁支付。 二...
    英文名叫夏天閱讀 2,003評論 0 7
  • 東西丟了,尤其是經(jīng)常用的,心情總是不會太好。我勸自己“或許是與此物今生有緣無份吧",但心里還是惆悵,不像說句話那么...
    蕭近風閱讀 219評論 0 0
  • 一天比一天起得晚,為什么呢?累了,冷了還是懶了?也許都有,其實主要還是慵懶了。 睡得太久也不是什么好事,腰酸背痛的...
    流浪癡人閱讀 117評論 0 0
  • 65d44a2ea11c閱讀 422評論 0 0

友情鏈接更多精彩內(nèi)容