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

本文介绍了三种常见的第三方平台对接方式:通过POST请求上传JSON字符串、以流形式上传JSON字符串及报文透传与socket字符串上传,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在最近的工作中,开始接收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();
			}else
				throw new IOException("Unexpected code " + response);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.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的使用和通讯报文的转换。


    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值