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; }
}
}