using LiveForum.IService.Others;
using LiveForum.Model.Dto.Wechat;
using Microsoft.Extensions.Logging;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Models;
using System;
using System.Threading.Tasks;
namespace LiveForum.Service.Others
{
///
/// 微信小程序服务实现
/// 使用 SKIT.FlurlHttpClient.Wechat.Api 实现
///
public class WechatMiniProgramService : IWechatMiniProgramService
{
private readonly IWechatApiClientManager _clientManager;
private readonly ILogger _logger;
public WechatMiniProgramService(
IWechatApiClientManager clientManager,
ILogger logger)
{
_clientManager = clientManager ?? throw new ArgumentNullException(nameof(clientManager));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
///
/// 通过 code 获取用户的 openId 和 sessionKey
///
public async Task GetLoginInfoByCodeAsync(string jsCode)
{
if (string.IsNullOrWhiteSpace(jsCode))
{
throw new ArgumentException("jsCode 不能为空", nameof(jsCode));
}
try
{
// 从 Manager 获取最新客户端实例(支持动态配置更新)
var client = _clientManager.GetClient();
if (client == null)
{
_logger.LogError("微信 API 客户端不可用");
return new WechatLoginInfoDto
{
IsSuccessful = false,
ErrorMessage = "微信 API 客户端不可用,请检查配置"
};
}
// 调用微信 API
var request = new SnsJsCode2SessionRequest
{
JsCode = jsCode
};
var response = await client.ExecuteSnsJsCode2SessionAsync(request);
// 转换为业务 DTO
return new WechatLoginInfoDto
{
OpenId = response.OpenId,
SessionKey = response.SessionKey,
UnionId = response.UnionId,
IsSuccessful = response.IsSuccessful(),
ErrorCode = response.ErrorCode,
ErrorMessage = response.ErrorMessage
};
}
catch (Exception ex)
{
_logger.LogError(ex, "获取微信登录信息失败,jsCode: {JsCode}", jsCode?.Substring(0, Math.Min(10, jsCode?.Length ?? 0)));
return new WechatLoginInfoDto
{
IsSuccessful = false,
ErrorMessage = $"获取微信登录信息失败:{ex.Message}"
};
}
}
///
/// 通过手机号 code 获取用户手机号
///
public async Task GetPhoneNumberByCodeAsync(string phoneCode)
{
if (string.IsNullOrWhiteSpace(phoneCode))
{
throw new ArgumentException("phoneCode 不能为空", nameof(phoneCode));
}
try
{
var client = _clientManager.GetClient();
if (client == null)
{
_logger.LogError("微信 API 客户端不可用");
return null;
}
// 获取手机号接口需要 access_token,先获取它
var accessTokenRequest = new CgibinTokenRequest();
var accessTokenResponse = await client.ExecuteCgibinTokenAsync(accessTokenRequest);
if (!accessTokenResponse.IsSuccessful())
{
_logger.LogError("获取 access_token 失败: ErrorCode={ErrorCode}, ErrorMessage={ErrorMessage}",
accessTokenResponse.ErrorCode, accessTokenResponse.ErrorMessage);
return null;
}
_logger.LogInformation("获取 access_token 成功, token前10位: {TokenPrefix}...",
accessTokenResponse.AccessToken?.Substring(0, Math.Min(10, accessTokenResponse.AccessToken?.Length ?? 0)));
var request = new WxaBusinessGetUserPhoneNumberRequest
{
Code = phoneCode,
AccessToken = accessTokenResponse.AccessToken
};
_logger.LogInformation("开始获取手机号, phoneCode前10位: {PhoneCodePrefix}..., AccessToken是否存在: {HasToken}",
phoneCode?.Substring(0, Math.Min(10, phoneCode?.Length ?? 0)),
!string.IsNullOrEmpty(request.AccessToken));
var response = await client.ExecuteWxaBusinessGetUserPhoneNumberAsync(request);
if (response.IsSuccessful() && response.PhoneInfo != null)
{
_logger.LogInformation("获取手机号成功: {Phone}", response.PhoneInfo.PurePhoneNumber ?? response.PhoneInfo.PhoneNumber);
return response.PhoneInfo.PurePhoneNumber ?? response.PhoneInfo.PhoneNumber;
}
_logger.LogWarning("获取手机号失败: ErrorCode={ErrorCode}, ErrorMessage={ErrorMessage}",
response.ErrorCode, response.ErrorMessage);
return null;
}
catch (Exception ex)
{
_logger.LogError(ex, "获取微信手机号异常");
return null;
}
}
}
}