Taro/JS/H5/小程序:純前端解決小程序微信支付統一下單和調起支付


這個文章不會說具體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加到安全域名中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM