這個文章不會說具體0到1的代碼流程,我會着重講幾個問題的解決
准備以下依賴
"md5": "^2.2.1", "xml-js": "^1.6.11", "xmldom": "^0.1.27"
支付主要遇到的問題如下:
1.獲取openid
2.統一下單,拿到預單號(我起的,全名叫預支付交易會話標識)
3.再次簽名調起支付
4.支付后的處理
1.獲取openid很簡單,調用Taro.login()拿到code,傳給后端獲取openid,這個必須后端拿
2.統一下單的幾個問題:
大概需要這么些必填參數:
{ appid: '', // appid mch_id: '', // 商戶id nonce_str:'', // 隨機字符串 body: '', // 商品簡單描述 out_trade_no: '', // 商戶系統內部訂單號,唯一 total_fee: '', // 訂單總金額,單位為分 spbill_create_ip: '', // 你的ip,要后端傳給你 notify_url: '', // 通知地址,微信調的,告訴你支付的情況 trade_type: 'JSAPI', openid: '' }
①隨機字符串
②簽名
③XML的組裝與解析
①
export function randomString(len = 32) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; const maxPos = chars.length; let pwd = ''; for (let i = 0; i < len; i++) { pwd += chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; }
②
准備一個參數如下
const params = { appid: '', mch_id: '', nonce_str:randomString(32), body: '', out_trade_no: '', total_fee: '', spbill_create_ip: '', notify_url: '', trade_type: 'JSAPI', openid: '' }
簽名:
const sign = signFunc(params)
params.sign = sign
簽名函數
export function signFunc(data) { // 1.對key字典排序 const sortArr = Object.keys(data).sort() // 2.轉URL鍵值對 // const qsString = stringify(sortObj) let qsString = '' sortArr.map((t, index) => { if (index === 0) { qsString = `${t}=${data[t]}` } else { qsString = `${qsString}&${t}=${data[t]}` } }) // 3.拼接string+key const stringSignTemp = qsString + `&key=${key}` // 4.MD5簽名 const sign = md5(stringSignTemp).toUpperCase() return sign }
注意,我注釋的那句,是一個叫做qs的npm庫提供 ,不要用它對參數生成 URL鍵值對,因為它會把 再次簽名時,會把=轉成%3d
console.log(stringify({ package: 'prepay_id=wx2017033010242291fcfe0db70013231072' }))
輸出:
package=prepay_id%3Dwx2017033010242291fcfe0db70013231072
這樣的值不符合要求,md5處理后是和官方對不上 ,一定要package=prepay_id=wx2017033010242291fcfe0db70013231072
③
統一下單的參數必須是xml
發送請求,header要設置如下
'Content-Type': 'text/plain',
const xml =
`<xml>
<appid>${params.appid}</appid>
<openid>${ConfirmStore.openId}</openid>
<body>${params.body}</body>
<mch_id>${params.mch_id}</mch_id>
<nonce_str>${params.nonce_str}</nonce_str>
<notify_url>${params.notify_url}</notify_url>
<out_trade_no>${params.out_trade_no}</out_trade_no>
<spbill_create_ip>${params.spbill_create_ip}</spbill_create_ip>
<total_fee>${params.total_fee}</total_fee>
<trade_type>${params.trade_type}</trade_type>
<sign>${params.sign}</sign>
</xml>`
Taro.request({ url: `${unifyOrderUrl}`, header: { 'Content-Type': 'text/plain', }, method: 'POST', data: { xml, }, })
返回結果,xml的解析
由於小程序無dom,所以不可用 DOMParser() ,解決辦法是使用xmldom這個庫
示例寫法:xml字符串轉json
// 若結果data為以下
const data = `
<xml>
<appid></appid>
<timeStamp></timeStamp>
<nonce_str></nonce_str>
<package></package>
<signType></signType>
</xml>`
const doc = new DOMParser().parseFromString(data); const result = convert.xml2json(doc, { compact: true, spaces: 4 }); const { xml } = JSON.parse(result)
xml直接用即可
3可以參考2,主要問題也是簽名
4.記得做好支付成功或者失敗的處理
注意事項:
1.調用支付使用的noncestr這個參數必須和商家服務器調用統一下單接口返回的那個noncestr一致
https://developers.weixin.qq.com/community/develop/doc/000c209934c8d0bad528fc8bc56800
2.請在小程序后台,把微信支付統一下單URLhttps://api.mch.weixin.qq.com/pay/unifiedorder加到安全域名中
