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人的会场…… 闲话不表,进入正题吧,本 ...
随机推荐
- duxapp:基于Taro使用模块化开发,提升开发效率
duxapp是基于Taro二次开发的模块化框架 使用这个框架,结合框架提供的UI库和工具库,能帮助你快速且高质量的完成项目,且能实现同时开发小程序.H5.APP(React Native),并且保证各 ...
- vscode单行注释失效解决办法
第一种情况: bug:在使用快捷键注释的时候,只有style和script标签里的内容注释有问题,无法使用快捷键注释. 解决方法:禁用vscode的插件Jinja. 第二种情况 方法一 1.Ctrl+ ...
- CPU性能测试基准(Dhrystone)学习
简介 Dhrystone是测量处理器运算能力的最常见基准程序之一,常用于处理器的整型运算性能的测量.程序是用C语言编写的,因此C编译器的编译效率对测试结果也有很大影响. Dhrystone是由Rein ...
- usb请求块以及提交方式
URB结构体 struct urb { /* private: usb core and host controller only fields in the urb */ struct kref k ...
- 深度解析Spring AI:请求与响应机制的核心逻辑
我们在前面的两个章节中基本上对Spring Boot 3版本的新变化进行了全面的回顾,以确保在接下来研究Spring AI时能够避免任何潜在的问题.今天,我们终于可以直接进入主题:Spring AI是 ...
- Oracle、MySQL等数据库故障处理优质文章分享 | 10月汇总
墨天轮社区于9月起持续举办[聊聊故障处理那些事儿]DBA专题征文活动,每月进行评优发奖,鼓励大家记录工作中遇到的数据库故障处理过程,不仅用于自我复盘与分析,同时也能帮助其他的同仁们避坑. 上月为大家梳 ...
- DDD之领域服务与应用服务
领域服务: 聚合中的实体没有业务逻辑代码,只有对象的创建,对象的初始化,状态管理等个体相关的代码: 对于聚合内的业务逻辑,我们编写领域服务Domain service 而对于聚合协作以及聚合与外部系统 ...
- what can i say?
今天也是打了一场让我GG的考试 首先来个炸裂的: 全场唯一爆0的,堪称MVP what can i say 赛时一共交了三遍,就最后一遍GG了. 分析一下原因吧: wa的码: #include< ...
- Redisson 工作原理-源码分析
时间不在于你拥有多少,而在于你怎样使用. 1:Redisson 是什么 个人理解:一种 可重入.持续阻塞.独占式的 分布式锁协调框架,可从 ReentrantLock 去看它. ①:可重入锁 拿到锁的 ...
- 比较var和let的区别
什么是作用域 块级作用域:即在{}花括号内的域,由{ }包括,比如if{}块.for(){}块.注意函数快也叫做块 函数作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体都是有定义的. JS ...