文檔真的很重要,不論是寫仍是看的人都應該認真點php
本文主要寫給公衆平臺h5支付開發者html
真的,區分大小寫,注意前面的參數就不多會出現問題了。前端
除了博客園,這篇文章的內容也放在這裏本身的blog 【http://mimeay.cc/】web
這一步不設計開發。。。不詳說。ajax
微信公衆平臺-> 微信支付-> 開發配置,見微信官方圖,具體細節見圖片數據庫
接口地址 :https://api.mch.weixin.qq.com/pay/unifiedorderexpress
必須提交的參數json
appid 公衆平臺的appid attach 自定義消息 body 商品類別【商品信息均可以】 mch_id 商戶平臺的帳號 nonce_str 隨機字符串,不超過32位 notify_url 微信生成prepay_id後,會發送請求到所設置的回調地址 out_trade_no 商戶自定義生成的訂單號,要保證不能重複 spbill_create_ip 客戶端的ip地址 total_fee 支付的金額,以分爲單位 trade_type 交易類型 取值有JSAPI,NATIVE,APP ,由於是在h5頁面觸發支付,我選擇了 JSAPI,要根據實際需求選擇
根據項目,須要提交的參數後端
openid 標示用戶的id 【下面會貼相關連接】,若是是h5支付開發就必定要傳
以上提交參數要注意區分大小寫【若是有大寫的話】,針對幾個參數說明一下 openid :用戶受權後,微信會在你設置的受權回調域名後拼接code參數,經過這個code的值,而後經過code換取網頁受權accesstoken。 api
openid。請注意,這裏須要經過網頁受權獲取
mch_id :註冊商戶平臺後,微信會把商戶號和密碼發到指定的郵箱,這裏用到商戶帳號而已
看代碼啦
爲了展現,我把內容整合成在一塊兒,實際開發並無寫在一塊兒
let config = { appid : '這裏是appid', mch_id : '商戶平臺帳號' notify_url : 'http://mimeay.cc/pay/receive', key : '在商戶平臺設置的' } let util = { createNonceStr () { return Math.random().toString(36).substr(2, 15); }, createTimestamp () { return parseInt(new Date().getTime() / 1000) + ''; }, raw (args) { let keys = Object.keys(args); keys = keys.sort() let newArgs = {}; keys.forEach(function (key) { newArgs[key] = args[key]; }); let string = ''; for (let k in newArgs) { string += '&' + k + '=' + newArgs[k]; } string = string.substr(1); return string; }, paySign (data,key) { let stringA,stringSignTemp,sign; stringA = module.exports.raw(data); stringSignTemp = stringA +'&key=' + key; sign = md5(stringSignTemp).toUpperCase(); return sign; }, post_request_xml(url,data){ // 這裏返回響應的內容 } }
生成 prepay_id
unified_order ({openid,ip,out_trade_no,total_fee,category = '記念品',trade_type = 'JSAPI',device_info = 'WEB',attach = '網上商城'}){ let baseUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; let nonce_str = util.createNonceStr(); // ip 能夠從請求對象取 // openid 經過客戶端傳遞 // out_trade_no 請求統一下單前先生成【無論用戶最終是否完成支付】 // total_fee 支付金額,單位爲分,經過商品的id從數據庫獲取價格並轉化成分【前端傳遞金額不可靠】 // 其餘參數不傳則默認 let data = { appid : config.appid, attach : attach, body : '公司名-' + category, mch_id : config.mch_id, nonce_str: nonce_str, notify_url : config.notify_url, openid : openid, out_trade_no : out_trade_no, spbill_create_ip : ip, total_fee:total_fee, trade_type : trade_type, device_info : device_info }; let sign = util.paySign(data,config.key); data['sign'] = sign; let xmlData = { xml : data } //jstoxml.toXML 是把js轉換成xml的一個方法來的 let xml = jstoxml.toXML(xmlData); // post_request_xml return util.post_request_xml(baseUrl,xml).then((result)=>{ const {sign,prepay_id,return_code,return_msg} = result; if(return_code == 'FAIL'){ return { return_code, return_msg } }else{ return { return_code, return_msg, prepay_id : prepay_id } } }) }
結合prepay_id生成客戶端支付請求的參數,這裏的 appId, timeStamp, nonceStr, package, signType嚴格區分大小寫,我一開始沒注意,把參數都小寫了,結果致使客戶端簽名失敗
wx_pay_sign (prepay_id){ let baseUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; let nonce_str,data,sign,timestamp,xmlData,xml,_package; nonce_str = util.createNonceStr(); timestamp = util.createTimestamp(); _package = 'prepay_id=' + prepay_id; //這裏的參數要區分大小寫 data = { appId : config.appId, timeStamp : timestamp, nonceStr : nonce_str, package : _package, signType : 'MD5' } // appId, timeStamp, nonceStr, package, signType sign = util.paySign(data,config.key); data['paySign'] = sign; return data; }
到此,後端統一下單作的事情告一段落
還記得wx_pay_sign函數作的事情嗎,假設咱們經過接口請求,拿到了wx_pay_sign返回的值
$.ajax({ url : 'xxxxxxx', type : 'post', data : { openid : '經過受權拿到的openid' }, success (json){ const {code,data,msg} = json; if(code == 0){ wx.chooseWXPay({ timestamp: data.timeStamp, // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符 nonceStr: data.nonceStr, // 支付簽名隨機串,不長於 32 位 package: data.package, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***) signType: data.signType, // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5' paySign: data.paySign, // 支付簽名 success: function (res) { // 支付成功後的回調函數 } }); } } })
<xml> <appid>xxxxx</appid> </xml>
<xml> <appid></appid> <mch_id>23123123</mch_id> </xml>
由於是爲了展現給你們看,因此對代碼有所修改,可能會出現錯誤,請你們理解。你們若是在作微信h5支付開發過程當中有遇到問題,可加我qq【200909050】,我盡本身能力幫忙。