using BPA.Kitchen.Core;
using BPA.KitChen.GroupMealOrder.Core.CacheOption;
using BPA.KitChen.WeChat.WechatServer.Dtos;
using BPA.KitChen.WeChat.WechatServer.Service;
using Furion;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using System.Text;
namespace Black_B_Project.Application.WechatServer.Service
{
///
/// 微信小程序服务端方法
///
public class WechatService : IWechatService, ITransient
{
private readonly IMemoryCache _memoryCache;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IDistributedCache _redisClient;
public WechatService(IMemoryCache memoryCache, IHttpContextAccessor httpContextAccessor, IDistributedCache redisClient)
{
_memoryCache = memoryCache;
_httpContextAccessor = httpContextAccessor;
_redisClient = redisClient;
}
///
/// 解密获取用户完整信息
///
///
public WeChatUserInfo Decryptuserinfo(DecryptVM decryptVM)
{
WeChatUserInfo info = new();
try
{
AESHelper.AesKey = decryptVM.session_key;
AESHelper.AesIV = decryptVM.aesiv;
string decrstr = AESHelper.AESDecrypt(decryptVM.encryptedData);
info = JSON.Deserialize(decrstr);
}
catch (Exception)
{
//BPALog.WriteLog("解析用户信息失败", LogEnum.Error, param: info);
throw Oops.Oh("解析失败,session_key已过期");
}
return info;
}
///
/// 用户登录,获取openid
///
///
///
public WeChatUserInfo WxLogin(DecryptVM vm)
{
var appid = _httpContextAccessor.HttpContext.Request.Headers["AppId"].ToString();
var config = ApolloApplication.Configs.Find(x => x.Key == appid);
if (config == null)
{
throw Oops.Oh("AppId不能为空!");
}
WeChatUserInfo userinfo = new();
if (!string.IsNullOrEmpty(vm.code))
{
var opt = config.WechatConfig;
var apiUrl = $"https://api.weixin.qq.com/sns/jscode2session?appid={opt.Appid}&secret={opt.AppSecret}&js_code={vm.code}&grant_type=authorization_code";
var response = apiUrl.GetAsStringAsync().Result;
//todo 记录openID进入数据库
var loginData = JSON.Deserialize(response);
if (loginData.session_key == null)
{
throw Oops.Oh($"登录失败,请重试!{response}");
}
vm.session_key = loginData.session_key;
vm.openId = loginData.openid;
userinfo.openId = loginData.openid;
userinfo.session_key = loginData.session_key;
userinfo.TmplIds.Add(config.WechatConfig.AppMessagetTakeAway);
return userinfo;
}
else
{
throw Oops.Oh($"登录失败,请重试!");
}
}
///
/// 获取微信token
///
///
[AllowAnonymous]
public async Task AccessToken(string appid)
{
var config = ApolloApplication.Configs.Find(x => x.Key == appid);
//过期时间
string tokenExpiresName = $"{appid}_TokenExpires";
//数据
string accessTokenName = $"{appid}_AccessToken";
var expiresTimeout = await _redisClient.GetStringAsync(tokenExpiresName);
//判断是否存在缓存
if (expiresTimeout == null)
{
var opt = config.WechatConfig;
var response = await $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={opt.Appid}&secret={opt.AppSecret}".GetAsStringAsync();
WechatToken res = JSON.Deserialize(response);
if (!string.IsNullOrEmpty(res.access_token))
{
DistributedCacheEntryOptions distributedCacheEntryOptions = new();
//Token
await _redisClient.SetStringAsync(accessTokenName, res.access_token, distributedCacheEntryOptions);
//存入当前时间
var currtime = DateTime.Now;
await _redisClient.SetStringAsync(tokenExpiresName, currtime.ToString(), distributedCacheEntryOptions);
return res.access_token;
}
}
//存在对比是否过期
TimeSpan ts = DateTime.Now - Convert.ToDateTime(expiresTimeout);
//如果总秒数大于6500秒,那么视为过期,重新获取
if (ts.TotalSeconds >= 6500)
{
var opt = config.WechatConfig;
var response = await $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={opt.Appid}&secret={opt.AppSecret}".GetAsStringAsync();
WechatToken res = JSON.Deserialize(response);
if (!string.IsNullOrEmpty(res.access_token))
{
DistributedCacheEntryOptions distributedCacheEntryOptions = new();
//Token
await _redisClient.SetStringAsync(accessTokenName, res.access_token, distributedCacheEntryOptions);
//存入当前时间
var currtime = DateTime.Now;
await _redisClient.SetStringAsync(tokenExpiresName, currtime.ToString(), distributedCacheEntryOptions);
return res.access_token;
}
}
else
{
//没过期就取
var wechatToken = await _redisClient.GetStringAsync(accessTokenName);
return wechatToken;
}
return null;
}
///
/// 发送预定通知
///
///
///
public async Task SendReserveMessage(ReserveInput input)
{
var config = ApolloApplication.Configs.Find(x => x.Key == input.AppId);
try
{
var param = new
{
touser = input.OpenId,
template_id = config.WechatConfig.AppMessagetTakeAway,
page = "pages/homeNew/homeNew",
data = new
{
time1 = new { value = input.ReserveTime },
thing2 = new { value = input.ReserveWarning },
}
};
var access_token = await AccessToken(input.AppId);
var res = JSON.Serialize(param);
var response = await $"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token}".SetBody(res).PostAsStringAsync();
}
catch (Exception ex)
{
return false;
}
return true;
}
///
/// 获取手机号
///
///
///
public async Task WxPhone(string code)
{
var appid = _httpContextAccessor.HttpContext.Request.Headers["AppId"].ToString();
if (string.IsNullOrEmpty(code))
{
throw Oops.Bah("code不能为空");
}
if (string.IsNullOrEmpty(appid))
{
throw Oops.Bah("appid不能为空");
}
var access_token = await AccessToken(appid);
var respones = await $"https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={access_token}".SetBody(new
{
code
}).PostAsStringAsync();
WechatPhoneMsg wechatPhone = JSON.Deserialize(respones);
return wechatPhone;
}
///
/// 发送服务号
///
///
public async Task Uniform_send()
{
var token = _memoryCache.Get("weToken");
if (token == null)
{
await GetWechatTokenAsync();
token = _memoryCache.Get("weToken");
}
var response = await $"https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token={token.ToString()}".PostAsStreamAsync();
StreamReader readStream = new StreamReader(response.Stream, Encoding.UTF8);
var data = readStream.ReadToEnd();
return data;
}
///
/// 获取微信token
///
///
public async Task GetWechatTokenAsync()
{
var opt = App.GetOptions();
var response = await $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={opt.Appid}&secret={opt.AppSecret}".GetAsStreamAsync();
StreamReader readStream = new StreamReader(response.Stream, Encoding.UTF8);
var data = readStream.ReadToEnd();
var res = JSON.Deserialize(data);
_memoryCache.Set("weToken", res.access_token);
return _memoryCache.Get("weToken").ToString();
}
///
/// 用户支付完成后,获取该用户的 UnionId,无需用户授权。本接口支持第三方平台代理查询。
///
///
///
///
public async Task GetPaidunionid(string token, string openid)
{
var response = await $"https://api.weixin.qq.com/wxa/getpaidunionid?access_token={token}&openid={openid}".GetAsStreamAsync();
StreamReader readStream = new StreamReader(response.Stream, Encoding.UTF8);
return readStream.ReadToEnd();
}
}
}