微信企業付款到銀行卡 .NET

企業付款到銀行卡 .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)

請求參數:


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. 請求參數
      這裏寫圖片描述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章