最近做工行的網上支付接口,其中也遇到了不少問題,現在整理一下發布出來希望能對需要的人有所幫助。
參考了下面博客:http://www.cnblogs.com/gonganruyi/archive/2011/07/01/2095463.html
1、首先需要注冊工行提供的ICBCEBankUtil.dll,將ICBCEBankUtil.dll和infosecapi.dll復制到system32文件夾下CMD輸入regsvr32 ICBCEBankUtil.dll注冊控件。WINDOWS SERVER2008/2012等系統需要運行管理員命令提示符。
2、拆分銀行提供的.pfx證書文件,生成.key 和.crt兩個文件,記住拆分時設置的私鑰密碼。將ebb2cpublic.crt(公鑰文件)、Name.key、Name.crt三個文件復制到指定目錄。
3、下面是代碼

<form method="post" action="<%= icmcModel.OrderPostUrl %>" id="order"> <div style="width: 500px; margin: auto auto; padding: 10px; line-height: 30px;"> 正在跳轉至工商銀行支付地址..... </div> <input type="hidden" name="interfaceName" value="<%= icmcModel.InterfaceName %>" /> <input type="hidden" name="interfaceVersion" value="<%= icmcModel.InterfaceVersion %>" /> <input type="hidden" name="tranData" value="<%= icmcModel.TranData %>" /> <input type="hidden" name="merSignMsg" value="<%= icmcModel.MerSignMsg %>" /> <input type="hidden" name="merCert" value="<%= icmcModel.MerCert %>" /> <script type="text/javascript"> document.getElementById("order").submit();</script> </form>

