GPRS前置服务开发——第三方平台对接

来源:互联网 发布:js 报错invalid date 编辑:程序博客网 时间:2024/06/14 18:13

在最近的工作中,开始接收GPRS服务的前置服务业务,其中我做的最多的就是和第三方平台对接。在这里记录下目前遇到的几种第三方平台对接的形式。

(一)将报文数据整理为JSON字符串后以POST请求上传

这里主要根据第三方协议来进行业务代码的编写,传入诶的data为json字符串,url为了方便做成了可配置的方式。这里用到的HttpUtil会在下方贴出

public static String doTransf(String data, String url) {try {url = url + "?" + data;logger.info("向后台服务器url:" + url);String result = HttpUtil.requestPost(url, "");logger.info("后台服务器回复json:" + result);// 接收到的json 需要转成tcp数据if (StringUtil.isNotEmpty(result)) {// 成功HashMap<String, Object> map = JksonUtil.toBean(result, HashMap.class);if (map != null && !map.isEmpty()) {if (map.get("status").toString().equals("200")) {return result;} else {// 失败logger.error("后台服务器返回,错误码:" + map.get("status") + ",错误信息:" + map.get("data"));return null;}} else {logger.error("解析json失败,json字符串为:" + result);}} else {logger.error("请求失败");}} catch (Exception e) {logger.error("请求" + url + "异常:" + e.getMessage());e.printStackTrace();return "";}return "";}
HttpUtil

public class HttpUtil {public static final String GET_TYPE = "GET";public static final String POST_TYPE = "POST";private static MyLogger logger = LogManager.getLogger(HttpUtil.class);public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json;charset=utf-8");public static String requestGet(String url) throws IOException {// 创建一个OkHttpClient对象OkHttpClient okHttpClient = new OkHttpClient();Request request = new Request.Builder().url(url).build();try {Response response = okHttpClient.newCall(request).execute();if (response.isSuccessful()){ return response.body().string();}elsethrow new IOException("Unexpected code " + response);} catch (IOException e) {// TODO Auto-generated catch blocklogger.error("GET请求"+ e.getClass() + "异常:" + e.getMessage());throw e;}}public static String requestPost(String url, String json)throws Exception {try {// 创建一个OkHttpClient对象OkHttpClient okHttpClient = new OkHttpClient();// 创建一个RequestBody(参数1:数据类型 参数2传递的json串)RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json);// 创建一个请求对象Request request = new Request.Builder().url(url).post(requestBody).build();// 发送请求获取响应Response response = okHttpClient.newCall(request).execute();// 判断请求是否成功if (response.isSuccessful()) {// 打印服务端返回结果String result = response.body().string();return result;}else{logger.error("返回错误码:" + response.code()); }} catch (IOException e) {logger.error("POST请求"+ e.getClass() + "异常:" + e.getMessage());throw e;} catch (Exception e){logger.error("POST请求"+ e.getClass() + "异常:" + e.getMessage());throw e;}return "";}public static Response post(String url, String json)throws Exception {try {// 创建一个OkHttpClient对象OkHttpClient okHttpClient = new OkHttpClient();// 创建一个RequestBody(参数1:数据类型 参数2传递的json串)RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json);// 创建一个请求对象Request request = new Request.Builder().url(url).post(requestBody).build();// 发送请求获取响应Response response = okHttpClient.newCall(request).execute();// 判断请求是否成功// 打印服务端返回结果return response;} catch (IOException e) {logger.error("POST请求"+ e.getClass() + "异常:" + e.getMessage());throw e;} catch (Exception e){logger.error("POST请求"+ e.getClass() + "异常:" + e.getMessage());throw e;}}}

(二)将报文数据整理为JSON字符串后以流的形式上传

这里的RequestEntity和ResponseMsg都需要根据协议去定义就不贴出来了。唯一需要注意的是,在回复的json中,可能存在双层嵌套例如:{"data":{"sign":"xxx"},"message":"成功","status":200},则需要在ResponseMsg另外定义一个data实体,然后sign作为其属性即可。此外,一定要记得写get/set方法。

public boolean doUpData(NewWanDaTrade entity){boolean flag = false;String url =PropertiesUtil.getValue("Three_Interface");logger.info("请求地址====>URL:"+url);try {System.out.println("发送的json:"+JksonUtil.toJson(entity));RequestEntity req = new StringRequestEntity(JksonUtil.toJson(entity),"application/json","utf-8");//RequestEntity req = new StringRequestEntity("trade_list:"+JksonUtil.toJson(entity),"application/json","utf-8");HttpClient client =  new HttpClient();//client.getHttpConnectionManager().getParams().setConnectionTimeout(3000);//client.getParams().setSoTimeout(3000);PostMethod post = new PostMethod(url);post.setRequestEntity(req);client.executeMethod(post);String recJson = post.getResponseBodyAsString();logger.info("收到回复====>msg:"+recJson);ResponseMsg res = JksonUtil.toBean(recJson, ResponseMsg.class);//这里的判定条件需要更改if("200".equals(res.getStatus())){flag =  true;logger.warn("<======上传成功!======>");}else{logger.warn("上传失败!收到消息====>:"+res.getMessage());}} catch (IOException e) {logger.error("<======请求失败======>");return flag;}return flag;}

    (三)报文透传(一般用于银联)和socket字符串上传  
    透传的意思就是我们解析出data域中的数据后不做处理,直接通过socket发送到第三方,只需要知道对方的ip和端口就可以了。直接调用下面这个工具就可以,不过需要注意的是,这个工具里面分为发送字符串和byte数组两总形式。在一次项目中,第三方平台只需要报文,而我错传了一次字符(调用的第一个方法),就导致java.net.SocketTimeoutException: Read timed out  这个异常,目前也一直没有时间细想其中原因,当时的想法有如下几种(希望大神看到顺便提点一下!) 
    1、是第三方不接收字符串从而不回复导致我这边接收不到消息,导致我str = reader.readLine();这句话抛出该异常。  
    2、readLine()该方法是根据“\r”,“\n”进行一行读数据的读取,而第三方发送过来的是一个byte数组,导致该方法出现异常。  
    后来我就自己重载了一个可以传byte数组的方法,利用TCP协议的会累计到一定量的数据才会发送的特性,用循环一个个写进去。最后返回的报文需要自己根据协议定义长度,有点不方便,以后有机会优化一下。
    public class SocketUtil {private static final MyLogger logger = LogManager.getLogger(SocketUtil.class);public static String SocketSendAndReseive(long sessionId, String ip, int port, String sendbuff) {String str = "";Socket socket = null;PrintWriter writer = null;BufferedReader reader = null;int timeout = 20;try {socket = new Socket(ip, port);socket.setSoTimeout(timeout * 1000);socket.setReuseAddress(true);writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));writer.write(sendbuff);writer.flush();str = reader.readLine();} catch (BindException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "连接异常, 异常原因:" + e.getMessage());e.printStackTrace();} catch (IOException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "连接失败, 异常原因:" + e.getMessage());e.printStackTrace();} finally {try {if (writer != null) {writer.close();}if (reader != null) {reader.close();}if (socket != null && socket.isConnected()) {socket.close();}} catch (IOException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "关闭连接异常,异常原因" + e.getMessage());}}return str;}public static String SocketSendAndReseive(long sessionId, String ip, int port, byte[] sendbuff) {Socket socket = null;DataOutputStream out = null;BufferedInputStream in = null;int timeout = 10;byte us[] = new byte[31];try {socket = new Socket(ip, port);socket.setSendBufferSize(1024);socket.setReceiveBufferSize(1024);socket.setSoTimeout(timeout * 1000);socket.setReuseAddress(true);out = new DataOutputStream(socket.getOutputStream());in = new BufferedInputStream(socket.getInputStream());for(int i = 0;i < sendbuff.length;i++){out.write(sendbuff[i]);}out.flush(); //得到的us是十进制的字节数组in.read(us, 0, 31);//System.out.println(StringUtils.bytesToHexStr(us));} catch (BindException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "连接异常, 异常原因:" + e.getMessage());e.printStackTrace();} catch (IOException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "连接失败, 异常原因:" + e.getMessage());e.printStackTrace();} finally {try {if (out != null) {out.close();}if (in != null) {in.close();}if (socket != null && socket.isConnected()) {socket.close();}} catch (IOException e) {logger.error("session id:" + sessionId + "," + ip + ":" + port + "关闭连接异常,异常原因" + e.getMessage());}}//需要处理成原16进制字符串return StringUtils.bytesToHexStr(us);}}
    以上是我目前所遇到的几种形式,我在后续的工作中遇到新的情形会持续更新。
    我想我之后的文章会记录一下Mina的使用和通讯报文的转换。


    阅读全文
    0 0
    原创粉丝点击