您的位置:首页 > 编程语言 > Java开发

使用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(账号序号)不要输入值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