一、 前期准備
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;
#endregion
View 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