ChouBox/Utile/HuanMeng.DotNetCore/WeChat/MiniProgram.cs
2025-04-23 19:20:23 +08:00

149 lines
5.2 KiB
C#

using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace HuanMeng.DotNetCore.WeChat
{
/// <summary>
/// 小程序帮助类
/// </summary>
/// <param name="appId"></param>
/// <param name="secret"></param>
/// <param name="database"></param>
/// <param name="_httpClientFactory"></param>
public class MiniProgram(string appId, string secret, IDatabase database, IHttpClientFactory? _httpClientFactory)
{
public string AppId { get; set; } = appId;
string key = $"WeChat:{appId}";
// Method to get user's OpenID
public async Task<(string openId, string unionid, string session_key)> GetOpenid(string code)
{
string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={appId}&secret={secret}&js_code={code}&grant_type=authorization_code";
var resUserInfo = await GetCurlData(url);
if (resUserInfo.ContainsKey("errcode"))
{
return (null, null, null);
}
string openid = resUserInfo.GetValueOrDefault("openid")?.ToString() ?? "";
string unionid = resUserInfo.GetValueOrDefault("unionid")?.ToString() ?? "";
string session_key = resUserInfo.GetValueOrDefault("session_key")?.ToString() ?? "";
return new(openid, unionid, session_key);
}
// Get user info based on access token and openid
public async Task<dynamic> GetUserInfoAsync(string openid)
{
var accessToken = await GetAccessToken();
string url = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openid}&lang=zh_CN";
var response = await GetCurlData(url);
return response;
}
public async Task<string> GetAccessToken()
{
var accessTokenInfo = GetConfig();
if (accessTokenInfo != null)
{
return accessTokenInfo?.Access_token;
}
else
{
string url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}";
var resAccessToken = await GetCurlData(url);
if (resAccessToken.ContainsKey("errcode"))
{
throw new Exception("获取微信token失败");
}
string accessToken = resAccessToken["access_token"].ToString();
int expiresIn = Convert.ToInt32(resAccessToken["expires_in"]);
long accessTokenTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + expiresIn;
var data = new AccessToken(accessToken, accessTokenTime);
SetConfig(data);
return accessToken;
}
}
// Helper method for GET requests
private async Task<Dictionary<string, object>> GetCurlData(string url)
{
using HttpClient client = _httpClientFactory.CreateClient();
var response = await client.GetStringAsync(url);
return JsonConvert.DeserializeObject<Dictionary<string, object>>(response);
}
// Helper method for POST requests
private async Task<Dictionary<string, object>> PostCurlData(string url, object data)
{
using HttpClient client = _httpClientFactory.CreateClient();
var json = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
}
// Helper method for HTTP POST data
private async Task<string> HttpPostData(string url, object data)
{
using HttpClient client = _httpClientFactory.CreateClient();
var json = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
private AccessToken? GetConfig()
{
var json = database.StringGet(key);
if (!string.IsNullOrEmpty(json))
{
return JsonConvert.DeserializeObject<AccessToken>(json);
}
return null;
}
private void SetConfig(AccessToken access)
{
var outTime = new TimeSpan(0, 0, 7000);
database.StringSet(key, JsonConvert.SerializeObject(access), outTime);
}
}
/// <summary>
///
/// </summary>
public class AccessToken
{
public string? Access_token { get; }
public long Access_token_time { get; }
public AccessToken(string? access_token, long access_token_time)
{
Access_token = access_token;
Access_token_time = access_token_time;
}
public AccessToken()
{
}
}
}