//用戶賬號(身份證) this.userIdCardNumber = Request.QueryString["userIdCardNumber"]; //充值金額,(工商銀行按分進行計算) // this.money = (Convert.ToInt32(Request.QueryString["payMnoney"]) * 100).ToString(); this.money = "1"; //生成訂單號 string orderId = DateTime.Now.ToString("yyyyMMddHHmmss") + userIdCardNumber.Substring(userIdCardNumber.Length - 5, 5) + Inhua.Common.Rand.Number(5); StringBuilder strXml = new StringBuilder(); strXml.Append("<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\"?>"); strXml.Append("<B2CReq>"); //接口名稱 strXml.Append("<interfaceName>" + icmcModel.InterfaceName + "</interfaceName>"); //接口版本號 strXml.Append("<interfaceVersion>" + icmcModel.InterfaceVersion + "</interfaceVersion>"); //訂單信息 strXml.Append("<orderInfo>"); //交易日期時間 strXml.Append("<orderDate>" + icmcModel.OrderDate + "</orderDate>"); //支付幣種 strXml.Append("<curType>" + icmcModel.CurType + "</curType>"); //商戶代碼 strXml.Append("<merID>" + icmcModel.MerID + "</merID>"); //訂單信息列表 strXml.Append("<subOrderInfoList>"); //訂單信息 strXml.Append("<subOrderInfo>"); //訂單編號 strXml.Append("<orderid>" + orderId + "</orderid>"); //訂單金額 //strXml.Append("<amount>" + user.ExaminationModel.Examination_fees.ToString("0.00") + "</amount> "); strXml.Append("<amount>" + money + "</amount> "); //分期付款期數 1代表全額付款 strXml.Append("<installmentTimes>1</installmentTimes>"); //商戶賬號 strXml.Append("<merAcct>" + icmcModel.MerAcct + "</merAcct>"); //商品編號 strXml.Append("<goodsID>" + icmcModel.Orderid + "</goodsID>"); //商品名稱 strXml.Append("<goodsName>商品名稱</goodsName>"); //商品數量 strXml.Append("<goodsNum>1</goodsNum>"); //已含運費金額 strXml.Append("<carriageAmt></carriageAmt>"); strXml.Append("</subOrderInfo>"); strXml.Append("</subOrderInfoList>"); strXml.Append("</orderInfo>"); strXml.Append("<custom>"); //檢驗聯名標志 取值“1”:客戶支付時,網銀判斷該客戶是否與商戶聯名 strXml.Append("<verifyJoinFlag>" + icmcModel.VerifyJoinFlag + "</verifyJoinFlag>"); //語言版本 取值:“EN_US”為英文版;取值:“ZH_CN”或其他為中文版 strXml.Append("<Language>ZH_CN</Language>"); strXml.Append("</custom>"); strXml.Append("<message>"); //支持訂單支付的銀行卡種類 strXml.Append("<creditType>2</creditType>"); //通知類型 strXml.Append("<notifyType>" + icmcModel.NotifyType + "</notifyType>"); //結果發送類型 strXml.Append("<resultType>" + icmcModel.ResultType + "</resultType>"); //商戶reference strXml.Append("<merReference>" + icmcModel.MerReference + "</merReference>"); //客戶端IP 當商戶reference項送空時,該項必輸 strXml.Append("<merCustomIp>" + icmcModel.MerIP + "</merCustomIp>"); //虛擬商品/實物商品標志位 取值“0”:虛擬商品 取值“1”,實物商品 strXml.Append("<goodsType>0</goodsType>"); //買家用戶號 strXml.Append("<merCustomID></merCustomID>"); //買家聯系電話 strXml.Append("<merCustomPhone></merCustomPhone>"); //收貨地址 strXml.Append("<goodsAddress></goodsAddress>"); //訂單備注 strXml.Append("<merOrderRemark></merOrderRemark>"); //商城提示 strXml.Append("<merHint></merHint>"); //備注字段1 strXml.Append("<remark1></remark1>"); //備注字段2 strXml.Append("<remark2></remark2>"); //返回商戶URL //strXml.Append("<merURL>http://localhost/</merURL>"); //string url = tools.GetRootVirtualPath();System.Configuration.ConfigurationManager.AppiiciSettings["aa"] string merURL = "http://" + icmcModel.MerIP + "/PayOnline/ReturnPayment.aspx"; strXml.Append("<merURL>" + merURL + "</merURL>"); //返回商戶變量 strXml.Append("<merVAR>" + Inhua.Common.Encryption.Encrypt(userIdCardNumber) + "</merVAR>"); strXml.Append("</message>"); strXml.Append("</B2CReq>"); //獲取工商銀行驗證 icmcModel.TranData = strXml.ToString(); CBCOnlinePayment.CBCPayOnline.GetCheckInfo(icmcModel);

