欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信企业付款到银行卡 .NET

程序员文章站 2024-03-02 23:00:10
...

企业付款到银行卡 .NET 版的 ,了解一下?

  1. 是不是按照微信的文档看不懂?
  2. 是不是按照微信文档走完流程后还是存在问题?
  3. 是不是网上找不到.NET 代码?
  4. 是不是 “解密真实姓名或银行卡号出错”?

(我打客服电话 95017 电话问的微信 企业付款到银行卡API 能用吧?微信不知道哪个二货客服跟我说不能用,然后第二天朋友打电话问客服,客服说能用!就问你屌不屌~~~)


服务器部署错误移驾

X509 certificate not loading private key file on server


描述

企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向银行卡付款,针对部分有开发能力的商户,提供通过API完成企业付款到银行卡的功能。


首先你的微信商户平台需要满足微信企业付款到银行卡的要求 也就是什么连续一个月要有收入什么之类的


请求

请求地址:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
双向证书:是

  1. 证书文档地址
  2. 证书下载地址:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>证书下载
  3. 商户证书安全:证书文件不能放在web服务器虚拟目录,应放在有访问权限控制的目录中,防止被他人下载。商户服务器要做好病毒和木马防护工作,不被非法侵入者窃取证书文件。
  4. 使用商户证书
    ◆ apiclient_cert.p12是商户证书文件,除PHP外的开发均使用此证书文件(.NET 使用这个证书)。
    ◆ 商户如果使用.NET环境开发,请确认Framework版本大于2.0,必须在操作系统上双击安装证书apiclient_cert.p12后才能被正常调用。
    商户证书调用或安装都需要使用到密码,该密码的值为微信商户号(mch_id)

请求参数:
微信企业付款到银行卡 .NET


MD5签名生成

(不说了,文档说的很清楚了)

  1. MD5签名生成算法

获取RSA加密公钥API

  1. 调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设存储为public.pem
  2. 确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥
  3. 用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式【.NET RSA 加密是没有这个填充模式的】
  4. 得到进行rsa加密并转base64之后的密文
  5. 将密文作为参数传给 银行卡号 和 真实姓名
  6. 接口默认输出PKCS#1格式的公钥,商户需根据自己开发的语言选择公钥格式 【.NET 使用 PKCS#8

RSA公钥格式PKCS#1,PKCS#8互转说明,是在Linux 系统上转的哦

  1. PKCS#1 转 PKCS#8:
    1. openssl rsa -RSAPublicKey_in -in -pubout
  2. PKCS#8 转 PKCS#1:
    1. openssl rsa -pubin -in -RSAPublicKey_out

  1. RSA加密公钥API文档地址
  2. RSA加密公钥API请求地址

    1. 请求证书:是 [ 证书同上 ]
    2. 请求参数
      微信企业付款到银行卡 .NET

3、RSA加密请求成功后返回【 pub_key 是 PKCS#1 格式公钥 】
微信企业付款到银行卡 .NET

微信默认返回 PKCS#1 格式的,.NET 需要 PKCS#8 格式的。

示例:PKCS#1 转 PKCS#8 ,linux 输入这段命令

openssl rsa -RSAPublicKey_in -in 获取到的公钥存储为xx.pem后的文件路径 -pubout

微信企业付款到银行卡 .NET
【 红框 = 获取到的公钥存储为xx.pem 文件 】
【 绿框 = 命令 】
【 黄框 = 转换成功的 PKCS#8 】
【 pem 文件内容 】
微信企业付款到银行卡 .NET


标准RSA 加密算法

对收款方银行卡号,收款方用户名进行加密
这一块的代码是整个企业付款到银行卡接口比较难的一点

微信文档内告诉我们:拿着获取到的公钥对收款方银行卡号,收款方用户名 进行标准RSA加密算法加密

这个时候你从网上找一段.NET RSA 加密算法……. 是不是发现怎么请求都不正确。反复确认了参数及公钥后实在找不到问题所在,
于是你打了这个电话 95017 没错,微信帮助中心………. 几小时后发现他们并不能解决你的问题………
根据本人真实故事编写

没错,我的问题就是【 解密真实姓名或银行卡号出错 】
微信企业付款到银行卡 .NET

为什么会报这个错误?
你的公钥是微信提供的,这点没错。
你的参数反复检查也没错。
你得RSA 加密当时我觉得也没错。
那么问题只有一个 Visual Studio 错了!没错!就是它的错,地表最强IDE 的错。

(开玩笑的。。。。)


其实错误的是 RSA 加密(我是从网上淘的加密方法)。


解决方法:
你去支付宝提供的接口处下载一个支付接口,然后从支付宝接口内找 RSA 加密。
有点可耻不过问题就解决了。支付宝接口地址


微信企业付款到银行卡,成功后会告诉你微信侧受理成功
微信企业付款到银行卡 .NET

代码


请求:企业付款到银行卡


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);
        }
    }