The business scenario of the company needs to use the function of wechat account distribution. After debugging the official website documents for a whole afternoon, the process of using Nodejs wechat account distribution is recorded.
The premise condition
- Open the function of account splitting in my product and payment extension tool in the product Center of wechat merchant platform
- Add the ledger receiver. If this step is not set, return a * sub-ledger receiver relationship does not exist. Please check the relationship of each receiver in the parameter. * error
- Get the merchant ID and Secrect from the merchant platform
- You need to upload apiclient_cert.pem and apiclient_key to a directory on the server
The specific implementation
// @router post -> share -> /common/payment/share
async share() {
const { ctx } = this
const nonce_str = ctx.service.wx.randomStr()
/ / merchant id
const mch_id = '123456'
// x applet appid
const appid = 'wx123456'
/ / order number
const out_order_no = '1609745196755nFvdMaYub2'
// wechat Pay order number
const transaction_id = '4200000801202101044301662433'
/ / merchants secrect
const key = '9813490da1ffb80afaa36f6f1265e490'
// The parameters of this section are explained in detail on the official website documentation
const params = {
appid,
mch_id,
nonce_str,
out_order_no,
receivers: `[{"account": "123qwe","amount": 1,"description": "description","type": "PERSONAL_OPENID"}]`.sign_type: 'HMAC-SHA256',
transaction_id,
}
// The signature must be hMAC-sha256
const sign = ctx.service.wx.sign(params, key, 'HMAC-SHA256')
// xmlString
const formData = `<xml>
<appid>${appid}</appid>
<mch_id>${mch_id}</mch_id>
<nonce_str>${nonce_str}</nonce_str>
<out_order_no>${out_order_no}</out_order_no>
<transaction_id>${transaction_id}</transaction_id>
<sign>${sign}</sign>
<sign_type>HMAC-SHA256</sign_type>
<receivers>${params.receivers}</receivers>
</xml>`
const res = await ctx.curl(
"https://api.mch.weixin.qq.com/secapi/pay/profitsharing",
{
// Apiclient_cert is required
cert: fs.readFileSync(path.join(__dirname,'.. /.. /.. /cert/apiclient_cert.pem')),
// The apiclient_key certificate is required
key: fs.readFileSync(path.join(__dirname,'.. /.. /.. /cert/apiclient_key.pem')),
method: "post".data: formData,
}
)
const datastring = res.data.toString()
xml2js.parseString(datastring, (err, result) = > {
if (err) {
ctx.throw(422, err)
}
console.log(result)
})
}
// randomStr
// Generate random strings
randomStr(len = 24) {
const str =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let result = ' ';
for (let i = 0; i < len; i++) {
result += str[Math.floor(Math.random() * str.length)];
}
return result;
}
/ / signature
// McHKey is the merchant secrect, otherwise the signature will not pass
sign(data, mchKey, signType = 'MD5') {
const keys = [];
for (const key in data) {
if(data[key] ! = =undefined) { keys.push(key); }}// Dictionary sort =>key=value
const stringA = keys
.sort()
.map(key= > `${key}=The ${decodeURIComponent(data[key])}`)
.join('&');
// Splice the merchant key
const stringSignTemp = stringA + '&key=' + mchKey;
/ / encryption
let hash;
if (signType === 'MD5') {
hash = crypto.createHash('md5').update(stringSignTemp);
} else {
hash = crypto.createHmac('sha256', mchKey).update(stringSignTemp, 'utf8');
}
const paySign = hash.digest('hex').toUpperCase();
return paySign;
}
Copy the code
If you encounter a signature failure. You can step your formData into the interface signature verification tool for verification.
Other common problems of the ledger interface