国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

坑爹的微信支付v3,其實沒有那么坑

2019-11-17 02:47:32
字體:
來源:轉載
供稿:網友

坑爹的微信支付v3,其實沒有那么坑

研究微信開發一年多了,每個新接口,都會第一時間進行研究。微信支付開放很久,一直沒機會接觸到支付接口,等了好久終于從朋友那兒搞到了接口,從此開始了我兩天多的支付接口的研究。

拿到這個接口文檔的第一個想法就是這也沒什么難的嘛, 和支付寶、財付通、網銀在線等一些傳統接口的思路邏輯都是一樣的,覺得差不多最多一個下午就可以搞定,結果第一步調用統一支付接口就給來了個下馬威,不管怎么改,就一直返回簽名錯誤。第一次遇到簽名錯誤,首先想到的是應該是沒有正確理解簽名的生成規則,又從頭看了幾次簽名的生成規則,每次都是的理解都是一樣的,試了改幾次還是不行。 這一次已經開始懷疑騰訊的文檔寫的有問題,一邊找其他資料一邊在心里罵騰訊寫文檔的作者。在園子里看到了到處都是坑的微信支付V3后,更加確認是微信的文檔的問題。現在想想當時的想法太幼稚了,大部分自信心爆棚的人,在遇到解決不了的問題時總是會懷疑是不是別人給的東西不對,而不會從自身找問題,一句話總結就是一到便秘就怪地球沒引力。(各位看官請勿對號入座,純屬個人見解,勿噴)。

現在說正題。。

從開始遇到錯誤到最后解決簽名的問題,總結的問題就是我在生成簽名的時候把參數進行了編碼,而官方給的開發文檔并沒有說要做url編碼,另外一個就是我進入了一個死胡同,總覺得自己的理解與實現過程沒有問題,但最后當我把之前寫的代碼完全放棄,推倒重做后,問題終于解決。興奮之極。下面從頭說下我的理解與解決方法。

官方文檔中接口調用規則:

? 認證方式:HTTPS 認證,退款和沖正接口調用需要商戶證書(證書在審核郵件附件

中)

? 請求采用 POST 方式

? 提交和返回結果采用 xml 格式

? 字符集默認使用 UTF-8,請勿使用其它字符集

? 商戶與微信之間的交互(特別是 Native 回調和支付通知回調),都需要驗證簽名

? 處理返回時先判斷協議返回錯誤碼,再判斷業務返回錯誤碼,最后判斷交易狀態

下面是官方的簽名生成方法

a.對所有傳入參數按照字段名的 ASCII 碼從小到大排序(字典序)后,使用 URL 鍵值對的格式(即 key1=value1&key2=value2…)拼接成字符串 string1,注意:值為空的參數不參與簽名

b. 在 string1 最 后 拼 接 上 key=Key( 商 戶 支 付 密 鑰 ) 得 到 stringSignTemp 字 符 串 , 并 對 stringSignTemp 進行 md5 運算,再將得到的字符串所有字符 轉換為大寫,得到 sign 值

下面是我所理解的簽名生成規則:

1,所有的參數都是小寫的

2,參數的值不需要做任何處理,包括url編碼

3,確保必須的參數不能為空,且是正確無誤的。

下面是示范過程:

要傳入的參數分別為:appid,mch_id,nonce_str,body,attach,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid(jsapi必須),PRoduct_id(native必須)。

首先將鍵值對存入Dictionary<string,string>中,其次根據key值升序排序,代碼如下: var dictemp = dic.OrderBy(d => d.Key);

然后將鍵值對轉換成url形式后,在末尾鏈接上key值,例如:appid=****&attach=****…………&key=******,最后進行md5加密并將加密后的字符串轉換成大寫。這里需要特別注意的是,md5加密是需要將字符集轉換成utf-8,否則中文商品描述會出現亂碼。

 1  public static string MD5(string pwd) 2         { 3             MD5 md5 = new MD5CryptoServiceProvider(); 4             byte[] data = System.Text.Encoding.UTF8.GetBytes(pwd); 5             byte[] md5data = md5.ComputeHash(data); 6             md5.Clear(); 7             string str = ""; 8             for (int i = 0; i < md5data.Length; i++) 9             {10                 str += md5data[i].ToString("x").PadLeft(2, '0');11             }12             return str;13         }
md5加密

生成簽名后將sign=簽名 鍵值對添加到生成簽名時生成的dictemp中,然后將dictemp轉換成xml,post到https://api.mch.weixin.QQ.com/pay/unifiedorder,返回值也是xml,最后對xml進行解析,為了保證安全性,需將解析后的鍵值對進行簽名校驗。

