C#民生一碼付支付總結


  首先吐槽下,民生支付真心坑爹、坑爹、坑爹。如果有下輩子,肯定不會接民生支付。

  言歸正傳,首先先去官方demo里下載c#接口demo文檔。地址:https://wxpay.cmbc.com.cn/cmbcpaydoc/downIndex.jsp

  

  在程序文件夾下找到你需要的dll,dll分x64和x86,根據你項目系統版本選擇對應的dll。本人這里引用的是x86dll。

  1.把dll復制到項目中,文件屬性設置為始終復制。

  

  2.下面就開始寫一些支付代碼,主要從demo中提取。(注:民生demo里面方法雜合在一起,要把方法分開來),這里我就不貼demo代碼了,直接貼我整合過的代碼。

  

     [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int Initialize();

        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int Uninitialize();


        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int SignData_PKCS1(string pszAlgorithm,
                                                 byte[] pbySourceData,
                                                 int nSourceSize,
                                                 string pszPFXFilePath,
                                                 string pszPFXPassword,
                                                 string pszHashAlg,
                                                 ref IntPtr ppszBase64PKCS1Signature);

        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int VerifyDataSignature_PKCS1(string pszAlgorithm,
                                                            byte[] pbySourceData,
                                                            int nSourceSize,
                                                            string pszBase64CertContent,
                                                            string pszHashAlg,
                                                            string pszBase64PKCS1Signature);
        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int SetZvalueFlag(int IsWithZValue);


        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int EncryptDataToCMSEnvelope(string pszAlgorithm,
                                                           byte[] pbyPlainData,
                                                           int nPlainDataSize,
                                                           string pszBase64CertContent,
                                                           string pszSymEncAlg,
                                                           ref IntPtr ppszBase64CMSEnvelope);

        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern int DecryptDataFromCMSEnvelope(string pszAlgorithm,
                                                             string pszBase64CMSEnvelope,
                                                             string pszPFXFilePath,
                                                             string pszPFXPassword,
                                                             ref IntPtr ppbyPlainData,
                                                             ref int pnPlainDataSize);

        [DllImport("SADK.CMBC.x86.dll")]
        //[DllImport("SADK.CMBC.x64.dll")]
        public static extern void FreeMemory(IntPtr ptrBuf);

        /// <summary>
        /// 一碼付
        /// </summary>
        /// <param name="merchantSeq">訂單流水</param>
        /// <returns></returns>
        public string doYardPay(string merchantSeq)
        {
            //根據訂單號查詢訂單信息
            PayOrderDomain payOrderDomain = new PayOrderDomain();
            PAY_Order parOrder = new PAY_Order();
            List<PAY_Order> payOrderList = payOrderDomain.GetByOrderNoList(merchantSeq);
            if (payOrderList != null && payOrderList.Count > 0)
            {
                parOrder = payOrderList.First();
            }
            else
            {
                return "Order does not exist";
            }
decimal amount = decimal.Multiply((decimal)parOrder.Amount, (decimal)100);
            amount = 1;
            // 拼接請求參數
            string strContext = "";
       // 官方提供的支付地址
var payUrl = YardPadConfig.PayUrl; string plateFormId = YardPadConfig.PlateFormId; string merchantNum = YardPadConfig.MerchantNo; string signStr = "&amount=" + amount + "&merchantNum=" + merchantNum + "&merchantSeq=" + newOrderNo + "&platformId=" + plateFormId; // 獲取簽名 string sign = Sign(signStr); if (!String.IsNullOrEmpty(sign)) { // 生成二維碼地址 strContext = payUrl + signStr + "&sign=" + sign; } return strContext; } /// <summary> /// 交易查詢 /// </summary> /// <param name="merchantSeq">訂單號</param> /// <param name="sysId">系統id</param> /// <returns></returns> public void PayQuery(string merchantSeq, string systemCode) { PayOrderDomain payOrderDomain = new PayOrderDomain(); PAY_Order payOrder = new PAY_Order(); List<PAY_Order> payOrderLists = payOrderDomain.GetList(merchantSeq, systemCode); if (payOrderLists != null && payOrderLists.Count > 0) { payOrder = payOrderLists.First(); if (!"Paied".Equals(payOrder.Status)) { // 拼接請求參數 PayQueryModel p = new PayQueryModel(); p.merchantNo = YardPadConfig.MerchantNo; p.merchantSeq = payOrder.Order_No; p.platformId = YardPadConfig.PlateFormId; p.orgvoucherNo = ""; p.reserve = ""; p.tradeType = "1"; // 1 支付 2退款 string payJson = SerializeHelper.ToJson<PayQueryModel>(p); // 獲取簽名 string sign = Sign(payJson); if (!String.IsNullOrEmpty(sign)) { FPayQueryModel fp = new FPayQueryModel(); fp.sign = sign; fp.body = payJson; string fpayJson = SerializeHelper.ToJson<FPayQueryModel>(fp); // 信息加密 string encrypt = Encrypt(fpayJson); // 請求地址 string queryUrl = YardPadConfig.QueryUrl; // 請求的參數json BusinessContentModel business = new BusinessContentModel(); business.businessContext = encrypt; business.merchantNo = ""; business.merchantSeq = ""; business.reserve1 = ""; business.reserve2 = ""; business.reserve3 = ""; business.reserve4 = ""; business.reserve5 = ""; business.reserveJson = ""; business.securityType = ""; business.sessionId = ""; business.source = ""; business.transCode = ""; business.transDate = ""; business.transTime = ""; business.version = ""; string param = SerializeHelper.ToJson<BusinessContentModel>(business); // 調用api string result = PostMoths(queryUrl, param); // 信息解密 ResultModel resultModel = SerializeHelper.FromJson<ResultModel>(result); if ("S".Equals(resultModel.gateReturnType)) { string decrypt = Decrypt(resultModel.businessContext); RFPayQueryModel fpayquerymodel = SerializeHelper.FromJson<RFPayQueryModel>(decrypt); RPayQueryModel payquerymodel = SerializeHelper.FromJson<RPayQueryModel>(fpayquerymodel.body); string resultSign = CheckSign(fpayquerymodel.sign, SerializeHelper.ToJson<RPayQueryModel>(payquerymodel)); // 驗簽 if ("0".Equals(resultSign)) {//驗簽成功,更新訂單表狀態 List<PAY_Order> payOrderList = payOrderDomain.GetByOrderNoList(payquerymodel.merchantSeq); if (payOrderList != null && payOrderList.Count > 0) { payOrder = payOrderList.First(); payOrder.Status = "Paied"; payOrder.Pay_Time = DateTime.Now; payOrder.UpdateDate = DateTime.Now; payOrderDomain.Modify(payOrder.ID, payOrder); } } } } } } } /// <summary> /// 簽名 /// </summary> /// <param name="file"></param> /// <param name="signStr"></param> /// <returns></returns> public string Sign(string signStr) { int nResult = -1; // Declear Parameters //**************簽名和驗簽測試源數據******************************// string pszAlgorithm = "SM2"; // 測試商戶私鑰 //string pszPFXFilePath = HttpContext.Current.Server.MapPath("~/Templates/cust0001.sm2"); // 正式商戶私鑰 string pszPFXFilePath = HttpContext.Current.Server.MapPath("~/Templates/xjtlu.sm2"); string pszPFXPassword = YardPadConfig.MerchantPwd; string pszHashAlg = "SM3"; string strSourceData = signStr; byte[] pbySourcddeData = System.Text.Encoding.UTF8.GetBytes(strSourceData); //string strSourceData = "abcdefg"; int nSourceSize = pbySourcddeData.Length; byte[] pbySourceData = null; IntPtr pszBase64PKCS1Signature = IntPtr.Zero; string sign = ""; nResult = Initialize(); if (0 == nResult) { Console.WriteLine("Initialize Success! \n"); } else { Console.WriteLine("Initialize FILED! \n Error code : " + nResult); goto exit; } SetZvalueFlag(1); // 對源數據簽名,簽名請選擇簽名證書 char[] cc = strSourceData.ToCharArray(); pbySourceData = System.Text.Encoding.UTF8.GetBytes(cc); nResult = SignData_PKCS1(pszAlgorithm, pbySourceData, nSourceSize, pszPFXFilePath, pszPFXPassword, pszHashAlg, ref pszBase64PKCS1Signature); if (0 == nResult) { sign = Marshal.PtrToStringAnsi(pszBase64PKCS1Signature); Console.WriteLine(sign + "-Sign Success! \n"); } else { Console.WriteLine("Sign FILED! \n Error code : " + nResult); goto exit; } exit: //釋放由程序分配的內存,避免程序內存泄露 if (IntPtr.Zero != pszBase64PKCS1Signature) { FreeMemory(pszBase64PKCS1Signature); } // 當不再使用工具包時,調用Uninitialize函數反初始化工具包 nResult = Uninitialize(); if (0 == nResult) { Console.WriteLine("Uninitialize Success! \n"); } else { Console.WriteLine("Uninitialize FILED! \n Error code : " + nResult); } //Console.Read(); return sign; } /// <summary> /// 加密 /// </summary> /// <param name="json"></param> /// <returns></returns> public string Encrypt(string json) { int nResult = -1; //******************加密和解密測試源示例**********************// string pszEncryptAlgorithm = "SM2"; // 測試民生公鑰 //string file = HttpContext.Current.Server.MapPath("~/Templates/cmbcTest.cer"); // 正式民生公鑰 string file = HttpContext.Current.Server.MapPath("~/Templates/cmbc.cer"); //string pszBase64CertEncryptContent = ReadFile(file); // 取公鑰的值 去掉首尾的注釋 string pszBase64CertEncryptContent = "MIIClzCCAjugAwIBAgIFECYUJxAwDAYIKoEcz1UBg3UFADAlMQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQ0ZDQSBTTTIgT0NBMTAeFw0xNTAzMjYwNjEwMzFaFw0yMDAzMjYwNjEwMzFaMIGDMQswCQYDVQQGEwJDTjESMBAGA1UECgwJQ0ZDQSBPQ0ExMQ0wCwYDVQQLDARDTUJDMRkwFwYDVQQLDBBPcmdhbml6YXRpb25hbC0xMTYwNAYDVQQDDC0wMzA1QDcxMDAwMTg5ODhA5Lqk5piT6ZO26KGMUDJQ6LWE6YeR5omY566hQDEwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQ24zsOiNcNELoSdqCtX2Kn0ppIJUZ22WmKcU7Payx0M7tpXY2p6OZUaAzDkPr / Kc4pnTAnMNw4ySuFn5nuxHymo4H2MIHzMB8GA1UdIwQYMBaAFFyTWCBaJHNWEBtkUBDs6afKB0ERMAwGA1UdEwQFMAMBAQAwSAYDVR0gBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3VzL3VzLTE0Lmh0bTA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmNmY2EuY29tLmNuL1NNMi9jcmwxMTQwLmNybDALBgNVHQ8EBAMCA + gwHQYDVR0OBBYEFBA91H5B / osNLL3dY4BB13cjLl / 2MBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGCCqBHM9VAYN1BQADSAAwRQIgOIofwSmSbkSu5jJw17o + X7JKcH / NpX + PUvlss7le2XUCIQCGHTGqr76HdqCX0ukkt7ORmpmepcTpDG5ng9QW4DqtAw =="; pszBase64CertEncryptContent = pszBase64CertEncryptContent.Trim(); string pszSymEncAlg = "SM4"; // Declear Parameters string strSourceData = json; byte[] pbySourcddeData = System.Text.Encoding.UTF8.GetBytes(strSourceData); //string strSourceData = "abcdefg"; int nSourceSize = pbySourcddeData.Length; IntPtr pszBase64CMSEnvelope = IntPtr.Zero; string strBase64CMSEnvelope = ""; string cipher = ""; nResult = Initialize(); if (0 == nResult) { Console.WriteLine("Initialize Success! \n"); } else { Console.WriteLine("Initialize FILED! \n Error code : " + nResult); goto exit; } //********************加密數字信封*********************// char[] cc = strSourceData.ToCharArray(); pbySourcddeData = System.Text.Encoding.UTF8.GetBytes(cc); //int nSourceSize2 = pbySourcddeData.Length; nResult = EncryptDataToCMSEnvelope(pszEncryptAlgorithm, pbySourcddeData, nSourceSize, pszBase64CertEncryptContent, pszSymEncAlg, ref pszBase64CMSEnvelope); if (0 == nResult) { cipher = Marshal.PtrToStringAnsi(pszBase64CMSEnvelope); Console.WriteLine(cipher + " EncryptDataToCMSEnvelope Success! \n"); Console.WriteLine("EncryptDataToCMSEnvelope Success! \n"); } else { Console.WriteLine("EncryptDataToCMSEnvelope FILED! \n Error code : " + nResult); goto exit; } strBase64CMSEnvelope = Marshal.PtrToStringAnsi(pszBase64CMSEnvelope); FreeMemory(pszBase64CMSEnvelope); pszBase64CMSEnvelope = IntPtr.Zero; exit: //釋放由程序分配的內存,避免程序內存泄露 if (IntPtr.Zero != pszBase64CMSEnvelope) { FreeMemory(pszBase64CMSEnvelope); } // 當不再使用工具包時,調用Uninitialize函數反初始化工具包 nResult = Uninitialize(); if (0 == nResult) { Console.WriteLine("Uninitialize Success! \n"); } else { Console.WriteLine("Uninitialize FILED! \n Error code : " + nResult); } //Console.Read(); return strBase64CMSEnvelope; } /// <summary>/// 解密 /// </summary> /// <param name="strBase64CMSEnvelope">加密信息</param> /// <returns></returns> public string Decrypt(string strBase64CMSEnvelope) { int nResult = -1; string strSourceDatanew = ""; //******************加密和解密測試源示例**********************// string pszEncryptAlgorithm = "SM2"; // 測試商戶私鑰 //string pszEncryptPFXFilePath = HttpContext.Current.Server.MapPath("~/Templates/cust0001.sm2"); // 正式商戶私鑰 string pszEncryptPFXFilePath = HttpContext.Current.Server.MapPath("~/Templates/xjtlu.sm2"); string pszEncryptPFXPassword = YardPadConfig.MerchantPwd; // Declear Parameters IntPtr pbyDecryptPlainData = IntPtr.Zero; int nDecryptPlainDataSize = 0; nResult = Initialize(); if (0 == nResult) { Console.WriteLine("Initialize Success! \n"); } else { Console.WriteLine("Initialize FILED! \n Error code : " + nResult); goto exit; } //***********************解密數字信封*************************// nResult = DecryptDataFromCMSEnvelope(pszEncryptAlgorithm, strBase64CMSEnvelope, pszEncryptPFXFilePath, pszEncryptPFXPassword, ref pbyDecryptPlainData, ref nDecryptPlainDataSize); byte[] pbyDecryptSourceData = new byte[nDecryptPlainDataSize]; Marshal.Copy(pbyDecryptPlainData, pbyDecryptSourceData, 0, nDecryptPlainDataSize); strSourceDatanew = System.Text.Encoding.UTF8.GetString(pbyDecryptSourceData); //strSourceData = Marshal.PtrToStringAnsi(pbyDecryptPlainData); FreeMemory(pbyDecryptPlainData); pbyDecryptPlainData = IntPtr.Zero; if (0 == nResult) { Console.WriteLine(strSourceDatanew + "-DecryptDataFromCMSEnvelope Success! \n"); } else { Console.WriteLine("DecryptDataFromCMSEnvelope FILED! \n Error code : " + nResult); goto exit; } exit: //釋放由程序分配的內存,避免程序內存泄露 if (IntPtr.Zero != pbyDecryptPlainData) { FreeMemory(pbyDecryptPlainData); } // 當不再使用工具包時,調用Uninitialize函數反初始化工具包 nResult = Uninitialize(); if (0 == nResult) { Console.WriteLine("Uninitialize Success! \n"); } else { Console.WriteLine("Uninitialize FILED! \n Error code : " + nResult); } //Console.Read(); return strSourceDatanew; } /// <summary> /// 驗簽 /// </summary> /// <param name="strBase64PKCS1Signature">簽名</param> /// <param name="json">簽名以外的參數</param> /// <returns></returns> public string CheckSign(string strBase64PKCS1Signature, string json) { int nResult = -1; // Declear Parameters //**************簽名和驗簽測試源數據******************************// string pszAlgorithm = "SM2"; string pszHashAlg = "SM3"; // 測試商戶公鑰 //string file = HttpContext.Current.Server.MapPath("~/Templates/cust0001.cer"); // 正式民生公鑰 string file = HttpContext.Current.Server.MapPath("~/Templates/cmbc.cer"); string pszBase64CertContent = ReadFile(file); string strSourceData = json; byte[] pbySourcddeData = System.Text.Encoding.UTF8.GetBytes(strSourceData); //string strSourceData = "abcdefg"; int nSourceSize = pbySourcddeData.Length; byte[] pbySourceData = null; nResult = Initialize(); if (0 == nResult) { Console.WriteLine("Initialize Success! \n"); } else { Console.WriteLine("Initialize FILED! \n Error code : " + nResult); goto exit; } // 對源數據簽名,簽名請選擇簽名證書 char[] cc = strSourceData.ToCharArray(); pbySourceData = System.Text.Encoding.UTF8.GetBytes(cc); // 驗簽 nResult = VerifyDataSignature_PKCS1(pszAlgorithm, pbySourceData, nSourceSize, pszBase64CertContent, pszHashAlg, strBase64PKCS1Signature); if (0 == nResult) { Console.WriteLine("Verify Success! \n"); } else { Console.WriteLine("Verify FILED! \n Error code : " + nResult); goto exit; } exit: // 當不再使用工具包時,調用Uninitialize函數反初始化工具包 nResult = Uninitialize(); if (0 == nResult) { Console.WriteLine("Uninitialize Success! \n"); } else { Console.WriteLine("Uninitialize FILED! \n Error code : " + nResult); } //Console.Read(); return "" + nResult; } /// <summary> /// post請求 /// </summary> /// <param name="url"></param> /// <param name="param"></param> /// <returns></returns> public string PostMoths(string url, string param) { string strURL = url; System.Net.HttpWebRequest request; request = (System.Net.HttpWebRequest)WebRequest.Create(strURL); request.Method = "POST"; request.ContentType = "application/json;charset=UTF-8"; string paraUrlCoded = param; byte[] payload; payload = System.Text.Encoding.UTF8.GetBytes(paraUrlCoded); request.ContentLength = payload.Length; Stream writer = request.GetRequestStream(); writer.Write(payload, 0, payload.Length); writer.Close(); System.Net.HttpWebResponse response; response = (System.Net.HttpWebResponse)request.GetResponse(); System.IO.Stream s; s = response.GetResponseStream(); string StrDate = ""; string strValue = ""; StreamReader Reader = new StreamReader(s, Encoding.UTF8); while ((StrDate = Reader.ReadLine()) != null) { strValue += StrDate + "\r\n"; } return strValue; }

   /// <summary> /// 讀文件 /// </summary> /// <param name="path">文件路徑</param> /// <returns></returns> public static string ReadFile(string Path) { try { FileStream fs = new FileStream(Path, FileMode.Open); StreamReader sr = new StreamReader(fs, Encoding.UTF8); string nextLine; string content = ""; while ((nextLine = sr.ReadLine()) != null) { if (nextLine.Contains("-----BEGIN CERTIFICATE-----") || nextLine.Contains("-----END CERTIFICATE-----")) { continue; } else content = content + nextLine; } sr.Close(); return content; } catch { return "<span style='color:red; font-size:x-large;'>Sorry,The Ariticle wasn't found!! It may have been deleted accidentally from Server.</span>"; } }

 

   cmbcTest.cer 為民生銀行公鑰證書

      cust0001.sm2 為測試商戶私鑰證書

      cust0001.cer 為測試商戶公鑰證書

       測試環境: 使用商戶私鑰簽名,商戶公鑰加密;使用商戶私鑰解密,商戶公鑰驗簽。
    正式環境: 簽名解密用商戶私鑰,加密驗簽用民生公鑰

     支付回調

    

/// <summary>
        /// 一碼付回調
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string ENotify()
        {
            string isOk = "FAILED";
            byte[] byts = new byte[Request.InputStream.Length];
            Request.InputStream.Read(byts, 0, byts.Length);
            // 獲取json數據
            string req = System.Text.Encoding.Default.GetString(byts);if (String.IsNullOrEmpty(req))
            {
                return isOk;
            }
            NotifyModel notify = new NotifyModel();
            notify = SerializeHelper.FromJson<NotifyModel>(req);
            // 解密json數據
            string decStr = yardPayService.Decrypt(notify.context);

            RFPayQueryModel rfPayQueryModel = new RFPayQueryModel();
            rfPayQueryModel = SerializeHelper.FromJson<RFPayQueryModel>(decStr);
            // 驗證簽名是否正確
            string sign = yardPayService.CheckSign(rfPayQueryModel.sign, decStr);
            if ("0".Equals(sign))
            {// 獲取訂單詳細信息
                PayNotifyModel payNotifyModel = new PayNotifyModel();
                payNotifyModel = SerializeHelper.FromJson<PayNotifyModel>(rfPayQueryModel.body);//驗簽成功,更新訂單表狀態
                PayOrderRelationDomain payOrderRelationDomain = new PayOrderRelationDomain();
                List<PAY_Order_Relation> payOrderRelationList = payOrderRelationDomain.GetByOrderNoList(payNotifyModel.orderNo);
                if (payOrderRelationList != null && payOrderRelationList.Count > 0)
                {
                    PAY_Order_Relation payOrderRelation = payOrderRelationList.First();
                    PayOrderDomain payOrderDomain = new PayOrderDomain();
                    PAY_Order payOrder = new PAY_Order();
                    List<PAY_Order> payOrderList = payOrderDomain.GetByOrderNoList(payOrderRelation.Original_Order_No);
                    if (payOrderList != null && payOrderList.Count > 0)
                    {
                        payOrder = payOrderList.First();
                        payOrder.Status = "Paied";
                        payOrder.UpdateDate = DateTime.Now;
                        payOrder.NotifyNum = 1;
                        payOrder.NotifyTime = DateTime.Now.AddMinutes(5);
                        payOrderDomain.Modify(payOrder.ID, payOrder);

                       

                        isOk = "SUCCESS";
                    }
                }
            }

            return isOk;
        }

 

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM