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