1、问题描述
最近做小程序的线上支付,跟第三方对接的时候在“微信下单”时一直频繁的报错“传入openid为空”。于是梳理了一下古老的小程序代码,发现openid是在app.js中最先获取并存入缓存,在经过中间一系列无用页面后,在下单时再次取出发送到后台用于微信下单。ok开始分析问题。
2、问题分析:ROUND1
既然进入微信小程序后最先获取openid并存入缓存,微信缓存又有时候不靠谱,会不会是因为中间时间太久,缓存没了??ok开始解决问题
3、问题解决:ROUND1
在app.js中获取到openid后在缓存中和全局变量中各放一份,取出时做非空判断(ps:在获取到openid后打印到控制台)。结果就是ps这一下发现了问题关键所在:::在最开始app.js向程序后端发送请求获取openid时,返回了一个“java.io.IOException: Invalid Http response”。原来不是微信小程序缓存的时效性导致的,是压根就没获取到openid啊!
获取openid代码如下:HttpURLConnection发送(url:获取openid的地址;param:相关入参)
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
logger.info("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
4、问题分析:ROUND2
既然是无效响应,那就干脆换一种发送Get请求的方式(不是懒得扒拉源码哈,后面会说鸡肋的原因,还好没扒拉)。
5、问题解决:ROUND2
提到HTTP请求,就不得不说HttpClient和HttpURLConnection这两大方法:
1、HttpClient:它拥有众多的API,而且实现比较稳定,bug数量也很少。
2、HttpURLConnection:是一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序。API相对HttpClient较为简单,但这也意味着他又良好的可扩展性。(HttpURLConnection一直存在着一些令人厌烦的bug)
简单来说,HttpClient就是一个增强版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做;HttpURLConnection没有提供的有些功能,HttpClient也提供了,但它只是关注于如何发送请求、接收响应,以及管理HTTP连接。
使用HttpClient发送Get请求如下:
// 获得Http客户端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
String result = "";
// 创建Get请求
HttpGet httpGet = new HttpGet(url + "?" + param);
// 响应模型
CloseableHttpResponse response = null;
try {
// 配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间(单位毫秒)
.setConnectTimeout(5000)
// 设置请求超时时间(单位毫秒)
.setConnectionRequestTimeout(5000)
// socket读写超时时间(单位毫秒)
.setSocketTimeout(5000)
// 设置是否允许重定向(默认为true)
.setRedirectsEnabled(true).build();
// 将上面的配置信息 运用到这个Get请求里
httpGet.setConfig(requestConfig);
// 由客户端执行(发送)Get请求
response = httpClient.execute(httpGet);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
result = EntityUtils.toString(responseEntity);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
6、问题频出:RUOND3
报错:Illegal character in query at index 77。
非法字符,首先想到的是汉字问题,这很简单使用URLEncoder.encode规范一下就好。但是转念一想,我们的发送请求,从地址到入参,哪里来的汉字。但还是开始了一次次的测试,原地打转。最后突然意识到:尼玛空格也是非法字符······(后面不说了,不好意思)