微信支付的那些坑!!!

微信支付的那些坑!

 

開通和審覈php

微信支付和支付寶商家平臺同樣,都是要審覈資質的,支付寶我的認證可使用擔保支付,雖然須要用戶確認收貨以後才能收到資金,可是好歹也是能用的。微信直接不讓我的使用支付。只有企業以上級別的服務號才能申請。html

開通&認證前端

支付寶註冊企業帳號,進行企業認證,我總共就花了10分鐘,包括公司資質審覈,打款到公帳確認公帳等步驟。效率高到簡直沒法想象。 微信支付須要已經認證過的服務號才能開通支付。提交完資質,等待審覈,花了5個工做日的時間才告訴我資質審覈過了,對,沒錯,是5個工做日,中間隔了一個週末,微信稱2-7個工做日認證完成,仍是實現諾言了。web

開通支付算法

支付寶須要簽約服務,這裏我簽約的是即時到賬的,花了2天時間。 微信開通認證以後,登錄商戶平臺配置一下就能夠開幹了,這點從速度方面比支付寶強點,由於它把支付用途啥的都放到第一步的認證裏面了,而支付寶是放在後面的簽約服務裏面進行審覈的。json

這些步驟完成以後,就能夠開始開發了。雖然如此,從總體進度上面,支付寶仍是略勝微信一籌的。api

開發安全

文檔&DEMO微信

微信的文檔,恩,在微信公衆平臺有一份,在商戶平臺又有另一份,並且內容還不同。。。我主要須要在公衆號裏面支付,因此選擇了微信的JSAPI。在公衆平臺裏面,關於JS支付的只有一小段。以下:app

signature 的值是用多個參數 sha1 加密的結果,詳細流程即:

1, 經過 appid +appsecert 獲取公衆號的 access_token(不是用戶的 access_token)
2, 根據 1 的access_token 來獲取 jsapi_ticket
3, 生成一個隨機字符串 nonceStr(16)位
4, 生成一當前時間綴 timestamp
5, 獲取當前網頁 URL(#號後不要)

獲取到以上 5 步以後,將 jsapi_ticket,nonceStr, timestamp,URL 組成 Query String(GET 參數),即:

$queryString ="jsapi_ticket=XXX&noncestr=XXX&timestamp=XXX&url=XXX";

生成 Query String 要注意:
1,Query String 的順序不能變(按我給的示例)
2,Query String 中的 key 要全小寫
3,Query String 中的 value 區分大小寫
4,URL 要確保只獲取 # 號以前部分(有 # 號的話)
5,Query String 要確保沒有被 urlencode(若是使用 http_build_query 的話須要 urldecode 一次)

signature 的值就是 sha1 加密後的結果,即:

$signature =sha1($queryString);

 

wx.chooseWXPay({

    timestamp:0, // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符

    nonceStr:'', // 支付簽名隨機串,不長於 32 位

    package:'', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)

    signType:'', // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5'

    paySign:'', // 支付簽名

    success:function (res) {

        // 支付成功後的回調函數

    }

});

備註:prepay_id 經過微信支付統一下單接口拿到,paySign 採用統一的微信支付 Sign 簽名生成方法,注意這裏appId 也要參與簽名,appId 與 config 中傳入的 appId 一致,即最後參與簽名的參數有appId, timeStamp, nonceStr, package, signType。

 

微信支付統一下單接口文檔:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1

 

微信支付簽名算法:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3

 

微信支付開發教程:https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN

看完方法,有點暈,在看完下面給出的三個連接裏面的內容,更暈了。而後又在商戶平臺找到一份文檔。

傳送門

這裏給了比較詳細的資料,也給出了js示例:

    注:JS API的返回結果get_brand_wcpay_request:ok僅在用戶成功完成支付時返回。因爲前端交互複雜,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail能夠統一處理爲用戶遇到錯誤或者主動放棄,沒必要細化區分。

示例代碼以下:

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();

}

恩,因而我結合了文檔和找到的demo,結合這一段內容開始測試,結果發現,徹底沒反應。是的,在個人iPhone上面是沒有反應的,也許哪裏出了問題,一直搞不出反應。 而後我想到了前面還有一種chooseWXPay,搜索了一下,這是新版接口的方法。結合下面的文檔參數的計算,成功了。結果是這樣的

wx.chooseWXPay({

               appId: '{{ $jsParameters['appId'] }}',

               timestamp: '{{ $jsParameters['timeStamp'] }}', // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符

               nonceStr: '{{ $jsParameters['nonceStr'] }}', // 支付簽名隨機串,不長於 32 位

               package: '{{ $jsParameters['package'] }}', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)

               signType: '{{ $jsParameters['signType'] }}', // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5'

               paySign: '{{ $jsParameters['paySign'] }}', // 支付簽名

               success: function (res) {

                   if(res.errMsg == "chooseWXPay:ok" ) {

                        //支付成功

                   }else{

                        alert(res.errMsg);

                   }

               },

               cancel:function(res){

                   //支付取消

               }

            });

這裏的$jsParameters是在後臺使用微信支付的DEMO裏面提供的class生成的。

include_once("WxPayPubHelper.php");

...

public function getParameters(Order $order)

