中国建设银行接口使用详细说明
建行的接口相对于支付宝,Q业务充值和移动,联通,电信,缴费接口要复杂一些,接口分为两块,一块是商户到银行,另外一块是银行到商户
商户到银行
交易流程如下:
商户到银行
其实这一步是把自己卡里的钱转到商户的帐上,就是转账,
代码实现其实很简单,我们先来分析一上要传的参考吧
域名
|
名称
|
类型
|
备注
|
MERCHANTID
|
商户代码
|
CHAR(9)
|
由建行统一分配
|
POSID
|
商户柜台代码
|
CHAR(9)
|
由建行统一分配,缺省为000000000
|
BRANCHID
|
分行代码
|
CHAR(9)
|
由建行统一指定
|
ORDERID
|
定单号
|
CHAR(30)
|
由商户提供,最长30位,按实际长度给出
|
PAYMENT
|
付款金额
|
NUMBER(16,2)
|
由商户提供,按实际金额给出
|
CURCODE
|
币种
|
CHAR(2)
|
缺省为01-人民币
|
REMARK1
|
备注1
|
CHAR(30)
|
网银不处理,直接传到城综网
|
REMARK2
|
备注2
|
CHAR(30)
|
网银不处理,直接传到城综网
|
TXCODE
|
交易码
|
CHAR(6)
|
由建行统一分配为520100
|
MAC
|
MAC校验域
|
CHAR(32)
|
采用标准MD5算法,由商户实现
|
这是建行文档说的说明,很明显这是使用Http的方式来实现的
下面我们动手来实现 一下吧,
我是把所有的参数生成了一个实体类这样方便,而且规范化,
来看看这个Model吧
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ClientSystem.AliPay { /// <summary> /// 建行传入参数 /// </summary> public class CBBTextModel { private string _MERCHANTID = "" ; /// <summary> /// 商户代码 由建行统一分配 /// </summary> public string MERCHANTID { get { return _MERCHANTID; } set { _MERCHANTID = value; } } private string _POSID = "" ; /// <summary> /// 商户柜台代码 由建行统一分配,缺省为000000000 /// </summary> public string POSID { get { return _POSID; } set { _POSID = value; } } private string _BRANCHID = "" ; /// <summary> /// 分行代码 由建行统一指定 /// </summary> public string BRANCHID { get { return _BRANCHID; } set { _BRANCHID = value; } } private string _ORDERID = "" ; /// <summary> /// 定单号 由商户提供,最长30位,按实际长度给出 /// </summary> public string ORDERID { get { return _ORDERID; } set { _ORDERID = value; } } private decimal _PAYMENT = 0m; /// <summary> /// 付款金额 由商户提供,按实际金额给出 /// </summary> public decimal PAYMENT { get { return _PAYMENT; } set { _PAYMENT = value; } } private string _CURCODE = "" ; /// <summary> /// 币种 缺省为01-人民币 /// </summary> public string CURCODE { get { return _CURCODE; } set { _CURCODE = value; } } private string REMARK1 = "" ; /// <summary> /// 备注1 网银不处理,直接传到城综网 /// </summary> public string REMARK11 { get { return REMARK1; } set { REMARK1 = value; } } private string REMARK2 = "" ; /// <summary> /// 备注2 网银不处理,直接传到城综网 /// </summary> public string REMARK21 { get { return REMARK2; } set { REMARK2 = value; } } private string _TXCODE = "" ; /// <summary> /// 交易码 由建行统一分配为520100 /// </summary> public string TXCODE { get { return _TXCODE; } set { _TXCODE = value; } } private string _MAC = "" ; /// <summary> /// MAC校验域 采用标准MD5算法,由商户实现 /// </summary> public string MAC { get { return _MAC; } set { _MAC = value; } } private string _url = "" ; /// <summary> /// URL /// </summary> public string Url { get { return _url; } set { _url = value; } } } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#region //预定义方法或是变量 /// <summary> /// 请求指定 URL 资源,并获取响应结果 /// </summary> /// <param name="url">需要请求的 URL 资源</param> /// <returns> /// 响应结果; /// 出现任意异常,均返回字串"Runtime Error" /// </returns> private string RequestContent( string url) { string content = string .Empty; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.KeepAlive = false ; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); content = reader.ReadToEnd(); reader.Close(); } catch (Exception) { content = "Runtime Error" ; } return content; } /// <summary> /// 传入明文,返回用MD%加密后的字符串 /// </summary> /// <param name="str">要加密的字符串</param> /// <returns>用MD5加密后的字符串</returns> public static string ToMD5( string str) { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "md5" ); } #endregion |
看一下充值按钮下面实现吧
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
if (textBox1.Text.Trim() == "" || textBox1.Text.Trim() == null ) { MessageBoxForm objm = new MessageBoxForm( "您输入的金额不能为空!!!" , "提示信息" ); objm.ShowDialog(); return ; } string orid = OfficeInfo.ofId.ToString().Trim() + "_" + DateTime.Now.Ticks.ToString(); Alipay objalipay = new Alipay(); objalipay.APID = orid; objalipay.addTime = DateTime.Now; objalipay.total_fee = Convert.ToDecimal(textBox1.Text.ToString().Trim()); objalipay.trade_status = "客户端提交" ; objalipay.Text1 = DateTime.Now.ToString(); objalipay.Text2 = "建行接口" ; objalipay.Text3 = "" ; objalipay.Text4 = "" ; objalipay.Text5 = "" ; decimal money = Convert.ToDecimal(user.GetListBy(OfficeInfo.ofPara1, 13).ToString().Trim()); if (money > Convert.ToDecimal(textBox1.Text.Trim())) { MessageBoxForm objm = new MessageBoxForm( "你输入的最小金额不能低于" + money + "元!!!" , "提示信息" ); objm.ShowDialog(); return ; } if (user.AddAlipay(OfficeInfo.ofPara1, objalipay)) { CBBTextModel objcbbText = new CBBTextModel(); //商户代码 由建行统一分配 objcbbText.MERCHANTID = "00000000000000" ; //商户柜台代码 由建行统一分配,缺省为000000000 objcbbText.POSID = "00000000000000" ; //分行代码 由建行统一指定 objcbbText.BRANCHID = "00000000000000" ; // 定单号 由商户提供,最长30位,按实际长度给出 objcbbText.ORDERID = orid.Trim(); //付款金额 由商户提供,按实际金额给出 objcbbText.PAYMENT = Convert.ToDecimal(textBox1.Text.Trim()); //币种 缺省为01-人民币 objcbbText.CURCODE = "01" ; //备注1 网银不处理,直接传到城综网 objcbbText.REMARK11 = "" ; //备注2 网银不处理,直接传到城综网 objcbbText.REMARK21 = "" ; //交易码 由建行统一分配为520100 objcbbText.TXCODE = "520100" ; //MAC校验域 采用标准MD5算法,由商户实现 objcbbText.MAC = "qwertyuioplkjhgfdsazxcvbnm901234" ; //URL objcbbText.Url = "https://ibsbjstar.ccb.com.cn/app/ccbMain" ; //要加密的串 string canshu = "MERCHANTID=" + objcbbText.MERCHANTID.Trim() + "&POSID=" + objcbbText.POSID.Trim() + "&BRANCHID=" + objcbbText.BRANCHID.Trim() + "&ORDERID=" + objcbbText.ORDERID.Trim() + "&PAYMENT=" + objcbbText.PAYMENT.ToString().Trim() + "&CURCODE=" + objcbbText.CURCODE + "&TXCODE=" + objcbbText.TXCODE.Trim() + "&REMARK1=&REMARK2=" ; objcbbText.MAC = ToMD5(canshu.Trim()).ToLower().Trim(); string strURl = objcbbText.Url + "?" + canshu + "&MAC=" + objcbbText.MAC.Trim(); webBrowser1.Url = new Uri(strURl.Trim()); } } |
在这里大家一定要注意把 objcbbText.MAC = ToMD5(canshu.Trim()).ToLower().Trim();
加密后的字符串改成小写的
上面所提到的
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
string orid = OfficeInfo.ofId.ToString().Trim() + "_" + DateTime.Now.Ticks.ToString(); Alipay objalipay = new Alipay(); objalipay.APID = orid; objalipay.addTime = DateTime.Now; objalipay.total_fee = Convert.ToDecimal(textBox1.Text.ToString().Trim()); objalipay.trade_status = "客户端提交" ; objalipay.Text1 = DateTime.Now.ToString(); objalipay.Text2 = "建行接口" ; objalipay.Text3 = "" ; objalipay.Text4 = "" ; objalipay.Text5 = "" ; decimal money = Convert.ToDecimal(user.GetListBy(OfficeInfo.ofPara1, 13).ToString().Trim()); if (money > Convert.ToDecimal(textBox1.Text.Trim())) { MessageBoxForm objm = new MessageBoxForm( "你输入的最小金额不能低于" + money + "元!!!" , "提示信息" ); objm.ShowDialog(); return ; } |
这一部分代码是记录日志的,大家可以参考一下
我们现在只要运行程序就会出现如下界面所显示的内容
下面的操作就是输入你的卡号密码就可以了,
转账成功后我们这一步的工作就算是做完了
银行到商户
接下来的这一步 是很关键的一步,是当我们转账成功后,银行发给我们系统的一个处理结束,里面的参数如下
域名
|
名称
|
类型
|
备注
|
POSID
|
商户柜台代码
|
CHAR(9)
|
从商户传送的信息中获得
|
BRANCHID
|
分行代码
|
CHAR(9)
|
从商户传送的信息中获得
|
ORDERID
|
定单号
|
CHAR(30)
|
从商户传送的信息中获得
|
PAYMENT
|
付款金额
|
NUMBER(16,2)
|
从商户传送的信息中获得
|
CURCODE
|
币种
|
CHAR(2)
|
从商户传送的信息中获得
|
REMARK1
|
备注一
|
CHAR(30)
|
从商户传送的信息中获得
|
REMARK2
|
备注二
|
CHAR(30)
|
从商户传送的信息中获得
|
SUCCESS
|
成功标志
|
CHAR(1)
|
成功时返回Y
|
SIGN
|
数字签名
|
CHAR(256)
|
|
在这里我们首先要新建一个Asp.net的网站,只要在一个网页下面书写代码就成了。
第一步我们要写出来要加密 的串
01
02
03
04
|
string canshu = "POSID=000000000&BRANCHID=0000000&ORDERID=" + Request.QueryString[ "ORDERID" ].Trim() + "&PAYMENT=" + Request.QueryString[ "PAYMENT" ].Trim() + "&CURCODE=" + Request.QueryString[ "CURCODE" ].Trim() + "&REMARK1=" + Request.QueryString[ "REMARK1" ].Trim() + "&REMARK2=" + Request.QueryString[ "REMARK2" ].Trim() + "&ACC_TYPE=" + Request.QueryString[ "ACC_TYPE" ].Trim() + "&SUCCESS=" + Request.QueryString[ "SUCCESS" ].Trim(); |
19991101&REMARK2=merchantname&SUCCESS=Y
比较1)、2)结果。
下面我们要做的工作就是如何验证这个串是否一致了,先说一下MD5withRSA签名程序吧,这是加密算法是由MD5加密和RSA加密算法组合而来的
具体的说明请大家在网上找找吧,很容易找到这里就不再多说了
我们来看看主要是怎么验证的吧
银行发过来的签名是通过RSA加密后的签名,在签名是会生成一个公钥,这个公钥我们可以从这里下载的到
用我们的账户登录建行的商户平台,如下地方可以下载的到
另外在登录这个系统时要验证客户端的证书,证书的下载可以在建行的主而上直接找到,根据自己的客户号和密码可以下载,具体的大家还得根据建行服务
人员的提示操作的好
有了这个我们还要一个CCBRSA.dll文件,这个是建行用来验证加密串的具体的使用方法看下面的程序,怎么样添加Dll的引用我就不多说了,大家自己找找
01
02
03
04
05
06
07
08
09
10
|
//传过来的签名; string sign = Request.QueryString[ "SIGN" ]; //本地Key值 string mysign = ConfigurationManager.AppSettings[ "PublicKey" ].ToString().Trim(); CCBRSA.RSASig rsa; //注册一下regsvr32 CCBRSA.dll 文件 rsa = new CCBRSA.RSASigClass(); bool bRet; rsa.setPublicKey(mysign); bRet = rsa.verifySigature(sign, canshu); |
bRet是一个Boolean值可以直接用它来做IF的判断。
在这里我多说几句如果我们直接这样运行的话可能会报错如下
Retrieving the COM class factory for component with CLSID
{A5C5C388-A972-4CCF-93E2-7F97E82C9EBA} failed due to the following
error: 80040154.
由于用到了CCBRSA.dll这个动态链接库文件,所以要先注册一下这个文件,建议把这个文件复制到system32目录下然后开始运行输入 regsvr32
CCBRSA.dll 确定就可以了.
另外还要安装一下msjavx86.exe ,java虚拟机。可能是有部分需要调用到java的一些库吧,所以需要安装这个。我把Dll文件和这个文件提供下载
如下 打包下载
我验证的时候一般要验证如下三个方面就算是可以了
01
02
03
04
05
|
//调试用,中国建设银行服务器返回时的完整路径。 if ( bRet && success == "Y" && Request.UserHostName.Trim() == "建行IP" ) //验证中国建设银行发过来的消息,签名是否正确 { 在这里写我们自己的代码吧。。。。。。。。。。。。 } |
过多的代码不方便贴出来,呵呵,大家如果也在开发这块的东东,而且 有问题的话可以交流一下,呵呵
我们把代码写完之后直接发布到一个能被外网访问到的电脑上就行了, 然后在商户的后写上这个页面的地方就行了,看下面的图
第一个地址是时时的只有用户单击确定成功按钮时才会调用 ,一般不使用,就是支付宝里的时时调用方式
第二个是异步的,就是说不管你单击不单击只要有帐 到,都会调用 在使用的时候要输入一下交易密码哦
好了,我们的工作就到这里吧,
哎,为了方便大家理解我还是把大部分代码贴一下吧
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
代码 using System; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.IO; using SystemModel; using System.Net; using ccbText; using System.Text; using System.Security.Cryptography; public partial class _Default : System.Web.UI.Page { //加载事件 protected void Page_Load( object sender, EventArgs e) { if (!IsPostBack) { // try { //要加密的串 //要加密的串 string canshu = "POSID=0000000&BRANCHID=0000000&ORDERID=" + Request.QueryString[ "ORDERID" ].Trim() + "&PAYMENT=" +Request.QueryString[ "PAYMENT" ].Trim() + "&CURCODE=" + Request.QueryString[ "CURCODE" ].Trim() + "&REMARK1=" + Request.QueryString[ "REMARK1" ].Trim() + "&REMARK2=" + Request.QueryString[ "REMARK2" ].Trim() + "&ACC_TYPE=" + Request.QueryString[ "ACC_TYPE" ].Trim()+ "&SUCCESS=" + Request.QueryString[ "SUCCESS" ].Trim(); //传过来的签名; string sign = Request.QueryString[ "SIGN" ]; //本地Key值 string mysign = ConfigurationManager.AppSettings[ "PublicKey" ].ToString().Trim(); CCBRSA.RSASig rsa; //注册一下regsvr32 CCBRSA.dll 文件 rsa = new CCBRSA.RSASigClass(); bool bRet; rsa.setPublicKey(mysign); bRet = rsa.verifySigature(sign, canshu); string success = Request.QueryString[ "SUCCESS" ].ToString().Trim(); //更新自己数据库的订单语句,请自己填写一下 string strOrderNO = Request.QueryString[ "ORDERID" ]; //订单号 string strPrice = Request.QueryString[ "PAYMENT" ]; //金额 string strTradeStatus = Request.QueryString[ "SUCCESS" ]; //订单状态 //调试用,中国建设银行服务器返回时的完整路径。 if ( bRet && success == "Y" && Request.UserHostName.Trim() == "建行IP" ) //验证中国建设银行发过来的消息,签名是否正确 { //更新自己数据库的订单语句,请自己填写一下 result=.....这里写上你更新数据库的方法 //成功 if (result.Trim() == "0" ) { //这里要改变交易的状态,或是给用户上账 Response.Write( "商户:" + login[0].ToString().Trim() + "<br>金额:" + strPrice + " 交易成功" ); //成功,可美化该页面,提示信息 ////写文本,纪录中国建设银行返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库) string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + " 交易信息" + "商户:" + login[1].ToString().Trim() + "<br>金额:" + strPrice + " 交易成功" + Request.UserHostName.Trim(); StreamWriter fs = new StreamWriter(Server.MapPath( "Return_DATA/" + DateTime.Now.ToString().Replace( ":" , "" )) + ".txt" , false , System.Text.Encoding.Default); fs.Write(TOEXCELLR); fs.Close(); //修改订单状态 } else if (result == "-1" ) { //修改订单状态 ////写文本,纪录中国建设银行返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库) string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + "perky_" + result.Trim() + Request.UserHostName.Trim(); StreamWriter fs = new StreamWriter(Server.MapPath( "Return_DATA/" + "e" + DateTime.Now.ToString().Replace( ":" , "" )) + ".txt" , false , System.Text.Encoding.Default); fs.Write(TOEXCELLR); fs.Close(); //修改订单状态 Response.Write( "查询订单时失败!!! 请确定你是否下单!!!" ); } else { //修改订单状态 ////写文本,纪录中国建设银行返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库) string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + "perky_" + result.Trim() + Request.UserHostName.Trim(); StreamWriter fs = new StreamWriter(Server.MapPath( "Return_DATA/" + "e" + DateTime.Now.ToString().Replace( ":" , "" )) + ".txt" , false , System.Text.Encoding.Default); fs.Write(TOEXCELLR); fs.Close(); Response.Write( "重复使用界面无效!!!" ); } } else { Response.Write( "------------------------------------------" ); Response.Write( "<br>Result:responseTxt=" ); Response.Write( "<br>Result:mysign=" + mysign); Response.Write( "<br>Result:sign=" + sign); Response.Write( "支付失败" ); ////写文本,纪录中国建设银行返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库) string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + Request.UserHostName.Trim(); StreamWriter fs = new StreamWriter(Server.MapPath( "Return_DATA/" + "e" + DateTime.Now.ToString().Replace( ":" , "" )) + ".txt" , false , System.Text.Encoding.Default); fs.Write(TOEXCELLR); fs.Close(); //修改订单状态 } } catch (Exception ex) { ////写文本,纪录中国建设银行返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库) string TOEXCELLR = Request.Url.ToString() + " " + ex.Message.ToString() + Request.UserHostName.Trim(); StreamWriter fs = new StreamWriter(Server.MapPath( "Return_DATA/" + "m" + DateTime.Now.ToString().Replace( ":" , "" )) + ".txt" , false , System.Text.Encoding.Default); fs.Write(TOEXCELLR); fs.Close(); } } } } |