public class ICBC { private string _orderPostUrl = "https://B2C.icbc.com.cn/servlet/ICBCINBSEBusinessServlet"; private string _interfaceName = "ICBC_PERBANK_B2C"; private string _interfaceVersion = "1.0.0.11"; private string _orderid; /// <summary> /// 訂單金額 /// </summary> private string _amount; /// <summary> /// 支付幣種 /// </summary> private string _curType = "001"; /// <summary> /// 商戶代碼 /// </summary> private string _merID = "向銀行申請"; /// <summary> /// 商戶賬號 /// </summary> private string _merAcct = "交易賬號"; /// <summary> /// 檢驗聯名標志 /// 取值“1”:客戶支付時,網銀判斷該客戶是否與商戶聯名,是則按上送金額扣帳,否則展現未聯名錯誤;取值“0”:不檢驗客戶是否與商戶聯名,按上送金額扣帳。 /// </summary> private string _verifyJoinFlag = "0"; /// <summary> /// 通知類型 /// 在交易轉賬處理完成后把交易結果通知商戶的處理模式。 /// 取值“HS”:在交易完成后實時將通知信息以HTTP協議POST方式,主動發送給商戶,發送地址為商戶端隨訂單數據提交的接收工行支付結果的URL即表單中的merURL字段; /// 取值“AG”:在交易完成后不通知商戶。商戶需使用瀏覽器登錄工行的B2C商戶服務網站,或者使用工行提供的客戶端程序API主動獲取通知信息。 /// </summary> private string _notifyType = "HS"; /// <summary> /// 返回商戶URL /// 必須合法的URL,交易結束,將客戶引導到商戶的此url,即通過客戶瀏覽器post交易結果信息到商戶的此URL /// 注意:該URL應使用http協議(不能使用https協議),端口號應為80或不指定。 /// </summary> private string _merURL; /// <summary> /// 結果發送類型 /// 選輸 /// 取值“0”:無論支付成功或者失敗,銀行都向商戶發送交易通知信息; /// 取值“1”,銀行只向商戶發送交易成功的通知信息。 /// 只有通知方式為HS時此值有效,如果使用AG方式,可不上送此項,但簽名數據中必須包含此項,取值可為空。 /// </summary> private string _resultType = "1"; /// <summary> /// 支付日期 /// </summary> private string _orderDate = System.DateTime.Now.ToString("yyyyMMddHHmmss"); /// <summary> /// 訂單簽名數據 /// 必輸, ///商戶使用工行提供的簽名API和商戶證書將tranData的xml明文串進行簽名,得到二進制簽名數據,然后進行BASE64編碼后得到可視的merSignMsg; ///注意:簽名時是針對tranData的xml明文,不是將tranData進行BASE64編碼后的串; /// </summary> private string _merSignMsg; /// <summary> /// 商城證書公鑰 /// 商戶用二進制方式讀取證書公鑰文件后,進行BASE64編碼后產生的字符串; /// </summary> private string _merCert; /// <summary> /// 商品編號 /// </summary> private string _goodsID = "001"; /// <summary> /// 商品名稱 /// </summary> private string _goodsName = ""; /// <summary> /// 商品數量 /// </summary> private string _goodsNum = "1"; /// <summary> /// 已含運費金額 /// </summary> private string _carriageAmt; /// <summary> /// 備注字段1 /// </summary> private string _remark1; /// <summary> /// 備注字段2 /// </summary> private string _remark2; /// <summary> /// 商城提示 /// </summary> private string _merHint; /// <summary> /// 整合所有交易數據形成的xml明文串,並做BASE64編碼; /// 具體格式定義見下文; /// 注意: /// 需有xml頭屬性;整個字段使用BASE64編碼; /// xml明文中沒有回車換行和多余空格; /// </summary> private string _tranData; /// <summary> /// 上送商戶網站域名(支持通配符,例如“*.某B2C商城.com”),如果上送,工行會在客戶支付訂單時,校驗商戶上送域名與客戶跳轉工行支付頁面之前網站域名的一致性。 /// </summary> private string _merReference = System.Configuration.ConfigurationManager.AppSettings["WebUrl"]; private string _merIP = System.Configuration.ConfigurationManager.AppSettings["WebIP"]; private bool _isCheck = false; /// <summary> /// 是否檢測成功 /// </summary> public bool IsCheck { get { return _isCheck; } set { _isCheck = value; } } /// <summary> /// 服務域名 /// </summary> public string MerReference { get { return _merReference; } set { _merReference = value; } } /// <summary> /// 服務IP /// </summary> public string MerIP { get { return _merIP; } set { _merIP = value; } } /// <summary> /// 報文數據 /// </summary> public string TranData { get { return _tranData; } set { _tranData = value; } } /// <summary> /// 工商支付接口路徑 /// </summary> public string OrderPostUrl { get { return _orderPostUrl; } set { _orderPostUrl = value; } } /// <summary> /// 接口名稱 /// </summary> public string InterfaceName { get { return _interfaceName; } set { _interfaceName = value; } } /// <summary> /// 接口版本號 /// </summary> public string InterfaceVersion { get { return _interfaceVersion; } set { _interfaceVersion = value; } } /// <summary> /// 訂單號 /// </summary> public string Orderid { get { return _orderid; } set { _orderid = value; } } /// <summary> /// 訂單金額 /// </summary> public string Amount { get { return _amount; } set { _amount = value; } } /// <summary> /// 支付幣種 RMB:001 /// </summary> public string CurType { get { return _curType; } set { _curType = value; } } /// <summary> /// 商戶代碼 /// </summary> public string MerID { get { return _merID; } set { _merID = value; } } /// <summary> /// 商戶賬號 /// </summary> public string MerAcct { get { return _merAcct; } set { _merAcct = value; } } /// <summary> /// 檢驗聯名標志 /// 取值“1”:客戶支付時,網銀判斷該客戶是否與商戶聯名,是則按上送金額扣帳,否則展現未聯名錯誤; /// 取值“0”:不檢驗客戶是否與商戶聯名,按上送金額扣帳。 /// </summary> public string VerifyJoinFlag { get { return _verifyJoinFlag; } set { _verifyJoinFlag = value; } } /// <summary> /// 通知類型 /// 取值“HS”:在交易完成后實時將通知信息以HTTP協議POST方式,主動發送給商戶,發送地址為商戶端隨訂單數據提交的接收工行支付結果的URL即表單中的merURL字段; /// 取值“AG”:在交易完成后不通知商戶。商戶需使用瀏覽器登錄工行的B2C商戶服務網站,或者使用工行提供的客戶端程序API主動獲取通知信息。 /// </summary> public string NotifyType { get { return _notifyType; } set { _notifyType = value; } } /// <summary> /// 返回商戶URL /// </summary> public string MerURL { get { return _merURL; } set { _merURL = value; } } /// <summary> /// 結果發送類型 /// </summary> public string ResultType { get { return _resultType; } set { _resultType = value; } } /// <summary> /// 交易日期時間 /// </summary> public string OrderDate { get { return _orderDate; } set { _orderDate = value; } } /// <summary> /// 訂單簽名數據 /// </summary> public string MerSignMsg { get { return _merSignMsg; } set { _merSignMsg = value; } } /// <summary> /// 商城證書公鑰 /// </summary> public string MerCert { get { return _merCert; } set { _merCert = value; } } /// <summary> /// 商品編號 /// </summary> public string GoodsID { get { return _goodsID; } set { _goodsID = value; } } /// <summary> /// 商品名稱 /// </summary> public string GoodsName { get { return _goodsName; } set { _goodsName = value; } } /// <summary> /// 商品數量 /// </summary> public string GoodsNum { get { return _goodsNum; } set { _goodsNum = value; } } /// <summary> /// 已含運費金額 /// </summary> public string CarriageAmt { get { return _carriageAmt; } set { _carriageAmt = value; } } /// <summary> /// 備注字段1 /// </summary> public string Remark1 { get { return _remark1; } set { _remark1 = value; } } /// <summary> /// 備注字段2 /// </summary> public string Remark2 { get { return _remark2; } set { _remark2 = value; } } /// <summary> /// 商城提示 /// </summary> public string MerHint { get { return _merHint; } set { _merHint = value; } } }

if (Request.Form["notifyData"] != null) { try { ICBC icbcInfo = new ICBC(); icbcInfo.TranData = Request.Form["notifyData"]; icbcInfo.MerSignMsg = Request.Form["signMsg"].ToString(); icbcInfo = CBCOnlinePayment.CBCPayOnline.GetCheckReturnInfo(icbcInfo); //自定義返回的變量 this.userIdCardNumber = Inhua.Common.Encryption.Decrypt(Request.Form["merVAR"].ToString()); var query = SpringFactory.BusinessFactory.GetStudent(userIdCardNumber); if (icbcInfo.IsCheck) { DataSet myds = new DataSet(); StringReader strReader = new StringReader(icbcInfo.TranData); myds.ReadXml(strReader); DataTable mytable = new DataTable(); mytable = myds.Tables["bank"]; string payDate = myds.Tables["orderInfo"].Rows[0]["orderDate"].ToString().Trim(); string amount = myds.Tables["subOrderInfo"].Rows[0]["amount"].ToString().Trim(); string orderid = myds.Tables["subOrderInfo"].Rows[0]["orderid"].ToString().Trim(); if (null != mytable && mytable.Rows.Count > 0) { if (mytable.Rows[0]["tranStat"].ToString().Trim() == "1") { //這里做成功操作 string s2 = payDate.Substring(0, 4) + "-" + payDate.Substring(4, 2) + "-" + payDate.Substring(6, 2) + " " + payDate.Substring(8, 2) + ":" + payDate.Substring(10, 2); DateTime time1 = DateTime.Parse(s2); query.PaymentSucceed(amount, orderid);//支付成功,修改余額 } else { SpringFactory.BusinessFactory.GetStudent(this.userIdCardNumber).AddOrderLogs("0", false, "", "未知錯誤"); } } } } catch (Exception ex) { SpringFactory.BusinessFactory.GetStudent(this.userIdCardNumber).AddOrderLogs("0", false, "", ex.Message); } } else { var result = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); result.AddLogs("銀行數據返回失敗,請通知管理員!"); } }

public static class CBCPayOnline { private static string amount; /// <summary> /// 銀行證書文件地址 /// </summary> static string strCertFN = HttpContext.Current.Server.MapPath("~/ICBCcert/ebb2cpublic.crt"); /// <summary> /// 商戶證書文件地址 /// </summary> static string strCertFNM = HttpContext.Current.Server.MapPath("~/ICBCcert/zzjy001.crt"); /// <summary> /// 私鑰文件名 /// </summary> static string strKeyFN = HttpContext.Current.Server.MapPath("~/ICBCcert/zzjy001.key"); /// <summary> /// 私鑰口令 /// </summary> static string strKey = "12345678"; static string api_url = "https://corporbank.icbc.com.cn/servlet/ICBCINBSEBusinessServlet"; static string post_params = "APIName=EAPI&APIVersion=001.001.002.001&MerReqData="; static string cert_path = HttpContext.Current.Server.MapPath("~/ICBCcert/zzjy001.pfx"); //商戶證書 HttpContext.Current.Server.MapPath("~/ICBCcert/rcsc1.crt"); public static void Load() { System.Threading.Thread t = new System.Threading.Thread(CheckOrder); t.Start(); } static CBCPayOnline() { } /// <summary> /// 檢查未提交訂單 /// </summary> public static void CheckOrder() { var query = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); while (true) { var list = query.GetOrderPayList(); ICBC icbcInfo = new ICBC(); string outMess = ""; foreach (var l1 in list) { try { var user = SpringFactory.BusinessFactory.GetStudent(l1.userName); string mess = CheckOrder(l1.OrderID, l1.PayDate.ToString("yyyyMMdd"), icbcInfo.MerID, icbcInfo.MerAcct, out outMess); if (mess.Length > 5)//未返回錯誤編碼,返回xml數據 { DataSet myds = new DataSet(); StringReader strReader = new StringReader(mess); myds.ReadXml(strReader); string stat = myds.Tables["out"].Rows[0]["tranStat"].ToString(); if (stat == "1" || stat == "0") { amount = myds.Tables["out"].Rows[0]["amount"].ToString(); user.PaymentSucceed(amount, l1.OrderID); } } else { string pays = ""; switch (mess) { case "40972": pays = "API查詢的訂單不存在"; break; case "40973": pays = "API查詢過程中系統異常"; break; case "40976": pays = "API查詢系統異常"; break; case "40977": pays = "商戶證書信息錯"; break; case "40978": pays = "解包商戶請求數據報錯"; break; case "40979": pays = "查詢的訂單不存在"; break; case "40980": pays = "API查詢過程中系統異常"; break; case "40981": pays = "給商戶打包返回數據錯"; break; case "40982": pays = "系統錯誤"; break; case "40983": pays = "查詢的訂單不唯一"; break; case "40987": pays = "商戶代碼或者商城賬號有誤"; break; case "40947": pays = "給商戶打包返回數據錯"; break; case "40948": pays = "商城狀態非法"; break; case "40949": pays = "商城類別非法"; break; case "40950": pays = "商城應用類別非法"; break; case "40951": pays = "商戶證書id狀態非法"; break; case "40952": pays = "商戶證書id未綁定"; break; case "40953": pays = "商戶id權限非法"; break; case "40954": pays = "檢查商戶狀態時數據庫異常"; break; } //清除不存在的訂單 if (mess == "40972") { if (DateTime.Now.AddMonths(-6) > l1.PayDate) { var result = SpringFactory.BusinessFactory.GetStudent(l1.userName); result.OrderFaild(l1.OrderID); } } else//添加錯誤日志 { SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs("錯誤編碼:" + mess + "," + pays, l1.OrderID); } } } catch (Exception e) { SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs(e.Message, l1.OrderID); throw e; } } System.Threading.Thread.Sleep(1000 * 60 * 30); } } /// <summary> /// 根據訂單號查詢訂單 /// </summary> /// <param name="orderID"></param> /// <returns></returns> public static string ChenkOrder(string orderID, DateTime? payDate, string userIdCardNumber) { if (orderID.Trim().Length != 24) { return "訂單號不正確,請輸入24位訂單號"; } ICBC icbcInfo = new ICBC(); //查詢充值日志 var logModel = SpringFactory.BusinessFactory.GetBusinessAnonymousUser().GetPayLogsByOrderId(orderID, userIdCardNumber); if (logModel != null) { return "已經繳費成功。"; } string outMess = ""; string zfrq = orderID.Substring(0, 8);//支付日期 if (payDate != null && payDate != DateTime.MinValue) { zfrq = payDate.Value.ToString("yyyyMMdd"); } var payModel = SpringFactory.BusinessFactory.GetBusinessAnonymousUser().GetOrderModel(orderID, userIdCardNumber); string mess = CheckOrder(orderID, zfrq, icbcInfo.MerID, icbcInfo.MerAcct, out outMess); if (mess.Length > 5)//未返回錯誤編碼,返回xml數據 { DataSet myds = new DataSet(); StringReader strReader = new StringReader(mess); try { myds.ReadXml(strReader); } catch { throw new Exception("錯誤數據:" + mess); } //查詢訂單列表 var user = SpringFactory.BusinessFactory.GetStudent(userIdCardNumber); string stat = myds.Tables["out"].Rows[0]["tranStat"].ToString(); amount = myds.Tables["out"].Rows[0]["amount"].ToString(); if (stat == "1" || stat == "0") { if (payModel != null) { user.PaymentSucceed(amount, orderID); return "已經支付成功!\r\n訂單號" + orderID + "\r\n支付金額:" + amount; } else { string payTimes = myds.Tables["in"].Rows[0]["tranDate"].ToString(); user.UpdatePaymentInformation(amount, orderID, userIdCardNumber); return "已經支付成功!"; } } else { string pays = ""; if (stat == "2") pays = "支付失敗"; else pays = "可疑交易"; //添加錯誤日志 SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs("支付失敗或可疑交易," + stat, orderID); return pays; } } else { string pays = ""; switch (mess) { case "40972": pays = "API查詢的訂單不存在"; break; case "40973": pays = "API查詢過程中系統異常"; break; case "40976": pays = "API查詢系統異常"; break; case "40977": pays = "商戶證書信息錯"; break; case "40978": pays = "解包商戶請求數據報錯"; break; case "40979": pays = "查詢的訂單不存在"; break; case "40980": pays = "API查詢過程中系統異常"; break; case "40981": pays = "給商戶打包返回數據錯"; break; case "40982": pays = "系統錯誤"; break; case "40983": pays = "查詢的訂單不唯一"; break; case "40987": pays = "商戶代碼或者商城賬號有誤"; break; case "40947": pays = "給商戶打包返回數據錯"; break; case "40948": pays = "商城狀態非法"; break; case "40949": pays = "商城類別非法"; break; case "40950": pays = "商城應用類別非法"; break; case "40951": pays = "商戶證書id狀態非法"; break; case "40952": pays = "商戶證書id未綁定"; break; case "40953": pays = "商戶id權限非法"; break; case "40954": pays = "檢查商戶狀態時數據庫異常"; break; } //清除不存在的訂單 if (mess == "40972") { if (payModel != null) { var result = SpringFactory.BusinessFactory.GetStudent(payModel.userName); result.OrderFaild(orderID); } } else//添加失敗失敗日志 { if (payModel != null) { SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs("錯誤編碼:" + mess + pays, orderID); } } return pays; } } /// <summary> /// 獲取工商銀行驗證信息 /// </summary> /// <param name="argIcbc"></param> /// <returns></returns> public static DataTransfer.ICBC GetCheckInfo(DataTransfer.ICBC argIcbc) { string strMerSignMsg = string.Empty; B2CUtil icbcObj = new B2CUtil(); int jg = icbcObj.init(strCertFN, strCertFNM, strKeyFN, strKey); if (jg == 0) { argIcbc.MerSignMsg = icbcObj.signC(argIcbc.TranData, argIcbc.TranData.Length); if (argIcbc.MerSignMsg == "") { int returnCode = icbcObj.getRC(); SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs("錯誤編碼:" + returnCode + ",簽名錯誤", ""); } argIcbc.MerCert = icbcObj.getCert(1); byte[] bytes = Encoding.Default.GetBytes(argIcbc.TranData); argIcbc.TranData = Convert.ToBase64String(bytes); } else { SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs(jg.ToString() + ",證書錯誤或私鑰錯誤編碼", ""); } return argIcbc; } /// <summary> /// 獲取工商銀行驗證信息 /// </summary> /// <param name="argIcbc"></param> /// <returns></returns> public static DataTransfer.ICBC GetCheckReturnInfo(DataTransfer.ICBC argIcbc) { string strMerSignMsg = string.Empty; B2CUtil icbcObj = new B2CUtil(); if (icbcObj.init(strCertFN, strCertFNM, strKeyFN, strKey) == 0) { argIcbc.TranData = Decode(argIcbc.TranData); //判斷驗證銀行簽名是否成功 if (icbcObj.verifySignC(argIcbc.TranData, argIcbc.TranData.Length, argIcbc.MerSignMsg, argIcbc.MerSignMsg.Length) == 0) { argIcbc.IsCheck = true; } else argIcbc.IsCheck = false;//todo:簽名失敗 } else { argIcbc.IsCheck = false; } return argIcbc; } /// <summary> /// 加密信息 /// </summary> /// <param name="data"></param> /// <returns></returns> public static string Encode(string data) { try { return Inhua.Common.Encryption.Encrypt(data); } catch (Exception e) { throw new Exception(e.Message); } } /// <summary> /// 解密信息 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string Decode(string str) { byte[] outputb = Convert.FromBase64String(str); string orgStr = Encoding.Default.GetString(outputb); return orgStr; } /// <summary> /// 查詢訂單 /// </summary> /// <param name="strOrderNum">訂單號</param> /// <param name="strTranDate">交易日期</param> /// <param name="strShopCode">商家代碼</param> /// <param name="strShopAccount">商城賬號</param> /// <param name="errInfo"></param> /// <returns></returns> public static string CheckOrder(string strOrderNum, string strTranDate, string strShopCode, string strShopAccount, out string errInfo) { try { errInfo = string.Empty; StringBuilder sb = new StringBuilder(); sb.Append("<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?><ICBCAPI><in><orderNum>"); sb.Append(strOrderNum); sb.Append("</orderNum><tranDate>"); sb.Append(strTranDate); sb.Append("</tranDate><ShopCode>"); sb.Append(strShopCode); sb.Append("</ShopCode><ShopAccount>"); sb.Append(strShopAccount); sb.Append("</ShopAccount></in></ICBCAPI>"); string post_data = post_params + sb.ToString(); string retruenstring = PostDataBySSL(post_data, api_url, cert_path, strKey, out errInfo); if (retruenstring.Length <= 5) { return retruenstring; } return HttpUtility.UrlDecode(retruenstring); } catch (Exception ex) { var result = SpringFactory.BusinessFactory.GetBusinessAnonymousUser(); result.AddLogs(ex.Message, ""); errInfo = ex.Message; return ex.Message; } } /// <summary> /// 發送SSL加密請求 /// </summary> /// <param name="post_data"></param> /// <param name="url"></param> /// <param name="cert_path"></param> /// <param name="cert_password"></param> /// <param name="errInfo"></param> /// <returns></returns> public static string PostDataBySSL(string post_data, string url, string cert_path, string cert_password, out string errInfo) { errInfo = string.Empty; try { ASCIIEncoding encoding = new ASCIIEncoding(); byte[] data = encoding.GetBytes(post_data); if (cert_path != string.Empty) ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); WebRequest webRequest = WebRequest.Create(url); HttpWebRequest httpRequest = webRequest as HttpWebRequest; if (cert_path.ToLower().EndsWith(".cer")) { httpRequest.ClientCertificates.Add(X509Certificate.CreateFromCertFile(cert_path)); } else { //SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs(cert_path); httpRequest.ClientCertificates.Add(new X509Certificate2(cert_path, cert_password, X509KeyStorageFlags.MachineKeySet)); } httpRequest.KeepAlive = true; httpRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)"; httpRequest.ContentType = "application/x-www-form-urlencoded"; httpRequest.Method = "POST"; httpRequest.ContentLength = data.Length; Stream requestStream = httpRequest.GetRequestStream(); requestStream.Write(data, 0, data.Length); requestStream.Close(); Stream responseStream = null; responseStream = httpRequest.GetResponse().GetResponseStream(); string stringResponse = string.Empty; if (responseStream != null) { using (StreamReader responseReader = new StreamReader(responseStream, Encoding.GetEncoding("GBK"))) { stringResponse = responseReader.ReadToEnd(); } responseStream.Close(); } return stringResponse; } catch (Exception e) { errInfo = e.Message; SpringFactory.BusinessFactory.GetBusinessAnonymousUser().AddLogs(e.Message, ""); return string.Empty; } } public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } }
現在來說一說可能遇到的問題(我本人遇到了以下錯誤,windows server2012的服務器):
1、發布到服務器后,跳轉到支付頁面時報下圖所示錯誤:
提問的時候有人說是ICBCEBankUtil.dll沒有注冊的原因,但事實上我注冊過多次,每次都提示注冊成功。搜索一番之后終於解決了這個問題,打開IIS 選擇,應用程序池-選擇你的程序所使用的應用程序池-右鍵-高級設置-啟用32位應用程序項設置為True(默認False)。
如下圖所示:
2、做工行查詢接口的時候在本地沒有問題,發布到服務器上之后一直報錯系統找不到指定的文件,而服務器上證書文件是存在的。具體代碼如下:
我排查過在執行 httpRequest.ClientCertificates.Add(new X509Certificate2(cert_path, cert_password));這一句代碼的時候拋異常了,“系統找不到指定的文件“,但是證書文件我已經上產到服務器上了。折騰了N長時間后終於解決了,把原來的X509Certificate2 cert = new X509Certificate2(cert_path, "12345678");加了一個參數改為:X509Certificate2 cert= new X509Certificate2(cert_path, cert_password, X509KeyStorageFlags.MachineKeySet) 。具體過程參考我的博問http://q.cnblogs.com/q/54288/
這篇文章就寫到這里,希望能對大家有所幫助