🥭 refactor(WorkWx): 重构企业微信插件
This commit is contained in:
parent
b7ad4a5294
commit
90da6d08b5
@ -42,6 +42,7 @@
|
|||||||
<ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
|
<ProjectReference Include="..\Admin.NET.Core\Admin.NET.Core.csproj" />
|
||||||
<ProjectReference Include="..\Plugins\Admin.NET.Plugin.GoView\Admin.NET.Plugin.GoView.csproj" />
|
<ProjectReference Include="..\Plugins\Admin.NET.Plugin.GoView\Admin.NET.Plugin.GoView.csproj" />
|
||||||
<ProjectReference Include="..\Plugins\Admin.NET.Plugin.ReZero\Admin.NET.Plugin.ReZero.csproj" />
|
<ProjectReference Include="..\Plugins\Admin.NET.Plugin.ReZero\Admin.NET.Plugin.ReZero.csproj" />
|
||||||
|
<ProjectReference Include="..\Plugins\Admin.NET.Plugin.WorkWeixin\Admin.NET.Plugin.WorkWeixin.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"Account": "",
|
"Account": "",
|
||||||
"Password": ""
|
"Password": ""
|
||||||
},
|
},
|
||||||
"HttpBin": { // 测试接口服务配置
|
"HttpBin": { // 获取Ip
|
||||||
"EnabledLog": true,
|
"EnabledLog": true,
|
||||||
"UseCookies": false,
|
"UseCookies": false,
|
||||||
"EnabledProxy": false,
|
"EnabledProxy": false,
|
||||||
@ -22,6 +22,17 @@
|
|||||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
||||||
},
|
},
|
||||||
"Timeout": 5
|
"Timeout": 5
|
||||||
|
},
|
||||||
|
"WorkWeixin": { // 企业微信
|
||||||
|
"EnabledLog": true,
|
||||||
|
"UseCookies": false,
|
||||||
|
"EnabledProxy": false,
|
||||||
|
"HttpName": "WORK_WEIXIN",
|
||||||
|
"BaseAddress": "https://qyapi.weixin.qq.com",
|
||||||
|
"Headers": {
|
||||||
|
"User-Agent": "WORK_WEIXIN"
|
||||||
|
},
|
||||||
|
"Timeout": 60
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
using Admin.NET.Plugin.WorkWeixin;
|
||||||
using Furion.Localization;
|
using Furion.Localization;
|
||||||
using Furion.Logging;
|
using Furion.Logging;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -19,11 +20,13 @@ public class TestService : IDynamicApiController
|
|||||||
private readonly UserManager _userManager;
|
private readonly UserManager _userManager;
|
||||||
private readonly IEventPublisher _eventPublisher;
|
private readonly IEventPublisher _eventPublisher;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly WorkWxUserService _workWxUserService;
|
||||||
|
|
||||||
public TestService(UserManager userManager, IEventPublisher eventPublisher, ILoggerFactory loggerFactory)
|
public TestService(UserManager userManager, IEventPublisher eventPublisher, WorkWxUserService workWxUserService, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_eventPublisher = eventPublisher;
|
_eventPublisher = eventPublisher;
|
||||||
|
_workWxUserService = workWxUserService;
|
||||||
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName); // 日志过滤标识(会写入数据库)
|
_logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName); // 日志过滤标识(会写入数据库)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +71,15 @@ public class TestService : IDynamicApiController
|
|||||||
_logger.LogWarning($"信息{DateTime.Now}");
|
_logger.LogWarning($"信息{DateTime.Now}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信测试
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<List<UserIdListWorkWxOutput.DeptUserInfo>> UserIdList()
|
||||||
|
{
|
||||||
|
return (await _workWxUserService.GetUserIdList())?.DeptUser;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 匿名上传文件测试
|
/// 匿名上传文件测试
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -20,6 +20,11 @@ public sealed class HttpRemotesOptions : IConfigurableOptions
|
|||||||
/// 获取Ip地址接口
|
/// 获取Ip地址接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public HttpRemoteItem HttpBin { get; set; }
|
public HttpRemoteItem HttpBin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信接口配置
|
||||||
|
/// </summary>
|
||||||
|
public HttpRemoteItem WorkWeixin { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
|
|
||||||
|
|
||||||
"WorkWeixin": {
|
|
||||||
"CorpId": "xxxx", // 企业ID
|
|
||||||
"CorpSecret": "xxxx" // 企业微信凭证密钥
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,7 +9,22 @@ namespace Admin.NET.Plugin.WorkWeixin.Const;
|
|||||||
public class WorkWeixinConst
|
public class WorkWeixinConst
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// API分组名称
|
/// 企业微信缓存建
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string GroupName = "WorkWeixin";
|
public const string KeyWorkWeixinToken = "work_weixin_token";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信CorpId
|
||||||
|
/// </summary>
|
||||||
|
public const string WorkWeixinCorpId = "work_weixin_corp_id";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信CorpSecret
|
||||||
|
/// </summary>
|
||||||
|
public const string WorkWeixinCorpSecret = "work_weixin_corp_secret";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信分布式锁
|
||||||
|
/// </summary>
|
||||||
|
public const string KeyLockWorkWeixin = "dis_lock_work_weixin";
|
||||||
}
|
}
|
||||||
@ -5,8 +5,14 @@
|
|||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
global using Admin.NET.Core;
|
global using Admin.NET.Core;
|
||||||
|
global using Admin.NET.Core.Service;
|
||||||
global using Furion;
|
global using Furion;
|
||||||
|
global using Furion.DependencyInjection;
|
||||||
|
global using Furion.EventBus;
|
||||||
global using Furion.HttpRemote;
|
global using Furion.HttpRemote;
|
||||||
|
global using Lazy.Captcha.Core;
|
||||||
|
global using Microsoft.AspNetCore.Http;
|
||||||
|
global using Microsoft.AspNetCore.Mvc;
|
||||||
global using Newtonsoft.Json;
|
global using Newtonsoft.Json;
|
||||||
global using System.ComponentModel.DataAnnotations;
|
global using System.ComponentModel.DataAnnotations;
|
||||||
global using System.Text.Json.Serialization;
|
global using System.Text.Json.Serialization;
|
||||||
@ -1,25 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
using Furion.ConfigurableOptions;
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Option;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 企业微信配置项
|
|
||||||
/// </summary>
|
|
||||||
public class WorkWeixinOptions : IConfigurableOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 企业ID
|
|
||||||
/// </summary>
|
|
||||||
public string CorpId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 企业微信凭证密钥
|
|
||||||
/// </summary>
|
|
||||||
public string CorpSecret { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,425 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建群聊会话输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class CreatAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 群名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
[Required(ErrorMessage = "群名称不能为空"), MaxLength(50, ErrorMessage = "群名称最多不能超过50个字符")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群主Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("owner")]
|
|
||||||
[JsonPropertyName("owner")]
|
|
||||||
[Required(ErrorMessage = "群主Id不能为空")]
|
|
||||||
public string Owner { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群成员Id列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("userlist")]
|
|
||||||
[JsonPropertyName("userlist")]
|
|
||||||
[NotEmpty(ErrorMessage = "群成员列表不能为空")]
|
|
||||||
public List<string> UserList { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("chatid")]
|
|
||||||
[JsonPropertyName("chatid")]
|
|
||||||
[Required(ErrorMessage = "群Id不能为空"), MaxLength(32, ErrorMessage = "群Id最多不能超过32个字符")]
|
|
||||||
public string ChatId { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改群聊会话输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class UpdateAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 群Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("chatid")]
|
|
||||||
[JsonPropertyName("chatid")]
|
|
||||||
[Required(ErrorMessage = "群Id不能为空"), MaxLength(32, ErrorMessage = "群Id最多不能超过32个字符")]
|
|
||||||
public string ChatId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
[Required(ErrorMessage = "群名称不能为空"), MaxLength(50, ErrorMessage = "群名称最多不能超过50个字符")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群主Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("owner")]
|
|
||||||
[JsonPropertyName("owner")]
|
|
||||||
[Required(ErrorMessage = "群主Id不能为空")]
|
|
||||||
public string Owner { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加成员的id列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("add_user_list")]
|
|
||||||
[JsonPropertyName("add_user_list")]
|
|
||||||
public List<string> AddUserList { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 踢出成员的id列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("del_user_list")]
|
|
||||||
[JsonPropertyName("del_user_list")]
|
|
||||||
public List<string> DelUserList { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 应用消息推送输入基类参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 群Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("chatid")]
|
|
||||||
[JsonPropertyName("chatid")]
|
|
||||||
[Required(ErrorMessage = "群Id不能为空"), MaxLength(32, ErrorMessage = "群Id最多不能超过32个字符")]
|
|
||||||
public string ChatId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 消息类型
|
|
||||||
/// </summary>
|
|
||||||
/// <example>text:文本消息</example>
|
|
||||||
/// <example>image:图片消息</example>
|
|
||||||
/// <example>voice:图片消息</example>
|
|
||||||
/// <example>video:视频消息</example>
|
|
||||||
/// <example>file:文件消息</example>
|
|
||||||
/// <example>textcard:文本卡片</example>
|
|
||||||
/// <example>news:图文消息</example>
|
|
||||||
/// <example>mpnews:图文消息(存储在企业微信)</example>
|
|
||||||
/// <example>markdown:markdown消息</example>
|
|
||||||
[JsonProperty("msgtype")]
|
|
||||||
[JsonPropertyName("msgtype")]
|
|
||||||
[Required(ErrorMessage = "消息类型不能为空")]
|
|
||||||
protected string MsgType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否是保密消息
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("safe")]
|
|
||||||
[JsonPropertyName("safe")]
|
|
||||||
[Required(ErrorMessage = "消息类型不能为空")]
|
|
||||||
public int Safe { get; set; }
|
|
||||||
|
|
||||||
public SendBaseAppChatInput(string chatId, string msgType, bool safe = false)
|
|
||||||
{
|
|
||||||
ChatId = chatId;
|
|
||||||
MsgType = msgType;
|
|
||||||
Safe = safe ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送文本消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendTextAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("text")]
|
|
||||||
[JsonPropertyName("text")]
|
|
||||||
public object Text { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文本消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="content"></param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendTextAppChatInput(string chatId, string content, bool safe = false) : base(chatId, "text", safe)
|
|
||||||
{
|
|
||||||
Text = new { content };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送图片消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendImageAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("image")]
|
|
||||||
[JsonPropertyName("image")]
|
|
||||||
public object Image { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图片消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="mediaId"></param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendImageAppChatInput(string chatId, string mediaId, bool safe = false) : base(chatId, "image", safe)
|
|
||||||
{
|
|
||||||
Image = new { media_id = mediaId };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送语音消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendVoiceAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("voice")]
|
|
||||||
[JsonPropertyName("voice")]
|
|
||||||
public object Voice { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 语音消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="mediaId"></param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendVoiceAppChatInput(string chatId, string mediaId, bool safe = false) : base(chatId, "voice", safe)
|
|
||||||
{
|
|
||||||
Voice = new { media_id = mediaId };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送视频消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendVideoAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("video")]
|
|
||||||
[JsonPropertyName("video")]
|
|
||||||
public object Video { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 视频消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="title"></param>
|
|
||||||
/// <param name="description"></param>
|
|
||||||
/// <param name="mediaId"></param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendVideoAppChatInput(string chatId, string title, string description, string mediaId, bool safe = false) : base(chatId, "video", safe)
|
|
||||||
{
|
|
||||||
Video = new
|
|
||||||
{
|
|
||||||
media_id = mediaId,
|
|
||||||
description,
|
|
||||||
title
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送视频消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendFileAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("file")]
|
|
||||||
[JsonPropertyName("file")]
|
|
||||||
public object File { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文件消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="mediaId"></param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendFileAppChatInput(string chatId, string mediaId, bool safe = false) : base(chatId, "video", safe)
|
|
||||||
{
|
|
||||||
File = new { media_id = mediaId };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送文本卡片消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendTextCardAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("textcard")]
|
|
||||||
[JsonPropertyName("textcard")]
|
|
||||||
public object TextCard { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 文本卡片消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="title">标题</param>
|
|
||||||
/// <param name="description">描述</param>
|
|
||||||
/// <param name="url">点击后跳转的链接</param>
|
|
||||||
/// <param name="btnTxt">按钮文字</param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendTextCardAppChatInput(string chatId, string title, string description, string url, string btnTxt, bool safe = false) : base(chatId, "textcard", safe)
|
|
||||||
{
|
|
||||||
TextCard = new
|
|
||||||
{
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
url,
|
|
||||||
btntxt = btnTxt
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息项
|
|
||||||
/// </summary>
|
|
||||||
public class SendNewsItem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标题
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("title")]
|
|
||||||
[JsonPropertyName("title")]
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 描述
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("description")]
|
|
||||||
[JsonPropertyName("description")]
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 描述
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("url")]
|
|
||||||
[JsonPropertyName("url")]
|
|
||||||
public string Url { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息的图片链接(推荐大图1068 * 455,小图150 * 150)
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("picurl")]
|
|
||||||
[JsonPropertyName("picurl")]
|
|
||||||
public string PicUrl { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送图文消息输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendNewsAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("news")]
|
|
||||||
[JsonPropertyName("news")]
|
|
||||||
public object News { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="newsList">图文消息列表</param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendNewsAppChatInput(string chatId, List<SendNewsItem> newsList, bool safe = false) : base(chatId, "news", safe)
|
|
||||||
{
|
|
||||||
News = new { articles = newsList };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息项
|
|
||||||
/// </summary>
|
|
||||||
public class SendMpNewsItem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标题
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("title")]
|
|
||||||
[JsonPropertyName("title")]
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 缩略图media_id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("thumb_media_id")]
|
|
||||||
[JsonPropertyName("thumb_media_id")]
|
|
||||||
public string ThumbMediaId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 作者
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("author")]
|
|
||||||
[JsonPropertyName("author")]
|
|
||||||
public string Author { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 点击“阅读原文”之后的页面链接
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("content_source_url")]
|
|
||||||
[JsonPropertyName("content_source_url")]
|
|
||||||
public string ContentSourceUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息的内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("content")]
|
|
||||||
[JsonPropertyName("content")]
|
|
||||||
public string Content { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息的描述
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("digest")]
|
|
||||||
[JsonPropertyName("digest")]
|
|
||||||
public string Digest { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 推送图文消息(存储在企业微信)输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class SendMpNewsAppChatInput : SendBaseAppChatInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 消息内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("mpnews")]
|
|
||||||
[JsonPropertyName("mpnews")]
|
|
||||||
public object MpNews { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 图文消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <param name="mpNewsList">图文消息列表</param>
|
|
||||||
/// <param name="safe"></param>
|
|
||||||
public SendMpNewsAppChatInput(string chatId, List<SendMpNewsItem> mpNewsList, bool safe = false) : base(chatId, "mpnews", safe)
|
|
||||||
{
|
|
||||||
MpNews = new { articles = mpNewsList };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
public class CreatAppChatOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 群聊的唯一标志
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("chatid")]
|
|
||||||
[JsonPropertyName("chatid")]
|
|
||||||
public string ChatId { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy.AppChat;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 群聊会话远程调用服务
|
|
||||||
/// </summary>
|
|
||||||
public interface IWorkWeixinAppChatHttp : IHttpDeclarative
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建群聊会话
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <inheritdoc cref="https://developer.work.weixin.qq.com/document/path/90245"/>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/appchat/create")]
|
|
||||||
Task<CreatAppChatOutput> Create([Query("access_token")] string accessToken, [Body] CreatAppChatInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改群聊会话
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <inheritdoc cref="https://developer.work.weixin.qq.com/document/path/98913"/>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/appchat/update")]
|
|
||||||
Task<CreatAppChatOutput> Update([Query("access_token")] string accessToken, [Body] UpdateAppChatInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取群聊会话
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="chatId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <inheritdoc cref="https://developer.work.weixin.qq.com/document/path/98914"/>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/appchat/get")]
|
|
||||||
Task<CreatAppChatOutput> Get([Query("access_token")] string accessToken, [Query("chatid")] string chatId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 应用推送消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <inheritdoc cref="https://developer.work.weixin.qq.com/document/path/90248"/>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/appchat/send")]
|
|
||||||
Task<BaseWorkOutput> Send([Query("access_token")] string accessToken, [Body] SendBaseAppChatInput body);
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
public class AuthAccessTokenHttpOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取到的凭证
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("access_token")]
|
|
||||||
[JsonPropertyName("access_token")]
|
|
||||||
public string AccessToken { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 凭证的有效时间(秒)
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("expires_in")]
|
|
||||||
[JsonPropertyName("expires_in")]
|
|
||||||
public int ExpiresIn { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy.AppChat;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 授权会话远程服务
|
|
||||||
/// </summary>
|
|
||||||
public interface IWorkWeixinAuthHttp : IHttpDeclarative
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 获取接口凭证
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="corpId">企业ID</param>
|
|
||||||
/// <param name="corpSecret">应用的凭证密钥</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <inheritdoc cref="https://developer.work.weixin.qq.com/document/path/91039"/>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/gettoken")]
|
|
||||||
Task<AuthAccessTokenHttpOutput> GetToken([Query("corpid")] string corpId, [Query("corpsecret")] string corpSecret);
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建部门输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class DepartmentHttpInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("id")]
|
|
||||||
[JsonPropertyName("id")]
|
|
||||||
public long? Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 父部门id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("parentid")]
|
|
||||||
[JsonPropertyName("parentid")]
|
|
||||||
public long? ParentId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 英文名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name_en")]
|
|
||||||
[JsonPropertyName("name_en")]
|
|
||||||
public string NameEn { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 序号
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("order")]
|
|
||||||
[JsonPropertyName("order")]
|
|
||||||
public int? Order { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门Id列表输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class DepartmentIdOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("department_id")]
|
|
||||||
[JsonPropertyName("department_id")]
|
|
||||||
public List<DepartmentItemOutput> DepartmentList { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门Id输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class DepartmentItemOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("id")]
|
|
||||||
[JsonPropertyName("id")]
|
|
||||||
public long? Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 父部门id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("parentid")]
|
|
||||||
[JsonPropertyName("parentid")]
|
|
||||||
public long? ParentId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 序号
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("order")]
|
|
||||||
[JsonPropertyName("order")]
|
|
||||||
public int? Order { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class DepartmentOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("id")]
|
|
||||||
[JsonPropertyName("id")]
|
|
||||||
public long? Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 父部门id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("parentid")]
|
|
||||||
[JsonPropertyName("parentid")]
|
|
||||||
public long? ParentId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 英文名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("name_en")]
|
|
||||||
[JsonPropertyName("name_en")]
|
|
||||||
public string NameEn { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门负责人列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("department_leader")]
|
|
||||||
[JsonPropertyName("department_leader")]
|
|
||||||
public List<string> Leaders { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 序号
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("order")]
|
|
||||||
[JsonPropertyName("order")]
|
|
||||||
public int? Order { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy.AppChat;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门远程调用服务
|
|
||||||
/// </summary>
|
|
||||||
public interface IDepartmentHttp : IHttpDeclarative
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建部门
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90205
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/department/create")]
|
|
||||||
Task<BaseWorkIdOutput> Create([Query("access_token")] string accessToken, [Body] DepartmentHttpInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 修改部门
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90206
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/department/update")]
|
|
||||||
Task<BaseWorkOutput> Update([Query("access_token")] string accessToken, [Body] DepartmentHttpInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除部门
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90207
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/department/delete")]
|
|
||||||
Task<BaseWorkOutput> Delete([Query("access_token")] string accessToken, [Query] long id);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取部门Id列表
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90208
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/department/simplelist")]
|
|
||||||
Task<DepartmentIdOutput> SimpleList([Query("access_token")] string accessToken, [Query] long id);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取部门详情
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90208
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/department/get")]
|
|
||||||
Task<DepartmentOutput> Get([Query("access_token")] string accessToken, [Query] long id);
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标签输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class TagHttpInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标签id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("tagid")]
|
|
||||||
[JsonPropertyName("tagid")]
|
|
||||||
public long? TagId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标签名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("tagname")]
|
|
||||||
[JsonPropertyName("tagname")]
|
|
||||||
public string TagName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 增加标签成员输入参数
|
|
||||||
/// </summary>
|
|
||||||
public class TagUsersTagInput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标签id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("tagid")]
|
|
||||||
[JsonPropertyName("tagid")]
|
|
||||||
public long TagId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 企业成员ID列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("userlist")]
|
|
||||||
[JsonPropertyName("userlist")]
|
|
||||||
public List<string> UserList { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 企业部门ID列表
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("partylist")]
|
|
||||||
[JsonPropertyName("partylist")]
|
|
||||||
public List<long> PartyList { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 新增标签输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class TagIdHttpOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标签Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("tagid")]
|
|
||||||
[JsonPropertyName("tagid")]
|
|
||||||
public long? TagId { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标签列表输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class TagListHttpOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 标签Id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("taglist")]
|
|
||||||
[JsonPropertyName("taglist")]
|
|
||||||
public List<TagHttpInput> TagList { get; set; }
|
|
||||||
}
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin.Proxy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标签远程调用服务
|
|
||||||
/// </summary>
|
|
||||||
public interface ITagHttp : IHttpDeclarative
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 创建标签
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90210
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/tag/create")]
|
|
||||||
Task<BaseWorkIdOutput> Create([Query("access_token")] string accessToken, [Body] TagHttpInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新标签名字
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90211
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/tag/update")]
|
|
||||||
Task<TagIdHttpOutput> Update([Query("access_token")] string accessToken, [Body] TagHttpInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除标签
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90212
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="tagId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/tag/delete")]
|
|
||||||
Task<BaseWorkOutput> Delete([Query("access_token")] string accessToken, [Query("tagid")] long tagId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取标签详情
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90213
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="tagId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/tag/get")]
|
|
||||||
Task<DepartmentOutput> Get([Query("access_token")] string accessToken, [Query("tagid")] long tagId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 增加标签成员
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90214
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers")]
|
|
||||||
Task<DepartmentOutput> AddTagUsers([Query("access_token")] string accessToken, [Body] TagUsersTagInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 删除标签成员
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90215
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <param name="body"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Post("https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers")]
|
|
||||||
Task<DepartmentOutput> DelTagUsers([Query("access_token")] string accessToken, [Body] TagUsersTagInput body);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取标签列表
|
|
||||||
/// https://developer.work.weixin.qq.com/document/path/90216
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="accessToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Get("https://qyapi.weixin.qq.com/cgi-bin/tag/list")]
|
|
||||||
Task<TagListHttpOutput> List([Query("access_token")] string accessToken);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
using Admin.NET.Plugin.WorkWeixin.Const;
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 系统配置表种子数据
|
||||||
|
/// </summary>
|
||||||
|
[IgnoreUpdateSeed]
|
||||||
|
public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 种子数据
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IEnumerable<SysConfig> HasData()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
[
|
||||||
|
new SysConfig{ Id=1330000000001, Name="企业微信CorpId", Code=WorkWeixinConst.WorkWeixinCorpId, Value="", SysFlag=YesNoEnum.Y, Remark= "企业微信接口获取凭证的CorpId", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2025-04-10 00:00:00") },
|
||||||
|
new SysConfig{ Id=1330000000002, Name="企业微信CorpSecret", Code=WorkWeixinConst.WorkWeixinCorpSecret, Value="", SysFlag=YesNoEnum.Y, Remark= "企业微信接口获取凭证的CorpSecret", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2025-04-10 00:00:00") },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 需授权基类,继承此类,自动追加令牌
|
||||||
|
/// </summary>
|
||||||
|
public class AuthWorkWxInput
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信接口输出基类
|
||||||
|
/// </summary>
|
||||||
|
public class BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 返回码
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("errcode")]
|
||||||
|
public int ErrCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对返回码的文本描述内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("errmsg")]
|
||||||
|
public string ErrMsg { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信接口输出基类
|
||||||
|
/// </summary>
|
||||||
|
public class BasePageWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 分页游标,下次请求时填写以获取之后分页的记录。如果该字段返回空则表示已没有更多数据
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("next_cursor")]
|
||||||
|
public string NextCursor { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 带id的输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class BaseIdWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
public long? Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取接口凭证输入参数
|
||||||
|
/// </summary>
|
||||||
|
/// https://developer.work.weixin.qq.com/document/path/91039
|
||||||
|
[HttpRemoteApi(Action = "gettoken", Desc = "获取接口凭证", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class TokenWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 企业标识
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("corpid")]
|
||||||
|
public string CorpId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业密钥
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("corpsecret")]
|
||||||
|
public string CorpSecret { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取接口凭证输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class TokenWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取到的凭证
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("access_token")]
|
||||||
|
public string AccessToken { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 凭证的有效时间(秒)
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("expires_in")]
|
||||||
|
public int ExpiresIn { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用推送消息工厂类
|
||||||
|
/// </summary>
|
||||||
|
public static class AppChatMessageFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 文本消息
|
||||||
|
/// </summary>
|
||||||
|
public static TextAppChatMessage CreateTextMessage(string chatId, string content, int? safe = null)
|
||||||
|
{
|
||||||
|
return new TextAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
Text = new TextContent { Content = content },
|
||||||
|
Safe = safe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片消息
|
||||||
|
/// </summary>
|
||||||
|
public static ImageAppChatMessage CreateImageMessage(string chatId, string mediaId, int? safe = null)
|
||||||
|
{
|
||||||
|
return new ImageAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
Image = new MediaContent { MediaId = mediaId },
|
||||||
|
Safe = safe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语音消息
|
||||||
|
/// </summary>
|
||||||
|
public static VoiceAppChatMessage CreateVoiceMessage(string chatId, string mediaId)
|
||||||
|
{
|
||||||
|
return new VoiceAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
Voice = new MediaContent { MediaId = mediaId }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息
|
||||||
|
/// </summary>
|
||||||
|
public static VideoAppChatMessage CreateVideoMessage(string chatId, string mediaId, string title = null, string description = null, int? safe = null)
|
||||||
|
{
|
||||||
|
return new VideoAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
Video = new VideoContent { MediaId = mediaId, Title = title, Description = description },
|
||||||
|
Safe = safe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件消息
|
||||||
|
/// </summary>
|
||||||
|
public static FileAppChatMessage CreateFileMessage(string chatId, string mediaId, int? safe = null)
|
||||||
|
{
|
||||||
|
return new FileAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
File = new MediaContent { MediaId = mediaId },
|
||||||
|
Safe = safe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本卡片消息
|
||||||
|
/// </summary>
|
||||||
|
public static TextCardAppChatMessage CreateTextCardMessage(string chatId, string title, string description, string url, string btnTxt = null, int? safe = null)
|
||||||
|
{
|
||||||
|
return new TextCardAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
TextCard = new TextCardContent { Title = title, Description = description, Url = url, BtnTxt = btnTxt },
|
||||||
|
Safe = safe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Markdown消息
|
||||||
|
/// </summary>
|
||||||
|
public static MarkdownAppChatMessage CreateMarkdownMessage(string chatId, string content)
|
||||||
|
{
|
||||||
|
return new MarkdownAppChatMessage
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
Markdown = new MarkdownContent { Content = content }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,410 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用推送消息基类
|
||||||
|
/// </summary>
|
||||||
|
[HttpRemoteApi(Action = "appchat/send", Desc = "应用消息推送", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public abstract class AppChatMessageInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
[Required(ErrorMessage = "群聊ID不能为空")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息类型
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("msgtype")]
|
||||||
|
[Required(ErrorMessage = "消息类型不能为空")]
|
||||||
|
public abstract string MsgType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表示是否是保密消息,0表示否,1表示是,默认0
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("safe")]
|
||||||
|
[Range(0, 1, ErrorMessage = "安全标识只能是0或1")]
|
||||||
|
public int? Safe { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本消息
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>特殊说明:content字段可以支持换行,换行符请用转义过的'\n'
|
||||||
|
/// </remarks>
|
||||||
|
public class TextAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "text";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("text")]
|
||||||
|
[Required(ErrorMessage = "文本消息内容不能为空")]
|
||||||
|
public TextContent Text { get; set; } = new TextContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片消息
|
||||||
|
/// </summary>
|
||||||
|
public class ImageAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "image";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图片消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("image")]
|
||||||
|
[Required(ErrorMessage = "图片消息内容不能为空")]
|
||||||
|
public MediaContent Image { get; set; } = new MediaContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语音消息
|
||||||
|
/// </summary>
|
||||||
|
public class VoiceAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "voice";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语音消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("voice")]
|
||||||
|
[Required(ErrorMessage = "语音消息内容不能为空")]
|
||||||
|
public MediaContent Voice { get; set; } = new MediaContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息
|
||||||
|
/// </summary>
|
||||||
|
public class VideoAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "video";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("video")]
|
||||||
|
[Required(ErrorMessage = "视频消息内容不能为空")]
|
||||||
|
public VideoContent Video { get; set; } = new VideoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件消息
|
||||||
|
/// </summary>
|
||||||
|
public class FileAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "file";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("file")]
|
||||||
|
[Required(ErrorMessage = "文件消息内容不能为空")]
|
||||||
|
public MediaContent File { get; set; } = new MediaContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本卡片消息
|
||||||
|
/// </summary>
|
||||||
|
public class TextCardAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "textcard";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本卡片消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("textcard")]
|
||||||
|
[Required(ErrorMessage = "文本卡片消息内容不能为空")]
|
||||||
|
public TextCardContent TextCard { get; set; } = new TextCardContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息
|
||||||
|
/// </summary>
|
||||||
|
public class NewsAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "news";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("news")]
|
||||||
|
[Required(ErrorMessage = "图文消息内容不能为空")]
|
||||||
|
public NewsContent News { get; set; } = new NewsContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息(mpnews)
|
||||||
|
/// </summary>
|
||||||
|
public class MpNewsAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "mpnews";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("mpnews")]
|
||||||
|
[Required(ErrorMessage = "图文消息内容不能为空")]
|
||||||
|
public MpNewsContent MpNews { get; set; } = new MpNewsContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Markdown消息
|
||||||
|
/// </summary>
|
||||||
|
public class MarkdownAppChatMessage : AppChatMessageInput
|
||||||
|
{
|
||||||
|
public override string MsgType => "markdown";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Markdown消息内容
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("markdown")]
|
||||||
|
[Required(ErrorMessage = "Markdown消息内容不能为空")]
|
||||||
|
public MarkdownContent Markdown { get; set; } = new MarkdownContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本消息内容
|
||||||
|
/// </summary>
|
||||||
|
public class TextContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 消息内容,最长不超过2048个字节
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("content")]
|
||||||
|
[Required(ErrorMessage = "消息内容不能为空")]
|
||||||
|
[StringLength(2048, ErrorMessage = "消息内容长度不能超过2048个字节")]
|
||||||
|
public string Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 媒体内容基类
|
||||||
|
/// </summary>
|
||||||
|
public class MediaContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 媒体文件id,可以调用上传临时素材接口获取
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("media_id")]
|
||||||
|
[Required(ErrorMessage = "媒体文件ID不能为空")]
|
||||||
|
public string MediaId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息内容
|
||||||
|
/// </summary>
|
||||||
|
public class VideoContent : MediaContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息的标题,不超过128个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("title")]
|
||||||
|
[StringLength(128, ErrorMessage = "视频标题长度不能超过128个字节")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频消息的描述,不超过512个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("description")]
|
||||||
|
[StringLength(512, ErrorMessage = "视频描述长度不能超过512个字节")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文本卡片消息内容
|
||||||
|
/// </summary>
|
||||||
|
public class TextCardContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标题,不超过128个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("title")]
|
||||||
|
[Required(ErrorMessage = "标题不能为空")]
|
||||||
|
[StringLength(128, ErrorMessage = "标题长度不能超过128个字节")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述,不超过512个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("description")]
|
||||||
|
[Required(ErrorMessage = "描述不能为空")]
|
||||||
|
[StringLength(512, ErrorMessage = "描述长度不能超过512个字节")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 点击后跳转的链接
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("url")]
|
||||||
|
[Required(ErrorMessage = "跳转链接不能为空")]
|
||||||
|
[Url(ErrorMessage = "链接格式不正确")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按钮文字。默认为"详情",不超过4个文字,超过自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("btntxt")]
|
||||||
|
[StringLength(4, ErrorMessage = "按钮文字长度不能超过4个字符")]
|
||||||
|
public string BtnTxt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息文章
|
||||||
|
/// </summary>
|
||||||
|
public class Article
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标题,不超过128个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("title")]
|
||||||
|
[Required(ErrorMessage = "文章标题不能为空")]
|
||||||
|
[StringLength(128, ErrorMessage = "文章标题长度不能超过128个字节")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述,不超过512个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("description")]
|
||||||
|
[StringLength(512, ErrorMessage = "文章描述长度不能超过512个字节")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 点击后跳转的链接
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("url")]
|
||||||
|
[Required(ErrorMessage = "文章链接不能为空")]
|
||||||
|
[Url(ErrorMessage = "文章链接格式不正确")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息的图片链接,支持JPG、PNG格式
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("picurl")]
|
||||||
|
[Url(ErrorMessage = "图片链接格式不正确")]
|
||||||
|
public string PicUrl { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息内容
|
||||||
|
/// </summary>
|
||||||
|
public class NewsContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息,一个图文消息支持1到8条图文
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("articles")]
|
||||||
|
[Required(ErrorMessage = "图文消息不能为空")]
|
||||||
|
[MinLength(1, ErrorMessage = "至少需要1条图文消息")]
|
||||||
|
[MaxLength(8, ErrorMessage = "最多只能有8条图文消息")]
|
||||||
|
public List<Article> Articles { get; set; } = new List<Article>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息(mpnews)文章
|
||||||
|
/// </summary>
|
||||||
|
public class MpArticle
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标题,不超过128个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("title")]
|
||||||
|
[Required(ErrorMessage = "文章标题不能为空")]
|
||||||
|
[StringLength(128, ErrorMessage = "文章标题长度不能超过128个字节")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息缩略图的media_id,可以通过素材管理接口获得
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("thumb_media_id")]
|
||||||
|
[Required(ErrorMessage = "缩略图媒体ID不能为空")]
|
||||||
|
public string ThumbMediaId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息的作者,不超过64个字节
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("author")]
|
||||||
|
[StringLength(64, ErrorMessage = "作者长度不能超过64个字节")]
|
||||||
|
public string Author { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息点击"阅读原文"之后的页面链接
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("content_source_url")]
|
||||||
|
[Url(ErrorMessage = "原文链接格式不正确")]
|
||||||
|
public string ContentSourceUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息的内容,支持html标签,不超过666K个字节
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("content")]
|
||||||
|
[Required(ErrorMessage = "文章内容不能为空")]
|
||||||
|
public string Content { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息的描述,不超过512个字节,超过会自动截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("digest")]
|
||||||
|
[StringLength(512, ErrorMessage = "摘要长度不能超过512个字节")]
|
||||||
|
public string Digest { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息(mpnews)内容
|
||||||
|
/// </summary>
|
||||||
|
public class MpNewsContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 图文消息,一个图文消息支持1到8条图文
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("articles")]
|
||||||
|
[Required(ErrorMessage = "图文消息不能为空")]
|
||||||
|
[MinLength(1, ErrorMessage = "至少需要1条图文消息")]
|
||||||
|
[MaxLength(8, ErrorMessage = "最多只能有8条图文消息")]
|
||||||
|
public List<MpArticle> Articles { get; set; } = new List<MpArticle>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Markdown消息内容
|
||||||
|
/// </summary>
|
||||||
|
public class MarkdownContent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// markdown内容,最长不超过2048个字节,必须是utf8编码
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("content")]
|
||||||
|
[Required(ErrorMessage = "Markdown内容不能为空")]
|
||||||
|
[StringLength(2048, ErrorMessage = "Markdown内容长度不能超过2048个字节")]
|
||||||
|
public string Content { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建群聊会话输入参数
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2024/11/29
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/appchat/create?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:只允许企业自建应用调用,且应用的可见范围必须是根部门
|
||||||
|
/// <br/>限制说明:群成员人数不可超过管理端配置的"群成员人数上限",最大不可超过2000人,每企业创建群数不可超过1000/天
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90245
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "appchat/create", Desc = "创建群聊会话", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class CreateChatWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊名,最多50个utf8字符,超过将截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
[StringLength(50, ErrorMessage = "群聊名长度不能超过50个字符")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 指定群主的id。如果不指定,系统会随机从userlist中选一人作为群主
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[Required(ErrorMessage = "群主id不能为空")]
|
||||||
|
[CustomJsonProperty("owner")]
|
||||||
|
public string Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群成员id列表。至少2人,至多2000人
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
[NotEmpty(ErrorMessage = "群成员列表不能为空")]
|
||||||
|
[MinLength(2, ErrorMessage = "群成员至少需要2人")]
|
||||||
|
[MaxLength(2000, ErrorMessage = "群成员最多不能超过2000人")]
|
||||||
|
public List<string> UserList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊的唯一标志,不能与已有的群重复;字符串类型,最长32个字符。只允许字符0-9及字母a-zA-Z。如果不填,系统会随机生成群id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
[RegularExpression("^[a-zA-Z0-9]{0,32}$", ErrorMessage = "群ID只能包含字母和数字,且长度不能超过32个字符")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改群聊会话输入参数
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2023/04/18
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/appchat/update?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:只允许企业自建应用调用,且应用的可见范围必须是根部门
|
||||||
|
/// <br/>限制说明:chatid所代表的群必须是该应用所创建,群成员人数不可超过2000人,每企业变更群的次数不可超过1000次/小时
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/98913
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "appchat/update", Desc = "修改群聊会话", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class UpdateChatWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
[Required(ErrorMessage = "群聊ID不能为空")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新的群聊名。若不需更新,请忽略此参数。最多50个utf8字符,超过将截断
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
[StringLength(50, ErrorMessage = "群聊名长度不能超过50个字符")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新群主的id。若不需更新,请忽略此参数。课程群聊群主必须拥有课程群创建权限,del_user_list包含群主时本字段必填
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("owner")]
|
||||||
|
public string Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加成员的id列表
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("add_user_list")]
|
||||||
|
[MaxLength(2000, ErrorMessage = "添加成员列表不能超过2000人")]
|
||||||
|
public List<string> AddUserList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 踢出成员的id列表
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("del_user_list")]
|
||||||
|
[MaxLength(2000, ErrorMessage = "踢出成员列表不能超过2000人")]
|
||||||
|
public List<string> DelUserList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取群聊会话输入参数
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2023/04/20
|
||||||
|
/// <br/>请求方式:GET(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/appchat/get?access_token=ACCESS_TOKEN&chatid=CHATID
|
||||||
|
/// <br/>权限说明:只允许企业自建应用调用,且应用的可见范围必须是根部门;chatid所代表的群必须是该应用所创建;第三方不可调用
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/98914
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "appchat/get", Desc = "获取群聊会话", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class GetChatWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
[Required(ErrorMessage = "群聊ID不能为空")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用消息推送输入参数
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2024/07/11
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/appchat/send?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:只允许企业自建应用调用,且应用的可见范围必须是根部门
|
||||||
|
/// <br/>限制说明:chatid所代表的群必须是该应用所创建,消息发送量有限制,成员接收消息有限制
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90248
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "appchat/send", Desc = "应用消息推送", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class SendChatWorkWxInput
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建群聊会话输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class CreateChatWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊的唯一标志
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取群聊会话输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class GetChatWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊信息
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("chat_info")]
|
||||||
|
public ChatInfoDto ChatInfo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊信息
|
||||||
|
/// </summary>
|
||||||
|
public class ChatInfoDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊唯一标志
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("chatid")]
|
||||||
|
public string ChatId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群主id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("owner")]
|
||||||
|
public string Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群成员id列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
public List<string> UserList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 群聊类型,0表示普通群聊,1表示课程群聊
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("chat_type")]
|
||||||
|
public int ChatType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信群聊会话服务 🧩
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxAppChatService(WorkWxBaseService baseService) : ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建群聊会话
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<CreateChatWorkWxOutput> CreateChat(CreateChatWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<CreateChatWorkWxInput, CreateChatWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改群聊会话
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> UpdateChat(UpdateChatWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UpdateChatWorkWxInput, BaseWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送纯文本消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="content">内容</param>
|
||||||
|
/// <param name="safe">安全标识</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendText(string chatId, string content, int? safe = null)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<TextAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateTextMessage(chatId, content, safe));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送文本卡片消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="title">标题</param>
|
||||||
|
/// <param name="description">内容</param>
|
||||||
|
/// <param name="url">跳转链接</param>
|
||||||
|
/// <param name="btnTxt">按钮文本</param>
|
||||||
|
/// <param name="safe">安全标识</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendTextCard(string chatId, string title, string description, string url, string btnTxt = null, int? safe = null)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<TextCardAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateTextCardMessage(chatId, title, description, url, btnTxt, safe));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送Markdown消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="content">内容</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendMarkdown(string chatId, string content)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<MarkdownAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateMarkdownMessage(chatId, content));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送图片消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="mediaId">媒体文件ID</param>
|
||||||
|
/// <param name="safe">安全标识</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendImage(string chatId, string mediaId, int? safe = null)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<ImageAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateImageMessage(chatId, mediaId, safe));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送语音消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="mediaId">媒体文件ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendVoice(string chatId, string mediaId)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<VoiceAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateVoiceMessage(chatId, mediaId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送视频消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="mediaId">媒体文件ID</param>
|
||||||
|
/// <param name="title">标题</param>
|
||||||
|
/// <param name="description">描述</param>
|
||||||
|
/// <param name="safe">安全标识</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendVideo(string chatId, string mediaId, string title = null, string description = null, int? safe = null)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<VideoAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateVideoMessage(chatId, mediaId, title, description, safe));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 推送文件消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">群聊Id</param>
|
||||||
|
/// <param name="mediaId">媒体文件ID</param>
|
||||||
|
/// <param name="safe">安全标识</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> SendFile(string chatId, string mediaId, int? safe = null)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<FileAppChatMessage, BaseWorkWxOutput>(AppChatMessageFactory.CreateFileMessage(chatId, mediaId, safe));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建部门
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2023/08/15
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:第三方仅通讯录应用可以调用
|
||||||
|
/// <br/>限制说明:部门最大层级15层,部门总数不超过3万个,每个部门下节点不超过3万个
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90205
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "department/create", Desc = "创建部门", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class CreateDeptWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门名称。同一个层级的部门名称不能重复。长度限制为1~64个UTF-8字符,字符不能包括\:*?"<>|
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
[Required(ErrorMessage = "部门名称不能为空")]
|
||||||
|
[StringLength(64, MinimumLength = 1, ErrorMessage = "部门名称长度必须在1-64个字符之间")]
|
||||||
|
[RegularExpression(@"^[^\\:*?""<>|]+$", ErrorMessage = "部门名称不能包含\\:*?\"<>|字符")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 英文名称。同一个层级的部门名称不能重复。需要在管理后台开启多语言支持才能生效
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("name_en")]
|
||||||
|
[StringLength(64, MinimumLength = 1, ErrorMessage = "英文名称长度必须在1-64个字符之间")]
|
||||||
|
[RegularExpression(@"^[^\\:*?""<>|]*$", ErrorMessage = "英文名称不能包含\\:*?\"<>|字符")]
|
||||||
|
public string NameEn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 父部门id,32位整型
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("parentid")]
|
||||||
|
[Required(ErrorMessage = "父部门ID不能为空")]
|
||||||
|
[Range(1, long.MaxValue, ErrorMessage = "父部门ID必须大于0")]
|
||||||
|
public long ParentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在父部门中的次序值。order值大的排序靠前
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("order")]
|
||||||
|
[Range(0, 4294967295, ErrorMessage = "排序值必须在0-4294967295之间")]
|
||||||
|
public long? Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id,32位整型,指定时必须大于1
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
[Range(2, long.MaxValue, ErrorMessage = "部门ID必须大于1")]
|
||||||
|
public long? Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新部门
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2023/08/15
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:应用须拥有指定部门的管理权限,第三方仅通讯录应用可以调用
|
||||||
|
/// <br/>限制说明:部门最大层级15层,部门总数不超过3万个,每个部门下节点不超过3万个
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90206
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "department/update", Desc = "更新部门", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class UpdateDeptWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
[Required(ErrorMessage = "部门ID不能为空")]
|
||||||
|
[Range(1, long.MaxValue, ErrorMessage = "部门ID必须大于0")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门名称。长度限制为1~64个UTF-8字符,字符不能包括\:*?"<>|
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
[StringLength(64, MinimumLength = 1, ErrorMessage = "部门名称长度必须在1-64个字符之间")]
|
||||||
|
[RegularExpression(@"^[^\\:*?""<>|]+$", ErrorMessage = "部门名称不能包含\\:*?\"<>|字符")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 英文名称,需要在管理后台开启多语言支持才能生效
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("name_en")]
|
||||||
|
[StringLength(64, MinimumLength = 1, ErrorMessage = "英文名称长度必须在1-64个字符之间")]
|
||||||
|
[RegularExpression(@"^[^\\:*?""<>|]*$", ErrorMessage = "英文名称不能包含\\:*?\"<>|字符")]
|
||||||
|
public string NameEn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 父部门id
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("parentid")]
|
||||||
|
[Range(1, long.MaxValue, ErrorMessage = "父部门ID必须大于0")]
|
||||||
|
public long? ParentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在父部门中的次序值。order值大的排序靠前
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("order")]
|
||||||
|
[Range(0, 4294967295, ErrorMessage = "排序值必须在0-4294967295之间")]
|
||||||
|
public long? Order { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除部门
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2020/03/30
|
||||||
|
/// <br/>请求方式:GET(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=ACCESS_TOKEN&id=ID
|
||||||
|
/// <br/>权限说明:应用须拥有指定部门的管理权限,第三方仅通讯录应用可以调用
|
||||||
|
/// <br/>限制说明:不能删除根部门;不能删除含有子部门、成员的部门
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90207
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "department/delete", Desc = "删除部门", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class DeleteDeptWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id。(注:不能删除根部门;不能删除含有子部门、成员的部门)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
[Required(ErrorMessage = "部门ID不能为空")]
|
||||||
|
[Range(2, long.MaxValue, ErrorMessage = "部门ID必须大于1(不能删除根部门)")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取子部门ID列表
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2023/09/06
|
||||||
|
/// <br/>请求方式:GET(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token=ACCESS_TOKEN&id=ID
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/95350
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "department/simplelist", Desc = "获取子部门ID列表", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class DeptSimpleListWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id。获取指定部门及其下的子部门(递归)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:否</remarks>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
public long? Id { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建部门输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class CreateDepartmentWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建的部门id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门基础信息
|
||||||
|
/// </summary>
|
||||||
|
public class DeptWorkWxBaseInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 父部门id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("parentid")]
|
||||||
|
public long ParentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 排序值
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("order")]
|
||||||
|
public long Order { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取子部门ID列表输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class DeptSimpleListWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门列表数据
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department_id")]
|
||||||
|
public List<DeptWorkWxBaseInfo> DeptList { get; set; } = new List<DeptWorkWxBaseInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门数量
|
||||||
|
/// </summary>
|
||||||
|
public int Count => DeptList?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门ID列表
|
||||||
|
/// </summary>
|
||||||
|
public List<long> DeptIds => DeptList?.Select(d => d.Id).ToList() ?? new List<long>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按父部门分组
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<long, List<DeptWorkWxBaseInfo>> GroupByParent()
|
||||||
|
{
|
||||||
|
var result = new Dictionary<long, List<DeptWorkWxBaseInfo>>();
|
||||||
|
|
||||||
|
if (DeptList == null) return result;
|
||||||
|
|
||||||
|
foreach (var dept in DeptList)
|
||||||
|
{
|
||||||
|
if (!result.ContainsKey(dept.ParentId))
|
||||||
|
{
|
||||||
|
result[dept.ParentId] = new List<DeptWorkWxBaseInfo>();
|
||||||
|
}
|
||||||
|
result[dept.ParentId].Add(dept);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信部门服务 🧩
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxDeptService(WorkWxBaseService baseService) : ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建部门
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseIdWorkWxOutput> Create(CreateDeptWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<CreateDeptWorkWxInput, BaseIdWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新部门
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Update(UpdateDeptWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UpdateDeptWorkWxInput, BaseWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除部门
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">部门id</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Delete(long id)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeleteDeptWorkWxInput, BaseWorkWxOutput>(new() { Id = id });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取子部门ID列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">部门id。获取指定部门及其下的子部门(递归)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<DeptSimpleListWorkWxOutput> Get(long id)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeptSimpleListWorkWxInput, DeptSimpleListWorkWxOutput>(new() { Id = id });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标签
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2020/06/08
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/tag/create?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:创建的标签属于该应用,只有该应用的secret才可以增删成员
|
||||||
|
/// <br/>限制说明:标签总数不能超过3000个
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90210
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "tag/create", Desc = "创建标签", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class CreateTagWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签名称,长度限制为32个字以内(汉字或英文字母),标签名不可与其他标签重名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagname")]
|
||||||
|
[Required]
|
||||||
|
[StringLength(32, MinimumLength = 1)]
|
||||||
|
public string TagName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签id,非负整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
public long? TagId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新标签名字
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2020/04/02
|
||||||
|
/// <br/>请求方式:POST(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/tag/update?access_token=ACCESS_TOKEN
|
||||||
|
/// <br/>权限说明:调用的应用必须是指定标签的创建者
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90211
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "tag/update", Desc = "更新标签名字", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class UpdateTagWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签ID
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
[Required]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签名称,长度限制为32个字(汉字或英文字母),标签不可与其他标签重名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagname")]
|
||||||
|
[Required]
|
||||||
|
[StringLength(32, MinimumLength = 1)]
|
||||||
|
public string TagName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除标签
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>最后更新:2020/04/02
|
||||||
|
/// <br/>请求方式:GET(HTTPS)
|
||||||
|
/// <br/>请求地址:https://qyapi.weixin.qq.com/cgi-bin/tag/delete?access_token=ACCESS_TOKEN&tagid=TAGID
|
||||||
|
/// <br/>权限说明:调用的应用必须是指定标签的创建者
|
||||||
|
/// <br/>文档地址:https://developer.work.weixin.qq.com/document/path/90212
|
||||||
|
/// </remarks>
|
||||||
|
[HttpRemoteApi(Action = "tag/delete", Desc = "删除标签", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class DeleteTagWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签ID
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>是否必填:是</remarks>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
[Required(ErrorMessage = "标签ID不能为空")]
|
||||||
|
[Range(1, long.MaxValue, ErrorMessage = "标签ID必须大于0")]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签成员
|
||||||
|
/// </summary>
|
||||||
|
[HttpRemoteApi(Action = "tag/get", Desc = "获取标签成员", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class TagMembersWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签ID
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
[Required]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 增加标签成员
|
||||||
|
/// </summary>
|
||||||
|
[HttpRemoteApi(Action = "tag/addtagusers", Desc = "增加标签成员", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class AddTagMembersWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签ID
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
[Required]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业成员ID列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
[MaxLength(1000)]
|
||||||
|
public List<string> UserList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业部门ID列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("partylist")]
|
||||||
|
[MaxLength(100)]
|
||||||
|
public List<long> PartyList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除标签成员
|
||||||
|
/// </summary>
|
||||||
|
[HttpRemoteApi(Action = "tag/deltagusers", Desc = "删除标签成员", HttpMethod = HttpMethodEnum.Post)]
|
||||||
|
public class DeleteTagMembersWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签ID
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
[Required]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业成员ID列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
[MaxLength(1000)]
|
||||||
|
public List<string> UserList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业部门ID列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("partylist")]
|
||||||
|
[MaxLength(100)]
|
||||||
|
public List<long> PartyList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签列表
|
||||||
|
/// </summary>
|
||||||
|
[HttpRemoteApi(Action = "tag/list", Desc = "获取标签列表", HttpMethod = HttpMethodEnum.Get)]
|
||||||
|
public class TagListWorkWxInput : AuthWorkWxInput
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标签输出
|
||||||
|
/// </summary>
|
||||||
|
public class CreateTagWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签成员信息
|
||||||
|
/// </summary>
|
||||||
|
public class TagMemberWorkWxInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员账号
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员名称
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签成员输出
|
||||||
|
/// </summary>
|
||||||
|
public class TagMembersWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagname")]
|
||||||
|
public string TagName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签中包含的成员列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
public List<TagMemberWorkWxInfo> UserList { get; set; } = new List<TagMemberWorkWxInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签中包含的部门id列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("partylist")]
|
||||||
|
public List<long> PartyList { get; set; } = new List<long>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 增加标签成员输出
|
||||||
|
/// </summary>
|
||||||
|
public class AddTagMembersWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 非法的成员账号列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidlist")]
|
||||||
|
public string InvalidList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法的部门id列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidparty")]
|
||||||
|
public List<long> InvalidParty { get; set; } = new List<long>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除标签成员输出
|
||||||
|
/// </summary>
|
||||||
|
public class DeleteTagMembersWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 非法的成员账号列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidlist")]
|
||||||
|
public string InvalidList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法的部门id列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidparty")]
|
||||||
|
public List<long> InvalidParty { get; set; } = new List<long>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签基本信息
|
||||||
|
/// </summary>
|
||||||
|
public class TagInfoWorkWx
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagid")]
|
||||||
|
public long TagId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标签名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("tagname")]
|
||||||
|
public string TagName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签列表输出
|
||||||
|
/// </summary>
|
||||||
|
public class TagListWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标签列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("taglist")]
|
||||||
|
public List<TagInfoWorkWx> TagList { get; set; } = new List<TagInfoWorkWx>();
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信标签服务 🧩
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxTagService(WorkWxBaseService baseService) : ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建标签
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<CreateTagWorkWxOutput> Create(CreateTagWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<CreateTagWorkWxInput, CreateTagWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新标签
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Update(UpdateTagWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UpdateTagWorkWxInput, BaseWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除标签
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">标签ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Delete(long id)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeleteTagWorkWxInput, BaseWorkWxOutput>(new(){ TagId = id });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">标签ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<TagMembersWorkWxOutput> Get(long id)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<TagMembersWorkWxInput, TagMembersWorkWxOutput>(new(){ TagId = id });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 增加标签成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<AddTagMembersWorkWxOutput> AddTagMembers(AddTagMembersWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<AddTagMembersWorkWxInput, AddTagMembersWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除标签成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<DeleteTagMembersWorkWxOutput> DeleteTagMembers(DeleteTagMembersWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeleteTagMembersWorkWxInput, DeleteTagMembersWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取标签列表
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<TagListWorkWxOutput> GetList()
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<TagListWorkWxInput, TagListWorkWxOutput>(new());
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,899 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建成员输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class CreateUserWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 因填写不存在的部门,新增的部门列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("created_department_list")]
|
||||||
|
public CreatedDepartmentListDto CreatedDepartmentList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增部门列表
|
||||||
|
/// </summary>
|
||||||
|
public class CreatedDepartmentListDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门信息列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department_info")]
|
||||||
|
public List<DepartmentInfo> DepartmentInfo { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门信息
|
||||||
|
/// </summary>
|
||||||
|
public class DepartmentInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 部门名称
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门ID
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取成员输出参数
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <br/>注意:应用只能获取可见范围内的成员信息,且每种应用获取的字段有所不同
|
||||||
|
/// <br/>从2022年6月20号开始,新创建的自建应用与代开发应用不再返回敏感字段
|
||||||
|
/// </remarks>
|
||||||
|
public class UserWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员UserID。对应管理端的账号,企业内必须唯一。不区分大小写,长度为1~64个字节;第三方应用返回的值为open_userid
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员名称;第三方不可获取,调用时返回userid以代替name;代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员所属部门id列表,仅返回该应用有查看权限的部门id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department")]
|
||||||
|
public List<long> Department { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门内的排序值,默认为0。数量必须和department一致,数值越大排序越前面
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("order")]
|
||||||
|
public List<long> Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 职务信息;代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("position")]
|
||||||
|
public string Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手机号码,代开发自建应用需要管理员授权且成员oauth2授权获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("mobile")]
|
||||||
|
public string Mobile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 性别。0表示未定义,1表示男性,2表示女性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("gender")]
|
||||||
|
public int? Gender { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 性别描述
|
||||||
|
/// </summary>
|
||||||
|
public string GenderDesc => Gender switch
|
||||||
|
{
|
||||||
|
1 => "男",
|
||||||
|
2 => "女",
|
||||||
|
0 => "未定义",
|
||||||
|
_ => "未知"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 邮箱,代开发自建应用需要管理员授权且成员oauth2授权获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("email")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业邮箱,代开发自建应用需要管理员授权且成员oauth2授权获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("biz_mail")]
|
||||||
|
public string BizMail { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表示在所在的部门内是否为部门负责人,数量与department一致
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("is_leader_in_dept")]
|
||||||
|
public List<int> IsLeaderInDept { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直属上级UserID,返回在应用可见范围内的直属上级列表,最多有1个直属上级
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("direct_leader")]
|
||||||
|
public List<string> DirectLeader { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 头像url。代开发自建应用需要管理员授权且成员oauth2授权获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("avatar")]
|
||||||
|
public string Avatar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 头像缩略图url
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("thumb_avatar")]
|
||||||
|
public string ThumbAvatar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 座机。代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("telephone")]
|
||||||
|
public string Telephone { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 别名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("alias")]
|
||||||
|
public string Alias { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址。代开发自建应用需要管理员授权且成员oauth2授权获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("address")]
|
||||||
|
public string Address { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 全局唯一ID。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("open_userid")]
|
||||||
|
public string OpenUserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主部门,仅当应用对主部门有查看权限时返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("main_department")]
|
||||||
|
public long? MainDepartment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扩展属性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("extattr")]
|
||||||
|
public CreateUserWorkWxInput.ExtAttrDto ExtAttr { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("status")]
|
||||||
|
public int? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态描述
|
||||||
|
/// </summary>
|
||||||
|
public string StatusDesc => Status switch
|
||||||
|
{
|
||||||
|
1 => "已激活",
|
||||||
|
2 => "已禁用",
|
||||||
|
4 => "未激活",
|
||||||
|
5 => "退出企业",
|
||||||
|
_ => "未知状态"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 员工个人二维码URL
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("qr_code")]
|
||||||
|
public string QrCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对外职务
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("external_position")]
|
||||||
|
public string ExternalPosition { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员对外属性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("external_profile")]
|
||||||
|
public CreateUserWorkWxInput.ExternalProfileDto ExternalProfile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否为部门负责人(主部门)
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLeader
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsLeaderInDept == null || Department == null || MainDepartment == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var mainDeptIndex = Department.IndexOf(MainDepartment.Value);
|
||||||
|
return mainDeptIndex >= 0 && mainDeptIndex < IsLeaderInDept.Count && IsLeaderInDept[mainDeptIndex] == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已激活
|
||||||
|
/// </summary>
|
||||||
|
public bool IsActive => Status == 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取主部门名称(需要外部传入部门映射)
|
||||||
|
/// </summary>
|
||||||
|
public string GetMainDepartmentName(Dictionary<long, string> departmentMap)
|
||||||
|
{
|
||||||
|
if (MainDepartment.HasValue && departmentMap != null && departmentMap.TryGetValue(MainDepartment.Value, out var name))
|
||||||
|
return name;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频号信息(响应)
|
||||||
|
/// </summary>
|
||||||
|
public class WechatChannelsResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 视频号名称
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("nickname")]
|
||||||
|
public string Nickname { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 视频号状态
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("status")]
|
||||||
|
public int? Status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门成员输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class DeptUserSimpleListWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
public List<DepartmentUserSimpleInfo> UserList { get; set; } = new List<DepartmentUserSimpleInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员数量
|
||||||
|
/// </summary>
|
||||||
|
public int Count => UserList?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含成员
|
||||||
|
/// </summary>
|
||||||
|
public bool HasUsers => Count > 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取用户ID列表
|
||||||
|
/// </summary>
|
||||||
|
public List<string> UserIds => UserList?.Select(u => u.UserId).ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取OpenUserID列表
|
||||||
|
/// </summary>
|
||||||
|
public List<string> OpenUserIds => UserList?.Where(u => !string.IsNullOrEmpty(u.OpenUserId))
|
||||||
|
.Select(u => u.OpenUserId)
|
||||||
|
.ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门成员简略信息
|
||||||
|
/// </summary>
|
||||||
|
public class DepartmentUserSimpleInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员UserID。对应管理端的账号
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员名称,第三方应用可能返回userid代替name
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员所属部门列表。列表项为部门ID,32位整型
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department")]
|
||||||
|
public List<long> Department { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 全局唯一ID。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("open_userid")]
|
||||||
|
public string OpenUserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取显示名称(优先显示name,如果没有则显示userid)
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName => !string.IsNullOrEmpty(Name) ? Name : UserId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含指定部门
|
||||||
|
/// </summary>
|
||||||
|
public bool ContainsDepartment(long departmentId)
|
||||||
|
{
|
||||||
|
return Department?.Contains(departmentId) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取主部门(第一个部门)
|
||||||
|
/// </summary>
|
||||||
|
public long? MainDepartment => Department?.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门成员详情输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class DeptUserDetailListWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userlist")]
|
||||||
|
public List<DepartmentUserDetailInfo> UserList { get; set; } = new List<DepartmentUserDetailInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员数量
|
||||||
|
/// </summary>
|
||||||
|
public int Count => UserList?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含成员
|
||||||
|
/// </summary>
|
||||||
|
public bool HasUsers => Count > 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取已激活的成员列表
|
||||||
|
/// </summary>
|
||||||
|
public List<DepartmentUserDetailInfo> ActiveUsers => UserList?.Where(u => u.IsActive).ToList() ?? new List<DepartmentUserDetailInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门负责人列表
|
||||||
|
/// </summary>
|
||||||
|
public List<DepartmentUserDetailInfo> LeaderUsers => UserList?.Where(u => u.IsLeader).ToList() ?? new List<DepartmentUserDetailInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取用户ID列表
|
||||||
|
/// </summary>
|
||||||
|
public List<string> UserIds => UserList?.Select(u => u.UserId).ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按状态分组统计
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, int> GetStatusStatistics()
|
||||||
|
{
|
||||||
|
return UserList?
|
||||||
|
.GroupBy(u => u.StatusDesc)
|
||||||
|
.ToDictionary(g => g.Key, g => g.Count()) ?? new Dictionary<string, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门成员详细信息
|
||||||
|
/// </summary>
|
||||||
|
public class DepartmentUserDetailInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 成员UserID。对应管理端的账号
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员名称;第三方不可获取,调用时返回userid以代替name
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 英文名
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("english_name")]
|
||||||
|
public string EnglishName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员所属部门id列表,仅返回该应用有查看权限的部门id
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department")]
|
||||||
|
public List<long> Department { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门内的排序值,默认为0。数量必须和department一致
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("order")]
|
||||||
|
public List<long> Order { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 职务信息;代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("position")]
|
||||||
|
public string Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 手机号码,代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("mobile")]
|
||||||
|
public string Mobile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 性别。0表示未定义,1表示男性,2表示女性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("gender")]
|
||||||
|
public int? Gender { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 性别描述
|
||||||
|
/// </summary>
|
||||||
|
public string GenderDesc => Gender switch
|
||||||
|
{
|
||||||
|
1 => "男",
|
||||||
|
2 => "女",
|
||||||
|
0 => "未定义",
|
||||||
|
_ => "未知"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 邮箱,代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("email")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业邮箱,代开发自建应用不返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("biz_mail")]
|
||||||
|
public string BizMail { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表示在所在的部门内是否为部门负责人。0-否;1-是
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("is_leader_in_dept")]
|
||||||
|
public List<int> IsLeaderInDept { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直属上级UserID,返回在应用可见范围内的直属上级列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("direct_leader")]
|
||||||
|
public List<string> DirectLeader { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 头像url。第三方仅通讯录应用可获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("avatar")]
|
||||||
|
public string Avatar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 头像缩略图url。第三方仅通讯录应用可获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("thumb_avatar")]
|
||||||
|
public string ThumbAvatar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 座机。代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("telephone")]
|
||||||
|
public string Telephone { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 别名;第三方仅通讯录应用可获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("alias")]
|
||||||
|
public string Alias { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扩展属性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("extattr")]
|
||||||
|
public CreateUserWorkWxInput.ExtAttrDto ExtAttr { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("status")]
|
||||||
|
public int? Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 状态描述
|
||||||
|
/// </summary>
|
||||||
|
public string StatusDesc => Status switch
|
||||||
|
{
|
||||||
|
1 => "已激活",
|
||||||
|
2 => "已禁用",
|
||||||
|
4 => "未激活",
|
||||||
|
5 => "退出企业",
|
||||||
|
_ => "未知状态"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 地址。代开发自建应用需要管理员授权才返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("address")]
|
||||||
|
public string Address { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 全局唯一ID。仅第三方应用可获取
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("open_userid")]
|
||||||
|
public string OpenUserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 主部门,仅当应用对主部门有查看权限时返回
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("main_department")]
|
||||||
|
public long? MainDepartment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 员工个人二维码URL
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("qr_code")]
|
||||||
|
public string QrCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对外职务
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("external_position")]
|
||||||
|
public string ExternalPosition { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员对外属性
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("external_profile")]
|
||||||
|
public CreateUserWorkWxInput.ExternalProfileDto ExternalProfile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取显示名称(优先显示name,如果没有则显示userid)
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName => !string.IsNullOrEmpty(Name) ? Name : UserId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已激活
|
||||||
|
/// </summary>
|
||||||
|
public bool IsActive => Status == 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否为部门负责人(主部门)
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLeader
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsLeaderInDept == null || Department == null || MainDepartment == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var mainDeptIndex = Department.IndexOf(MainDepartment.Value);
|
||||||
|
return mainDeptIndex >= 0 && mainDeptIndex < IsLeaderInDept.Count && IsLeaderInDept[mainDeptIndex] == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含指定部门
|
||||||
|
/// </summary>
|
||||||
|
public bool ContainsDepartment(long departmentId)
|
||||||
|
{
|
||||||
|
return Department?.Contains(departmentId) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取主部门排序值
|
||||||
|
/// </summary>
|
||||||
|
public long? GetMainDepartmentOrder()
|
||||||
|
{
|
||||||
|
if (Order == null || Department == null || MainDepartment == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var mainDeptIndex = Department.IndexOf(MainDepartment.Value);
|
||||||
|
return mainDeptIndex >= 0 && mainDeptIndex < Order.Count ? Order[mainDeptIndex] : (long?)null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// userid转openid输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class ConvToOpenIdWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信成员userid对应的openid
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("openid")]
|
||||||
|
public string OpenId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// openid转userid输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class ConvToUserIdWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 该openid在企业微信对应的成员userid
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 邀请成员输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class InviteUserWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 非法成员列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invaliduser")]
|
||||||
|
public List<string> InvalidUser { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法部门列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidparty")]
|
||||||
|
public List<long> InvalidParty { get; set; } = new List<long>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法标签列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("invalidtag")]
|
||||||
|
public List<long> InvalidTag { get; set; } = new List<long>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 有效成员数量
|
||||||
|
/// </summary>
|
||||||
|
public int ValidUserCount => (InputUserCount - InvalidUserCount);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 有效部门数量
|
||||||
|
/// </summary>
|
||||||
|
public int ValidPartyCount => (InputPartyCount - InvalidPartyCount);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 有效标签数量
|
||||||
|
/// </summary>
|
||||||
|
public int ValidTagCount => (InputTagCount - InvalidTagCount);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法成员数量
|
||||||
|
/// </summary>
|
||||||
|
public int InvalidUserCount => InvalidUser?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法部门数量
|
||||||
|
/// </summary>
|
||||||
|
public int InvalidPartyCount => InvalidParty?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 非法标签数量
|
||||||
|
/// </summary>
|
||||||
|
public int InvalidTagCount => InvalidTag?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 输入成员数量(需要在调用时设置)
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public int InputUserCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 输入部门数量(需要在调用时设置)
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public int InputPartyCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 输入标签数量(需要在调用时设置)
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public int InputTagCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否全部有效
|
||||||
|
/// </summary>
|
||||||
|
public bool IsAllValid => InvalidUserCount == 0 && InvalidPartyCount == 0 && InvalidTagCount == 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取邀请结果摘要
|
||||||
|
/// </summary>
|
||||||
|
public string GetInviteSummary()
|
||||||
|
{
|
||||||
|
var summary = new StringBuilder();
|
||||||
|
summary.Append("邀请结果: ");
|
||||||
|
|
||||||
|
if (InvalidUserCount > 0)
|
||||||
|
{
|
||||||
|
summary.Append($"{InvalidUserCount}个无效成员");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InvalidPartyCount > 0)
|
||||||
|
{
|
||||||
|
if (summary.Length > 12) summary.Append(", ");
|
||||||
|
summary.Append($"{InvalidPartyCount}个无效部门");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InvalidTagCount > 0)
|
||||||
|
{
|
||||||
|
if (summary.Length > 12) summary.Append(", ");
|
||||||
|
summary.Append($"{InvalidTagCount}个无效标签");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsAllValid)
|
||||||
|
{
|
||||||
|
summary.Append("全部有效");
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取加入企业二维码输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class JoinQrcodeWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 二维码链接,有效期7天
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("join_qrcode")]
|
||||||
|
public string JoinQrcode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 二维码尺寸描述
|
||||||
|
/// </summary>
|
||||||
|
public string QrcodeSizeDesc => SizeType switch
|
||||||
|
{
|
||||||
|
1 => "171x171",
|
||||||
|
2 => "399x399",
|
||||||
|
3 => "741x741",
|
||||||
|
4 => "2052x2052",
|
||||||
|
_ => "未知尺寸"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 尺寸类型(从URL中解析)
|
||||||
|
/// </summary>
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
|
public int? SizeType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(JoinQrcode))return null;
|
||||||
|
var match = Regex.Match(JoinQrcode, @"qr_size=(\d)");
|
||||||
|
return match.Success ? int.Parse(match.Groups[1].Value) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 成员Id输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class UserIdWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户userid
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取成员ID列表输出参数
|
||||||
|
/// </summary>
|
||||||
|
public class UserIdListWorkWxOutput : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 分页游标,下次请求时填写以获取之后分页的记录
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("next_cursor")]
|
||||||
|
public string NextCursor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户-部门关系列表
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("dept_user")]
|
||||||
|
public List<DeptUserInfo> DeptUser { get; set; } = new List<DeptUserInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户数量
|
||||||
|
/// </summary>
|
||||||
|
public int UserCount => DeptUser?.Count ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否还有更多数据
|
||||||
|
/// </summary>
|
||||||
|
public bool HasMore => !string.IsNullOrEmpty(NextCursor);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取去重后的用户ID列表
|
||||||
|
/// </summary>
|
||||||
|
public List<string> DistinctUserIds => DeptUser?.Select(d => d.UserId).Distinct().ToList() ?? new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按部门分组用户
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<long, List<string>> GroupUsersByDepartment()
|
||||||
|
{
|
||||||
|
var result = new Dictionary<long, List<string>>();
|
||||||
|
|
||||||
|
if (DeptUser == null) return result;
|
||||||
|
|
||||||
|
foreach (var item in DeptUser)
|
||||||
|
{
|
||||||
|
if (!result.ContainsKey(item.Department))
|
||||||
|
{
|
||||||
|
result[item.Department] = new List<string>();
|
||||||
|
}
|
||||||
|
result[item.Department].Add(item.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按用户分组部门
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, List<long>> GroupDepartmentsByUser()
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, List<long>>();
|
||||||
|
|
||||||
|
if (DeptUser == null) return result;
|
||||||
|
|
||||||
|
foreach (var item in DeptUser)
|
||||||
|
{
|
||||||
|
if (!result.ContainsKey(item.UserId))
|
||||||
|
{
|
||||||
|
result[item.UserId] = new List<long>();
|
||||||
|
}
|
||||||
|
result[item.UserId].Add(item.Department);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户-部门关系信息
|
||||||
|
/// </summary>
|
||||||
|
public class DeptUserInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户userid,当用户在多个部门下时会有多条记录
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("userid")]
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户所属部门
|
||||||
|
/// </summary>
|
||||||
|
[CustomJsonProperty("department")]
|
||||||
|
public long Department { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信成员工具类
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxUserHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否包含敏感字段(根据应用类型判断)
|
||||||
|
/// </summary>
|
||||||
|
public static bool HasSensitiveFields(UserWorkWxOutput user, bool isNewApp)
|
||||||
|
{
|
||||||
|
if (isNewApp)
|
||||||
|
{
|
||||||
|
// 新应用无法获取的敏感字段
|
||||||
|
return string.IsNullOrEmpty(user.Avatar) &&
|
||||||
|
string.IsNullOrEmpty(user.Mobile) &&
|
||||||
|
string.IsNullOrEmpty(user.Email) &&
|
||||||
|
string.IsNullOrEmpty(user.BizMail) &&
|
||||||
|
string.IsNullOrEmpty(user.QrCode) &&
|
||||||
|
string.IsNullOrEmpty(user.Address) &&
|
||||||
|
(user.Gender == null || user.Gender == 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取显示名称(优先显示name,如果没有则显示userid)
|
||||||
|
/// </summary>
|
||||||
|
public static string GetDisplayName(UserWorkWxOutput user)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(user.Name) ? user.Name : user.UserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取完整的部门信息
|
||||||
|
/// </summary>
|
||||||
|
public static string GetDepartmentInfo(UserWorkWxOutput user, Dictionary<long, string> departmentMap)
|
||||||
|
{
|
||||||
|
if (user.Department == null || departmentMap == null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var departments = user.Department
|
||||||
|
.Select(deptId => departmentMap.TryGetValue(deptId, out var name) ? $"{name}({deptId})" : deptId.ToString())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return string.Join(", ", departments);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信成员服务 🧩
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxUserService(WorkWxBaseService baseService) : ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<CreateUserWorkWxOutput> Create(CreateUserWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<CreateUserWorkWxInput, CreateUserWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">成员UserID。对应管理端的账号,企业内必须唯一。不区分大小写,长度为1~64个字节</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<UserWorkWxOutput> Get(string userId)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UserWorkWxInput, UserWorkWxOutput>(new() { UserId = userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Update(UpdateUserWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UpdateUserWorkWxInput, BaseWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">成员UserID。对应管理端的账号</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> Delete(string userId)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeleteUserWorkWxInput, BaseWorkWxOutput>(new() { UserId = userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量删除成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> DeleteUser(BatchDeleteUserWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<BatchDeleteUserWorkWxInput, BaseWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<DeptUserSimpleListWorkWxOutput> SimpleListDept(DeptUserSimpleListWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeptUserSimpleListWorkWxInput, DeptUserSimpleListWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取部门成员详情
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<DeptUserDetailListWorkWxOutput> DeptUserDetail(DeptUserDetailListWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<DeptUserDetailListWorkWxInput, DeptUserDetailListWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// userid转openid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<ConvToOpenIdWorkWxOutput> UserIdToOpenId(ConvToOpenIdWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<ConvToOpenIdWorkWxInput, ConvToOpenIdWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// openid转userid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<ConvToUserIdWorkWxOutput> OpenIdToUserId(ConvToUserIdWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<ConvToUserIdWorkWxInput, ConvToUserIdWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登录二次验证
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">成员UserID。对应管理端的账号</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<BaseWorkWxOutput> AuthSucc(string userId)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UserAuthSuccessWorkWxInput, BaseWorkWxOutput>(new() { UserId = userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 邀请成员
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<InviteUserWorkWxOutput> InviteUser(InviteUserWorkWxInput input)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<InviteUserWorkWxInput, InviteUserWorkWxOutput>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取加入企业二维码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sizeType">qrcode尺寸类型,1: 171 x 171; 2: 399 x 399; 3: 741 x 741; 4: 2052 x 2052</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<JoinQrcodeWorkWxOutput> GetJoinQrcode(int? sizeType)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<JoinQrcodeWorkWxInput, JoinQrcodeWorkWxOutput>(new() { SizeType = sizeType });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过手机号获取成员ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mobile">用户在企业微信通讯录中的手机号码。长度为5~32个字节</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<UserIdWorkWxOutput> GetUserIdByMobile(string mobile)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UserIdByMobileWorkWxInput, UserIdWorkWxOutput>(new() { Mobile = mobile });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过邮箱获取成员ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="email">邮箱</param>
|
||||||
|
/// <param name="emailType">邮箱类型:1-企业邮箱(默认);2-个人邮箱</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<UserIdWorkWxOutput> GetUserIdByEmail(string email, int? emailType = 1)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UserIdByEmailWorkWxInput, UserIdWorkWxOutput>(new(){ Email = email, EmailType = emailType });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取成员ID列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cursor">用于分页查询的游标,字符串类型,由上一次调用返回,首次调用不填</param>
|
||||||
|
/// <param name="limit">分页,预期请求的数据量,取值范围 1 ~ 10000</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<UserIdListWorkWxOutput> GetUserIdList(string cursor = null, int? limit = 20)
|
||||||
|
{
|
||||||
|
return await baseService.SendAsync<UserIdListWorkWxInput, UserIdListWorkWxOutput>(new(){ Cursor = cursor, Limit = limit });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信成员更新工具类
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxUserUpdateHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 从现有成员信息创建更新对象
|
||||||
|
/// </summary>
|
||||||
|
public static UpdateUserWorkWxInput CreateFromExisting(UserWorkWxOutput existingUser)
|
||||||
|
{
|
||||||
|
return new UpdateUserWorkWxInput
|
||||||
|
{
|
||||||
|
UserId = existingUser.UserId,
|
||||||
|
Name = existingUser.Name,
|
||||||
|
Alias = existingUser.Alias,
|
||||||
|
Mobile = existingUser.Mobile,
|
||||||
|
Email = existingUser.Email,
|
||||||
|
Department = existingUser.Department,
|
||||||
|
Order = existingUser.Order,
|
||||||
|
Position = existingUser.Position,
|
||||||
|
Gender = existingUser.Gender,
|
||||||
|
Telephone = existingUser.Telephone,
|
||||||
|
IsLeaderInDept = existingUser.IsLeaderInDept,
|
||||||
|
DirectLeader = existingUser.DirectLeader,
|
||||||
|
Enable = existingUser.Status == 1 ? 1 : (existingUser.Status == 2 ? 0 : (int?)null),
|
||||||
|
ExtAttr = existingUser.ExtAttr,
|
||||||
|
ExternalPosition = existingUser.ExternalPosition,
|
||||||
|
ExternalProfile = existingUser.ExternalProfile,
|
||||||
|
Address = existingUser.Address,
|
||||||
|
MainDepartment = existingUser.MainDepartment
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建部门更新信息
|
||||||
|
/// </summary>
|
||||||
|
public static UpdateUserWorkWxInput CreateDepartmentUpdate(string userId, List<long> departments, List<long> orders = null, List<int> isLeaders = null)
|
||||||
|
{
|
||||||
|
var input = new UpdateUserWorkWxInput
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Department = departments
|
||||||
|
};
|
||||||
|
|
||||||
|
if (orders != null && orders.Count == departments.Count)
|
||||||
|
{
|
||||||
|
input.Order = orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLeaders != null && isLeaders.Count == departments.Count)
|
||||||
|
{
|
||||||
|
input.IsLeaderInDept = isLeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建基础信息更新
|
||||||
|
/// </summary>
|
||||||
|
public static UpdateUserWorkWxInput CreateBasicInfoUpdate(string userId, string name = null, string mobile = null, string email = null, string position = null)
|
||||||
|
{
|
||||||
|
return new UpdateUserWorkWxInput
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Name = name,
|
||||||
|
Mobile = mobile,
|
||||||
|
Email = email,
|
||||||
|
Position = position
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建状态更新
|
||||||
|
/// </summary>
|
||||||
|
public static UpdateUserWorkWxInput CreateStatusUpdate(string userId, bool enable)
|
||||||
|
{
|
||||||
|
return new UpdateUserWorkWxInput
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
Enable = enable ? 1 : 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
|
//
|
||||||
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
|
//
|
||||||
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using Admin.NET.Plugin.WorkWeixin.Const;
|
||||||
|
using Furion.FriendlyException;
|
||||||
|
using Furion.JsonSerialization;
|
||||||
|
using Furion.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Admin.NET.Plugin.WorkWeixin;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 企业微信接口基类服务 🧩
|
||||||
|
/// </summary>
|
||||||
|
public class WorkWxBaseService(
|
||||||
|
SysCacheService sysCacheService,
|
||||||
|
SysConfigService sysConfigService,
|
||||||
|
IHttpRemoteService httpRemoteService,
|
||||||
|
IOptions<HttpRemotesOptions> options) : ITransient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 发起请求
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">输入类型</typeparam>
|
||||||
|
/// <typeparam name="R">返回类型</typeparam>
|
||||||
|
/// <param name="input">输入参数</param>
|
||||||
|
/// <returns>返回结果</returns>
|
||||||
|
public async Task<R> SendAsync<T, R>(T input) where R : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
var attr = typeof(T).GetCustomAttribute<HttpRemoteApiAttribute>();
|
||||||
|
if (attr == null || string.IsNullOrWhiteSpace(attr.Action) || string.IsNullOrWhiteSpace(attr.Desc))
|
||||||
|
throw Oops.Oh($"接口入参类型({typeof(T).FullName})未正确配置[HttpRemoteApi]特性");
|
||||||
|
|
||||||
|
// 拼接请求地址,并设置token
|
||||||
|
var url = options.Value.WorkWeixin.BaseAddress + $"/cgi-bin/{attr.Action}?";
|
||||||
|
if (input is AuthWorkWxInput)
|
||||||
|
{
|
||||||
|
var token = sysCacheService.Get<string>(WorkWeixinConst.KeyWorkWeixinToken) ?? await GetTokenAsync();
|
||||||
|
url += "access_token=" + token;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponseMessage response;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = attr.HttpMethod switch
|
||||||
|
{
|
||||||
|
HttpMethodEnum.Get => await httpRemoteService.GetAsync(
|
||||||
|
url + input.ToCustomJsonPropertyQueryString(),
|
||||||
|
builder => builder.SetHttpOptions(options.Value.WorkWeixin, attr.Desc)),
|
||||||
|
HttpMethodEnum.Post => await httpRemoteService.PostAsync(url,
|
||||||
|
builder => builder.SetHttpOptions(options.Value.WorkWeixin, attr.Desc)
|
||||||
|
.SetContent(new StringContent(JSON.Serialize(input, CustomJsonPropertyConverter.Options), Encoding.UTF8, "application/json"))),
|
||||||
|
_ => throw Oops.Oh($"[企业微信] 不支持的请求方式{attr.HttpMethod.ToString()}:({typeof(T).FullName})"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
throw Oops.Oh("[企业微信] 服务不可用,请检查网路是否正常" + ex.Message);
|
||||||
|
}
|
||||||
|
return await HandleHttpResponseAsync<R>(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理HTTP响应
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="respMsg"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="HttpRequestException"></exception>
|
||||||
|
private async Task<R> HandleHttpResponseAsync<R>(HttpResponseMessage respMsg) where R : BaseWorkWxOutput
|
||||||
|
{
|
||||||
|
if (!respMsg.IsSuccessStatusCode) throw Oops.Oh("[企业微信] 请求失败");
|
||||||
|
|
||||||
|
var responseContent = await respMsg.Content.ReadAsStringAsync();
|
||||||
|
if (string.IsNullOrWhiteSpace(responseContent)) throw Oops.Oh("[企业微信] 响应体为空");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var resp = JSON.Deserialize<R>(responseContent, CustomJsonPropertyConverter.Options);
|
||||||
|
if (resp?.ErrCode == 0) return resp;
|
||||||
|
throw Oops.Oh("[企业微信] 请求失败:" + resp?.ErrMsg);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex.Message);
|
||||||
|
throw Oops.Oh((ex is AppFriendlyException ? "" : "[企业微信] 序列化失败:") + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取企业微信接口凭证
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<string> GetTokenAsync()
|
||||||
|
{
|
||||||
|
using var disposable = sysCacheService.BeginCacheLock(WorkWeixinConst.KeyLockWorkWeixin);
|
||||||
|
var result = await SendAsync<TokenWorkWxInput, TokenWorkWxOutput>(new()
|
||||||
|
{
|
||||||
|
CorpId = await sysConfigService.GetConfigValueByCode(WorkWeixinConst.WorkWeixinCorpId),
|
||||||
|
CorpSecret = await sysConfigService.GetConfigValueByCode(WorkWeixinConst.WorkWeixinCorpSecret)
|
||||||
|
});
|
||||||
|
sysCacheService.Set(WorkWeixinConst.KeyWorkWeixinToken, result.AccessToken, TimeSpan.FromSeconds(result.ExpiresIn));
|
||||||
|
return result.AccessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,6 @@
|
|||||||
//
|
//
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
using Admin.NET.Plugin.WorkWeixin.Option;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@ -16,7 +15,6 @@ public class Startup : AppStartup
|
|||||||
{
|
{
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddConfigurableOptions<WorkWeixinOptions>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
|
||||||
//
|
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
|
||||||
//
|
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
||||||
|
|
||||||
namespace Admin.NET.Plugin.WorkWeixin;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 企业微信接口输出基类
|
|
||||||
/// </summary>
|
|
||||||
public class BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 返回码
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("errcode")]
|
|
||||||
[JsonPropertyName("errcode")]
|
|
||||||
public int ErrCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 对返回码的文本描述内容
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("errmsg")]
|
|
||||||
[JsonPropertyName("errmsg")]
|
|
||||||
public string ErrMsg { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 带id的输出参数
|
|
||||||
/// </summary>
|
|
||||||
public class BaseWorkIdOutput : BaseWorkOutput
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// id
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("id")]
|
|
||||||
[JsonPropertyName("id")]
|
|
||||||
public long? Id { get; set; }
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user