sunpengfei
2025-11-20 1deb3d68f4caf2f54107e67c991ec9e50b360fa0
Merge branch 'dev-818-3.4.2.12' of http://120.26.58.240:8888/r/ApiTools into dev-818-3.4.2.12
7个文件已修改
5个文件已添加
422 ■■■■■ 已修改文件
ApiTools.Application/ApiTools.Application.csproj 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/ApiTools.Application.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Commands/SaveWxCommandHandler.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Commands/SaveWxSettingCommandHandler.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/WxUtils/Queries/GetWxSettingQueryHandler.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/ApiTools.Core.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/ApiTools.Core.xml 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Entities/WxmpUtils/WxSetting.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Enums/Resources/EnumResourceController.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSettingCommand.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ApiTools.Application/ApiTools.Application.csproj
@@ -8,6 +8,11 @@
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>
    <ItemGroup>
      <Compile Remove="WxUtils\Commands\SaveWxCommandHandler.cs" />
    </ItemGroup>
    <ItemGroup>
        <None Remove="ApiTools.Application.xml" />
    </ItemGroup>
ApiTools.Application/ApiTools.Application.xml
@@ -287,5 +287,13 @@
            <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>
            <returns></returns>
        </member>
    </members>
</doc>
ApiTools.Application/WxUtils/Commands/SaveWxCommandHandler.cs
New file
@@ -0,0 +1,29 @@
using ApiTools.Core;
using Baidu.Aip;
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.CommonServer.Application
{
    public class SaveWxCommandHandler(WxmpUtils utils) : IRequestHandler<SaveWxSettingCommand, Guid>
    {
        public async Task<Guid> Handle(SaveWxSettingCommand request, CancellationToken cancellationToken)
        {
            return await utils.WxSend(new SendRequest
            {
                WxmpCode = request.Code,
                EnvVersion = request.EnvVersion,
                template_id = request.t,
                page = request.ChannelCreatedUserId,
                touser = request.ChannelCreatedUserId,
                data =
                miniprogram_state=
                lang=
            }, request.TemplateParam, cancellationToken);
        }
    }
}
ApiTools.Application/WxUtils/Commands/SaveWxSettingCommandHandler.cs
New file
@@ -0,0 +1,53 @@
using ApiTools.Core;
using Furion.DatabaseAccessor;
using Mapster;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.CommonServer.Application
{
    public class SaveWxSettingCommandHandler(IRepository<WxSetting> rep) :IRequestHandler<SaveWxSettingCommand, Guid>
    {
        private readonly IRepository<WxSetting> rep = rep;
        /// <summary>
        /// 保存微信配置
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<Guid> Handle(SaveWxSettingCommand request, CancellationToken cancellationToken)
        {
            var logier = JwtUtils.GetCurrentLogier();
            var entity = await rep.AsQueryable()
                .Where(it => it.Code == request.Code)
                .FirstOrDefaultAsync();
            var add = false;
            if (entity == null)
            {
                entity = new WxSetting();
                entity.Code = request.Code;
                entity.AppId = request.AppId;
                entity.AppSecret = request.AppSecret;
                entity.EnvVersion = request.EnvVersion;
                add = true;
            }
            request.Adapt(entity);
            if (add)
            {
                await rep.InsertAsync(entity);
            }
            else
            {
                await rep.UpdateAsync(entity);
            }
            return entity.Id;
            //return Guid.NewGuid();
        }
    }
}
ApiTools.Application/WxUtils/Queries/GetWxSettingQueryHandler.cs
New file
@@ -0,0 +1,34 @@
using ApiTools.Core;
using Furion.DatabaseAccessor;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.CommonServer.Application
{
    //public class GetWxSettingQueryHandler(IRepository<SmsSetting> rep, IRepository<SmsLog> repSmsLog) : IRequestHandler<GetSmsSettingQuery, GetSmsSettingQueryResult>
    //{
    //    private readonly IRepository<SmsSetting> rep = rep;
    //    private readonly IRepository<SmsLog> repSmsLog = repSmsLog;
    //    /// <summary>
    //    /// 查询短信配置
    //    /// </summary>
    //    /// <param name="request"></param>
    //    /// <param name="cancellationToken"></param>
    //    /// <returns></returns>
    //    public async Task<GetSmsSettingQueryResult> Handle(GetSmsSettingQuery request, CancellationToken cancellationToken)
    //    {
    //        var logier = JwtUtils.GetCurrentLogier();
    //        var detail = await rep.AsQueryable().AsNoTracking()
    //            .Where(it => it.ChannelId == logier.ChannelId)
    //            .GetDetail<SmsSetting, GetSmsSettingQueryResult>();
    //        detail.Accesses = detail.Accesses.OrderBy(it => it.Sort).ToList();
    //        return detail;
    //    }
    //}
}
ApiTools.Core/ApiTools.Core.csproj
@@ -39,4 +39,8 @@
      </None>
    </ItemGroup>
    <ItemGroup>
      <Folder Include="Models\WxmpUtils\Queries\" />
    </ItemGroup>
