using Aliyun.OSS;
|
using Azure.Core;
|
using FlexJobApi.Core.Utils.WxmpUtils;
|
using Furion.FriendlyException;
|
using Furion.HttpRemote;
|
using Mapster;
|
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Options;
|
using Newtonsoft.Json;
|
using System;
|
using System.Collections.Generic;
|
using System.IO;
|
using System.Linq;
|
using System.Net.Http.Json;
|
using System.Text;
|
using System.Text.Json.Nodes;
|
using System.Threading;
|
using System.Threading.Tasks;
|
|
namespace FlexJobApi.Core
|
{
|
/// <summary>
|
/// 微信小程序工具
|
/// </summary>
|
public class WxmpUtils
|
{
|
private readonly IOptions<WxmpOptions> options;
|
private readonly IHttpRemoteService httpRemoteService;
|
private readonly IDistributedCache distributedCache;
|
|
public WxmpUtils(
|
IOptions<WxmpOptions> options,
|
IHttpRemoteService httpRemoteService,
|
IDistributedCache distributedCache)
|
{
|
this.options = options;
|
this.httpRemoteService = httpRemoteService;
|
this.distributedCache = distributedCache;
|
}
|
|
public async Task<WxmpSnsJscode2sessionResponse> SnsJscode2sessionAsync(EnumUserType userType, string code, CancellationToken cancellationToken = default)
|
{
|
var option = options.Value.Items.FirstOrDefault(it => it.Code == userType.ToString());
|
if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
|
throw Oops.Oh(EnumErrorCodeType.s400, "登录失败,缺失配置:WxmpOptions");
|
if (code.IsNull())
|
throw Oops.Oh(EnumErrorCodeType.s400, "请填写WxmpCode");
|
var callback = await httpRemoteService.GetAsAsync<WxmpSnsJscode2sessionResponse>("https://api.weixin.qq.com/sns/jscode2session",
|
builder => builder.WithQueryParameters(new Dictionary<string, string>
|
{
|
{ "appid", option.AppId },
|
{ "secret", option.AppSecret },
|
{ "js_code", code },
|
{ "grant_type", "authorization_code" }
|
}));
|
if (callback == null || callback.errcode != 0)
|
throw Oops.Oh(EnumErrorCodeType.s510, $"登录失败:{callback.errmsg},请联系管理员");
|
return callback;
|
}
|
|
/// <summary>
|
/// 获取小程序接口调用凭据
|
/// </summary>
|
/// <param name="userType"></param>
|
/// <returns></returns>
|
public async Task<string> GetAccessToken(EnumUserType userType)
|
{
|
var cacheKey = $"Wxmp|{userType}|AccessToken";
|
var accessToken = await distributedCache.GetStringAsync(cacheKey);
|
if (accessToken.IsNull())
|
{
|
var option = options.Value.Items.FirstOrDefault(it => it.Code == userType.ToString());
|
if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
|
throw Oops.Oh(EnumErrorCodeType.s400, "获取小程序接口调用凭据失败,缺失配置:WxmpOptions");
|
var request = new WxmpGetAccessTokenRequest
|
{
|
Appid = option.AppId,
|
Secret = option.AppSecret,
|
};
|
var response = await httpRemoteService.GetAsStringAsync("https://api.weixin.qq.com/cgi-bin/token",
|
builder => builder.WithQueryParameters(JsonObject.Parse(request.ToJson())));
|
var callback = response.JsonTo<WxmpGetAccessTokenResponse>();
|
if (callback == null && callback.AccessToken.IsNull())
|
throw Oops.Oh(EnumErrorCodeType.s510, "获取小程序接口调用凭据失败");
|
accessToken = callback.AccessToken;
|
await distributedCache.SetStringAsync(cacheKey, accessToken, new DistributedCacheEntryOptions
|
{
|
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(callback.ExpiresIn - 300)
|
});
|
}
|
return accessToken;
|
}
|
|
/// <summary>
|
/// 获取小程序码
|
/// </summary>
|
/// <param name="command"></param>
|
/// <returns></returns>
|
public async Task<string> GetQrCodeOssUrl(WxmpGetQrCodeCommand command)
|
{
|
var option = options.Value.Items.FirstOrDefault(it => it.Code == command.UserType.ToString());
|
if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
|
throw Oops.Oh(EnumErrorCodeType.s400, "获取小程序码失败,缺失配置:WxmpOptions");
|
command.EnvVersion = option.EnvVersion;
|
var accessToken = await GetAccessToken(command.UserType);
|
var request = command.Adapt<WxmpGetQrCodeRequest>();
|
var jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings
|
{
|
NullValueHandling = NullValueHandling.Ignore
|
});
|
var response = await httpRemoteService.PostAsync("https://api.weixin.qq.com/wxa/getwxacodeunlimit",
|
builder => builder
|
.WithQueryParameter("access_token", accessToken)
|
.SetJsonContent(jsonContent));
|
response.EnsureSuccessStatusCode();
|
if (response.Content.Headers.ContentType.ToString() == "application/json; charset=UTF-8")
|
{
|
var jsonResult = await response.Content.ReadAsStringAsync();
|
var callback = jsonResult.JsonTo<WxmpGetQrCodeResponse>();
|
if (callback == null || callback.ErrorCode != 0)
|
throw Oops.Oh(EnumErrorCodeType.s510, $"获取小程序码失败:{callback.ErrorMessage},请联系管理员");
|
}
|
var stream = await response.Content.ReadAsStreamAsync();
|
var result = AliyunOSSUtils.Upload(command.OssScene, stream, command.OssFileName);
|
return result.Url;
|
}
|
}
|
}
|