sunpengfei
2025-11-21 9f7df6c82745bf3f3722114610653c77fac68a43
feat:开发
7个文件已删除
8个文件已修改
5个文件已添加
938 ■■■■ 已修改文件
ApiTools.Application/ApiTools.Application.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/ApiTools.Application.xml 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Commands/SaveWxCommandHandler.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Commands/SaveWxSettingCommandHandler.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Commands/WxmpSubscribMessageCommandHandler.cs 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Queries/GetWxSettingQueryHandler.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/ApiTools.Core.xml 228 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Entities/WxmpUtils/WxSetting.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Enums/Resources/EnumResourceController.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Enums/WxmpUtils/EnumTemplate.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Enums/WxmpUtils/EnumWxmpSubscribMessageTemplate.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSendCommand.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSettingCommand.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Models/WxmpUtils/Commands/WxmpSendSubscribMessageCommand.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Models/WxmpUtils/Commands/WxmpSubscribMessageNotifyCommand.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpSendSubscribMessageRequest.cs 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Web.Entry/appsettings.json 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/ApiTools.Application.csproj
@@ -16,4 +16,8 @@
        <ProjectReference Include="..\ApiTools.Core\ApiTools.Core.csproj" />
    </ItemGroup>
    <ItemGroup>
      <Folder Include="WxUtils\Queries\" />
    </ItemGroup>
</Project>
ApiTools.Application/ApiTools.Application.xml
@@ -215,6 +215,22 @@
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.Application.WxmpSubscribMessageCommandHandler.Handle(ApiTools.Core.WxmpSendSubscribMessageCommand,System.Threading.CancellationToken)">
            <summary>
            微信小程序发送订阅消息
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.Application.WxmpSubscribMessageCommandHandler.Handle(ApiTools.Core.WxmpSubscribMessageNotifyCommand,System.Threading.CancellationToken)">
            <summary>
            微信小程序订阅消息通知
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="T:ApiTools.CommonServer.Application.SaveSmsSettingCommandHandler">
            <summary>
            保存短信配置
@@ -282,22 +298,6 @@
        <member name="M:ApiTools.CommonServer.Application.GetSmsSettingQueryHandler.Handle(ApiTools.Core.GetSmsSettingQuery,System.Threading.CancellationToken)">
            <summary>
            查询短信配置
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.CommonServer.Application.SaveWxCommandHandler.Handle(ApiTools.Core.SaveWxSendCommand,System.Threading.CancellationToken)">
            <summary>
            该接口用于发送订阅消息
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.CommonServer.Application.SaveWxSettingCommandHandler.Handle(ApiTools.Core.SaveWxSettingCommand,System.Threading.CancellationToken)">
            <summary>
            保存微信配置
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
ApiTools.Application/WxUtils/Commands/SaveWxCommandHandler.cs
File was deleted
ApiTools.Application/WxUtils/Commands/SaveWxSettingCommandHandler.cs
File was deleted
ApiTools.Application/WxUtils/Commands/WxmpSubscribMessageCommandHandler.cs
New file
@@ -0,0 +1,66 @@
using Aop.Api.Domain;
using ApiTools.Core;
using log4net.Core;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Application
{
    public class WxmpSubscribMessageCommandHandler(
            ILogger<WxmpSubscribMessageCommandHandler> logger,
            WxmpUtils utils,
            IHttpContextAccessor httpContextAccessor
        ) :
        IRequestHandler<WxmpSendSubscribMessageCommand, Guid>,
        IRequestHandler<WxmpSubscribMessageNotifyCommand, bool>
    {
        private readonly ILogger<WxmpSubscribMessageCommandHandler> logger = logger;
        private readonly WxmpUtils utils = utils;
        private readonly IHttpContextAccessor httpContextAccessor = httpContextAccessor;
        /// <summary>
        /// 微信小程序发送订阅消息
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<Guid> Handle(WxmpSendSubscribMessageCommand request, CancellationToken cancellationToken)
        {
            await utils.WxmpSendSubscribMessage(new WxmpSendSubscribMessageRequest
            {
                Data = request.Data,
                TemplateId = request.Template.ToString(),
                Page = request.Page,
                WxmpCode = request.WxmpCode,
                Touser = request.Touser,
            });
            return Guid.Empty;
        }
        /// <summary>
        /// 微信小程序订阅消息通知
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Handle(WxmpSubscribMessageNotifyCommand request, CancellationToken cancellationToken)
        {
            var req = httpContextAccessor.HttpContext.Request;
            logger.LogInformation($"微信小程序订阅消息通知query:{req.QueryString.Value}");
            req.EnableBuffering();
            req.Body.Position = 0;
            using var reader = new StreamReader(req.Body, Encoding.UTF8, leaveOpen: true);
            var body = await reader.ReadToEndAsync();
            logger.LogInformation($"微信小程序订阅消息通知body:{body}");
            req.Body.Position = 0;
            return true;
        }
    }
}
ApiTools.Application/WxUtils/Queries/GetWxSettingQueryHandler.cs
File was deleted
ApiTools.Core/ApiTools.Core.xml
@@ -1280,31 +1280,6 @@
            状态
            </summary>
        </member>
        <member name="T:ApiTools.Core.WxSetting">
            <summary>
            微信配置
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxSetting.Code">
            <summary>
            编号
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxSetting.AppId">
            <summary>
            小程序ID
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxSetting.AppSecret">
            <summary>
            小程序密钥
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxSetting.EnvVersion">
            <summary>
            版本
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumErrorCodeType.s400">
            <summary>
            参数错误
