C#中国建设银行接口使用详细说明.docx
中国建设银行接口使用详细说明 Posted on 2010-07-22 18:59 苏飞 阅读(2782) 评论(17) 编辑 收藏 接口介绍 建行的接口相对于支付宝,Q业务充值和移动,联通,电信,缴费接口要复杂一些,接口分为两块,一块是商户到银行,另外一块是银行到商户商户到银行 交易流程如下: 网上支付业务流程步骤说明: 1) 客户登录商户网站,选择商户网站商品。2) 客户将选好的商品放入购物车,并下订单。商户提供商户代码、订单号、合计金额等信息;3) 客户选择代理付款的银行建行,确认后,商户代码、订单信息、合计金额通过浏览器URL传到建行网上银行站点;网上银行自动显示支付页面,客户首先选择是否使用建行证书,然后输入龙卡号和密码,选择“确定”。支付信息经加密后传送到网银中心;4) 网银中心接收客户支付信息,转发到银行后台业务处理系统;5) 银行后台业务系统处理后,返回处理结果给网银;6) 网银通知客户支付(扣帐)是否成功。如果扣帐成功,提示客户注意接收商户返回的送货信息;对于不需要立即响应的商户,跳过步骤7、8;7) 对于需要立即响应的商户,如果支付成功,网银将成功结果反馈给商户。若支付失败,不返回给商户信息8) 对于需要立即响应的商户,收到银行扣帐成功的通知后,发给客户送货信息。如客户收到银行支付(扣帐)成功通知(步骤6),但未收到商户送货信息,则需向商户查询。日终时,商户与开设结算帐户的建设银行(网银成员行)进行流水核对,对已支付但未得到商户确认的交易进行退款处理。 商户到银行 其实这一步是把自己卡里的钱转到商户的帐上,就是转账,代码实现其实很简单,我们先来分析一上要传的参考吧 个人客户在商户网站选择商品后,商户网站生成以下信息,传送到建行网站: 域名名称类型备注MERCHANTID商户代码CHAR(9)由建行统一分配POSID商户柜台代码CHAR(9)由建行统一分配,缺省为000000000BRANCHID分行代码CHAR(9)由建行统一指定ORDERID定单号CHAR(30)由商户提供,最长30位,按实际长度给出PAYMENT付款金额NUMBER(16,2)由商户提供,按实际金额给出CURCODE币种CHAR(2)缺省为01人民币REMARK1备注1CHAR(30)网银不处理,直接传到城综网REMARK2备注2CHAR(30)网银不处理,直接传到城综网TXCODE交易码CHAR(6)由建行统一分配为520100MACMAC校验域CHAR(32)采用标准MD5算法,由商户实现注:商户要保证定单号的唯一性。为了加快站点间接口开发,站点间接口的参数传送采用普通的URL方式,商户将以上信息包含在FORM中,在SUBMIT后将生成URL,如下所示:&TXCODE=520100&REMARK1=&REMARK2=&MAC=qwertyuioplkjhgfdsazxcvbnm901234 参与MAC运算的字符及其顺序如下:MERCHANTID=123456789&POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=500.00&CURCODE=01&TXCODE=520100&REMARK1=&REMARK2=注:字符串中变量名必须是大写字母。 这是建行文档说的说明,很明显这是使用Http的方式来实现的下面我们动手来实现 一下吧,我是把所有的参数生成了一个实体类这样方便,而且规范化,来看看这个Model吧 代码 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; 我们来准备两个方法吧,一个是Http连接来使用的一个是Md5加密,因为在文档里写到要使用Md5加密哦 代码 #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 看一下充值按钮下面实现吧 代码 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 = " /要加密的串 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();加密后的字符串改成小写的上面所提到的代码 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) 这一部分代码是记录日志的,大家可以参考一下我们现在只要运行程序就会出现如下界面所显示的内容下面的操作就是输入你的卡号密码就可以了,转账成功后我们这一步的工作就算是做完了 银行到商户 接下来的这一步 是很关键的一步,是当我们转账成功后,银行发给我们系统的一个处理结束,里面的参数如下 建行网站生成以下信息,传送到商户网站: 域名名称类型备注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)成功时返回YSIGN数字签名CHAR(256) 站点间接口的参数传送仍然采用普通的URL方式,信息包含在CGI参数,具体如下所示:HTTP:/MERCHANT.WEB.SITE/MERCHANT_CGI?POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=500.00&CURCODE=01&REMARK119991101&REMARK2=merchantname&SUCCESS=Y&SIGN=4b3ef029516193b7d969ac1840083635a3e0901b8cd526caa44c1a072f496d7f0d4bca3942c0d9030bede37c7809b835cec787eb39e18b7596a724fba9805b24714dfbb0f4a3fb430b32e075254a114d4c38a0ac52ef46a0ad33dec3fbfc15417402a1399e65e46996c0cf49fc7ffca9222f8cd693c8376b6f928828967bec42 注:?前的URL由商户在签约时提供 参与签名运算的字符及其顺序如下POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=500.00&CURCODE=01&REMARK119991101&REMARK2=merchantname&SUCCESS=Y注:字符串中变量名必须是大写字母。 如果商户的程序将MERCHANTID, POSID,BRANCHID, ORDERID, PAYMENT, CURCODE,TXCODE和MAC作为隐藏域(hidden),然后使用SUBMIT按纽,注意在 FORM的METHOD中使用“GET”的方式。 在这里我们首先要新建一个A的网站,只要在一个网页下面书写代码就成了。第一步我们要写出来要加密 的串 代码 /要加密的串 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(); 这是在我们接收数据时要用到的,这里建行提供了一个加密验证为银行将客户支付信息实时通知给商户时,使用的数字签名算法是MD5withRSA算法。商户验证签名的公钥在商户在网银系统开户,获取数字证书后,登录到网银系统中,通过下载公钥交易获取。 商户获取的公钥用X.509格式表示,并且将其按照每4位(bit)转换为一个16进制数的方式表示,产生16进制的字符串。 网上银行使用标准MD5withRSA算法对给商户的响应进行签名,产生1024位(bit)的签名结果,并且将其按照每4位(bit)转换为一个16进制数的方式表示,形成16进制的字符串,长度为256。 下面是对签名结果的表示方式的描述:1、对1024位的交易结果按4位为一个单位进行划分,共获得256段2、将每段看成一个16进制数,如0011为0X3,1101为0Xd。3、将这个数映射到ASCII码表,形成相应的字符,如0X2为“2”,0Xd为“d”。4、将这些字符连成一个字符串,长度为256。 例如:待签名的字符串为:POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=500.00&CURCODE=01&REMARK119991101&REMARK2=merchantname&SUCCESS=Y签名结果为:4b3ef029516193b7d969ac1840083635a3e0901b8cd526caa44c1a072f496d7f0d4bca3942c0d9030bede37c7809b835cec787eb39e18b7596a724fba9805b24714dfbb0f4a3fb430b32e075254a114d4c38a0ac52ef46a0ad33dec3fbfc15417402a1399e65e46996c0cf49fc7ffca9222f8cd693c8376b6f928828967bec42 当商户收到银行传来的CGI串后,从中获取签名(格式如上)和需签名的原文。商户端程序(商户自行开发MD5withRSA签名校验程序)将签名和商户端的公钥转换成二进制格式,与签名的原文一起对签名的正确性进行校验,校验步骤如下:1) 使用公钥进行签名的逆运算2) 使用标准MD5算法运算原文比较1)、2)结果。 下面我们要做的工作就是如何验证这个串是否一致了,先说一下MD5withRSA签名程序吧,这是加密算法是由MD5加密和RSA加密算法组合而来的具体的说明请大家在网上找找吧,很容易找到这里就不再多说了我们来看看主要是怎么验证的吧银行发过来的签名是通过RSA加密后的签名,在签名是会生成一个公钥,这个公钥我们可以从这里下载的到用我们的账户登录建行的商户平台,如下地方可以下载的到另外在登录这个系统时要验证客户端的证书,证书的下载可以在建行的主而上直接找到,根据自己的客户号和密码可以下载,具体的大家还得根据建行服务人员的提示操作的好有了这个我们还要一个CCBRSA.dll文件,这个是建行用来验证加密串的具体的使用方法看下面的程序,怎么样添加Dll的引用我就不多说了,大家自己找找代码/传过来的签名;stringsign=Request.QueryString"SIGN"/本地Key值stringmysign=ConfigurationManager.AppSettings"PublicKey".ToString().Trim();CCBRSA.RSASigrsa;/注册一下regsvr32CCBRSA.dll文件rsa=newCCBRSA.RSASigClass();boolbRet;rsa.setPublicKey(mysign);bRet=rsa.verifySigature(sign,canshu);bRet是一个Boolean值可以直接用它来做IF的判断。在这里我多说几句如果我们直接这样运行的话可能会报错如下Retrieving the COM class factory for component with CLSIDA5C5C388-A972-4CCF-93E2-7F97E82C9EBA failed due to the following error:80040154. 由于用到了CCBRSA.dll这个动态链接库文件,所以要先注册一下这个文件,建议把这个文件复制到system32目录下然后开始运行输入regsvr32CCBRSA.dll 确定就可以了. 另外还要安装一下msjavx86.exe,java虚拟机。可能是有部分需要调用到java的一些库吧,所以需要安装这个。我把Dll文件和这个文件提供下载如下打包下载 我验证的时候一般要验证如下三个方面就算是可以了代码/调试用,中国建设银行服务器返回时的完整路径。if(bRet&&success="Y"&&Request.UserHostName.Trim()="建行IP")/验证中国建设银行发过来的消息,签名是否正确在这里写我们自己的代码吧。过多的代码不方便贴出来,呵呵,大家如果也在开发这块的东东,而且 有问题的话可以交流一下,呵呵我们把代码写完之后直接发布到一个能被外网访问到的电脑上就行了, 然后在商户的后写上这个页面的地方就行了,看下面的图第一个地址是时时的只有用户单击确定成功按钮时才会调用 ,一般不使用,就是支付宝里的时时调用方式第二个是异步的,就是说不管你单击不单击只要有帐 到,都会调用 在使用的时候要输入一下交易密码哦好了,我们的工作就到这里吧,哎,为了方便大家理解我还是把大部分代码贴一下吧代码usingSystem;usingSystem.Configuration;usingSystem.Data;usingSystem.Linq;usingSystem.Web;usingSystem.Web