踩雷:Java发送Get请求给微信获取openID报“java.io.IOException: Invalid Http response”

本文记录了解决微信小程序支付过程中遇到的“传入openid为空”的错误。通过逐步排查,发现是由于openid获取阶段出现了无效HTTP响应。最终通过更换HTTP客户端库及清理入参中的空格解决了问题。

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

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规范一下就好。但是转念一想,我们的发送请求,从地址到入参,哪里来的汉字。但还是开始了一次次的测试,原地打转。最后突然意识到:尼玛空格也是非法字符······(后面不说了,不好意思)

7、果然就是入参空格的问题啦(由于我们的入参都是在平台配置存到数据库,输入或者复制难免有空格)。害,结果还冤枉了HttpURLConnection,不过也留了个心眼,以后从数据库取,参数拿出来一定要先去空格!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值