From 6ad7a6330add80e0b5a83227888df95e92d7ba87 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期二, 07 四月 2026 21:13:07 +0800
Subject: [PATCH] feat:微信登录

---
 tcm-training-admin-backend/src/test/java/com/tcm/training/admin/app/auth/service/AppAuthServiceTest.java |   84 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/tcm-training-admin-backend/src/test/java/com/tcm/training/admin/app/auth/service/AppAuthServiceTest.java b/tcm-training-admin-backend/src/test/java/com/tcm/training/admin/app/auth/service/AppAuthServiceTest.java
index 8330da4..984e318 100644
--- a/tcm-training-admin-backend/src/test/java/com/tcm/training/admin/app/auth/service/AppAuthServiceTest.java
+++ b/tcm-training-admin-backend/src/test/java/com/tcm/training/admin/app/auth/service/AppAuthServiceTest.java
@@ -2,11 +2,11 @@
 
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.tcm.training.admin.app.auth.dto.AppPasswordLoginRequest;
 import com.tcm.training.admin.app.auth.dto.AppPasswordResetRequest;
 import com.tcm.training.admin.app.auth.dto.AppPasswordResetVerifyRequest;
 import com.tcm.training.admin.app.auth.dto.AppSmsCodeSendRequest;
+import com.tcm.training.admin.app.auth.dto.AppWechatLoginRequest;
 import com.tcm.training.admin.app.auth.vo.AppLoginResponse;
 import com.tcm.training.admin.app.auth.vo.AppPasswordResetVerifyResponse;
 import com.tcm.training.admin.app.auth.vo.AppSmsCodeSendResponse;
@@ -31,10 +31,12 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -63,6 +65,9 @@
     private AppAuthSessionService appAuthSessionService;
 
     @Mock
+    private AppWechatAuthClient appWechatAuthClient;
+
+    @Mock
     private StringRedisTemplate stringRedisTemplate;
 
     @Mock
@@ -83,6 +88,7 @@
                 appSmsCodeService,
                 passwordEncoder,
                 appAuthSessionService,
+                appWechatAuthClient,
                 stringRedisTemplate
         );
     }
@@ -213,6 +219,82 @@
     }
 
     /**
+     * 微信已绑定用户登录时应更新微信资料并返回统一登录响应。
+     */
+    @Test
+    void wechatLoginShouldReuseExistingUser() {
+        AppWechatLoginRequest request = new AppWechatLoginRequest();
+        request.setAccessToken("access-token");
+        request.setOpenid("openid-1");
+
+        AppWechatUserProfile profile = new AppWechatUserProfile();
+        profile.setOpenid("openid-1");
+        profile.setNickname("微信昵称");
+        profile.setAvatar("https://cdn.example/avatar.png");
+        profile.setSex(2);
+
+        AppUser user = buildEnabledUser("13800138000", "ENCODED");
+        user.setWechatOpenid("openid-1");
+        user.setNickname(null);
+        user.setAvatar(null);
+
+        SaTokenInfo tokenInfo = new SaTokenInfo();
+        tokenInfo.setTokenValue("wechat-token");
+        tokenInfo.setTokenTimeout(7200L);
+
+        when(appWechatAuthClient.resolveUserProfile(request)).thenReturn(profile);
+        when(userMapper.selectOne(any())).thenReturn(user);
+        when(appAuthSessionService.getTokenInfo()).thenReturn(tokenInfo);
+
+        AppLoginResponse response = appAuthService.wechatLogin(request);
+
+        verify(userMapper).updateById(appUserCaptor.capture());
+        verify(userMapper, never()).insert(any());
+        assertEquals("openid-1", appUserCaptor.getValue().getWechatOpenid());
+        assertEquals("微信昵称", appUserCaptor.getValue().getNickname());
+        assertEquals("https://cdn.example/avatar.png", appUserCaptor.getValue().getAvatar());
+        assertEquals(Integer.valueOf(0), appUserCaptor.getValue().getGender());
+        assertEquals("微信昵称", response.getUser().getNickname());
+        assertEquals("https://cdn.example/avatar.png", response.getUser().getAvatar());
+    }
+
+    /**
+     * 微信首次登录时应自动创建普通用户并返回统一登录响应。
+     */
+    @Test
+    void wechatLoginShouldCreateUserWhenOpenidNotExists() {
+        AppWechatLoginRequest request = new AppWechatLoginRequest();
+        request.setAccessToken("access-token");
+        request.setOpenid("openid-new");
+
+        AppWechatUserProfile profile = new AppWechatUserProfile();
+        profile.setOpenid("openid-new");
+        profile.setNickname("新微信用户");
+        profile.setAvatar("https://cdn.example/new-avatar.png");
+        profile.setSex(1);
+
+        SaTokenInfo tokenInfo = new SaTokenInfo();
+        tokenInfo.setTokenValue("new-token");
+        tokenInfo.setTokenTimeout(7200L);
+
+        when(appWechatAuthClient.resolveUserProfile(request)).thenReturn(profile);
+        when(userMapper.selectOne(any())).thenReturn(null);
+        when(appAuthSessionService.getTokenInfo()).thenReturn(tokenInfo);
+
+        AppLoginResponse response = appAuthService.wechatLogin(request);
+
+        verify(userMapper).insert(appUserCaptor.capture());
+        verify(userMapper, never()).updateById(any());
+        assertNull(appUserCaptor.getValue().getPhone());
+        assertEquals("openid-new", appUserCaptor.getValue().getWechatOpenid());
+        assertEquals("新微信用户", appUserCaptor.getValue().getNickname());
+        assertEquals("https://cdn.example/new-avatar.png", appUserCaptor.getValue().getAvatar());
+        assertEquals(Integer.valueOf(1), appUserCaptor.getValue().getGender());
+        assertEquals(Integer.valueOf(0), appUserCaptor.getValue().getType());
+        assertEquals("new-token", response.getToken());
+    }
+
+    /**
      * 统一构造启用中的 APP 用户测试桩。
      */
     private AppUser buildEnabledUser(String phone, String password) {

--
Gitblit v1.7.1