Преглед изворни кода

多租户场景下必须每次请求时根据当前租户重建 WxMpService

xw пре 1 недеља
родитељ
комит
2f1f0866b7

+ 25 - 6
fs-user-app/src/main/java/com/fs/app/controller/store/WxH5MpScrmController.java

@@ -9,6 +9,7 @@ import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
+import com.fs.core.config.WxMpProperties;
 import com.fs.course.domain.FsUserCompanyUser;
 import com.fs.course.mapper.FsCourseWatchLogMapper;
 import com.fs.his.domain.FsUser;
@@ -49,6 +50,13 @@ public class WxH5MpScrmController {
     @Autowired
     private WxMpService wxMpService;
 
+    /**
+     * 注: WxMpProperties 内部从 ThreadLocal/DB 读当前租户配置, 必须每次请求时通过它创建 WxMpService,
+     * 不能直接复用上面那个 @Autowired 的 wxMpService(它是启动时就固化好的实例,多租户场景下永远是默认配置)
+     */
+    @Autowired
+    private WxMpProperties wxMpProperties;
+
     @Autowired
     private IFsUserScrmService userService;
 
@@ -72,13 +80,22 @@ public class WxH5MpScrmController {
     @ApiOperation("课程分享链接公众号登录")
     @PostMapping("/loginByMp")
     public R loginByMp(@Valid @RequestBody FsUserLoginByMpParam param) throws WxErrorException {
-        log.info("=====================进入小程序授权登录, 入参: {}", param);
+        log.info("=====================进入公众号授权登录, 入参: {}", param);
 
         // 参数校验
         if (StringUtils.isBlank(param.getCode())) {
             return R.error("code不存在");
         }
 
+        // 多租户场景下必须每次请求时根据当前租户重建 WxMpService,
+        WxMpService tenantWxMpService;
+        try {
+            tenantWxMpService = wxMpProperties.createFirstWxMpService();
+        } catch (Exception ex) {
+            log.error("创建租户 WxMpService 失败: {}", ex.getMessage(), ex);
+            return R.error("当前租户未配置公众号: " + ex.getMessage());
+        }
+
         // 公司状态校验
         Company company = companyService.selectCompanyById(param.getCompanyId());
         if (company == null || company.getStatus() == 0) {
@@ -92,10 +109,8 @@ public class WxH5MpScrmController {
         }
 
         try {
-            // 获取微信用户信息
-            WxOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(param.getCode());
-            WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
-
+            WxOAuth2AccessToken wxMpOAuth2AccessToken = tenantWxMpService.getOAuth2Service().getAccessToken(param.getCode());
+            WxOAuth2UserInfo wxMpUser = tenantWxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
 
             // 处理用户信息
             FsUserScrm user = processUserInfo(wxMpUser, company,companyUser,param);
@@ -117,7 +132,11 @@ public class WxH5MpScrmController {
 
 
         } catch (WxErrorException e) {
-            this.logger.error(e.getMessage(), e);
+            int errCode = e.getError() != null ? e.getError().getErrorCode() : 0;
+            this.logger.error("微信授权失败 errCode={}, code={}, msg={}", errCode, param.getCode(), e.getMessage(), e);
+            if (errCode == 40029) {
+                return R.error(40029, "授权 code 已失效, 请重新打开页面授权");
+            }
             return R.error("授权失败," + e.getMessage());
         }
     }

+ 1 - 1
fs-user-app/src/main/java/com/fs/framework/filter/AppTenantSwitchFilter.java

@@ -74,11 +74,11 @@ public class AppTenantSwitchFilter extends OncePerRequestFilter {
                                     HttpServletResponse response,
                                     FilterChain filterChain) throws ServletException, IOException {
         String tenantCode = request.getHeader(HEADER_TENANT_CODE);
+        String requestPath = request.getRequestURI();
 
         try {
             String loginPath = "/store/app/pay/hfPayNotify";
             AntPathMatcher pathMatcher = new AntPathMatcher();
-            String requestPath = request.getRequestURI();
             // 汇付回调接口,从参数里面拿租户编码
             if (pathMatcher.match(loginPath, requestPath)) {
                 String respData = request.getParameter("resp_data");