@@ -1525,7 +1500,7 @@
            短信工具
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumResourceController.CommonServerWxUtils">
        <member name="F:ApiTools.Core.EnumResourceController.CommonServerWxmpUtils">
            <summary>
            微信工具
            </summary>
@@ -1957,6 +1932,36 @@
            转账
            </summary>
        </member>
        <member name="T:ApiTools.Core.EnumWxmpSubscribMessageTemplate">
            <summary>
            微信小程序订阅消息模板
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumWxmpSubscribMessageTemplate.SettlementCompletedToSupplier">
            <summary>
            支付成功提醒  结算完成后向承揽端管理员推送
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumWxmpSubscribMessageTemplate.SettlementAuditCompletedToSupplier">
            <summary>
            报酬结算审核结果通知  甲方结算确认后向承揽端管理员推送
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumWxmpSubscribMessageTemplate.SettlementReceiveCompletedToUser">
            <summary>
            工资发放通知  结算完成后向C端人员通知
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumWxmpSubscribMessageTemplate.HireCompletedToUser">
            <summary>
            报名录用结果通知  被录用后向C端人员通知
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumWxmpSubscribMessageTemplate.ArrangeCompletedToUser">
            <summary>
            排班成功通知  排班后向C端人员通知
            </summary>
        </member>
        <member name="T:ApiTools.Core.IIsDisabled">
            <summary>
            是否已禁用
@@ -2001,6 +2006,16 @@
        <member name="P:ApiTools.Core.ITreeData`1.Code">
            <summary>
            编号
            </summary>
        </member>
        <member name="T:ApiTools.Core.Jobs.RefreshChannelWalletSignStatusJob">
            <summary>
            刷新渠道钱包状态
            </summary>
        </member>
        <member name="M:ApiTools.Core.Jobs.RefreshChannelWalletSignStatusJob.#ctor(ApiTools.Core.ChannelWalletRepository,ApiTools.Core.ChannelWalletService)">
            <summary>
            刷新渠道钱包状态
            </summary>
        </member>
        <member name="T:ApiTools.Core.RefreshChannelWalletTransactionStatusJob">
