149 lines
5.7 KiB
C#
149 lines
5.7 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 微信小程序服务实现
|
||
/// 使用 SKIT.FlurlHttpClient.Wechat.Api 实现
|
||
/// </summary>
|
||
public class WechatMiniProgramService : IWechatMiniProgramService
|
||
{
|
||
private readonly IWechatApiClientManager _clientManager;
|
||
private readonly ILogger<WechatMiniProgramService> _logger;
|
||
|
||
public WechatMiniProgramService(
|
||
IWechatApiClientManager clientManager,
|
||
ILogger<WechatMiniProgramService> logger)
|
||
{
|
||
_clientManager = clientManager ?? throw new ArgumentNullException(nameof(clientManager));
|
||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过 code 获取用户的 openId 和 sessionKey
|
||
/// </summary>
|
||
public async Task<WechatLoginInfoDto> 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}"
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过手机号 code 获取用户手机号
|
||
/// </summary>
|
||
public async Task<string?> 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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|