准备工作
需要启动NC,然后启动NC里面的Https客户端服务和签名服务。
然后需要确认下NC中间件是启动的,这个上一篇已经说过了。
创建项目
创建web项目或者java控制台项目均可,此处随便创建一个Java Project,并创建一个Test类用于测试,如下图:
查看接口文档
申请银企互联通过后,工行一般会发给接口文档,给我的是每个接口一个excel文件如下:
我们打开《查询当日明细.xls》文件,分析下参数:
- 交易代码:这个地方写死QPD即可
- 集团CIS号:这个就是前文提到的客户编号,这个需要问下工行
- 归属银行编号:这个应该是开户行的机构编号,也是需要问下工行工作人员
- 证书ID:再次出现证书ID了,这个就是类似于FangNC3.y.1102的文本
- 交易日期:NC中间件已经帮我们封装了,此处填写NotCare即可
- 交易时间:NC中间件已经帮我们封装了,此处填写NotCare即可
- 指令包序列号:NC中间件已经帮我们封装了,此处填写01即可
- 查询账号:这个是要查询的对公账号
- 地区代码:区域号,一般为四位,这个需要问下工行工作人员
- 发生额下限:填写0即可
- 发生额上线:填写0即可
- 其余选填项,填空即可
大部分都好理解,有个NC中间件已经封装的,解释如下,详细解释地址
完整的XML报文中关键信息说明:
1)、CIS、ID 将与Web.Config中的信息做校验。
2)、TranDate、TranTime、SignTime 等用户输入值将被忽略,由程序自动填充。
3)、如 XML中fSeqno长度<=3,则程序会使用自己产生的流水号。
个人建议:查询类的报文该字段可以空白或输入长度小于3的内容,交易类的请指定fseqno 内容(长度>3),避免发送请求后没有接收到回执而无从判断银行究竟接收到了指令没有。
4)、支持压缩模式提交大批量指令:rd 最外层头尾套<zip>、</zip>即可,比如:……<zip><rd>……</rd>……<rd>……</rd></zip>……
5)、程序自动替换内容的空白节点请使用<node></node>这种格式,如果写成<node/>这种,程序无法自动填充其数值。TranDate、TranTime、SignTime等字段,程序将自动补充,为避免部分系统自动将<TranDate></TranDate>变成<TranDate/>这种格式,可以随意输入些内容,比如<TranDate>NotCare</TranDate>。
编写程序
按照DEMO编写程序即可,如下所示:
package org.panda.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Base64;
public class Test {
//测试入口
public static void main(String[] args) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
String xml_text = "<?xml version=\"1.0\"encoding=\"GBK\"?>"
+ "<CMS>"
+ "<eb>"
+ "<pub>"
+ "<TransCode>QPD</TransCode>"
+ "<CIS>xxxx</CIS>" //注意此处填写真实CIS
+ "<BankCode>xxxx</BankCode>" //注意此处填写真实BankCode
+ "<ID>xxxx</ID>" //注意此处填写真实证书ID
+ "<TranDate>NotCare</TranDate>"
+ "<TranTime>NotCare</TranTime>"
+ "<fSeqno>01</fSeqno>"
+ "</pub>"
+ "<in>"
+ "<AccNo>xxxx</AccNo>" //注意此处填写真实账号
+ "<AreaCode>xxxx</AreaCode>" //注意此处填写地区编号
+ "<MinAmt>0</MinAmt>"
+ "<MaxAmt>0</MaxAmt>"
+ "<BeginTime></BeginTime>"
+ "<EndTime></EndTime>"
+ "<NextTag></NextTag>"
+ "<ReqReserved1></ReqReserved1>"
+ "<ReqReserved2></ReqReserved2>"
+ "<CurrType></CurrType>"
+ "<AcctSeq></AcctSeq>"
+ "</in>"
+ "</eb>"
+ "</CMS>";
byte[] textByte = xml_text.getBytes("GBK");
String encodedText = encoder.encodeToString(textByte);
String retMsg = sendPost("http://192.168.20.2:666/WebService.asmx/ICBC_YQHL","ver=0.0.1.0&b64_xml=" + encodedText);//注意此处192.168.20.2应填写真实NC中间件设备地址
int p1 = retMsg.indexOf("ReqResult=");
int p2 = retMsg.indexOf("</string>");
String realMsg=new String(decoder.decode(retMsg.substring(p1+10,p2)),"GBK");
System.out.println(realMsg);
}
//发送Http请求
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}
查看结果
如下图:RetCode为0,应该是表示返回成功了,后面还有一大片报文,excel文件里面描述的很清楚了,按照描述对xml报文进行处理即可。