首页 > 代码库 > 工行b2c开发记录-支付、通知接口

工行b2c开发记录-支付、通知接口

    今年接手一项目需要用到网银这块,接触有工行、建行等几家银行,工行网银开发在磕磕碰碰中终于结束了。现在写这个文章主要是记录下开发流程,便于以后翻阅。

一、工行b2c概述

以下简述处理流程:

wKiom1RO89vh8HTsAAGBXxai-68590.jpg

    1.      客户在商户网站浏览商品信息,签订订单;

    2.      商户按照工行B2C支付1.0.0.11接口形成提交数据,并使用工行提供API和商户证书对订单数据签名,形成form表单返回客户浏览器,表单action地址指向工行接收商户订单信息的servlet

    3.      客户确认使用工行支付后,提交此表单到工行;

    4.      工行网银系统接收此笔订单,对订单信息和商户信息进行检查;

    5.      通过检查则显示工行支付页面,1.0.0.11版本会提示客户输入交易卡号;

    6.      客户输入后提交;

    7.      银行查询客户相关信息;

    8.      返回客户在银行的预留信息;

    9.      客户确认;

    10.   返回交易确认页面;

    11.   不同类型客户使用各自认证方式进行交易确认,支持静态支付密码、动态口令卡、证书签名;

    12.   银行校验后进行支付处理;

    13.   工行进行支付指令处理后,如果商户需要工行实时通知,则工行将处理结果使用http协议post方式将通知消息数据提交到商户网站(这个接收银行通知消息的商户端地址是随商户订单数据提交银行的merURL字段),商户返回取货地址或关闭这个银行与其建立的连接后,银行才显示交易结果页面给客户。(注意1、发送通知和显示结果页面是串行的,所以商户端接收银行通知处理时间太长可能导致客户等待超时,造成银行不能将交易结果页面显示给客户。2、此连接是银行服务器自动和商户进行的连接,商户返回也是直接返回给银行,商户端不能对银行的这个请求进行重定向。)

    14.   工行进行支付指令处理后,如果商户不需要工行实时通知,则工行直接显示交易结果给客户。

    
二、“凡事预则立,不预则废”在了解工行b2c大概流程之后,来看两个接口:1、支付接口2、通知接口。

1、支付接口交易数据整合到一个xml格式串,作为表单的一项整体提交,FORM表单数据如下:

变量名称

变量命名

长度定义

说明

接口名称

interfaceName

MAX(30)

必输,

取值:“ICBC_PERBANK_B2C

接口版本号

interfaceVersion

MAX(15)

必输,

取值:“1.0.0.11

交易数据

tranData

无限制

必输,签名;

整合所有交易数据形成的xml明文串,并做BASE64编码;

具体格式定义见下文;

注意:

需有xml头属性;整个字段使用BASE64编码;

xml明文中没有回车换行和多余空格;

订单签名数据

merSignMsg

无限制

必输,

商户使用工行提供的签名API和商户证书将tranDataxml明文串进行签名,得到二进制签名数据,然后进行BASE64编码后得到可视的merSignMsg

注意:签名时是针对tranDataxml明文,不是将tranData进行BASE64编码后的串;

商城证书公钥

merCert

无限制

必输,

商户用二进制方式读取证书公钥文件后,进行BASE64编码后产生的字符串;


tranData数据具体格式定义参考(附件1)中的规则,需要注意的是:

通知类型:支付完成后,需要返回通知就用“HS”;不需要则用“AG”;这点自己在做的时候忽略了,导致接收返回参数时找原因比较痛苦,不提伤心事了。另一个就是

返回商户URL:端口要用80或不指定,必须合法的URL,交易结束,将客户引导到商户的此url,即通过客户浏览器post交易结果信息到商户的此URL,接收到银行信息后处理写法如下(java):

            String ResStr = "http://跳转到处理工行返回参数的地址";
            getResponse().addHeader("HTTP/1.1 200", "OK");
            getResponse().addHeader("Server", "Apache/1.39");
            getResponse().setIntHeader("Content-Length",ResStr.length());
            getResponse().addHeader("Content-type", "text/html");
            getResponse().getWriter().write(ResStr);
            getResponse().flushBuffer();

其他严格按照文档中规定的填写就可以了;

form表单如下:

<FORM action="https:/*****/servlet/NewB2cMerPayReqServlet" method="post" id="goBank" >
    <INPUT NAME="interfaceName" TYPE="hidden" value="http://www.mamicode.com/ICBC_PERBANK_B2C" ><br/>
    <INPUT NAME="interfaceVersion" TYPE="hidden" value="http://www.mamicode.com/1.0.0.11"><br/>
    <INPUT NAME="tranData" TYPE="hidden" value="http://www.mamicode.com/${rdate[0]}"><br/>
    <INPUT NAME="merSignMsg" TYPE="hidden" value="http://www.mamicode.com/${rdate[1]}"><br/>
    <INPUT NAME="merCert" TYPE="hidden" value="http://www.mamicode.com/${rdate[2]}"><br/>
</FORM>

这些数据定义完之后,根据工行提供的例子将交易数据,订单签名数据,商城证书公钥生成好传到前台from表单进行提交就ok了;

    2、通知接口,表单定义如下:(具体参数定义参考附件1文档)

变量名称

变量命名

长度定义

说明

返回商户变量

merVAR

无限制

取值:商户提交接口中merVAR字段当返回银行结果时,作为一个隐藏域变量,商户可以用此变量维护session等等。由客户端浏览器支付完成后提交通知结果时是明文传输,建议商户对此变量使用额外安全防范措施,如签名、base64银行端将此字段原样返回

通知结果数据

notifyData

无限制

银行通知消息,xml格式定义见下文,提交商户时对xml明文串进行了base64编码;

xml串中没有回车换行和多余空格;包含xml头属性,且格式固定;

银行对通知结果的签名数据

signMsg

无限制

银行使用自己证书对商户通知消息notifyData字段的xml格式明文串进行的签名,然后进行BASE64编码后的字符串。

注意:签名是对notifyDataxml明文进行签名,不是其BASE64编码后的串;签名后得到二进制数据,对此数据进行BASE64编码得到signMsg

 这里看到 merVAR 是原样返回的,所以就可以通过此变量进行自定义的验证等;通知结果数据,签名数据都是经过加密的,根据工行提供的解密方法进行解密,之后就能得到想要处理的数据了;

这里主要注意的是证书的选择,一般工行提供的证书是pfx格式,需要使用证书拆分工具将它拆成crt和key密钥在这里使用crt证书就可以;

工行b2c开发记录-支付、通知接口