using LifePayment.Domain.Shared; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; using Newtonsoft.Json; using System; using System.IO; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Caching; using ZeroD.Util; namespace LifePayment.Domain { public class WxManager : IWxManager { private readonly WxMiniAppOption _wxOptions; private readonly InformationOption _informationOption; private readonly WxMatchMakingMiniAppOption _wxMatchMakingMiniAppOption; private readonly ICommonManager _commonManager; private readonly IHttpClientFactory _httpClientFactory; private readonly IDistributedCache _distributedCache; public WxManager( ICommonManager commonManager, IHttpClientFactory httpClientFactory, IDistributedCache distributedCache, IOptionsMonitor wxOptionsMonitor, IOptionsMonitor informationOptionMonitor, IOptionsMonitor wxMatchMakingMiniAppOptionMonitor) { _commonManager = commonManager; _distributedCache = distributedCache; _httpClientFactory = httpClientFactory; _wxOptions = wxOptionsMonitor.CurrentValue; _informationOption = informationOptionMonitor.CurrentValue; _wxMatchMakingMiniAppOption = wxMatchMakingMiniAppOptionMonitor.CurrentValue; } public async Task GetWxMiniAccessToken() { var result = await _distributedCache.GetAsync(LifePaymentConstant.小程序Token缓存key); if (result != null) { return result; } var client = _httpClientFactory.CreateClient(LifePaymentConstant.WeChatHttpClientName); var url = $"{_wxOptions.Url}{string.Format(LifePaymentConstant.微信小程序获取Token, _wxOptions.AppId, _wxOptions.Secret)}"; var responseMessage = await client.GetAsync(url); var str = await responseMessage.Content.ReadAsStringAsync(); var res = JsonConvert.DeserializeObject(str); if (res == null || res.AccessToken.IsNullOrEmpty() || res.ExpiresIn == default) { throw new UserFriendlyException("获取小程序token失败"); } await _distributedCache.SetAsync(LifePaymentConstant.小程序Token缓存key, res.AccessToken, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(res.ExpiresIn - 360), }); return res.AccessToken; } public async Task GetWxCgiAccessToken() { var result = await _distributedCache.GetAsync(LifePaymentConstant.微信公众号Token缓存key); if (result != null) { return result; } var client = _httpClientFactory.CreateClient(LifePaymentConstant.WeChatHttpClientName); var url = $"{_informationOption.RequestUrl}{string.Format(LifePaymentConstant.微信小程序获取Token, _informationOption.AppId, _informationOption.AppSecret)}"; var responseMessage = await client.GetAsync(url); var str = await responseMessage.Content.ReadAsStringAsync(); var res = JsonConvert.DeserializeObject(str); if (res == null || res.AccessToken.IsNullOrEmpty() || res.ExpiresIn == default) { throw new UserFriendlyException("获取小程序token失败"); } await _distributedCache.SetAsync(LifePaymentConstant.微信公众号Token缓存key, res.AccessToken, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(res.ExpiresIn - 360), }); return res.AccessToken; } public async Task CreateQrCodeUrl(string name, CreateQrCodeInput input) { var res = await CreateQrCode(input); var reslut = _commonManager.GetOssUrl(LifePaymentConstant.扫码登录二维码路径, name, res, "png"); return reslut; } public async Task CreateQrCode(CreateQrCodeInput input) { var token = await GetWxMiniAccessToken(); string url = $"{_informationOption.RequestUrl}{string.Format(LifePaymentConstant.微信小程序创建二维码, token)}"; ; return await _commonManager.PostAsync(url, new { page = input.Page, scene = input.Scene, env_version = input.EnvVersion, width = input.Width, check_path = input.CheckPath, }); } public async Task GetWxIndentity(string code, WxMiniAppEnum wxMiniApp) { var appInfo = GetAppInfoByEnum(wxMiniApp); var url = $"{appInfo.Url}{string.Format(LifePaymentConstant.微信小程序身份会话信息, appInfo.AppId, appInfo.Secret, code)}"; var result = await _commonManager.PostAsync(url, null); return result; } public async Task GetWxOauth2AccessToken(string code) { var url = $"{_informationOption.RequestUrl}{string.Format(LifePaymentConstant.微信公众号获取access_token, _informationOption.AppId, _informationOption.AppSecret, code)}"; var result = await _commonManager.PostAsync(url, null); return result; } public async Task GetWxPublishWriting() { var token = await GetWxCgiAccessToken(); var input = new GetCgiWritingInput(); input.AccessToken = token; var url = $"{_wxOptions.Url}{string.Format(LifePaymentConstant.微信接口获取公众号文章, token)}"; var requestContent = new StringContent(JsonString.Object2Json(input), Encoding.UTF8, "application/json"); var client = _httpClientFactory.CreateClient(LifePaymentConstant.WeChatHttpClientName); var responseMessage = await client.PostAsync(url, requestContent); var str = await responseMessage.Content.ReadAsStringAsync(); var res = JsonConvert.DeserializeObject(str); return res; } public string GetPhoneNumber(string encryptedDataStr, string iv, string sessionKey) { return GetUserInfo(encryptedDataStr, iv, sessionKey)?.PhoneNumber; } public WxMiniAppUserInfo GetUserInfo(string encryptedDataStr, string iv, string sessionKey) { var result = string.Empty; RijndaelManaged rijalg = new RijndaelManaged(); rijalg.KeySize = 128; rijalg.Padding = PaddingMode.PKCS7; rijalg.Mode = CipherMode.CBC; rijalg.Key = Convert.FromBase64String(sessionKey); rijalg.IV = Convert.FromBase64String(iv); byte[] encryptedData = Convert.FromBase64String(encryptedDataStr); ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV); using (MemoryStream msDecrypt = new MemoryStream(encryptedData)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { result = srDecrypt.ReadToEnd(); } } } return JsonConvert.DeserializeObject(result); } private (string Url, string AppId, string Secret) GetAppInfoByEnum(WxMiniAppEnum wxMiniApp) { return wxMiniApp switch { WxMiniAppEnum.行业资讯 => (_wxOptions.Url, _wxOptions.AppId, _wxOptions.Secret), WxMiniAppEnum.人单合一 => (_wxMatchMakingMiniAppOption.Url, _wxMatchMakingMiniAppOption.AppId, _wxMatchMakingMiniAppOption.Secret), WxMiniAppEnum.生活缴费 => (_wxMatchMakingMiniAppOption.Url, _wxMatchMakingMiniAppOption.AppId, _wxMatchMakingMiniAppOption.Secret), _ => throw new UserFriendlyException("存在未实现的WxMiniAppEnum"), }; } } }