{

    $jsApi =new JsApi_pub();

   $unifiedOrder = new UnifiedOrder_pub();

   //$unifiedOrder->setParameter("detail",$this->order->product->brief_desc);//商品描述

   $unifiedOrder->setParameter("body",$order->product->name);//商品描述

   $unifiedOrder->setParameter("out_trade_no",$order->order_number);//商戶訂單號

   $unifiedOrder->setParameter("total_fee", $order->price *100);//總金額,騰訊默認支付金額單位爲【分】

   $unifiedOrder->setParameter("notify_url",WxPayConf_pub::NOTIFY_URL);//通知地址

   $unifiedOrder->setParameter("trade_type","JSAPI");//交易類型

    //非必填參數,商戶可根據實際狀況選填

   $unifiedOrder->setParameter("openid",Auth::user()->wx_openid);//商品ID

 

   $unifiedOrder->setParameter("product_id",$order->product->id);//商品ID

    $prepay_id= $unifiedOrder->getPrepayId();

    $jsApi->setPrepayId($prepay_id);

 

    return$jsApi->getParameters();

}

我描述你一臉啊,明顯第一個是用戶openid

還有這個

支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符

你很難搞清楚啥時候改用大寫,啥時候該用小寫。

還有這個

備註:prepay_id 經過微信支付統一下單接口拿到,paySign 採用統一的微信支付 Sign 簽名生成方法,注意這裏appId 也要參與簽名,appId 與 config 中傳入的 appId 一致,即最後參與簽名的參數有appId, timeStamp, nonceStr, package, signType。

就是在調用chooseWXPay的時候,你要本身加上appId,注意,I是大寫。不然採用JSAPI方式的時候會提示出錯。

還有這個

注:JS API的返回結果get_brand_wcpay_request:ok僅在用戶成功完成支付時返回。因爲前端交互複雜,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail能夠統一處理爲用戶遇到錯誤或者主動放棄,沒必要細化區分。

function(res){    

      if(res.err_msg == "get_brand_wcpay_request:ok" ) {}     // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功後返回    ok,但並不保證它絕對可靠。

   }

老版的接口裏面是這樣描述返回結果的。可是在新版裏面變了,是變了,可是滿世界找不到變成啥樣了。只能本身打出來測試,結果變成以下

 success:function (res) {

   if(res.errMsg == "chooseWXPay:ok" ) {

        //支付成功

        ...

新版接口裏面取消是沒有反應的,由於只有success回調。沒有任何一個地方說了如何監聽用戶取消支付。只能本身猜,結果,我果真猜對了。

success: function (res) {

  if(res.errMsg== "chooseWXPay:ok" ) {

      //支付成功

  }else{

     alert(res.errMsg);

  }

  },

cancel:function(res){

  //支付取消

}

你覺得是res.errMsg =="chooseWXPay:cancel"嗎?騷年,你仍是太年輕。

設置坑

一、要設置好安全支付目錄。這個啥意思?

一、全部使用JS API方式發起支付請求的連接地址,都必須在支付受權目錄之下;

二、最多設置3個支付受權目錄, 且域名必須經過ICP備案;

三、頭部要包含http或https,須細化到二級或三級目錄,以左斜槓「/」結尾。

修改會影響線上交易,距正式生效有十分鐘左右延遲,建議你避開交易高峯時間修改

就是說,你將要調用JSAPI的那個頁面的連接要在這個目錄之下才能夠。不然,會彈出提示說你的目錄沒權限。好比你調用JSAPI的頁面地址爲

那麼你要把安全目錄設置爲

這樣設置以後,若是你在以下地址調用,則會報錯

你能夠設置多個支付目錄,若是須要的話。

二、設置回調地址,這個不解釋。

三、設置警告地址,不解釋。

四、商戶平臺裏面設置密鑰,在登陸了商戶平臺以後,位於帳戶設置-API安全裏面,先裝數字證書,而後設置密鑰,32位字符串。設置完了,本身記下來,沒錯,要本身記下來,由於無法再查看了。

公衆號支付測試的時候測試連接要從公衆號裏點進去才能出現支付界面,否則會一直報chooseWXPay fail ,這是個大坑啊

 

 

 

最終前端調用代碼以下:

wx.config({

    debug:true,

    appId:jsonobj.appId, // 必填,公衆號的惟一標識

    timestamp:jsonobj.timeStamp, // 必填,生成簽名的時間戳

    nonceStr:jsonobj.nonceStr, // 必填,生成簽名的隨機串

    signature:jsonobj.signature, // 必填,微信簽名,這個簽名,和下面的paySign,不是同一個。生成方法,見http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html 附錄1

    jsApiList:[

      'chooseWXPay'

    ] // 必填,須要使用的JS接口列表

});

wx.ready(function(){

    wx.chooseWXPay({

        timestamp:jsonobj.timeStamp, // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符

        nonceStr:jsonobj.nonceStr, // 支付簽名隨機串,不長於 32 位

        package:jsonobj.package, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)

        signType:'MD5', // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5'

        paySign:jsonobj.paySign, // 支付簽名

        success:function (res) {

            //支付成功後的回調函數

            alert('paysuccess');

        },

        cencel:function(res){

            alert('cencelpay');

        },

        fail:function(res){

            alert('payfail');

            alert(JSON.stringify(res));

        }

    });

});

wx.error(function(res){

    alert(res.err_msg);

});

相關文章
相關標籤/搜索