using Microsoft.Extensions.Options; using System.Net.Http.Json; using System.Text.Json.Serialization; using TakeoutSaaS.Application.Identity.Abstractions; using TakeoutSaaS.Infrastructure.Identity.Options; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; namespace TakeoutSaaS.Infrastructure.Identity.Services; /// /// 微信 code2Session 实现 /// public sealed class WeChatAuthService(HttpClient httpClient, IOptions options) : IWeChatAuthService { private readonly WeChatMiniOptions _options = options.Value; public async Task Code2SessionAsync(string code, CancellationToken cancellationToken = default) { var requestUri = $"sns/jscode2session?appid={Uri.EscapeDataString(_options.AppId)}&secret={Uri.EscapeDataString(_options.Secret)}&js_code={Uri.EscapeDataString(code)}&grant_type=authorization_code"; using var response = await httpClient.GetAsync(requestUri, cancellationToken); response.EnsureSuccessStatusCode(); var payload = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); if (payload == null) { throw new BusinessException(ErrorCodes.Unauthorized, "微信登录失败:响应为空"); } if (payload.ErrorCode.HasValue && payload.ErrorCode.Value != 0) { var message = string.IsNullOrWhiteSpace(payload.ErrorMessage) ? $"微信登录失败,错误码:{payload.ErrorCode}" : payload.ErrorMessage; throw new BusinessException(ErrorCodes.Unauthorized, message); } if (string.IsNullOrWhiteSpace(payload.OpenId) || string.IsNullOrWhiteSpace(payload.SessionKey)) { throw new BusinessException(ErrorCodes.Unauthorized, "微信登录失败:返回数据无效"); } return new WeChatSessionInfo { OpenId = payload.OpenId, UnionId = payload.UnionId, SessionKey = payload.SessionKey }; } private sealed class WeChatSessionResponse { [JsonPropertyName("openid")] public string? OpenId { get; set; } [JsonPropertyName("unionid")] public string? UnionId { get; set; } [JsonPropertyName("session_key")] public string? SessionKey { get; set; } [JsonPropertyName("errcode")] public int? ErrorCode { get; set; } [JsonPropertyName("errmsg")] public string? ErrorMessage { get; set; } } }