|
|
@@ -3,13 +3,24 @@ package com.fs.app.utils;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fs.common.exception.CustomException;
|
|
|
-import com.fs.common.utils.http.HttpUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.http.NoHttpResponseException;
|
|
|
+import org.apache.http.client.config.RequestConfig;
|
|
|
+import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
+import org.apache.http.client.methods.HttpPost;
|
|
|
+import org.apache.http.entity.ContentType;
|
|
|
+import org.apache.http.entity.StringEntity;
|
|
|
+import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
+import org.apache.http.impl.client.HttpClients;
|
|
|
+import org.apache.http.util.EntityUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.SocketTimeoutException;
|
|
|
+
|
|
|
/**
|
|
|
* UniApp 一键登录(univerify)工具类,通过 uniCloud 云函数 URL 化接口换取手机号。
|
|
|
*/
|
|
|
@@ -18,6 +29,10 @@ public class UniVerifyUtil {
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(UniVerifyUtil.class);
|
|
|
|
|
|
+ private static final int CONNECT_TIMEOUT_MS = 10000;
|
|
|
+ private static final int SOCKET_TIMEOUT_MS = 30000;
|
|
|
+ private static final int MAX_RETRY = 2;
|
|
|
+
|
|
|
@Value("${univerify.cloud-function-url:https://env-00jy6gbd2vlk.dev-hz.cloudbasefunction.cn/getLoginMobile}")
|
|
|
private String cloudFunctionUrl;
|
|
|
|
|
|
@@ -36,7 +51,7 @@ public class UniVerifyUtil {
|
|
|
requestBody.put("access_token", accessToken);
|
|
|
requestBody.put("openid", openId);
|
|
|
|
|
|
- String response = HttpUtils.doPost(cloudFunctionUrl, requestBody.toJSONString());
|
|
|
+ String response = postWithRetry(cloudFunctionUrl, requestBody.toJSONString());
|
|
|
log.info("UniVerify 换号响应: {}", response);
|
|
|
if (StringUtils.isBlank(response)) {
|
|
|
throw new CustomException("获取手机号失败");
|
|
|
@@ -77,4 +92,60 @@ public class UniVerifyUtil {
|
|
|
}
|
|
|
return phoneNumber;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 云函数冷启动/开发版休眠时容易出现 NoHttpResponseException,做超时配置和有限重试。
|
|
|
+ */
|
|
|
+ private String postWithRetry(String url, String json) {
|
|
|
+ Exception last = null;
|
|
|
+ for (int attempt = 1; attempt <= MAX_RETRY; attempt++) {
|
|
|
+ try {
|
|
|
+ return doPost(url, json);
|
|
|
+ } catch (NoHttpResponseException | SocketTimeoutException e) {
|
|
|
+ last = e;
|
|
|
+ log.warn("UniVerify 请求无响应或超时,第{}次,url={},err={}", attempt, url, e.getMessage());
|
|
|
+ if (attempt < MAX_RETRY) {
|
|
|
+ try {
|
|
|
+ Thread.sleep(500L * attempt);
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ throw new CustomException("获取手机号被中断");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("UniVerify 请求失败,url={}", url, e);
|
|
|
+ throw new CustomException("一键登录服务暂时不可用,请稍后重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.error("UniVerify 多次请求仍无响应,url={}", url, last);
|
|
|
+ throw new CustomException("一键登录服务无响应,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String doPost(String url, String json) throws IOException {
|
|
|
+ RequestConfig requestConfig = RequestConfig.custom()
|
|
|
+ .setConnectTimeout(CONNECT_TIMEOUT_MS)
|
|
|
+ .setConnectionRequestTimeout(CONNECT_TIMEOUT_MS)
|
|
|
+ .setSocketTimeout(SOCKET_TIMEOUT_MS)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ try (CloseableHttpClient httpClient = HttpClients.custom()
|
|
|
+ .setDefaultRequestConfig(requestConfig)
|
|
|
+ .disableAutomaticRetries()
|
|
|
+ .build()) {
|
|
|
+ HttpPost post = new HttpPost(url);
|
|
|
+ post.setConfig(requestConfig);
|
|
|
+ post.setHeader("Connection", "close");
|
|
|
+ post.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON));
|
|
|
+
|
|
|
+ try (CloseableHttpResponse response = httpClient.execute(post)) {
|
|
|
+ int status = response.getStatusLine().getStatusCode();
|
|
|
+ String body = response.getEntity() == null ? null : EntityUtils.toString(response.getEntity(), "UTF-8");
|
|
|
+ if (status < 200 || status >= 300) {
|
|
|
+ log.error("UniVerify HTTP状态异常: status={}, body={}", status, body);
|
|
|
+ throw new CustomException("一键登录服务返回异常(" + status + ")");
|
|
|
+ }
|
|
|
+ return body;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|