liujie
2026-07-29 c560a88ab429cd164d8eb6fcec42a273b898e230
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.tourguide.api.mini;
 
import com.tourguide.common.api.ApiResponse;
import com.tourguide.integration.wechat.WechatMiniProgramClient;
import com.tourguide.integration.wechat.WechatPhoneAuthorization;
import com.tourguide.modules.user.domain.ClientType;
import com.tourguide.modules.user.dto.AuthResponse;
import com.tourguide.modules.user.dto.MiniUserResponse;
import com.tourguide.modules.user.dto.WechatPhoneLoginRequest;
import com.tourguide.modules.user.service.AuthService;
import com.tourguide.modules.user.service.MiniAccountService;
import com.tourguide.security.AppUserPrincipal;
import com.tourguide.security.BearerTokenResolver;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
 
/**
 * 游客小程序认证接口。
 * 通过微信登录凭证和手机号授权完成身份识别,仅签发和接收 MINI 客户端类型 Token。
 */
@RestController
@RequestMapping("/api/mini/auth")
public class MiniAuthController {
    private final AuthService authService;
    private final BearerTokenResolver tokenResolver;
    private final WechatMiniProgramClient wechatClient;
    private final MiniAccountService miniAccountService;
 
    public MiniAuthController(AuthService authService, BearerTokenResolver tokenResolver,
                              WechatMiniProgramClient wechatClient, MiniAccountService miniAccountService) {
        this.authService = authService;
        this.tokenResolver = tokenResolver;
        this.wechatClient = wechatClient;
        this.miniAccountService = miniAccountService;
    }
 
    /**
     * 使用微信登录 code 和手机号授权 code 登录小程序。
     * 接口先向微信换取 openid 与手机号,再查找或创建游客账号并签发 MINI Token。
     *
     * @param request 微信登录凭证和手机号授权凭证
     * @return Token 信息及当前游客基础资料
     */
    @PostMapping("/wechat-phone-login")
    public ApiResponse<AuthResponse<MiniUserResponse>> wechatPhoneLogin(
            @Valid @RequestBody WechatPhoneLoginRequest request) {
        WechatPhoneAuthorization authorization = wechatClient.authorizePhoneLogin(
                request.getLoginCode(), request.getPhoneCode());
        return ApiResponse.success(authService.loginMiniWechat(
                authorization.getOpenid(), authorization.getMobile()));
    }
 
    /**
     * 注销当前游客会话,使 Authorization 请求头中的 MINI Token 立即失效。
     *
     * @param authorization Bearer Token 请求头
     * @return 无业务数据的成功响应
     */
    @PostMapping("/logout")
    public ApiResponse<Void> logout(@RequestHeader("Authorization") String authorization) {
        authService.logout(tokenResolver.resolve(authorization), ClientType.MINI);
        return ApiResponse.success();
    }
 
    @DeleteMapping("/account")
    public ApiResponse<Void> cancelAccount(@AuthenticationPrincipal AppUserPrincipal principal,
                                           @RequestHeader("Authorization") String authorization) {
        miniAccountService.cancel(principal.getUserId(), tokenResolver.resolve(authorization));
        return ApiResponse.success();
    }
}