@@ -3268,64 +3283,39 @@
            签名名称
            </summary>
        </member>
        <member name="T:ApiTools.Core.SaveWxSendCommand">
        <member name="T:ApiTools.Core.WxmpSendSubscribMessageCommand">
            <summary>
            该接口用于发送订阅消息
            微信小程序发送订阅消息
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.WxmpCode">
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageCommand.WxmpCode">
            <summary>
            小程序编号
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.Template_id">
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageCommand.Template">
            <summary>
            所需下发的订阅模板id(做成枚举)
            所需下发的订阅模板id
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.Page">
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageCommand.Page">
            <summary>
            点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转(做到配置文件里面)
            点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.Touser">
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageCommand.Touser">
            <summary>
            接收者(用户)的 openid
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.Data">
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageCommand.Data">
            <summary>
            模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSendCommand.Lang">
        <member name="T:ApiTools.Core.WxmpSubscribMessageNotifyCommand">
            <summary>
            语言(默认中文)
            </summary>
        </member>
        <member name="T:ApiTools.Core.SaveWxSettingCommand">
            <summary>
            保存微信配置
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSettingCommand.Code">
            <summary>
            编号
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSettingCommand.AppId">
            <summary>
            小程序ID
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSettingCommand.AppSecret">
            <summary>
            小程序密钥
            </summary>
        </member>
        <member name="P:ApiTools.Core.SaveWxSettingCommand.EnvVersion">
            <summary>
            版本
            微信小程序订阅消息通知
            </summary>
        </member>
        <member name="M:ApiTools.Core.BaseRepository`2.GetQueryable(System.Boolean)">
@@ -6990,49 +6980,24 @@
            错误信息
            </summary>
        </member>
        <member name="T:ApiTools.Core.SendRequest">
            <summary>
            发送订阅消息
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.WxmpCode">
            <summary>
            小程序编号
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.EnvVersion">
            <summary>
            要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.Template_id">
            <summary>
            所需下发的订阅模板id
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.Page">
            <summary>
            点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.Touser">
            <summary>
            接收者(用户)的 openid
            </summary>
        </member>
        <member name="P:ApiTools.Core.SendRequest.Data">
            <summary>
            模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
            </summary>
        </member>
        <member name="T:ApiTools.Core.SendResponse">
            <summary>
            发送订阅消息-结果
            </summary>
        </member>
        <member name="T:ApiTools.Core.WxmpOptions">
            <summary>
            微信小程序配置
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpOptions.SubscribMessageTemplates">
            <summary>
            订阅消息模板
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpOptionsSubscribMessageTemplate.TemplateId">
            <summary>
            模板Id
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpOptionsSubscribMessageTemplate.Page">
            <summary>
            页面
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpOptionsItem.Code">
@@ -7055,6 +7020,61 @@
            版本
            </summary>
        </member>
        <member name="T:ApiTools.Core.WxmpSendSubscribMessageRequest">
            <summary>
            微信小程序发送订阅消息
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.WxmpCode">
            <summary>
            小程序编号
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.TemplateId">
            <summary>
            所需下发的订阅模板id
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.Page">
            <summary>
            点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.Touser">
            <summary>
            接收者(用户)的 openid
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.Data">
            <summary>
            模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.EnvVersion">
            <summary>
            跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageRequest.Lang">
            <summary>
            进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
            </summary>
        </member>
        <member name="T:ApiTools.Core.WxmpSendSubscribMessageResponse">
            <summary>
            微信小程序发送订阅消息
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageResponse.ErrorCode">
            <summary>
            错误码
            </summary>
        </member>
        <member name="P:ApiTools.Core.WxmpSendSubscribMessageResponse.ErrorMessage">
            <summary>
            错误信息
            </summary>
        </member>
        <member name="T:ApiTools.Core.WxmpUtils">
            <summary>
            微信小程序工具
@@ -7074,9 +7094,9 @@
            <param name="command"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.Core.WxmpUtils.WxSend(ApiTools.Core.SendRequest)">
        <member name="M:ApiTools.Core.WxmpUtils.WxmpSendSubscribMessage(ApiTools.Core.WxmpSendSubscribMessageRequest)">
            <summary>
            该接口用于发送订阅消息
            发送订阅消息
            </summary>
            <param name="command"></param>
            <returns></returns>
