Forráskód Böngészése

update 用户一键登录

ct 2 napja
szülő
commit
5619307ab5

+ 73 - 2
fs-user-app/src/main/java/com/fs/app/utils/UniVerifyUtil.java

@@ -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;
+            }
+        }
+    }
 }