node-koa2 微信支付,企业付款到零钱
微信支付用的V2版本
微信支付说明文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 参数详细说明请自行查看
// https://github.com/klover2/wechatpay-node-v3-ts/blob/master/index.ts
// https://blog.csdn.net/blackhost/article/details/100703911
微信支付2.0还是xml传输数据,用到了解析模块xml2js
接下来是请求微信支付,付款到零钱的主要代码,可以自行创建一个wxpay.js,将下面代码贴进去,
商户appid需要特别说明一下。如果你要是付款给公众号下的用户,就要填写公众号appid,付款给小程序下的用户,就要填写小程序的appid
我参与的项目,商户,小程序和公众号都有绑定,所以会稍稍复杂一点,当时我测试用的是小程序appid和小程序下的用户openid,大意了,应该是公众号的
const fs = require('fs')
const path = require('path')
const xml2js = require('xml2js')
const request = require('request')
const payUtil = require('./payUtil')
/**
* 微信-企业付款到零钱
*
* 注意的点是,企业付款到零钱,用的是公众号下的用户openid,所以appid要填成公众号的,保持一致,不能填小程序的
*/
exports.transfers = async (map) => {
let mapInfo = {}
// 商户appid
// 这里的商户appid是公众号appid
mapInfo.mch_appid = ''
// 商户id
mapInfo.mchid = ''
// 商户密钥
mapInfo.mchkey = ''
// 随机字符串
mapInfo.nonce_str = payUtil.getRnd32()
// 商户内部流水号
mapInfo.partner_trade_no = map.recordId
// 用户的openid
mapInfo.openid = map.openid
// 是否需要校验名字
mapInfo.check_name = 'NO_CHECK'
// 金额,单为是分
mapInfo.amount = map.amount * 100
// 描述
mapInfo.desc = '企业付款到零钱'
// ip,该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP。
mapInfo.spbill_create_ip = ''
// 签名
let sign = wxpay.transfersSign(mapInfo)
// 拼接xm字符串
let formData = "<xml>";
formData += "<mch_appid>" + mapInfo.mch_appid + "</mch_appid>";
formData += "<mchid>" + mapInfo.mchid + "</mchid>";
formData += "<nonce_str>" + mapInfo.nonce_str + "</nonce_str>";
formData += "<partner_trade_no>" + mapInfo.partner_trade_no + "</partner_trade_no>";
formData += "<openid>" + mapInfo.openid + "</openid>";
formData += "<check_name>" + mapInfo.check_name + "</check_name>";
formData += "<amount>" + mapInfo.amount + "</amount>";
formData += "<desc>" + mapInfo.desc + "</desc>";
formData += "<spbill_create_ip>" + mapInfo.spbill_create_ip + "</spbill_create_ip>";
formData += "<sign>" + sign + "</sign>";
formData += "</xml>";
console.log(formData)
// 请求路径
let url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'
return new Promise((resolve, reject) => {
request({
url: url,
// 需要证书
agentOptions: {
cert: fs.readFileSync(path.resolve(`./public/config/cert/${payConfig.wx_cert}`)),
key: fs.readFileSync(path.resolve(`./public/config/cert/${payConfig.wx_key}`))
},
method: 'post',
body: formData,
}, function (err, response, body) {
if (!err && response.statusCode == 200) {
// 创建一个解析xml的对象
let parser = new xml2js.Parser({
trim: true,
explicitArray: false,
explicitRoot: false
});
//解析签名结果xml转json
parser.parseString(body, (err, res) => {
console.log(res)
let result = {}
// 判断return_code 为fail的时候,的错误信息
if (res.return_code == 'FAIL') {
result.msg = res.return_msg
reject(result)
}
// return_code是success 的话, 只代表业务已受理, 并不代表已成功
// result_code是success 的话, 才算是付款成功, fail的话,返回错误信息
if (res.return_code == 'SUCCESS' && res.result_code == 'FAIL') {
result.msg = res.err_code_des
reject(result)
} else {
result.msg = ''
resolve(result)
}
})
}
reject(err)
})
})
}
在其他地方调用付款到零钱transfers方法
// 微信支付方法路径自行修改成自己的 const { transfers } = require('./wxpay') const { createOrderNumber } = require('./payUtil') let map = { // 金额 amount: 1, // 备注 desc: '提现', // 用户openid openid: '', // 系统内部流水号 recordId: createOrderNumber(), } try { let result = await transfers(map) ctx.body = { code: 200, msg: '提现到零钱成功,提醒用户稍后自行查看' } } catch (err) { console.log(err) // 捕捉请求微信支付的错误 ctx.body = { code: 500, msg: err.msg } return }
下面贴一些工具方法,自行创建一个payUtil.js,将下面代码贴入即可
// 生成随机随机32 位 字符串 exports.getRnd32 = () => { let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' let result = '' for (let i = 0; i < 32; i++) { let rnd = Math.floor(Math.random() * str.length) result += str[rnd] } return result } // 生成时间戳 exports.createTimeStamp = () => { return parseInt(new Date().getTime() / 1000) + ''; } // 生成订单编号 exports.createOrderNumber = () => { let str = '' for (let i = 0; i < 10; i++) { let num = Math.floor(Math.random() * 10) str += num } let time = new Date() let year = time.getFullYear().toString() let month = time.getMonth().toString() + 1 let day = time.getDate().toString() let hours = time.getHours().toString() let minutes = time.getMinutes().toString() let seconds = time.getSeconds().toString() let mill = time.getMilliseconds().toString() str += year += month += day += hours += minutes += seconds += mill return str; } // 按照ascll码排序 function raw(args) { var keys = Object.keys(args); keys = keys.sort() var newArgs = {}; keys.forEach(function (key) { newArgs[key] = args[key]; }); var string = ''; for (var k in newArgs) { string += '&' + k + '=' + newArgs[k]; } string = string.substr(1); return string; } /** * 企业付款到零钱签名 */ exports.transfersSign = (map) => { let ret = { mch_appid: map.mch_appid, mchid: map.mchid, nonce_str: map.nonce_str, partner_trade_no: map.partner_trade_no, openid: map.openid, check_name: map.check_name, amount: map.amount, desc: map.desc, spbill_create_ip: map.spbill_create_ip, } console.log(ret) var string = raw(ret); var key = map.mchkey; string = string + '&key=' + key; var crypto = require('crypto'); return crypto.createHash('md5').update(string, 'utf8').digest('hex').toUpperCase(); }
本文来自博客园,作者:时光凉忆,转载请注明原文链接:https://www.cnblogs.com/naturl/p/15393459.html

浙公网安备 33010602011771号