1 <xml><appid><![CDATA[******]]></appid><mch_id><![CDATA[******]]></mch_id><nonce_str><![CDATA[13120e01b82b48cfbebd4c9df66f0e47]]></nonce_str><body><![CDATA[神六]]></body><out_trade_no><![CDATA[ggggg673526]]></out_trade_no><total_fee><![CDATA[1000000]]></total_fee><spbill_create_ip><![CDATA[59.174.203.41]]></spbill_create_ip><notify_url><![CDATA[http://wxpay.ttyouni.net/aspx/order/notify.aspx]]></notify_url><trade_type><![CDATA[JSAPI]]></trade_type><openid><![CDATA[ozJkDj6yXuUsxIgS4xiJbtZMv2XQ]]></openid><sign><![CDATA[7CBA5A6BFF210BDA8C1AA33E9D803711]]></sign></xml>
正確的xml

校驗簽名無誤后,下一步就是取出預支付idprepay_id,然后調用微信支付js,注意:調用微信支付js之前也需要將所有參與調用的參數進行簽名,且這里的參與簽名的參數需要驗證遵守大小寫(騰訊有的時候真的很腦殘,一會全小寫,一會有大寫有小寫)。生成簽名后就可以調用微信支付js了,代碼如下:

 1 var WxPay= { 2     Pay: function (appId, timeStamp, nonceStr, package, signType, paySign,callback) { 3         WeixinJSBridge.invoke('getBrandWCPayRequest', { 4             "appId": appId,    //公眾號名稱,由商戶傳入 5             "timeStamp":timeStamp,    //時間戳,自 1970 年以來的秒數 6             "nonceStr": nonceStr, //隨機串 7             "package": package, 8             "signType": signType,    //微信簽名方式 9             "paySign": paySign //微信簽名10         }, function (res) {11             if (res.err_msg == "get_brand_wcpay_request:ok") {12                 callback();13             }14             // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg 將在用戶支付成功后返回 ok,但并不保證它絕對可靠。15         });16     }17 }
微信支付js

為了方便調用,我將微信支付js寫到了一個單獨的js文件,然后在頁面中載入,生成簽名用Ajax調用。調用代碼如下:

 1 <script> 2         $(function () { 3             $("#submit").click(function () { 4                 $.get("WxPay.ashx?action=jspayparam", { 5                     body: $("#body").val(), 6                     total_fee: $("#price").val(), 7                     out_trade_no: $("#order").val(), 8                     trade_type: "JSAPI", 9                     msgid:"<%=openid%>"10                 }, function (data) {11                     WxPay.Pay(data.appId, data.timeStamp, data.nonceStr, data.package, data.signType, data.paySign, function () {12                         alert("支付成功");13                     });14                 }, "json");15 16             });17         })18     </script>
支付js調用

這里我只傳入了一些和商品相關的參數,其他和商品無法的參數寫到了后臺代碼中。后臺收到請求后,將appid,mch_id等參數拼接成鍵值對進行進一步的處理,然后將處理后的結果返回給前臺。

 1         void GetJsPayParam(HttpContext context) 2         { 3             JsEntities jsEntities = new JsEntities() 4             { 5                 appId = appid, 6                 nonceStr = WxPayHelper.Utils.GetRandom(), 7                 package = string.Format("prepay_id={0}", GetPrepayId(context)), 8                 signType = "MD5", 9                 timeStamp = WxPayHelper.Utils.ConvertDateTimeInt(DateTime.Now).ToString()10             };11             string url, sign;12             WxPayHelper.Utils.GetUnifyUrlXml<JsEntities>(jsEntities, key, out url, out sign);13             jsEntities.paySign = sign;14             context.Response.Write(JsonConvert.SerializeObject(jsEntities));15         }
獲取js支付參數

下面是生成鍵值對的方法,由于請求支付的過程中,到處需要生成簽名,所以我將各個請求參數都寫成了一個個類,然后使用泛型類和反射動態生成字典鍵值對,請求url和xml。代碼如下:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临湘市| 遂昌县| 那坡县| 稷山县| 和顺县| 邵武市| 通榆县| 永济市| 调兵山市| 丹寨县| 石林| 敦化市| 黄龙县| 石棉县| 曲水县| 信丰县| 青岛市| 思茅市| 临朐县| 尼玛县| 隆德县| 潮州市| 梅州市| 阿拉善右旗| 大埔县| 三门县| 三河市| 贺兰县| 济宁市| 扬中市| 涪陵区| 喀喇| 铁岭市| 上犹县| 白玉县| 崇阳县| 微博| 资溪县| 鞍山市| 永登县| 明水县|