From 4af5ae8065b82268f23e8878455c869f11da9c07 Mon Sep 17 00:00:00 2001 From: zpc Date: Sun, 29 Mar 2026 20:03:12 +0800 Subject: [PATCH] feat(wechat): Add WeChat official account token and encryption key configuration - Add token and encodingAESKey fields to NotificationTemplatesConfig interface - Add UI form inputs for WeChat token and EncodingAESKey in system config page - Add configuration constants SaTokenKey and SaEncodingAesKeyKey to SystemConfigService - Update WeChatEventController to fetch token from database instead of hardcoded value - Make CheckSignature method async and retrieve token from ISystemConfigService - Update GetNotificationTemplates to include token and encodingAESKey from config - Update SetNotificationTemplates to persist token and encodingAESKey to database - Update mini app manifest with new appid - Enables dynamic WeChat server configuration without code changes --- admin/src/api/config.ts | 2 ++ admin/src/views/system/config.vue | 24 +++++++++++++++++++ miniapp/manifest.json | 2 +- .../Controllers/WeChatEventController.cs | 24 ++++++++++++------- .../Services/SystemConfigService.cs | 18 ++++++++++++++ 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/admin/src/api/config.ts b/admin/src/api/config.ts index 924ce2d..0c09497 100644 --- a/admin/src/api/config.ts +++ b/admin/src/api/config.ts @@ -189,6 +189,8 @@ export function setRealNamePrice(price: number) { * 服务号通知模板配置 */ export interface NotificationTemplatesConfig { + token?: string + encodingAESKey?: string unlockTemplateId?: string favoriteTemplateId?: string messageTemplateId?: string diff --git a/admin/src/views/system/config.vue b/admin/src/views/system/config.vue index faf3f3d..b7abdfe 100644 --- a/admin/src/views/system/config.vue +++ b/admin/src/views/system/config.vue @@ -313,6 +313,24 @@ style="margin-bottom: 24px;" /> + + +
在微信公众平台 → 基本配置 → 服务器配置中设置的Token,需保持一致
+
+ + + +
微信公众平台 → 基本配置 → 服务器配置中的消息加解密密钥,明文模式可不填
+
+ { try { const res = await getNotificationTemplates() if (res) { + templateForm.value.token = res.token || '' + templateForm.value.encodingAESKey = res.encodingAESKey || '' templateForm.value.unlockTemplateId = res.unlockTemplateId || '' templateForm.value.favoriteTemplateId = res.favoriteTemplateId || '' templateForm.value.messageTemplateId = res.messageTemplateId || '' @@ -709,6 +731,8 @@ const saveNotificationTemplates = async () => { savingTemplates.value = true try { await setNotificationTemplates({ + token: templateForm.value.token || undefined, + encodingAESKey: templateForm.value.encodingAESKey || undefined, unlockTemplateId: templateForm.value.unlockTemplateId || undefined, favoriteTemplateId: templateForm.value.favoriteTemplateId || undefined, messageTemplateId: templateForm.value.messageTemplateId || undefined, diff --git a/miniapp/manifest.json b/miniapp/manifest.json index 6af00ca..7bf37e5 100644 --- a/miniapp/manifest.json +++ b/miniapp/manifest.json @@ -1,6 +1,6 @@ { "name" : "相宜亲家", - "appid" : "__UNI__39EAECC", + "appid" : "__UNI__85044B9", "description" : "", "versionName" : "1.0.0", "versionCode" : "100", diff --git a/server/src/XiangYi.AppApi/Controllers/WeChatEventController.cs b/server/src/XiangYi.AppApi/Controllers/WeChatEventController.cs index 7985f04..4444a1f 100644 --- a/server/src/XiangYi.AppApi/Controllers/WeChatEventController.cs +++ b/server/src/XiangYi.AppApi/Controllers/WeChatEventController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using System.Security.Cryptography; using System.Text; using System.Xml.Linq; +using XiangYi.Application.Interfaces; using XiangYi.Core.Entities.Biz; using XiangYi.Core.Interfaces; @@ -19,30 +20,30 @@ public class WeChatEventController : ControllerBase private readonly IRepository _userRepository; private readonly ILogger _logger; private readonly IConfiguration _configuration; - - // 服务号Token(需要在微信公众平台配置) - private const string Token = "xiangyi2024"; + private readonly ISystemConfigService _configService; public WeChatEventController( IRepository userRepository, ILogger logger, - IConfiguration configuration) + IConfiguration configuration, + ISystemConfigService configService) { _userRepository = userRepository; _logger = logger; _configuration = configuration; + _configService = configService; } /// /// 微信服务器验证(GET请求) /// [HttpGet] - public IActionResult Verify(string signature, string timestamp, string nonce, string echostr) + public async Task Verify(string signature, string timestamp, string nonce, string echostr) { _logger.LogInformation("收到微信服务器验证请求: signature={Signature}, timestamp={Timestamp}, nonce={Nonce}", signature, timestamp, nonce); - if (CheckSignature(signature, timestamp, nonce)) + if (await CheckSignatureAsync(signature, timestamp, nonce)) { _logger.LogInformation("微信服务器验证成功"); return Content(echostr); @@ -169,9 +170,16 @@ public class WeChatEventController : ControllerBase /// /// 验证微信签名 /// - private bool CheckSignature(string signature, string timestamp, string nonce) + private async Task CheckSignatureAsync(string signature, string timestamp, string nonce) { - var arr = new[] { Token, timestamp, nonce }; + var token = await _configService.GetConfigValueAsync("sa_token"); + if (string.IsNullOrEmpty(token)) + { + _logger.LogWarning("服务号Token未配置"); + return false; + } + + var arr = new[] { token, timestamp, nonce }; Array.Sort(arr); var str = string.Join("", arr); diff --git a/server/src/XiangYi.Application/Services/SystemConfigService.cs b/server/src/XiangYi.Application/Services/SystemConfigService.cs index 64f72ee..888ea75 100644 --- a/server/src/XiangYi.Application/Services/SystemConfigService.cs +++ b/server/src/XiangYi.Application/Services/SystemConfigService.cs @@ -98,6 +98,8 @@ public class SystemConfigService : ISystemConfigService /// public const decimal DefaultRealNamePrice = 88m; + public const string SaTokenKey = "sa_token"; + public const string SaEncodingAesKeyKey = "sa_encoding_aes_key"; public const string SaUnlockTemplateIdKey = "sa_unlock_template_id"; public const string SaFavoriteTemplateIdKey = "sa_favorite_template_id"; public const string SaMessageTemplateIdKey = "sa_message_template_id"; @@ -355,6 +357,8 @@ public class SystemConfigService : ISystemConfigService { return new NotificationTemplatesDto { + Token = await GetConfigValueAsync(SaTokenKey), + EncodingAESKey = await GetConfigValueAsync(SaEncodingAesKeyKey), UnlockTemplateId = await GetConfigValueAsync(SaUnlockTemplateIdKey), FavoriteTemplateId = await GetConfigValueAsync(SaFavoriteTemplateIdKey), MessageTemplateId = await GetConfigValueAsync(SaMessageTemplateIdKey), @@ -367,6 +371,10 @@ public class SystemConfigService : ISystemConfigService { try { + if (!string.IsNullOrEmpty(templates.Token)) + await SetConfigValueAsync(SaTokenKey, templates.Token, "服务号验证Token"); + if (!string.IsNullOrEmpty(templates.EncodingAESKey)) + await SetConfigValueAsync(SaEncodingAesKeyKey, templates.EncodingAESKey, "服务号消息加解密密钥"); if (!string.IsNullOrEmpty(templates.UnlockTemplateId)) await SetConfigValueAsync(SaUnlockTemplateIdKey, templates.UnlockTemplateId, "服务号解锁通知模板ID"); if (!string.IsNullOrEmpty(templates.FavoriteTemplateId)) @@ -416,6 +424,16 @@ public class MemberIconsDto /// public class NotificationTemplatesDto { + /// + /// 服务号验证Token(微信公众平台配置的Token) + /// + public string? Token { get; set; } + + /// + /// 服务号消息加解密密钥(EncodingAESKey) + /// + public string? EncodingAESKey { get; set; } + /// /// 解锁通知模板ID ///