使用java开发工行银企互联中间件(NC方式)以及一些错误总结
2014-07-23 08:42
711 查看
最近公司上了SAP系统,财务那块需要与工行进行银企直连,由于SAP无法使用socket技术,而工行的签名还必须使用socket技术,所以我们使用Grails开发了工行的银企互联中间件,供SAP调用访问工行数据。
下面是中间件中的主要代码:
/**
* @Description 工行银企直连接口
* @param id 证书ID
* @param TransCode 交易代码
* @param BankCode 归属银行编号
* @param GroupCIS 集团CIS号
* @param packageId 指令包序列号
* @param sendTime 请求时间
* @param Cert 传空
* @param reqData xml请求字符串
* @param checkFlag 签名标志 ‘0’ 不需签名; ‘1’需要签名
* @param version http协议版本号 ‘0.0.1.0’或 ‘0.0.0.1’
* @return 首先判断是否成功,判定成功后解析xml字符串 。判定是否成功的条件为:返回的字符串中包含“ERRORCODE=”为失败;不包含“ERRORCODE=”为成功
*/
@WebMethod
@WebResult
String send(@WebParam String id,@WebParam String TransCode,@WebParam String BankCode,@WebParam String GroupCIS,@WebParam String packageId,@WebParam String sendTime,@WebParam String Cert,@WebParam String reqData,@WebParam String checkFlag,@WebParam String
version)
{
println reqData
println version
String resultTag=""
String encoding = "GBK";
def url="http://192.168.101.110:448/servlet/ICBCCMPAPIReqServlet?userID=${id}&PackageID=${packageId}&SendTime=${sendTime}"
if("1".equals(checkFlag)){
reqData=commonService.check(reqData,encoding)
}
println reqData
def responseString=""
NameValuePair[] params = new NameValuePair[9];
params[0]=new NameValuePair('Version',version)
params[1]=new NameValuePair('TransCode',TransCode)
params[2]=new NameValuePair('BankCode',BankCode)
params[3]=new NameValuePair('GroupCIS',GroupCIS)
params[4]=new NameValuePair('PackageID',packageId)
params[5]=new NameValuePair('Cert',Cert)
params[6]=new NameValuePair('reqData',reqData)
params[7]=new NameValuePair('ID',id)
params[8]=new NameValuePair('Content-Type',"application/x-www-form-urlencoded")
PostMethod postRequest = new PostMethod(url.trim());
postRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
HttpMethodParams p=new HttpMethodParams()
p.setVersion(HttpVersion.HTTP_1_1)
postRequest.setParams(p)
postRequest.setRequestBody(params);
responseString = commonService.executeMethod(postRequest,encoding);
if(!responseString ||responseString.toUpperCase().startsWith("ERRORCODE=")){
resultTag= responseString
}else{
responseString = responseString.substring(8,responseString.length())
resultTag=commonService.getContentFromBASE64(responseString)
}
resultTag=resultTag.replaceAll(" ","")
resultTag=resultTag.replaceAll("\u0000","")
println resultTag
return resultTag;
}
package cn.com.wz
import org.apache.commons.httpclient.Header
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.HttpException
import org.apache.commons.httpclient.SimpleHttpConnectionManager
import org.apache.commons.httpclient.methods.PostMethod
class CommonService {
/**
* @Description 执行post方法
* @param s
* @return
* @Create huxx 2014-07-15
*/
String executeMethod(PostMethod request, String encoding) throws Exception{
String responseContent = null;
InputStream responseStream = null;
BufferedReader rd = null;
//超时间隔
int connectTimeOut = 60000;
//让connectionmanager管理httpclientconnection时是否关闭连接
boolean alwaysClose = false;
//返回数据编码格式
HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));
try {
client.executeMethod(request);
if(encoding != null){
responseStream = request.getResponseBodyAsStream();
rd = new BufferedReader(new InputStreamReader(responseStream,
encoding));
String tempLine = rd.readLine();
StringBuffer tempStr = new StringBuffer();
String crlf=System.getProperty("line.separator");
while (tempLine != null)
{
tempStr.append(tempLine);
tempStr.append(crlf);
tempLine = rd.readLine();
}
responseContent = tempStr.toString();
}else
responseContent = request.getResponseBodyAsString();
Header locationHeader = request.getResponseHeader("location");
//返回代码为302,301时,表示页面己经重定向,则重新请求location的url,这在
//一些登录授权取cookie时很重要
if (locationHeader != null) {
return "500"
}
} catch (HttpException e) {
throw new Exception(e.getMessage());
} catch (IOException e) {
throw new Exception(e.getMessage());
} finally{
if(rd != null)
try {
rd.close();
} catch (IOException e) {
throw new Exception(e.getMessage());
}
if(responseStream != null)
try {
responseStream.close();
} catch (IOException e) {
throw new Exception(e.getMessage());
}
}
return responseContent;
}
/**
* @Description 使用base64对返回内容解密
* @param s
* @return
* @Create huxx 2014-07-15
*/
public String getContentFromBASE64(String s) {
if (s == null)
return null;
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
try {
def dd=decoder.decodeBuffer(s)
return new String(dd,"GBK")
} catch (Exception e) {
return null;
}
}
/**
* @Description 对xml包签名
* @param s
* @return
* @Create huxx 2014-07-15
*/
def check( def reqData,String encoding){
String result=""
def path="http://192.168.101.110:449"
def host="192.168.101.110"
def port="449"
Socket socket = new Socket()
BufferedReader bufferedReader;
BufferedWriter bufferedWriter;
try {
// def data=URLEncoder.encode(reqData,encoding)
def data=reqData
// socket=new Socket("192.168.101.110",449);// 建立连接,哪个ip,哪个端口号
SocketAddress dest = new InetSocketAddress("192.168.101.110", 449);
socket.connect(dest,0);
socket.setKeepAlive(true)
// 建立写入流,输出流,向服务器写数据,得到服务器回应
OutputStream out = socket.getOutputStream();
OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), encoding);
bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("POST " + path + " HTTP/1.1\r\n");
bufferedWriter.write("Host: " + host + "\r\n");
println data.length()
bufferedWriter.write("Content-Length: " + data.length() + "\r\n");
bufferedWriter.write("Content-Type: INFOSEC_SIGN/1.0\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.write(data);
bufferedWriter.flush();
def is =socket.getInputStream()
BufferedInputStream streamReader = new BufferedInputStream(is);
bufferedReader = new BufferedReader(new InputStreamReader(streamReader, encoding));
String line = null;
line = bufferedReader.readLine()
def flag=0
while((line!= null))
{
if(line.toUpperCase().indexOf("<SIGN>")>=0){
flag=1
}
if(line.toUpperCase().indexOf("</SIGN>")>=0){
flag=0
break
}
if(flag ==1){
result+=line
}
line = bufferedReader.readLine()
}
System.out.println(result);
out.close()
is.close()
} catch (Exception e) {
e.printStackTrace();
e.cause?.printStackTrace()
} finally {
try {
if (socket != null) {
socket.close();
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
//判断签名是否成功
result=result.replace("<sign>","")
return result
}
}
使用这几个方法基本就能正常向NC发送数据了。
在使用NC方式时,一个很重要的调试方法是查看NC产生的httpinfo.txt和signinfo.txt两个日志文件。通过日志文件可以查看我们传入的参数是否正确或缺失。
下面是我开发过程中遇到的一些不好理解的问题总结:
一、<RetCode>10385</RetCode><RetMsg>com.icbc.cmp.base.TranFailException:[4066]码制转换错误,网关对前台上送字段转换错</RetMsg>
此错误是由于传到工行的数据不完整或格式不对
我遇到的情况有:
1、post提交时 Version值(0.0.1.0或0.0.0.1)传送错误。(我犯的错误是在Version首字母没有大写,导致Version参数没有传过去 )
2、柜员号前面不能补0。工行给的接口说明中此字段是5位,如果柜员号为12 xml中必须写12 不可以写00012.
二、非账户管家无需上送序号 xml中的AcctSeq(账号序号)不要输入值
下面是中间件中的主要代码:
/**
* @Description 工行银企直连接口
* @param id 证书ID
* @param TransCode 交易代码
* @param BankCode 归属银行编号
* @param GroupCIS 集团CIS号
* @param packageId 指令包序列号
* @param sendTime 请求时间
* @param Cert 传空
* @param reqData xml请求字符串
* @param checkFlag 签名标志 ‘0’ 不需签名; ‘1’需要签名
* @param version http协议版本号 ‘0.0.1.0’或 ‘0.0.0.1’
* @return 首先判断是否成功,判定成功后解析xml字符串 。判定是否成功的条件为:返回的字符串中包含“ERRORCODE=”为失败;不包含“ERRORCODE=”为成功
*/
@WebMethod
@WebResult
String send(@WebParam String id,@WebParam String TransCode,@WebParam String BankCode,@WebParam String GroupCIS,@WebParam String packageId,@WebParam String sendTime,@WebParam String Cert,@WebParam String reqData,@WebParam String checkFlag,@WebParam String
version)
{
println reqData
println version
String resultTag=""
String encoding = "GBK";
def url="http://192.168.101.110:448/servlet/ICBCCMPAPIReqServlet?userID=${id}&PackageID=${packageId}&SendTime=${sendTime}"
if("1".equals(checkFlag)){
reqData=commonService.check(reqData,encoding)
}
println reqData
def responseString=""
NameValuePair[] params = new NameValuePair[9];
params[0]=new NameValuePair('Version',version)
params[1]=new NameValuePair('TransCode',TransCode)
params[2]=new NameValuePair('BankCode',BankCode)
params[3]=new NameValuePair('GroupCIS',GroupCIS)
params[4]=new NameValuePair('PackageID',packageId)
params[5]=new NameValuePair('Cert',Cert)
params[6]=new NameValuePair('reqData',reqData)
params[7]=new NameValuePair('ID',id)
params[8]=new NameValuePair('Content-Type',"application/x-www-form-urlencoded")
PostMethod postRequest = new PostMethod(url.trim());
postRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
HttpMethodParams p=new HttpMethodParams()
p.setVersion(HttpVersion.HTTP_1_1)
postRequest.setParams(p)
postRequest.setRequestBody(params);
responseString = commonService.executeMethod(postRequest,encoding);
if(!responseString ||responseString.toUpperCase().startsWith("ERRORCODE=")){
resultTag= responseString
}else{
responseString = responseString.substring(8,responseString.length())
resultTag=commonService.getContentFromBASE64(responseString)
}
resultTag=resultTag.replaceAll(" ","")
resultTag=resultTag.replaceAll("\u0000","")
println resultTag
return resultTag;
}
package cn.com.wz
import org.apache.commons.httpclient.Header
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.HttpException
import org.apache.commons.httpclient.SimpleHttpConnectionManager
import org.apache.commons.httpclient.methods.PostMethod
class CommonService {
/**
* @Description 执行post方法
* @param s
* @return
* @Create huxx 2014-07-15
*/
String executeMethod(PostMethod request, String encoding) throws Exception{
String responseContent = null;
InputStream responseStream = null;
BufferedReader rd = null;
//超时间隔
int connectTimeOut = 60000;
//让connectionmanager管理httpclientconnection时是否关闭连接
boolean alwaysClose = false;
//返回数据编码格式
HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));
try {
client.executeMethod(request);
if(encoding != null){
responseStream = request.getResponseBodyAsStream();
rd = new BufferedReader(new InputStreamReader(responseStream,
encoding));
String tempLine = rd.readLine();
StringBuffer tempStr = new StringBuffer();
String crlf=System.getProperty("line.separator");
while (tempLine != null)
{
tempStr.append(tempLine);
tempStr.append(crlf);
tempLine = rd.readLine();
}
responseContent = tempStr.toString();
}else
responseContent = request.getResponseBodyAsString();
Header locationHeader = request.getResponseHeader("location");
//返回代码为302,301时,表示页面己经重定向,则重新请求location的url,这在
//一些登录授权取cookie时很重要
if (locationHeader != null) {
return "500"
}
} catch (HttpException e) {
throw new Exception(e.getMessage());
} catch (IOException e) {
throw new Exception(e.getMessage());
} finally{
if(rd != null)
try {
rd.close();
} catch (IOException e) {
throw new Exception(e.getMessage());
}
if(responseStream != null)
try {
responseStream.close();
} catch (IOException e) {
throw new Exception(e.getMessage());
}
}
return responseContent;
}
/**
* @Description 使用base64对返回内容解密
* @param s
* @return
* @Create huxx 2014-07-15
*/
public String getContentFromBASE64(String s) {
if (s == null)
return null;
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
try {
def dd=decoder.decodeBuffer(s)
return new String(dd,"GBK")
} catch (Exception e) {
return null;
}
}
/**
* @Description 对xml包签名
* @param s
* @return
* @Create huxx 2014-07-15
*/
def check( def reqData,String encoding){
String result=""
def path="http://192.168.101.110:449"
def host="192.168.101.110"
def port="449"
Socket socket = new Socket()
BufferedReader bufferedReader;
BufferedWriter bufferedWriter;
try {
// def data=URLEncoder.encode(reqData,encoding)
def data=reqData
// socket=new Socket("192.168.101.110",449);// 建立连接,哪个ip,哪个端口号
SocketAddress dest = new InetSocketAddress("192.168.101.110", 449);
socket.connect(dest,0);
socket.setKeepAlive(true)
// 建立写入流,输出流,向服务器写数据,得到服务器回应
OutputStream out = socket.getOutputStream();
OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), encoding);
bufferedWriter = new BufferedWriter(streamWriter);
bufferedWriter.write("POST " + path + " HTTP/1.1\r\n");
bufferedWriter.write("Host: " + host + "\r\n");
println data.length()
bufferedWriter.write("Content-Length: " + data.length() + "\r\n");
bufferedWriter.write("Content-Type: INFOSEC_SIGN/1.0\r\n");
bufferedWriter.write("\r\n");
bufferedWriter.write(data);
bufferedWriter.flush();
def is =socket.getInputStream()
BufferedInputStream streamReader = new BufferedInputStream(is);
bufferedReader = new BufferedReader(new InputStreamReader(streamReader, encoding));
String line = null;
line = bufferedReader.readLine()
def flag=0
while((line!= null))
{
if(line.toUpperCase().indexOf("<SIGN>")>=0){
flag=1
}
if(line.toUpperCase().indexOf("</SIGN>")>=0){
flag=0
break
}
if(flag ==1){
result+=line
}
line = bufferedReader.readLine()
}
System.out.println(result);
out.close()
is.close()
} catch (Exception e) {
e.printStackTrace();
e.cause?.printStackTrace()
} finally {
try {
if (socket != null) {
socket.close();
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
//判断签名是否成功
result=result.replace("<sign>","")
return result
}
}
使用这几个方法基本就能正常向NC发送数据了。
在使用NC方式时,一个很重要的调试方法是查看NC产生的httpinfo.txt和signinfo.txt两个日志文件。通过日志文件可以查看我们传入的参数是否正确或缺失。
下面是我开发过程中遇到的一些不好理解的问题总结:
一、<RetCode>10385</RetCode><RetMsg>com.icbc.cmp.base.TranFailException:[4066]码制转换错误,网关对前台上送字段转换错</RetMsg>
此错误是由于传到工行的数据不完整或格式不对
我遇到的情况有:
1、post提交时 Version值(0.0.1.0或0.0.0.1)传送错误。(我犯的错误是在Version首字母没有大写,导致Version参数没有传过去 )
2、柜员号前面不能补0。工行给的接口说明中此字段是5位,如果柜员号为12 xml中必须写12 不可以写00012.
二、非账户管家无需上送序号 xml中的AcctSeq(账号序号)不要输入值
相关文章推荐
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
- Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结 java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错
- 工行银企互联遇到的一些问题总结
- Java开发中一些必备经典Eclipse插件以及使用集萃
- winform开发 总结1>winform程序使用线程的必要性,以及正确的使用方式
- EVC开发环境以及使用pocket pc的一些总结
- 使用Eclipse3.2.1+STP.0.4.0+Apache Tuscany开发SCA的Java组件(4)安装运行错误问题修正篇
- Zend Studio以及开发框架(引擎)使用上的个人总结(无参考价值、个人备忘)
- Java写的手机计费系统(作为学习参考的实例:关键是Java类库里面的date和Calendar的使用和相互转换,以及一些日期的实际问题)
- 对近期使用Nhibernate开发的一个项目的一些总结(一)
- java 开发小记:如何使用 MyEclipse 开发自己的类库(mylib.jar)以及引用(使用)她
- 【转载】JAVA 开发工具Jcreator使用技巧总结
- 最近工作中犯的一些错误,以及总结的体会
- 最近一些RAC使用中的错误提示(总结一下放在这里)
- xmlbeans 使用 以及 java.io.IOException CreateProcess error=2错误处理(转)
- 使用Spring、Hibernate、Struts的一些错误总结(转)
- java 反射的一些使用总结
- sql语句中导致索引失败的一些错误使用方式
- 原创:关于一些Java开发工具的使用心得(不断更新)