</Project>
ApiTools.Core/ApiTools.Core.xml
@@ -1280,6 +1280,31 @@
            状态
            </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>
            参数错误
@@ -1498,6 +1523,11 @@
        <member name="F:ApiTools.Core.EnumResourceController.CommonServerSmsUtils">
            <summary>
            短信工具
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumResourceController.CommonServerWxUtils">
            <summary>
            微信工具
            </summary>
        </member>
        <member name="F:ApiTools.Core.EnumResourceController.UserServerAuth">
@@ -3236,6 +3266,31 @@
        <member name="P:ApiTools.Core.GetSmsSettingQueryResultAccess.SignName">
            <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)">
@@ -6900,6 +6955,46 @@
            错误信息
            </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>
            微信小程序配置
@@ -6944,6 +7039,13 @@
            <param name="command"></param>
            <returns></returns>
        </member>
        <member name="M:ApiTools.Core.WxmpUtils.WxSend(ApiTools.Core.SendRequest)">
            <summary>
            该接口用于发送订阅消息
            </summary>
            <param name="command"></param>
            <returns></returns>
        </member>
        <member name="T:ApiTools.Core.XmlDoc">
            <summary>
            注释文档
ApiTools.Core/Entities/WxmpUtils/WxSetting.cs
New file
@@ -0,0 +1,36 @@
using Furion.DatabaseAccessor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ApiTools.Core
{
    /// <summary>
    /// 微信配置
    /// </summary>
    public class WxSetting : CommonEntity<MasterDbContextLocator>
    {
        /// <summary>
        /// 编号
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 小程序ID
        /// </summary>
        public string AppId { get; set; }
        /// <summary>
        /// 小程序密钥
        /// </summary>
        public string AppSecret { get; set; }
        /// <summary>
        /// 版本
        /// </summary>
        public string EnvVersion { get; set; }
    }
}
ApiTools.Core/Enums/Resources/EnumResourceController.cs
@@ -33,6 +33,12 @@
        CommonServerSmsUtils,
        /// <summary>
        /// 微信工具
        /// </summary>
        [ResourceController(EnumResourceService.CommonServer, "Wx")]
        CommonServerWxUtils,
        /// <summary>
        /// 用户认证
        /// </summary>
        [ResourceController(EnumResourceService.UserServer, "Auth")]
ApiTools.Core/Models/WxmpUtils/Commands/SaveWxSettingCommand.cs
New file
@@ -0,0 +1,36 @@
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.CommonServerWxUtils], Method = EnumResourceMethod.Post)]
    public class SaveWxSettingCommand : IRequest<Guid>
    {
        /// <summary>
        /// 编号
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 小程序ID
        /// </summary>
        public string AppId { get; set; }
        /// <summary>
        /// 小程序密钥
        /// </summary>
        public string AppSecret { get; set; }
        /// <summary>
        /// 版本
        /// </summary>
        public string EnvVersion { get; set; }
    }
}
ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs
@@ -106,4 +106,73 @@
        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/WxmpUtils.cs
@@ -1,6 +1,7 @@
using Aliyun.OSS;
using Azure.Core;
using Aop.Api.Domain;
using ApiTools.Core.Utils.WxmpUtils;
using Azure.Core;
using Furion.FriendlyException;
using Furion.HttpRemote;
using Mapster;
@@ -124,5 +125,42 @@
            var result = AliyunOSSUtils.Upload(command.OssScene, stream, command.OssFileName);
            return result.Url;
        }
        /// <summary>
        /// 该接口用于发送订阅消息
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public async Task<string> WxSend(SendRequest 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");
            command.EnvVersion = option.EnvVersion;
            var accessToken = await GetAccessToken(command.WxmpCode);
            var request = command.Adapt<SendRequest>();
            var jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore
            });
            var response = await httpRemoteService.PostAsync("https://api.weixin.qq.com/cgi-bin/message/subscribe/send",
                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<SendResponse>();
                if (callback == null || callback.ErrorCode != 0)
                    //throw Oops.Oh(EnumErrorCodeType.s510, $"获取小程序码失败:{callback.errmsg},请联系管理员");
                return jsonResult;
            }
            //var stream = await response.Content.ReadAsStreamAsync();
            //var result = AliyunOSSUtils.Upload(command, stream, command.OssFileName);
            return "";
        }
    }
}