ApiTools.Core/Entities/WxmpUtils/WxSetting.cs
File was deleted
ApiTools.Core/Enums/Resources/EnumResourceController.cs
@@ -35,8 +35,8 @@
        /// <summary>
        /// 微信工具
        /// </summary>
        [ResourceController(EnumResourceService.CommonServer, "Wx")]
        CommonServerWxUtils,
        [ResourceController(EnumResourceService.CommonServer, "Wxmp")]
        CommonServerWxmpUtils,
        /// <summary>
        /// 用户认证
ApiTools.Core/Enums/WxmpUtils/EnumTemplate.cs
File was deleted
ApiTools.Core/Enums/WxmpUtils/EnumWxmpSubscribMessageTemplate.cs
New file
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Core
{
    /// <summary>
    /// 微信小程序订阅消息模板
    /// </summary>
    public enum EnumWxmpSubscribMessageTemplate
    {
        /// <summary>
        /// 支付成功提醒  结算完成后向承揽端管理员推送
        /// </summary>
        SettlementCompletedToSupplier,
        /// <summary>
        /// 报酬结算审核结果通知  甲方结算确认后向承揽端管理员推送
        /// </summary>
        SettlementAuditCompletedToSupplier,
        /// <summary>
        /// 工资发放通知  结算完成后向C端人员通知
        /// </summary>
        SettlementReceiveCompletedToUser,
        /// <summary>
        /// 报名录用结果通知  被录用后向C端人员通知
        /// </summary>
        HireCompletedToUser,
        /// <summary>
        /// 排班成功通知  排班后向C端人员通知
        /// </summary>
        ArrangeCompletedToUser,
    }
}
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSendCommand.cs
File was deleted
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSettingCommand.cs
File was deleted
ApiTools.Core/Models/WxmpUtils/Commands/WxmpSendSubscribMessageCommand.cs
New file
@@ -0,0 +1,47 @@
using MediatR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Core
{
    /// <summary>
    /// 微信小程序发送订阅消息
    /// </summary>
    [Resource([EnumResourceController.CommonServerWxmpUtils], Method = EnumResourceMethod.Post)]
    public class WxmpSendSubscribMessageCommand : IRequest<Guid>
    {
        /// <summary>
        /// 小程序编号
        /// </summary>
        [Required]
        public string WxmpCode { get; set; }
        /// <summary>
        /// 所需下发的订阅模板id
        /// </summary>
        [Required]
        public EnumWxmpSubscribMessageTemplate Template { get; set; }
        /// <summary>
        /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
        /// </summary>
        public string Page { get; set; }
        /// <summary>
        /// 接收者(用户)的 openid
        /// </summary>
        [Required]
        public string Touser { get; set; }
        /// <summary>
        /// 模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
        /// </summary>
        [Required]
        public object Data { get; set; }
    }
}
ApiTools.Core/Models/WxmpUtils/Commands/WxmpSubscribMessageNotifyCommand.cs
New file
@@ -0,0 +1,22 @@
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Core
{
    /// <summary>
    /// 微信小程序订阅消息通知
    /// </summary>
    [Resource([EnumResourceController.CommonServerWxmpUtils], Method = EnumResourceMethod.Post)]
    public class WxmpSubscribMessageNotifyCommand : IRequest<bool>
    {
        public string ToUserName { get; set; }
        public string FromUserName { get; set; }
        public DateTime CreateTime { get; set; }
        public string MsgType { get; set; }
        public string Event { get; set; }
    }
}
ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs
@@ -106,73 +106,4 @@
        public string ErrorMessage { get; set; }
    }
    /// <summary>
    /// 发送订阅消息
    /// </summary>
    public class SendRequest
    {
        /// <summary>
        /// 小程序编号
        /// </summary>
        [JsonProperty("WxmpCode")]
        [Required]
        public string WxmpCode { get; set; }
        /// <summary>
        /// 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
        /// </summary>
        [JsonProperty("env_version")]
        public string EnvVersion { get; set; }
        /// <summary>
        /// 所需下发的订阅模板id
        /// </summary>
        [JsonProperty("Template_id")]
        [Required]
        public string Template_id { get; set; }
        /// <summary>
        /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
        /// </summary>
        [JsonProperty("Page")]
        [Required]
        public string Page { get; set; }
        /// <summary>
        /// 接收者(用户)的 openid
        /// </summary>
        [JsonProperty("Touser")]
        [Required]
        public string Touser { get; set; }
        /// <summary>
        /// 模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
        /// </summary>
        [JsonProperty("Data")]
        [Required]
        public object Data { get; set; }
        [JsonProperty("跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版")]
        [Required]
        public string Miniprogram_state { get; set; }
        [JsonProperty("进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN")]
        [Required]
        public string Lang { get; set; }
    }
    /// <summary>
    /// 发送订阅消息-结果
    /// </summary>
    public class SendResponse
    {
        [JsonProperty("ErrorCode")]
        public int ErrorCode { get; set; }
        [JsonProperty("errmsg")]
        public int errmsg { get; set; }
    }
}
ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs
@@ -18,6 +18,24 @@
        }
        public List<WxmpOptionsItem> Items { get; set; }
        /// <summary>
        /// 订阅消息模板
        /// </summary>
        public Dictionary<string, WxmpOptionsSubscribMessageTemplate> SubscribMessageTemplates { get; set; } = [];
    }
    public class WxmpOptionsSubscribMessageTemplate
    {
        /// <summary>
        /// 模板Id
        /// </summary>
        public string TemplateId { get; set; }
        /// <summary>
        /// 页面
        /// </summary>
        public string Page { get; set; }
    }
    public class WxmpOptionsItem
