feat: add WeChat OAuth login API for H5 one-tap authorize

POST /rbac/auth/wx-oauth-login exchanges code for openid and issues customer token.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-07-30 15:56:45 +08:00
parent 206dc3ef3c
commit 644da097bf
3 changed files with 54 additions and 0 deletions

View File

@ -37,6 +37,7 @@ public class WeChatRouteIntegrationTests
host.RoutePatterns.Should().Contain("wechat/customer/register");
host.RoutePatterns.Should().Contain("wechat/customer/bind");
host.RoutePatterns.Should().Contain("rbac/auth/wx-login/status");
host.RoutePatterns.Should().Contain("rbac/auth/wx-oauth-login");
}
[Fact]

View File

@ -31,6 +31,13 @@ public class OmsWxLoginInput
public string LoginUuid { get; set; } = string.Empty;
}
/// <summary>微信网页授权登录(code 换 openid)。</summary>
public class OmsWxOAuthLoginInput
{
[Required]
public string Code { get; set; } = string.Empty;
}
public class OmsCustomerOmsLoginInput
{
[Required]

View File

@ -190,6 +190,52 @@ public partial class AuthService(
return await BuildLoginResultAsync(userGuid.Value, OmsLoginType.Customer, cancellationToken);
}
/// <summary>
/// 微信网页授权登录(H5 内点按钮授权,无需扫码)。
/// </summary>
[AllowAnonymous]
[HttpPost("/rbac/auth/wx-oauth-login")]
public async Task<OmsLoginResultDto> WxOAuthLoginAsync(
[FromBody] OmsWxOAuthLoginInput input,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(input.Code))
{
throw new BusinessException("缺少微信授权 code");
}
var token = await WeChatMpApiClient.GetOAuthAccessTokenAsync(input.Code.Trim(), cancellationToken);
if (token == null || string.IsNullOrWhiteSpace(token.OpenId))
{
throw new BusinessException("微信授权失败,请重试");
}
var customer = await customerRepository.GetByWechatOpenidAsync(token.OpenId, cancellationToken);
if (customer == null)
{
throw new BusinessException("未绑定微信,请先注册或绑定账号");
}
if (customer.ParentCustomerId.HasValue)
{
throw new BusinessException("子客户不支持微信授权登录");
}
ValidateMainCustomerStatus(customer);
customer.LastLoginIp = httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString();
customer.LastLoginTime = DateTime.Now;
await customerRepository.UpdateAsync(customer, cancellationToken);
var userGuid = await GetRbacUserGuidByMapIdAsync(customer.UserId, cancellationToken);
if (!userGuid.HasValue)
{
throw new BusinessException("客户未关联用户");
}
return await BuildLoginResultAsync(userGuid.Value, OmsLoginType.Customer, cancellationToken);
}
private async Task<Customer?> ResolveCustomerFromWxSessionAsync(
WeChatLoginSessionPayload session,
CancellationToken cancellationToken)