微信服务号 - 微信支付
服务号可接入微信支付(JSAPI支付),用户在公众号网页内完成下单、支付,实现完整的交易闭环。
支付流程
| 步骤 | 操作方 | 说明 |
|---|---|---|
| 1. 统一下单 | 商户服务端 | 调用微信统一下单API,获取prepay_id |
| 2. 生成签名 | 商户服务端 | 用prepay_id等参数生成前端支付签名 |
| 3. 调起支付 | 前端页面 | 通过WeixinJSBridge或JS-SDK调起支付弹窗 |
| 4. 支付回调 | 微信服务器 | 支付成功后微信通知商户服务器 |
| 5. 结果通知 | 商户服务端 | 验证签名、更新订单状态、发送模板消息 |
统一下单 - 服务端
const crypto = require('crypto')
const axios = require('axios')
const MCH_ID = process.env.WX_MCH_ID
const MCH_KEY = process.env.WX_MCH_KEY
function generateSign(params) {
const str = Object.keys(params).sort()
.map(k => `${k}=${params[k]}`).join('&')
return crypto.createHash('md5')
.update(str + `&key=${MCH_KEY}`).digest('hex').toUpperCase()
}
async function unifiedOrder(openid, orderId, amount, description) {
const params = {
appid: APP_ID,
mch_id: MCH_ID,
nonce_str: crypto.randomBytes(16).toString('hex'),
body: description,
out_trade_no: orderId,
total_fee: amount,
spbill_create_ip: '127.0.0.1',
notify_url: 'https://example.com/pay/notify',
trade_type: 'JSAPI',
openid: openid
}
params.sign = generateSign(params)
const xml = Object.entries(params)
.map(([k, v]) => `<${k}>${v}</${k}>`).join('')
const { data } = await axios.post(
'https://api.mch.weixin.qq.com/pay/unifiedorder',
`<xml>${xml}</xml>`
)
return data
}
前端调起支付
function onBridgeReady(payParams) {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: payParams.appId,
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: 'MD5',
paySign: payParams.paySign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
alert('支付成功!')
location.href = '/order/success'
} else {
alert('支付取消或失败')
}
})
}