ApiTools.Core/Utils/WxmpUtils/WxmpSendSubscribMessageRequest.cs
New file
@@ -0,0 +1,80 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Core
{
    /// <summary>
    /// 微信小程序发送订阅消息
    /// </summary>
    public class WxmpSendSubscribMessageRequest
    {
        /// <summary>
        /// 小程序编号
        /// </summary>
        [JsonIgnore]
        public string WxmpCode { get; set; }
        /// <summary>
        /// 所需下发的订阅模板id
        /// </summary>
        [JsonProperty("template_id")]
        [Required]
        public string TemplateId { get; set; }
        /// <summary>
        /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
        /// </summary>
        [JsonProperty("page")]
        public string Page { get; set; }
        /// <summary>
        /// 接收者(用户)的 openid
        /// </summary>
        [JsonProperty("touser")]
        [Required]
        public string Touser { get; set; }
        /// <summary>
        /// 模板内容,格式形如{ "phrase3": { "value": "审核通过" }, "name1": { "value": "订阅" }, "date2": { "value": "2019-12-25 09:42" } }
        /// </summary>
        [JsonProperty("data")]
        [Required]
        public object Data { get; set; }
        /// <summary>
        /// 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
        /// </summary>
        [JsonProperty("miniprogram_state")]
        [Required]
        public string EnvVersion { get; set; }
        /// <summary>
        /// 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
        /// </summary>
        [JsonProperty("lang")]
        [Required]
        public string Lang { get; set; } = "zh_CN";
    }
    /// <summary>
    /// 微信小程序发送订阅消息
    /// </summary>
    public class WxmpSendSubscribMessageResponse
    {
        /// <summary>
        /// 错误码
        /// </summary>
        [JsonProperty("errcode")]
        public int ErrorCode { get; set; }
        /// <summary>
        /// 错误信息
        /// </summary>
        [JsonProperty("errmsg")]
        public string ErrorMessage { get; set; }
    }
}
ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs
@@ -130,19 +130,23 @@
        }
        /// <summary>
        /// 该接口用于发送订阅消息
        /// 发送订阅消息
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public async Task<string> WxSend(SendRequest command)
        public async Task WxmpSendSubscribMessage(WxmpSendSubscribMessageRequest command)
        {
            var option = options.Value.Items.FirstOrDefault(it => it.Code == command.WxmpCode);
            if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
                throw Oops.Oh(EnumErrorCodeType.s400, "获取小程序码失败,缺失配置:WxmpOptions");
                throw Oops.Oh(EnumErrorCodeType.s400, "发送订阅消息失败,缺失配置:WxmpOptions");
            command.EnvVersion = option.EnvVersion;
            if (!options.Value.SubscribMessageTemplates.ContainsKey(command.TemplateId))
                throw Oops.Oh(EnumErrorCodeType.s400, "发送订阅消息失败,模板不存在");
            var template = options.Value.SubscribMessageTemplates[command.TemplateId];
            command.TemplateId = template.TemplateId;
            if (command.Page.IsNull()) command.Page = template.Page;
            var accessToken = await GetAccessToken(command.WxmpCode);
            var request = command.Adapt<SendRequest>();
            var jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings
            var jsonContent = JsonConvert.SerializeObject(command, new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore
            });
