node-koa2 微信支付-企业付款到银行卡
微信支付用的V2版本
微信支付说明文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay_yhk.php?chapter=24_2 参数详细说明请自行查看
提示语:
微信支付2.0还是xml传输数据,用到了解析模块xml2js
可以自行创建一个wxpay.js,将下面获取公钥和付款到银行卡的代码贴进去
特别说明一下:付款到银行卡,不仅需要证书,还需要用微信提供的公钥(下面有获取代码示例),对收款方姓名和收款银行卡号,进行RSA加密,
上代码,
获取微信提供的加密公钥
/**
* 获取公钥
*
* 获取企业付款到银行卡的加密公钥
*/
exports.getpublickey = async (payConfig) => {
let mch_id = payConfig.Wechat_merchant_number
let mchkey = payConfig.Wechat_pay_key
let url = 'https://fraud.mch.weixin.qq.com/risk/getpublickey'
let formData = "<xml>" let mapInfo = {}
// 商户号
mapInfo.mch_id = mch_id
// 随机字符串
mapInfo.nonce_str = wxpay.getRnd32()
// 商户密钥
mapInfo.mchkey = mchkey
// 加密方式
mapInfo.sign_type = "MD5"
// 签名
let sign = wxpay.getpublickkeySign(mapInfo) formData += "<mch_id>" + mch_id + "</mch_id>"
formData += "<nonce_str>" + mapInfo.nonce_str + "</nonce_str>"
formData += "<sign>" + sign + "</sign>"
formData += "<sign_type>MD5</sign_type>"
formData += "</xml>"
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) {
let parser = new xml2js.Parser({
trim: true,
explicitArray: false,
explicitRoot: false
}); //解析签名结果xml转json
parser.parseString(body, (err, res) => {
console.log(res)
// console.log(res) if (res.return_code == 'FAIL') {
reject(res.return_msg)
}
// return_code是success 的话, 只代表退款业务已受理, 并不代表已退款成功
// result_code是success 的话, 才算是退款成功, fail的话,返回错误信息
if (res.return_code == 'SUCCESS' && res.result_code == 'FAIL') {
reject(res.err_code_des)
} else {
resolve(res.pub_key)
}
})
}
reject(err)
})
})
}
微信支付付款到银行卡的方法封装
const fs = require('fs')
const path = require('path')
const xml2js = require('xml2js')
const request = require('request')
const crypto = require('crypto')
const NodeRSA = require('node-rsa');
/**
* RSA加密
*
* RSA加密可以用crypto模块。也可以使用node-rsa模块,参考如下连接:https://www.cnblogs.com/huangdaozhang/p/11109417.html
*/
let encryptRSA = (key, hash) => {
return crypto.publicEncrypt(key, Buffer.from(hash)).toString('base64')
}
/**
* 付款到银行卡
*/
exports.payBank = async (map) => {
let publicKey = map.publicKey
let url = 'https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank'
let mapInfo = {}
// 商户号
mapInfo.mch_id = ''
// 商户密钥
mapInfo.mchkey = ''
// 商户付款单号
mapInfo.partner_trade_no = map.recordId
// 随机字符串
mapInfo.nonce_str = payUtil.getRnd32()
// 收款方开户行银行编号
mapInfo.bank_code = map.bankCode
// 收款方用户名
mapInfo.enc_true_name = encryptRSA(publicKey, map.payee)
// 收款方银行卡号
mapInfo.enc_bank_no = encryptRSA(publicKey, map.receivingAccount)
// 付款金额
mapInfo.amount = Math.round(map.amount * 100 * 100) / 100
// 付款说明
mapInfo.desc = map.desc
// 签名
let sign = payUtil.payBankSign(mapInfo)
// console.log(publicKey)
// const a_public_key = new NodeRSA(publicKey);
let formData = "<xml>";
formData += "<amount>" + mapInfo.amount + "</amount>";
formData += "<bank_code>" + mapInfo.bank_code + "</bank_code>";
// formData += "<desc>" + mapInfo.desc + "</desc>";
formData += "<enc_bank_no>" + mapInfo.enc_bank_no + "</enc_bank_no>";
formData += "<enc_true_name>" + mapInfo.enc_true_name + "</enc_true_name>";
formData += "<mch_id>" + mapInfo.mch_id + "</mch_id>";
formData += "<nonce_str>" + mapInfo.nonce_str + "</nonce_str>";
formData += "<partner_trade_no>" + mapInfo.partner_trade_no + "</partner_trade_no>";
formData += "<sign>" + sign + "</sign>";
formData += "</xml>";
console.log(formData)
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) {
let parser = new xml2js.Parser({
trim: true,
explicitArray: false,
explicitRoot: false
}); //解析签名结果xml转json
parser.parseString(body, (err, res) => {
console.log(res)
let result = {
recordId: mapInfo.partner_trade_no
}
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)
})
})
}
1. 接下来获取加密公钥,获取成功后,可以写入文件,,本人比较懒,没有搞呢。是不会变化的这个公钥
2. 获取公钥成功后,调用payBank方法,实现付款到银行卡
// 微信支付方法路径自行修改成自己的
const { payBank } = require('./wxpay')
const { createOrderNumber } = require('./payUtil') router.post('/', async () => {
let map = {
// 金额
amount: 1,
// 备注
desc: '提现',
// 用户openid
openid: '',
// 系统内部流水号
recordId: createOrderNumber(),
}
// 第一步先获取公钥
let publicKey;
try {
publicKey = await getpublickey(payConfig)
} catch (err) {
console.log(err)
ctx.body = {
code: 500,
msg: err
}
return
}
// 获取公钥成功后,调用payBank方法,付款到银行卡
try {
let result = await payBank(map)
ctx.body = {
code: 200,
msg: '微信受理成功, T+1到账'
}
} 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.payBankSign = (map) => {
let ret = {
amount: map.amount,
bank_code: map.bank_code,
enc_bank_no: map.enc_bank_no,
enc_true_name: map.enc_true_name,
mch_id: map.mch_id,
nonce_str: map.nonce_str,
desc: map.desc,
partner_trade_no: map.partner_trade_no,
}
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();
} /**
* 获取公钥进行签名
*/
exports.getpublickkeySign = (map) => {
let ret = {
mch_id: map.mch_id,
nonce_str: map.nonce_str,
sign_type: map.sign_type
}
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();
}
最后提一些我测试时出现的问题,有时你在本地测试的时候,会有如下报错
error:此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置
可以参考下面的链接:https://blog.csdn.net/yexiaomodemo/article/details/109316364
node-koa2 微信支付-企业付款到银行卡的更多相关文章
- 微信分账功能与微信支付企业付款相关内容详解(payjs版)
PAYJS开通微信分账功能以来,有很多同学咨询相关情况.很多同学关心有没有什么办法,可以让自己的商户号快速开通企业付款功能.这里就介绍下微信分账的具体相关内容,可以完美解决问题. 一.什么是微信分账? ...
- php 微信支付企业付款
1.所需参数 字段名 变量名 必填 示例值 类型 描述 公众账号appid mch_appid 是 wx8888888888888888 String 公众号的appId 商户号 mchid 是 19 ...
- JAVA微信支付——企业付款(企业向微信用户个人付款、转账)
本地开发环境支付回调调试方法可以参考:https://www.cnblogs.com/pxblog/p/11623053.html 需要自行引入相关依赖 官方文档地址:https://pay.weix ...
- php微信支付企业付款到零钱报错call faild, errorCode:58
这个报错一般是自己证书目录不是绝对目录,正确的目录结构应该是网站根目录下的:“C:\PHPWAMP_IN1\wwwroot\XXXX\XXXX.pem”. 还要注意的是文件夹命名一定 ...
- PHP微信商户支付 - 企业付款到零钱功能(即提现)技术资料汇总
PHP实现微信开发中提现功能(企业付款到用户零钱) 一.实现该功能目的 这几天在小程序里要实现用户从系统中提现到零钱的功能,查了一下文档可以使用 企业付款到用户零钱 来实现: 官方文档:https:/ ...
- PHP实现微信商户支付企业付款到零钱功能代码实例
本文为大家分享了PHP实现微信商户支付企业付款到零钱的具体代码,供大家参考,具体内容如下 微信支付开发文档 一.开通条件 企业付款为企业提供付款至用户零钱的能力,支持通过API接口付款,或通过微信支付 ...
- PHP微信商户支付企业付款到零钱功能
一 开通条件,就是首先要在微信平台设置好. 以下微信文档里有的,我这里大概掠几项比较重要的. 付款资金 企业付款到零钱资金使用商户号余额资金. 根据商户号的账户开通情况,实际出款账户有做区别: ◆ 默 ...
- PHP实现微信企业付款到个人零钱步骤
微信支付企业付款到零钱功能应用广泛,比如微信红包奖励,业务结算等.通过企业向个人付款,付款资金将直接进入用户微信零钱. 一 开通条件 付款资金 企业付款到零钱资金使用商户号余额资金. 根据商户号的 ...
- 微信企业向用户银行卡付款API开发详解(PHP)
最近在实现微信企业向用户银行卡付款时遇到了一些问题,发现官方文档说的太笼统,走了不少弯路,想要在此记录,希望可以帮到大家. 案例:企业付款到银行卡 微信接口链接:https://api.mch. ...
- 企业移动互联网O2O微信支付流程图
过去一周里最受关注的应该就是微信了,腾讯合作伙伴大会微信分论坛的火爆现场,没有亲临其境是无法想象的,近3000人报名,2000多人来到现场,试图进入只能容纳300人的会场…… 闲话不表,进入正题吧,本 ...
随机推荐
- 谷歌浏览器页面乱码问题在浏览器端解决,charset下载安装;
一 下载插件(百度网盘) 链接:https://pan.baidu.com/s/1o9Zuo2m 密码:rrcz 二 将下载好的插件拖到谷歌浏览器中 三 如果谷歌浏览器右下角出现如下图 ...
- python处理nii文件
第一步安装nibabel,可以使用命令:pip install nibabel 之后: from nibabel.viewers import OrthoSlicer3D as osdimport n ...
- Java日期时间API系列22-----Jdk8中java.time包中的新的日期时间API类,Month月份和DayOfWeek星期的计算。
Java8中为月份和星期新增的了,Month和DayOfWeek,来处理月份和星期的特殊问题,这2个类都是枚举类,对Month.DayOfWeek源码说明和简单应用,月份英文,月份英文简称,月份中文, ...
- 什么是SPA页面,它的优缺点?
什么是SPA spa是单页面应用(single page web application),浏览器会一开始就加载所需要的html.css.javascript.一旦页面加载完毕,整个页面就不会因为用户 ...
- k8s的pod的理解
pod共享相同的IP地址和端口空间. 这意味着在同一 pod中的容器运行的 多个进程需要注意不能绑定到相同的端口号, 否则会导致端口冲突, 但这只涉及同一pod中的容器. 由于每个pod都有独立的端口 ...
- 初学Linux的可以看看
Linux常用命令总结 自己简单总结的,希望对大家有帮助吧! 关机/重启 系统信息 文件以及目录 vim文件编辑器 打包压缩 用户和组 权限所有者 RPM YUM mount find 自己简单总结的 ...
- Python3 编程面试题
Python global 语句的作用 lambda 匿名函数好处 Python 错误处理 Python 内置错误类型 简述 any() 和 all() 方法 Python 中什么元素为假? 提高 P ...
- 为数据集而生的 SQL 控制台
随着数据集的使用量急剧增加,Hugging Face 社区已经变成了众多数据集默认存放的仓库.每月,海量数据集被上传到社区,这些数据集亟需有效的查询.过滤和发现. 每个月在 Hugging Face ...
- Postman 免登录测试后端接口
今天跟测试同学学习了下用Postman免登录测试后端接口,测试同学除了会对我们系统前端测试外,一些后端接口涉及危险操作也会使用Postman 对接口进行测试,这个时候就需要解决一个接口免登录的问题,他 ...
- LVM 使用与扩容总结
转载请注明出处: LVM(Logical Volume Manager,逻辑卷管理器)是一个用于Linux系统的磁盘管理工具.它提供了一种更加灵活的存储管理机制,可以方便地进行磁盘的扩容.缩减.快照以 ...