From fa232086731fbabcb6df070246d1b09f68930096 Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期三, 12 八月 2026 15:19:49 +0800
Subject: [PATCH] fix(config): 更新开发环境基础URL并优化界面显示

---
 talent-card-server/src/main/java/com/talentcard/server/business/auth/WeChatMiniProgramClient.java |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/auth/WeChatMiniProgramClient.java b/talent-card-server/src/main/java/com/talentcard/server/business/auth/WeChatMiniProgramClient.java
index 926a263..de71ca9 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/auth/WeChatMiniProgramClient.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/auth/WeChatMiniProgramClient.java
@@ -45,8 +45,14 @@
     }
 
     public String exchangePhoneNumber(String code) {
-        String token = clientAccessToken();
+        String token = clientAccessToken(false);
         Map<String, Object> response = post("/wxa/business/getuserphonenumber?access_token=" + encode(token), Map.of("code", code.trim()));
+        // 微信返回 40001 时,缓存的 access_token 可能已被其它实例刷新。使用稳定
+        // 令牌接口强制刷新一次并重试,避免把令牌问题误报成手机号授权失效。
+        if (number(response.get("errcode"), 0) == 40001) {
+            token = clientAccessToken(true);
+            response = post("/wxa/business/getuserphonenumber?access_token=" + encode(token), Map.of("code", code.trim()));
+        }
         ensureSuccess(response, "手机号授权已失效,请重新授权");
         Object phoneInfo = response.get("phone_info");
         if (!(phoneInfo instanceof Map<?, ?> raw)) throw new BusinessException(ErrorCode.CONFLICT, "未获取到微信手机号,请重新授权");
@@ -56,16 +62,24 @@
         return phone;
     }
 
-    private String clientAccessToken() {
+    private String clientAccessToken(boolean forceRefresh) {
         long now = System.currentTimeMillis();
-        if (!accessToken.isBlank() && now < accessTokenExpiresAt) return accessToken;
+        if (!forceRefresh && !accessToken.isBlank() && now < accessTokenExpiresAt) return accessToken;
         synchronized (this) {
             now = System.currentTimeMillis();
-            if (!accessToken.isBlank() && now < accessTokenExpiresAt) return accessToken;
-            Map<String, Object> response = get("/cgi-bin/token", Map.of(
-                    "grant_type", "client_credential",
+            if (!forceRefresh && !accessToken.isBlank() && now < accessTokenExpiresAt) return accessToken;
+            Map<String, Object> response = post("/cgi-bin/stable_token", Map.of(
                     "appid", required(properties.getAppId()),
-                    "secret", required(properties.getAppSecret())));
+                    "secret", required(properties.getAppSecret()),
+                    "grant_type", "client_credential",
+                    "force_refresh", forceRefresh));
+            // 兼容旧微信接口/网关:稳定令牌接口不可用时再回退到旧接口。
+            if (number(response.get("errcode"), 0) != 0 && !forceRefresh) {
+                response = get("/cgi-bin/token", Map.of(
+                "grant_type", "client_credential",
+                "appid", required(properties.getAppId()),
+                "secret", required(properties.getAppSecret())));
+            }
             ensureSuccess(response, "微信服务暂不可用,请稍后重试");
             String token = text(response.get("access_token"));
             long expiresIn = number(response.get("expires_in"), 7200);

--
Gitblit v1.7.1