微信企业付款到银行卡 .NET
企业付款到银行卡 .NET 版的 ,了解一下?
- 是不是按照微信的文档看不懂?
- 是不是按照微信文档走完流程后还是存在问题?
- 是不是网上找不到.NET 代码?
- 是不是 “解密真实姓名或银行卡号出错”?
(我打客服电话 95017 电话问的微信 企业付款到银行卡API 能用吧?微信不知道哪个二货客服跟我说不能用,然后第二天朋友打电话问客服,客服说能用!就问你屌不屌~~~)
服务器部署错误移驾
X509 certificate not loading private key file on server
描述
企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向银行卡付款,针对部分有开发能力的商户,提供通过API完成企业付款到银行卡的功能。
首先你的微信商户平台需要满足微信企业付款到银行卡的要求 也就是什么连续一个月要有收入什么之类的
请求
请求地址:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
双向证书:是
- 证书文档地址
- 证书下载地址:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>证书下载
- 商户证书安全:证书文件不能放在web服务器虚拟目录,应放在有访问权限控制的目录中,防止被他人下载。商户服务器要做好病毒和木马防护工作,不被非法侵入者窃取证书文件。
- 使用商户证书
◆ apiclient_cert.p12是商户证书文件,除PHP外的开发均使用此证书文件(.NET 使用这个证书)。
◆ 商户如果使用.NET环境开发,请确认Framework版本大于2.0,必须在操作系统上双击安装证书apiclient_cert.p12后才能被正常调用。
◆ 商户证书调用或安装都需要使用到密码,该密码的值为微信商户号(mch_id)
请求参数:
MD5签名生成
(不说了,文档说的很清楚了)
获取RSA加密公钥API
- 调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设存储为public.pem
- 确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥
- 用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式【.NET RSA 加密是没有这个填充模式的】
- 得到进行rsa加密并转base64之后的密文
- 将密文作为参数传给 银行卡号 和 真实姓名
- 接口默认输出PKCS#1格式的公钥,商户需根据自己开发的语言选择公钥格式 【.NET 使用 PKCS#8 】
RSA公钥格式PKCS#1,PKCS#8互转说明,是在Linux 系统上转的哦
- PKCS#1 转 PKCS#8:
- openssl rsa -RSAPublicKey_in -in -pubout
- PKCS#8 转 PKCS#1:
- openssl rsa -pubin -in -RSAPublicKey_out
- RSA加密公钥API文档地址
-
- 请求证书:是 [ 证书同上 ]
- 请求参数
3、RSA加密请求成功后返回【 pub_key 是 PKCS#1 格式公钥 】
微信默认返回 PKCS#1 格式的,.NET 需要 PKCS#8 格式的。
示例:PKCS#1 转 PKCS#8 ,linux 输入这段命令
openssl rsa -RSAPublicKey_in -in 获取到的公钥存储为xx.pem后的文件路径 -pubout
【 红框 = 获取到的公钥存储为xx.pem 文件 】
【 绿框 = 命令 】
【 黄框 = 转换成功的 PKCS#8 】
【 pem 文件内容 】
标准RSA 加密算法
对收款方银行卡号,收款方用户名进行加密
这一块的代码是整个企业付款到银行卡接口比较难的一点
微信文档内告诉我们:拿着获取到的公钥对收款方银行卡号,收款方用户名 进行标准RSA加密算法加密
这个时候你从网上找一段.NET RSA 加密算法……. 是不是发现怎么请求都不正确。反复确认了参数及公钥后实在找不到问题所在,
于是你打了这个电话 95017 没错,微信帮助中心………. 几小时后发现他们并不能解决你的问题………
根据本人真实故事编写
没错,我的问题就是【 解密真实姓名或银行卡号出错 】
为什么会报这个错误?
你的公钥是微信提供的,这点没错。
你的参数反复检查也没错。
你得RSA 加密当时我觉得也没错。
那么问题只有一个 Visual Studio 错了!没错!就是它的错,地表最强IDE 的错。
(开玩笑的。。。。)
其实错误的是 RSA 加密(我是从网上淘的加密方法)。
解决方法:
你去支付宝提供的接口处下载一个支付接口,然后从支付宝接口内找 RSA 加密。
有点可耻不过问题就解决了。支付宝接口地址
微信企业付款到银行卡,成功后会告诉你微信侧受理成功
代码
请求:企业付款到银行卡
WxPayData ,WxPayConfig,HttpService 这些类是微信其它接口提供的demo 中提取出来的,附上地址。
微信支付开发文档->SDK与DEMO下载
protected void payToBank()
{
//!! 证书不要放在web 目录,使用绝对路径放置在有权限的文件夹中
//!! pem文件不要放在web 目录,使用绝对路径放置在有权限的文件夹中
string url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
//pem 文件为PKCS#8 公钥
string pempath="d:/pub.pem";
string key= System.IO.File.ReadAllText(pempath);
WxPayData inputObj = new WxPayData();
inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
inputObj.SetValue("partner_trade_no", "201803122431231331");//商户订单号
inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
//.NET 自带的RSA 加密存在问题,使用支付宝接口内的RSA 加密通过。
inputObj.SetValue("enc_bank_no", Rsa.RSAEncrypt("银行卡号", pempath, null, true));//收款方银行卡号,采用标准RSA算法
inputObj.SetValue("enc_true_name", Rsa.RSAEncrypt("真实姓名", pempath, null, true));//收款方用户名
inputObj.SetValue("bank_code", "1003");//收款方开户行
inputObj.SetValue("amount", 100);//付款金额
inputObj.SetValue("desc", "测试付款");//付款金额
inputObj.SetValue("sign", inputObj.MakeSign().ToUpper());//签名
string xml = inputObj.ToXml();
string response = HttpService.Post(xml, url, true, 20);//调用HTTP通信接口以提交数据到API
//将xml格式的结果转换为对象以返回
WxPayData result = new WxPayData();
result.FromXml(response);
}
请求:获取RSA公钥
private string getpublickey() {
string url = "https://fraud.mch.weixin.qq.com/risk/getpublickey";
WxPayData inputObj = new WxPayData();
inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
inputObj.SetValue("sign_type", "MD5");
inputObj.SetValue("sign", inputObj.MakeSign().ToUpper());//签名
string xml = inputObj.ToXml();
string response = HttpService.Post(xml, url, true, 10);//调用HTTP通信接口以提交数据到API
WxPayData result = new WxPayData();
SortedDictionary<string, object> res=result.FromXml(response);
//公钥获取后存储为 pub.pem
}
支付宝RSA类
/* 支付宝RSA
* content 加密内容
* publicKeyPem 公钥
* charset 编码
* keyFromFile 公钥是否是文件
*/
public class Rsa
{
/** 默认编码字符集 */
private static string DEFAULT_CHARSET = "UTF-8";
public static string RSAEncrypt(string content, string publicKeyPem, string charset, bool keyFromFile)
{
string sPublicKeyPEM;
if (keyFromFile)
{
sPublicKeyPEM = File.ReadAllText(publicKeyPem);
}
else
{
sPublicKeyPEM = "-----BEGIN PUBLIC KEY-----\r\n";
sPublicKeyPEM += publicKeyPem;
sPublicKeyPEM += "-----END PUBLIC KEY-----\r\n\r\n";
}
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.PersistKeyInCsp = false;
RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);
if (string.IsNullOrEmpty(charset))
{
charset = DEFAULT_CHARSET;
}
byte[] data = Encoding.GetEncoding(charset).GetBytes(content);
int maxBlockSize = rsa.KeySize / 8 - 11; //加密块最大长度限制
if (data.Length <= maxBlockSize)
{
byte[] cipherbytes = rsa.Encrypt(data, true);
return Convert.ToBase64String(cipherbytes);
}
MemoryStream plaiStream = new MemoryStream(data);
MemoryStream crypStream = new MemoryStream();
Byte[] buffer = new Byte[maxBlockSize];
int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
while (blockSize > 0)
{
Byte[] toEncrypt = new Byte[blockSize];
Array.Copy(buffer, 0, toEncrypt, 0, blockSize);
Byte[] cryptograph = rsa.Encrypt(toEncrypt, false);
crypStream.Write(cryptograph, 0, cryptograph.Length);
blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
}
return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None);
}
}