一、 前期准備
Ps:工行運營提供開發文檔時,沒有直接提供支付組件ICBCEBankUtil.dll和infosecapi.dll,工行運營說有這個組件在文檔中,但是沒有找到,工行沒有技術提供支持,後來在網上自己找的。
二、 環境搭配
Ps:本人使用的是64位系統,支付組件是放在System64文件夾下的,如果系統是32位,支付組件要放在System32文件夾下。使用DOS命令請使用管理員權限運行,否則注冊失敗。
三、編碼
定義訂單實體類:
1 //基本信息 2 public class B2CReq 3 { 4 /// <summary> 5 /// 接口名稱 6 /// </summary> 7 public string interfaceName { get; set; } 8 /// <summary> 9 /// 接口版本號 10 /// </summary> 11 public string interfaceVersion { get; set; } 12 13 } 14 15 /// <summary> 16 /// 訂單信息 17 /// </summary> 18 public class OrderInfo 19 { 20 /// <summary> 21 /// 交易日期時間 22 /// </summary> 23 public string orderDate { get; set; } 24 /// <summary> 25 /// 訂單號 26 /// </summary> 27 public string orderid { get; set; } 28 /// <summary> 29 /// 訂單金額 30 /// </summary> 31 public string amount { get; set; } 32 /// <summary> 33 /// 分期付款期數 34 /// </summary> 35 public string installmentTimes { get; set; } 36 /// <summary> 37 /// 支付幣種 38 /// </summary> 39 public string curType { get; set; } 40 /// <summary> 41 /// 商戶代碼 42 /// </summary> 43 public string merID { get; set; } 44 /// <summary> 45 /// 商戶賬號 46 /// </summary> 47 public string merAcct { get; set; } 48 } 49 /// <summary> 50 /// 客戶信息 51 /// </summary> 52 public class Custom 53 { 54 /// <summary> 55 /// 聯名校驗標志 56 /// </summary> 57 public string verifyJoinFlag { get; set; } 58 /// <summary> 59 /// 語言版本 60 /// </summary> 61 public string Language { get; set; } 62 } 63 64 /// <summary> 65 /// 信息 66 /// </summary> 67 public class Message 68 { 69 /// <summary> 70 /// 商品編號 71 /// </summary> 72 public string goodsID { get; set; } 73 /// <summary> 74 /// 商品名稱 75 /// </summary> 76 public string goodsName { get; set; } 77 /// <summary> 78 /// 商品數量 79 /// </summary> 80 public string goodsNum { get; set; } 81 /// <summary> 82 /// 已含運費金額 83 /// </summary> 84 public string carriageAmt { get; set; } 85 /// <summary> 86 /// 商城提示 87 /// </summary> 88 public string merHint { get; set; } 89 /// <summary> 90 /// 備注字段1 91 /// </summary> 92 public string remark1 { get; set; } 93 /// <summary> 94 /// 備注字段2 95 /// </summary> 96 public string remark2 { get; set; } 97 /// <summary> 98 /// 通知商戶URL 99 /// </summary> 100 public string merURL { get; set; } 101 /// <summary> 102 /// 返回商戶變量 103 /// </summary> 104 public string merVAR { get; set; } 105 /// <summary> 106 /// 通知類型 107 /// </summary> 108 public string notifyType { get; set; } 109 /// <summary> 110 /// 結果發送類型 111 /// </summary> 112 public string resultType { get; set; } 113 /// <summary> 114 /// 備用字段1 115 /// </summary> 116 public string backup1 { get; set; } 117 /// <summary> 118 /// 備用字段2 119 /// </summary> 120 public string backup2 { get; set; } 121 /// <summary> 122 /// 備用字段3 123 /// </summary> 124 public string backup3 { get; set; } 125 /// <summary> 126 /// 備用字段4 127 /// </summary> 128 public string backup4 { get; set; } 129 }View Code
幫助類
public class XmlHelper { /// <summary> /// 根據模型生成一個xml,其中不包括類名 /// </summary> /// <param name="Model">模型</param> /// <param name="flag">屬性值為空,xml生成是否返回該屬性</param> /// <returns></returns> public static StringBuilder ModelToXml(object Model, Flag flag) { StringBuilder Xml = new StringBuilder(); Type t = Model.GetType(); System.Reflection.PropertyInfo[] properties = t.GetProperties(); foreach (var item in properties) { var PropertiesValue = item.GetValue(Model, null); string PropertiesName = item.Name; if (PropertiesValue == null || string.IsNullOrEmpty(PropertiesValue.ToString())) { if (flag==Flag.Y) { Xml.AppendFormat("<{0}>{1}</{0}>", PropertiesName, PropertiesValue); } } else { Xml.AppendFormat("<{0}>{1}</{0}>", PropertiesName, PropertiesValue); } } return Xml; } /// <summary> /// 根據模型生成一個xml,其他不包括類名 /// </summary> /// <param name="Model">模型</param> /// <param name="flag">屬性值為空,xml生成是否返回該屬性</param> /// <param name="sort">對屬性名稱排序/可選(升序、降序)</param> /// <returns></returns> public static StringBuilder ModelToXml(object Model, Flag flag,Sort sort=Sort.Asc) { StringBuilder Xml = new StringBuilder(); Type t = Model.GetType(); System.Reflection.PropertyInfo[] properties = t.GetProperties(); Dictionary<string, object> dic = new Dictionary<string, object>(); foreach (var item in properties) { var PropertiesValue = item.GetValue(Model, null); string PropertiesName = item.Name; dic.Add(PropertiesName, PropertiesValue); } //對屬性排序 var SortList = sort == Sort.Asc ? dic.OrderBy(o => o.Key) : dic.OrderByDescending(o => o.Key); foreach (var item in SortList) { if (item.Value == null || string.IsNullOrEmpty(item.Value.ToString())) { if (flag == Flag.Y) { Xml.AppendFormat("<{0}>{1}</{0}>", item.Key, item.Value); } } else { Xml.AppendFormat("<{0}>{1}</{0}>", item.Key, item.Value); } } return Xml; } /// <summary> /// 根據模型生成一個xml,其他不包括類名 /// </summary> /// <param name="Model">模型</param> /// <param name="flag">屬性值為空,xml生成是否返回該屬性</param> /// <param name="sort">對屬性名稱排序/可選(升序、降序)</param> /// <param name="RootName">父節點名稱</param> /// <returns></returns> public static StringBuilder ModelToXml(object Model, Flag flag, Sort sort,string RootName) { StringBuilder Xml = new StringBuilder(); Type t = Model.GetType(); System.Reflection.PropertyInfo[] properties = t.GetProperties(); Dictionary<string, object> dic = new Dictionary<string, object>(); Xml.AppendFormat("<{0}>",RootName); foreach (var item in properties) { var PropertiesValue = item.GetValue(Model, null); string PropertiesName = item.Name; dic.Add(PropertiesName, PropertiesValue); } //對屬性排序 var SortList = sort == Sort.Asc ? dic.OrderBy(o => o.Key) : dic.OrderByDescending(o => o.Key); foreach (var item in SortList) { if (item.Value == null || string.IsNullOrEmpty(item.Value.ToString())) { if (flag == Flag.Y) { Xml.AppendFormat("<{0}>{1}</{0}>", item.Key, item.Value); } } else { Xml.AppendFormat("<{0}>{1}</{0}>", item.Key, item.Value); } } Xml.AppendFormat("</{0}>", RootName); return Xml; } } /// <summary> /// 枚舉 /// </summary> public enum Flag { /// <summary> /// 是 /// </summary> Y, /// <summary> /// 否 /// </summary> N }; /// <summary> /// 排序 /// </summary> public enum Sort { /// <summary> /// 升序 /// </summary> Asc, /// <summary> /// 降序 /// </summary> Desc }; public class Too { //編碼內容 public static string Base64Encode(string str) { byte[] b = System.Text.Encoding.Default.GetBytes(str); //轉成Base64形式的System.String return Convert.ToBase64String(b); } //解碼內容 public static string Base64Decode(string str) { byte[] outputb = Convert.FromBase64String(str); string orgStr = Encoding.Default.GetString(outputb); return orgStr; } }View Code
組裝支付報文信息
#region 訂單信息 //在此自定義加密驗證 string merVAR = "";//訂單加密數據 string Url = "http://localhost:8076/Pay/Notify";//支付成功通知地址 string No = DateTime.Now.ToString("TestyyyyMMddHHmmssfff");//訂單號 string PayPrice = "100";//訂單金額以分為單位 string ProName = "充值卡";//產品名稱 string merID = "";//商戶號 string merAcct = "";//開戶帳號 ///基本信息 B2CReq req = new B2CReq(); req.interfaceName = "ICBC_WAPB_B2C"; req.interfaceVersion = "1.0.0.6"; //訂單信息 OrderInfo order = new OrderInfo(); order.orderDate = Convert.ToDateTime("2016/12/31 0:47:55").ToString("yyyyMMddHHmmss"); order.orderid = No; order.amount = PayPrice; order.installmentTimes = "1"; order.curType = "001"; order.merID = merID; order.merAcct = merAcct; //客戶信息 Custom custom = new Custom(); custom.verifyJoinFlag = "0"; custom.Language = "zh_CN"; //信息 Message message = new Message(); message.goodsID = ""; message.goodsName = ProName; message.goodsNum = ""; message.carriageAmt = ""; message.merHint = ""; message.remark1 = ""; message.remark2 = ""; message.merURL = Url; message.merVAR = merVAR; message.notifyType = "HS"; message.resultType = "1"; message.backup1 = ""; message.backup2 = ""; message.backup3 = ""; message.backup4 = ""; #endregion #region 組裝XML報文內容 //組裝xml報文內容 StringBuilder tranDataContent = new StringBuilder(); tranDataContent.Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); tranDataContent.Append("<B2CReq>"); tranDataContent.Append(XmlHelper.ModelToXml(order, Flag.Y, Sort.Asc, "orderInfo"));//訂單信息 tranDataContent.Append(XmlHelper.ModelToXml(custom, Flag.Y, Sort.Asc, "custom"));//客戶信息 tranDataContent.Append(XmlHelper.ModelToXml(message, Flag.Y, Sort.Asc, "message"));//信息 tranDataContent.Append("</B2CReq>"); #endregion #region 編碼報文內容、生成簽名 string tranData = null; string merSignMsg = null; string merCert = null; //生成支付訂單信息 tranData =Comm.Too.Base64Encode(tranDataContent.ToString()); B2CUtil icbcObj = new B2CUtil(); if (icbcObj.init(Server.MapPath("~/Deed/測試公鑰ebb2cpublic.crt"), Server.MapPath("~/Deed/rp03.crt"), Server.MapPath("~/Deed/rp03.key"), "12345678") == 0) { merSignMsg = icbcObj.signC(tranDataContent.ToString(), tranDataContent.Length);//生成簽名 } //BASE64商城證書公鑰 merCert = icbcObj.getCert(1); #endregion #region 數據准完成,發送至頁面 //參數傳至HTML ViewBag.interfaceName = req.interfaceName; ViewBag.interfaceVersion = req.interfaceVersion; ViewBag.clientType = "0"; ViewBag.tranData = tranData; ViewBag.merSignMsg = merSignMsg; ViewBag.merCert = merCert; #endregionView Code
發起支付H5
<form action="https://mywap2.icbc.com.cn/ICBCWAPBank/servlet/ICBCWAPEBizServlet" method="post" id="order"> <input name="interfaceName" id="interfaceName" type="hidden" value="@ViewBag.interfaceName"> <input name="interfaceVersion" id="interfaceVersion" type="hidden" value="@ViewBag.interfaceVersion"> <input name="clientType" id="clientType" type="hidden" value="@ViewBag.clientType"> <input name="tranData" id="tranData" type="hidden" value="@ViewBag.tranData"> <input name="merSignMsg" id="merSignMsg" type="hidden" value="@ViewBag.merSignMsg"> <input name="merCert" id="merCert" type="hidden" value="@ViewBag.merCert"> </form> <script > document.order.submit(); </script>View Code
發起支付App
<input name="interfaceName" id="interfaceName" type="hidden" value="@ViewBag.interfaceName"> <input name="interfaceVersion" id="interfaceVersion" type="hidden" value="@ViewBag.interfaceVersion"> <input name="clientType" id="clientType" type="hidden" value="@ViewBag.clientType"> <input name="tranData" id="tranData" type="hidden" value="@ViewBag.tranData"> <input name="merSignMsg" id="merSignMsg" type="hidden" value="@ViewBag.merSignMsg"> <input name="merCert" id="merCert" type="hidden" value="@ViewBag.merCert"> <script > ICBCUtil.submitOrder({ interfaceName:document.getElementById('interfaceName').value, interfaceVersion:document.getElementById('interfaceVersion').value, tranData:document.getElementById('tranData').value, merSignMsg:document.getElementById('merSignMsg').value, merCert:document.getElementById('merCert').value, }); </script>View Code
Ps:
1.在使用測試帳號的時候,訂單日期必須與測試服務器一致,可以使用工行提供的工具獲取服務器當前時間。
2.運行項目時需要啟用32應用程序。
3.測試期間一般是使用H5支付,正式商戶號申請完成之後,H5嵌入工行APP,使用工行APP支付。
組件下載
http://pan.baidu.com/s/1c2yyjWO