刚开发完工行网上支付接口。看过很多人也问过、写过这类的文章,内容和开发文档中一致,没什么纰漏。但实际开发中会遇到很多的小细节,在这里就遇到的问题和具体的开发例子说一说。
我的开发环境vs.net2003,语言C#。准备工作,按照文档里注册com组件、拆分证书并安装。开发文档中有一个pfx后缀的证书,和一个名为public.crt的公钥,这个公钥之后会用到。传递表单页面命名为Post.aspx,接收银行通知页面Get.aspx。Post前台代码如下:<%@ Page language="c#" %><HTML><HEAD> <title>工商银行在线支付</title> <meta http-equiv="content-type" content="text/html;charset=GBK"></HEAD><body> <% string order = "工行提交地址"; string interfaceName = "ICBC_PERBANK_B2C"; //接口名 string interfaceVersion = "1.0.0.0"; //版本号 string orderid = "订单号"; string amount ="订单金额"; string curType = "001"; //金额类型 string merID = "帐号"; string merAcct = "代码"; string verifyJoinFlag = "联名标志"; string notifyType = "HS";//通知类型 string merURL = "http://地址/Get.aspx"; //接收银行消息地址 string resultType = "0";//对应通知类型 string goodsID = "商品编号"; string goodsName = "商品名称"; string goodsNum = "商品数量"; string carriageAmt = "运费金额"; string merHint = "商城提示"; string orderDate = "订单时间"; //格式yyyyMMddHHmmss string merCert = "";//证书公钥,下面赋值 string remark1 = "备注1"; string remark2 = "备注2"; string path1 = "public.crt";//public公钥路径 string path2 = "icbm.crt";//拆分pfx后缀的证书后的公钥路径 string path3 = "icbm.key";//拆分pfx后缀的证书后的私钥路径 string key = "111111";//私钥保护密码 string merSignMsg = "";加密后的字符串,下面赋值 //下面是需要加密的明文字符串 string msg = interfaceName + interfaceVersion + merID + merAcct + merURL + notifyType + orderid + amount + curType + resultType + orderDate + verifyJoinFlag; ICBCEBANKUTILLib.B2CUtil obj = new ICBCEBANKUTILLib.B2CUtilClass(); //项目中引用组件,以声明的方式创建com组件。我不知道有没有其他的方式创建组件了。 if (obj.init(path1,path2,path3,key) == 0) //加载公钥、私钥、密码,如果返回0则初始化成功 { merSignMsg = obj.signC(msg,msg.Length);//加密明文 merCert = obj.getCert(1);//提取证书 } else { Response.Write(obj.getRC()); //返回签名失败信息 } %><form action="<%= order %>" name="order" method="post"><INPUT type=hidden value="<%= interfaceName %>" name=interfaceName> <INPUT type=hidden value="<%= interfaceVersion %>" name=interfaceVersion> <INPUT type=hidden value="<%= orderid %>" name=orderid> <INPUT type=hidden value="<%= amount %>" name=amount> <INPUT type=hidden value="<%= curType %>" name=curType> <INPUT type=hidden value="<%= merID %>" name=merID> <INPUT type=hidden value="<%= merAcct %>" name=merAcct> <INPUT type=hidden value="<%= verifyJoinFlag %>" name=verifyJoinFlag> <INPUT type=hidden value="<%= notifyType %>" name=notifyType> <INPUT type=hidden value="<%= merURL %>" name=merURL> <INPUT type=hidden value="<%= resultType %>" name=resultType> <INPUT type=hidden value="<%= orderDate %>" name=orderDate> <INPUT type=hidden value="<%= merSignMsg %>" name=merSignMsg> <INPUT type=hidden value="<%= merCert %>" name=merCert> <INPUT type=hidden value="<%= goodsID %>" name=goodsID> <INPUT type=hidden value="<%= goodsName %>" name=goodsName> <INPUT type=hidden value="<%= goodsNum %>" name=goodsNum> <INPUT type=hidden value="<%= carriageAmt %>" name=carriageAmt> <INPUT type=hidden value="<%= remark1 %>" name=remark1> <INPUT type=hidden value="<%= remark2 %>" name=remark2> <INPUT type=hidden size=60 value="<%= merHint %>" name=merHint> <input type="submit" value="立即支付"> </form></body></HTML>这个页面中的com组件初始化,文档中的asp例子的参数是(user.crt,user.crt,key,111111),前两个证书是一样的。经过确认后是如上的参数顺序。如果初始化失败的话,查看一下公钥、私钥的文件夹是否有权限,组件是否注册成功。除了注意提交的字符格式外,还有如果有中文的话指定一下字符集为GBK。虽然指定了字符集,但银行页面显示的还是乱码。银行的说法是我没有按接口的格式和标准来做,我不明白这只不过是个传递和接收,和接口有什么关系,难道银行显示的产品名不是从Form中获取的吗。不理解。
Get.aspx页面代码如下:<%@ Page language="c#" %><% //下面是获取银行返回的信息string amount = Request.Form["amount"].ToString();string comment=Request.Form["comment"].ToString();string curType=Request.Form["curType"].ToString();string JoinFlag=Request.Form["JoinFlag"].ToString();string merAcct=Request.Form["merAcct"].ToString();string merID=Request.Form["merID"].ToString();string notifyDate=Request.Form["notifyDate"].ToString();string orderDate=Request.Form["orderDate"].ToString();string orderid = Request.Form["orderid"].ToString();string remark1=Request.Form["remark1"].ToString();string remark2=Request.Form["remark2"].ToString();string resultType=Request.Form["resultType"].ToString();string TranSerialNo=Request.Form["TranSerialNo"].ToString();string tranStat=Request.Form["tranStat"].ToString();string UserNum=Request.Form["UserNum"].ToString();string verifyJoinFlag=Request.Form["verifyJoinFlag"].ToString();string interfaceName=Request.Form["interfaceName"].ToString();string interfaceVersion=Request.Form["interfaceVersion"].ToString();string signMsg = Request.Form["signMsg"].ToString();string path1 = "cpublic.crt";string path2 = "icbm.crt";string path3 = "icbm.key";string key = "111111";//下面是银行返回明文的格式string str = "interfaceName="+interfaceName+"&interfaceVersion="+interfaceVersion+"&orderid="+orderid+"&TranSerialNo="+TranSerialNo+"&amount="+amount+"&curType="+curType+"&merID="+merID+"&merAcct="+merAcct+"&verifyJoinFlag="+verifyJoinFlag+"&JoinFlag="+JoinFlag+"&UserNum="+UserNum+"&resultType="+resultType+"&orderDate="+orderDate+"¬ifyDate="+notifyDate+"&tranStat="+tranStat+"&comment="+comment+"&remark1="+remark1+"&remark2="+remark2; if (tranStat == "1") //判断银行处理订单的返回类型,1为支付成功 { ICBCEBANKUTILLib.B2CUtil obj = new ICBCEBANKUTILLib.B2CUtilClass(); obj.init(path1,path2,path3,key); //初始化组件
if ( obj.verifySignC(str,str.Length,signMsg,signMsg.Length) == 0) //判断验证银行签名是否成功 { 这里操作数据库 Response.Write(这里输出支付成功后网站自己的返回地址); } } else { 这里操作数据库 }%>这个页面要注意的是,不能有任何的html标记,只留下代码即可。因为银行有超时限制,所以这个页面操作不要太费时,要尽快结束操作或尽快返回网站地址。由于银行默认80端口,所以网站也要默认是80端口,否则会访问不到这个页面。自己开发时用的是银行提供的测试地址,这种情况有可能出现不返回银行通知的可能。正是环境下没什么问题。