@@ -151,22 +155,13 @@
                .WithQueryParameter("access_token", accessToken)
                .SetJsonContent(jsonContent));
            response.EnsureSuccessStatusCode();
            //var a = response.Content.Headers.ContentType.ToString();
            //application/json; encoding=utf-8
            //if (response.Content.Headers.ContentType.ToString() == "application/json; charset=UTF-8")
            if (response.Content.Headers.ContentType.ToString() == "application/json; encoding=utf-8")
            if (response.Content.Headers.ContentType.ToString() == "application/json; charset=UTF-8")
            {
                var jsonResult = await response.Content.ReadAsStringAsync();
                //var callback = jsonResult.JsonTo<SendResponse>();
                //if (callback == null || callback.ErrorCode != 0)
                    //throw Oops.Oh(EnumErrorCodeType.s510, $"获取小程序码失败:{callback.errmsg},请联系管理员");
                return jsonResult;
                var callback = jsonResult.JsonTo<WxmpSendSubscribMessageResponse>();
                if (callback == null || callback.ErrorCode != 0)
                    throw Oops.Oh(EnumErrorCodeType.s510, $"发送订阅消息失败:{callback.ErrorMessage},请联系管理员");
            }
            //var stream = await response.Content.ReadAsStreamAsync();
            //var result = AliyunOSSUtils.Upload(command, stream, command.OssFileName);
            return "";
        }
    }
}
ApiTools.Web.Entry/appsettings.json
@@ -52,7 +52,34 @@
        "AppSecret": "c03a62ad6822f1c925532c34183e7f7f",
        "EnvVersion": "trial"
      }
    ]
    ],
    "SubscribMessageTemplates": {
      // 支付成功提醒  结算完成后向承揽端管理员推送
      "SettlementCompletedToSupplier": {
        "TemplateId": "dz2HCc-EnR4WEfsuj2GuduF8SLu40J83xez1bLLbaC0",
        "Page": "pages/workbenches/workbenches"
      },
      // 报酬结算审核结果通知  甲方结算确认后向承揽端管理员推送
      "SettlementAuditCompletedToSupplier": {
        "TemplateId": "Qp6cetvhwONMS1y9LOBt4dZgq49Hc14lIsm-LVE0Hfo",
        "Page": "pages/workbenches/workbenches"
      },
      // 工资发放通知  结算完成后向C端人员通知
      "SettlementReceiveCompletedToUser": {
        "TemplateId": "pw-WntZZJjADXfLsxcs5S8pKlpTrSc-HtJs0ZZvqliE",
        "Page": "pages/home/index"
      },
      // 报名录用结果通知  被录用后向C端人员通知
      "HireCompletedToUser": {
        "TemplateId": "dz2HCc-EnR4WEfsuj2GuduF8SLu40J83xez1bLLbaC0",
        "Page": "pages/home/index"
      },
      // 排班成功通知  排班后向C端人员通知
      "ArrangeCompletedToUser": {
        "TemplateId": "dz2HCc-EnR4WEfsuj2GuduF8SLu40J83xez1bLLbaC0",
        "Page": "pages/home/index"
      }
    }
  },
  "Task": {
    "SettlementTime": "T0"