diff --git a/honey_box/common/server/auth.js b/honey_box/common/server/auth.js index 1cb80045..b8842b2e 100644 --- a/honey_box/common/server/auth.js +++ b/honey_box/common/server/auth.js @@ -88,13 +88,23 @@ export const isTokenExpired = () => { /** * 微信手机号快速验证登录 - * @param {String} code 微信手机号授权code(getPhoneNumber返回) + * @param {String} phoneCode 微信手机号授权code(getPhoneNumber返回) * @param {String} pid 推荐人ID * @returns {Promise} 登录结果 */ -export const wxPhoneLogin = async (code, pid = '') => { +export const wxPhoneLogin = async (phoneCode, pid = '') => { + // 先获取微信登录code,用于获取openid + const loginRes = await new Promise((resolve, reject) => { + uni.login({ + provider: 'weixin', + success: resolve, + fail: reject + }); + }); + return await RequestManager.post('/wxPhoneLogin', { - code, + phoneCode, + loginCode: loginRes.code, pid }); }; diff --git a/server/HoneyBox/src/HoneyBox.Api/Controllers/AuthController.cs b/server/HoneyBox/src/HoneyBox.Api/Controllers/AuthController.cs index f1b48ed8..e4e9af41 100644 --- a/server/HoneyBox/src/HoneyBox.Api/Controllers/AuthController.cs +++ b/server/HoneyBox/src/HoneyBox.Api/Controllers/AuthController.cs @@ -115,20 +115,21 @@ public class AuthController : ControllerBase /// /// POST /api/wxPhoneLogin /// - /// 使用微信getPhoneNumber获取的code进行登录,返回双Token(Access Token + Refresh Token) + /// 使用微信getPhoneNumber获取的code进行登录,同时使用uni.login的code获取openid用于微信支付 + /// 返回双Token(Access Token + Refresh Token) /// - /// 微信手机号登录请求参数,包含手机号授权code + /// 微信手机号登录请求参数,包含手机号授权code和登录code /// 登录成功返回LoginResponse(包含accessToken、refreshToken、expiresIn),失败返回错误信息 [HttpPost("wxPhoneLogin")] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] public async Task> WechatPhoneLogin([FromBody] WechatPhoneLoginRequest request) { - if (request == null || string.IsNullOrWhiteSpace(request.Code)) + if (request == null || string.IsNullOrWhiteSpace(request.PhoneCode)) { return ApiResponse.Fail("手机号授权code不能为空"); } - var result = await _authService.WechatPhoneLoginAsync(request.Code, request.Pid); + var result = await _authService.WechatPhoneLoginAsync(request.PhoneCode, request.LoginCode, request.Pid); if (result.Success && result.LoginResponse != null) { diff --git a/server/HoneyBox/src/HoneyBox.Core/Interfaces/IAuthService.cs b/server/HoneyBox/src/HoneyBox.Core/Interfaces/IAuthService.cs index 473c856d..ebb1447e 100644 --- a/server/HoneyBox/src/HoneyBox.Core/Interfaces/IAuthService.cs +++ b/server/HoneyBox/src/HoneyBox.Core/Interfaces/IAuthService.cs @@ -47,9 +47,10 @@ public interface IAuthService /// 微信手机号快速验证登录 /// /// 微信手机号授权code(getPhoneNumber返回) + /// 微信登录code(uni.login返回,用于获取openid) /// 推荐人ID /// 登录结果 - Task WechatPhoneLoginAsync(string phoneCode, int? pid); + Task WechatPhoneLoginAsync(string phoneCode, string? loginCode, int? pid); /// /// 记录登录信息 diff --git a/server/HoneyBox/src/HoneyBox.Core/Services/AuthService.cs b/server/HoneyBox/src/HoneyBox.Core/Services/AuthService.cs index d4aa54e6..eeff7679 100644 --- a/server/HoneyBox/src/HoneyBox.Core/Services/AuthService.cs +++ b/server/HoneyBox/src/HoneyBox.Core/Services/AuthService.cs @@ -386,15 +386,15 @@ public class AuthService : IAuthService /// /// 微信手机号快速验证登录 - /// 使用微信getPhoneNumber获取的code直接登录 + /// 使用微信getPhoneNumber获取的code直接登录,同时获取openid用于微信支付 /// - public async Task WechatPhoneLoginAsync(string phoneCode, int? pid) + public async Task WechatPhoneLoginAsync(string phoneCode, string? loginCode, int? pid) { - _logger.LogInformation("[AuthService] 微信手机号登录开始,pid={Pid}", pid); + _logger.LogInformation("[AuthService] 微信手机号登录开始,pid={Pid}, hasLoginCode={HasLoginCode}", pid, !string.IsNullOrEmpty(loginCode)); if (string.IsNullOrWhiteSpace(phoneCode)) { - _logger.LogWarning("[AuthService] 微信手机号登录失败:code为空"); + _logger.LogWarning("[AuthService] 微信手机号登录失败:phoneCode为空"); return new LoginResult { Success = false, @@ -417,7 +417,7 @@ public class AuthService : IAuthService }; } - // 调用微信API获取手机号 + // 1. 调用微信API获取手机号 _logger.LogInformation("[AuthService] 开始调用微信API获取手机号..."); var mobileResult = await _wechatService.GetMobileAsync(phoneCode); @@ -434,7 +434,26 @@ public class AuthService : IAuthService var mobile = mobileResult.Mobile; _logger.LogInformation("[AuthService] 获取手机号成功: {Mobile}", MaskMobile(mobile)); - // 根据手机号查找用户 + // 2. 如果有loginCode,获取openid + string? openId = null; + string? unionId = null; + if (!string.IsNullOrWhiteSpace(loginCode)) + { + _logger.LogInformation("[AuthService] 开始调用微信API获取openid..."); + var wechatResult = await _wechatService.GetOpenIdAsync(loginCode); + if (wechatResult.Success) + { + openId = wechatResult.OpenId; + unionId = wechatResult.UnionId; + _logger.LogInformation("[AuthService] 获取openid成功: {OpenId}", openId); + } + else + { + _logger.LogWarning("[AuthService] 获取openid失败: {Error},继续登录但无法使用微信支付", wechatResult.ErrorMessage); + } + } + + // 3. 根据手机号查找用户 var user = await _userService.GetUserByMobileAsync(mobile); if (user == null) @@ -444,31 +463,37 @@ public class AuthService : IAuthService var createDto = new CreateUserDto { Mobile = mobile, + OpenId = openId, + UnionId = unionId, Nickname = $"用户{Random.Shared.Next(100000, 999999)}", Headimg = GenerateDefaultAvatar(mobile), Pid = pid?.ToString() }; user = await _userService.CreateUserAsync(createDto); - - // 设置手机号已绑定状态 - await _userService.UpdateUserAsync(user.Id, new UpdateUserDto { Mobile = mobile }); - - _logger.LogInformation("[AuthService] 新用户创建成功: UserId={UserId}, Mobile={Mobile}", user.Id, MaskMobile(mobile)); + _logger.LogInformation("[AuthService] 新用户创建成功: UserId={UserId}, Mobile={Mobile}, OpenId={OpenId}", + user.Id, MaskMobile(mobile), openId ?? "null"); } else { _logger.LogInformation("[AuthService] 找到已有用户: UserId={UserId}", user.Id); + + // 4. 如果用户存在但没有openid,更新openid + if (!string.IsNullOrWhiteSpace(openId) && string.IsNullOrWhiteSpace(user.OpenId)) + { + _logger.LogInformation("[AuthService] 更新用户openid: UserId={UserId}", user.Id); + await _userService.UpdateUserAsync(user.Id, new UpdateUserDto { OpenId = openId, UnionId = unionId }); + } } - // 生成双 Token + // 5. 生成双 Token _logger.LogInformation("[AuthService] 开始生成双 Token: UserId={UserId}", user.Id); var loginResponse = await GenerateLoginResponseAsync(user, null); // 更新UserAccount表 await CreateOrUpdateAccountTokenAsync(user.Id, loginResponse.AccessToken); - _logger.LogInformation("[AuthService] 微信手机号登录成功: UserId={UserId}", user.Id); + _logger.LogInformation("[AuthService] 微信手机号登录成功: UserId={UserId}, HasOpenId={HasOpenId}", user.Id, !string.IsNullOrWhiteSpace(openId)); return new LoginResult { diff --git a/server/HoneyBox/src/HoneyBox.Core/Services/UserService.cs b/server/HoneyBox/src/HoneyBox.Core/Services/UserService.cs index f1bd66cf..3b133a2f 100644 --- a/server/HoneyBox/src/HoneyBox.Core/Services/UserService.cs +++ b/server/HoneyBox/src/HoneyBox.Core/Services/UserService.cs @@ -145,6 +145,9 @@ public class UserService : BaseService, IUserService if (!string.IsNullOrWhiteSpace(dto.Mobile)) user.Mobile = dto.Mobile; + if (!string.IsNullOrWhiteSpace(dto.OpenId)) + user.OpenId = dto.OpenId; + if (!string.IsNullOrWhiteSpace(dto.UnionId)) user.UnionId = dto.UnionId; diff --git a/server/HoneyBox/src/HoneyBox.Model/Models/Auth/CreateUserDto.cs b/server/HoneyBox/src/HoneyBox.Model/Models/Auth/CreateUserDto.cs index 935d9b10..1a944422 100644 --- a/server/HoneyBox/src/HoneyBox.Model/Models/Auth/CreateUserDto.cs +++ b/server/HoneyBox/src/HoneyBox.Model/Models/Auth/CreateUserDto.cs @@ -61,6 +61,11 @@ public class UpdateUserDto /// public string? Mobile { get; set; } + /// + /// 微信openid + /// + public string? OpenId { get; set; } + /// /// 微信unionid /// diff --git a/server/HoneyBox/src/HoneyBox.Model/Models/Auth/WechatPhoneLoginRequest.cs b/server/HoneyBox/src/HoneyBox.Model/Models/Auth/WechatPhoneLoginRequest.cs index 9c42bedb..d8d2d3e9 100644 --- a/server/HoneyBox/src/HoneyBox.Model/Models/Auth/WechatPhoneLoginRequest.cs +++ b/server/HoneyBox/src/HoneyBox.Model/Models/Auth/WechatPhoneLoginRequest.cs @@ -10,8 +10,14 @@ public class WechatPhoneLoginRequest /// /// 微信手机号授权code(getPhoneNumber返回的code) /// - [JsonPropertyName("code")] - public string Code { get; set; } = string.Empty; + [JsonPropertyName("phoneCode")] + public string PhoneCode { get; set; } = string.Empty; + + /// + /// 微信登录code(uni.login返回的code,用于获取openid) + /// + [JsonPropertyName("loginCode")] + public string? LoginCode { get; set; } /// /// 推荐人ID(前端可能传空字符串,所以用string接收)