From e496d4095ba7ec6ae9d794f457410e2f04866ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com> Date: Wed, 19 Jul 2023 07:29:49 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=E6=96=B0=E5=A2=9E=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=85=AC=E4=BC=97=E5=8F=B7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Infrastructure/Helper/DateTimeHelper.cs | 6 + .../Controllers/WxOpenController.cs | 43 +++++++ ZR.Admin.WebApi/appsettings.json | 5 + ZR.Common/Model/WxTokenResult.cs | 13 ++ ZR.Common/WxHelper.cs | 119 ++++++++++++++++++ ZR.Common/WxNoticeHelper.cs | 19 +-- 6 files changed, 191 insertions(+), 14 deletions(-) create mode 100644 ZR.Admin.WebApi/Controllers/WxOpenController.cs create mode 100644 ZR.Common/Model/WxTokenResult.cs create mode 100644 ZR.Common/WxHelper.cs diff --git a/Infrastructure/Helper/DateTimeHelper.cs b/Infrastructure/Helper/DateTimeHelper.cs index 37aa6b9..72076c4 100644 --- a/Infrastructure/Helper/DateTimeHelper.cs +++ b/Infrastructure/Helper/DateTimeHelper.cs @@ -100,6 +100,12 @@ namespace Infrastructure long unixTime = ((DateTimeOffset)dt).ToUnixTimeMilliseconds(); return unixTime; } + + public static long GetUnixTimeSeconds(DateTime dt) + { + long unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds(); + return unixTime; + } #endregion #region 获取日期天的最小时间 diff --git a/ZR.Admin.WebApi/Controllers/WxOpenController.cs b/ZR.Admin.WebApi/Controllers/WxOpenController.cs new file mode 100644 index 0000000..2ed4987 --- /dev/null +++ b/ZR.Admin.WebApi/Controllers/WxOpenController.cs @@ -0,0 +1,43 @@ +using Infrastructure.Extensions; +using Microsoft.AspNetCore.Mvc; +using System.Web; + +namespace ZR.Admin.WebApi.Controllers +{ + /// + /// 微信公众号 + /// + [Route("[controller]/[action]")] + [AllowAnonymous] + public class WxOpenController : BaseController + { + private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + public WxOpenController() { } + + /// + /// 获取签名 + /// + /// + /// + [Log(Title = "获取微信签名")] + [HttpGet] + public IActionResult GetSignature(string url = "") + { + url = HttpUtility.UrlDecode(url); + var appId = AppSettings.App(new string[] { "WxOpen", "AppID" }); + var noncestr = Guid.NewGuid().ToString().Replace("-", ""); + var timestamp = DateTimeHelper.GetUnixTimeSeconds(DateTime.Now); + var ticketResult = WxHelper.GetTicket(); + if (appId.IsEmpty()) return ToResponse(ResultCode.CUSTOM_ERROR, "appId未配置"); + if (ticketResult?.errcode != 0) + { + return ToResponse(ResultCode.CUSTOM_ERROR, "获取配置失败"); + } + + var signature = WxHelper.GetSignature(ticketResult.ticket, timestamp.ToString(), noncestr, url); + + return SUCCESS(new { appId, signature, noncestr, timestamp, url }); + } + + } +} diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json index 17494ba..2a47d0f 100644 --- a/ZR.Admin.WebApi/appsettings.json +++ b/ZR.Admin.WebApi/appsettings.json @@ -56,6 +56,11 @@ "CorpSecret": "", "SendUser": "@all" }, + //微信公众号设置 + "WxOpen": { + "AppID": "", + "AppSecret": "" + }, //代码生成配置 "gen": { "autoPre": true, //自动去除表前缀 diff --git a/ZR.Common/Model/WxTokenResult.cs b/ZR.Common/Model/WxTokenResult.cs new file mode 100644 index 0000000..bea1614 --- /dev/null +++ b/ZR.Common/Model/WxTokenResult.cs @@ -0,0 +1,13 @@ +namespace ZR.Common.Model +{ + public class WxTokenResult + { + /// + /// 0、正常 + /// + public int errcode { get; set; } + public string errmsg { get; set; } + public string access_token { get; set; } + public string ticket { get; set; } + } +} diff --git a/ZR.Common/WxHelper.cs b/ZR.Common/WxHelper.cs new file mode 100644 index 0000000..5063c8e --- /dev/null +++ b/ZR.Common/WxHelper.cs @@ -0,0 +1,119 @@ +using Infrastructure; +using Infrastructure.Extensions; +using Newtonsoft.Json; +using System; +using System.Security.Cryptography; +using System.Text; +using ZR.Common.Model; + +namespace ZR.Common +{ + public class WxHelper + { + private static readonly string GetTokenUrl = "https://api.weixin.qq.com/cgi-bin/token"; + private static readonly string GetTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; + private static readonly string AppID = AppSettings.App(new string[] { "WxOpen", "AppID" }); + private static readonly string AppSECRET = AppSettings.App(new string[] { "WxOpen", "AppSecret" }); + + /// + /// 获取访问token + /// + /// + /// {"errcode":0,"errmsg":"ok","access_token":"iCbcfE1OjfRhV0_io-CzqTNC0lnrudeW3oF5rhJKfmINaxLClLa1FoqAY_wEXtodYh_DTnrtAwZfzeb-NRXvwiOoqUTHx3i6QKLYcfBtF8y-xd5mvaeaf3e9mvTAPhmX0lkm1cLTwRLmoa1IwzgQ-QZEZcuIcntWdEMGseVYok3BwCGpC87bt6nNdgnekZdFVRp1uuaxoctDGlXpoQlQsA","expires_in":7200} + /// + private static WxTokenResult GetAccessToken() + { + if (AppID.IsEmpty() || AppSECRET.IsEmpty()) + { + Console.WriteLine("公众号配置错误"); + throw new ArgumentException("公众号配置错误"); + }; + var Ck = "wx_token"; + string getTokenUrl = $"{GetTokenUrl}?grant_type=client_credential&appid={AppID}&secret={AppSECRET}"; + if (CacheHelper.Get(Ck) is WxTokenResult tokenResult) + { + return tokenResult; + } + else + { + string result = HttpHelper.HttpGet(getTokenUrl); + + tokenResult = JsonConvert.DeserializeObject(result); + + if (tokenResult?.errcode == 0) + { + CacheHelper.SetCache(Ck, tokenResult, 110); + } + else + { + Console.WriteLine("GetAccessToken失败,结果=" + result); + throw new Exception("获取AccessToken失败"); + } + } + return tokenResult; + } + + /// + /// 获取ticket + /// + /// + public static WxTokenResult GetTicket() + { + WxTokenResult token = GetAccessToken(); + string ticket = token?.access_token; + var Ck = "wx_ticket"; + string getTokenUrl = $"{GetTicketUrl}?access_token={ticket}&type=jsapi"; + if (CacheHelper.Get(Ck) is WxTokenResult tokenResult) + { + return tokenResult; + } + else + { + string result = HttpHelper.HttpGet(getTokenUrl); + tokenResult = JsonConvert.DeserializeObject(result); + + if (tokenResult?.errcode == 0) + { + CacheHelper.SetCache(Ck, tokenResult, 110); + } + else + { + Console.WriteLine("GetTicket,结果=" + result); + throw new Exception("获取ticket失败"); + } + } + return tokenResult; + } + + /// + /// 返回正确的签名 + /// + /// + /// + /// + /// + /// + public static string GetSignature(string jsapi_ticket, string timestamp, string noncestr, string url = null) + { + if (string.IsNullOrEmpty(jsapi_ticket) || string.IsNullOrEmpty(noncestr) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(url)) + return null; + + //将字段添加到列表中。 + string[] arr = new[] + { + string.Format("jsapi_ticket={0}",jsapi_ticket), + string.Format("noncestr={0}",noncestr), + string.Format("timestamp={0}",timestamp), + string.Format("url={0}",url) + }; + //字典排序 + Array.Sort(arr); + //使用URL键值对的格式拼接成字符串 + var temp = string.Join("&", arr); + + var sha1Arr = SHA1.HashData(Encoding.UTF8.GetBytes(temp)); + + return BitConverter.ToString(sha1Arr).Replace("-", "").ToLower(); + } + } +} diff --git a/ZR.Common/WxNoticeHelper.cs b/ZR.Common/WxNoticeHelper.cs index 976feb6..a89ab73 100644 --- a/ZR.Common/WxNoticeHelper.cs +++ b/ZR.Common/WxNoticeHelper.cs @@ -1,6 +1,7 @@ using Infrastructure; using System.Collections.Generic; using System.Text.Json; +using ZR.Common.Model; namespace ZR.Common { @@ -44,7 +45,7 @@ namespace ZR.Common System.Console.WriteLine("请完成企业微信配置"); return (0, "请完成企业微信通知配置"); } - GetTokenResult tokenResult = GetAccessToken(); + WxTokenResult tokenResult = GetAccessToken(); if (tokenResult == null || tokenResult.errcode != 0) { @@ -74,7 +75,7 @@ namespace ZR.Common //返回结果 //{"errcode":0,"errmsg":"ok","invaliduser":""} string msgResult = HttpHelper.HttpPost(msgUrl, postData, "contentType/json"); - GetTokenResult getTokenResult = JsonSerializer.Deserialize(msgResult); + WxTokenResult getTokenResult = JsonSerializer.Deserialize(msgResult); System.Console.WriteLine(msgResult); return (getTokenResult?.errcode == 0 ? 100 : 0, getTokenResult?.errmsg); } @@ -89,12 +90,12 @@ namespace ZR.Common /// /// {"errcode":0,"errmsg":"ok","access_token":"iCbcfE1OjfRhV0_io-CzqTNC0lnrudeW3oF5rhJKfmINaxLClLa1FoqAY_wEXtodYh_DTnrtAwZfzeb-NRXvwiOoqUTHx3i6QKLYcfBtF8y-xd5mvaeaf3e9mvTAPhmX0lkm1cLTwRLmoa1IwzgQ-QZEZcuIcntWdEMGseVYok3BwCGpC87bt6nNdgnekZdFVRp1uuaxoctDGlXpoQlQsA","expires_in":7200} /// - private static GetTokenResult GetAccessToken() + private static WxTokenResult GetAccessToken() { string getTokenUrl = $"{GetTokenUrl}?corpid={CORPID}&corpsecret={CORPSECRET}"; string getTokenResult = HttpHelper.HttpGet(getTokenUrl); System.Console.WriteLine(getTokenResult); - GetTokenResult tokenResult = JsonSerializer.Deserialize(getTokenResult); + WxTokenResult tokenResult = JsonSerializer.Deserialize(getTokenResult); return tokenResult; } @@ -146,15 +147,5 @@ namespace ZR.Common }; return dic; } - - public class GetTokenResult - { - /// - /// 0、正常 - /// - public int errcode { get; set; } - public string errmsg { get; set; } - public string access_token { get; set; } - } } }