committed by
GitHub
102 changed files with 2366 additions and 333 deletions
@ -0,0 +1,43 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Response; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat; |
||||
|
/// <summary>
|
||||
|
/// 群聊操作接口
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/90244
|
||||
|
/// </remarks>
|
||||
|
public interface IWeChatWorkAppChatManager |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建群聊会话
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/90245
|
||||
|
/// </remarks>
|
||||
|
Task<WeChatWorkAppChatCreateResponse> CreateAsync( |
||||
|
WeChatWorkAppChatCreateRequest request, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
/// <summary>
|
||||
|
/// 修改群聊会话
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/98913
|
||||
|
/// </remarks>
|
||||
|
Task<WeChatWorkResponse> UpdateAsync( |
||||
|
WeChatWorkAppChatUpdateRequest request, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
/// <summary>
|
||||
|
/// 获取群聊会话
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/98914
|
||||
|
/// </remarks>
|
||||
|
Task<WeChatWorkAppChatInfoResponse> GetAsync( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Models; |
||||
|
public class WeChatWorkAppChatInfo |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群聊名
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("name")] |
||||
|
[JsonPropertyName("name")] |
||||
|
public virtual string Name { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群主id
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("owner")] |
||||
|
[JsonPropertyName("owner")] |
||||
|
public virtual string Owner { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群成员id列表
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("userlist")] |
||||
|
[JsonPropertyName("userlist")] |
||||
|
public virtual List<string> Users { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群聊唯一标志
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("chatid")] |
||||
|
[JsonPropertyName("chatid")] |
||||
|
public virtual string ChatId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
public class WeChatWorkAppChatCreateRequest : WeChatWorkAppChatRequest |
||||
|
{ |
||||
|
public WeChatWorkAppChatCreateRequest( |
||||
|
string agentId, |
||||
|
string name, |
||||
|
List<string> users, |
||||
|
string owner = null, |
||||
|
string chatId = null) |
||||
|
: base(agentId) |
||||
|
{ |
||||
|
Name = name; |
||||
|
Owner = owner; |
||||
|
Users = users; |
||||
|
ChatId = chatId; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 群聊名,最多50个utf8字符,超过将截断
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("name")] |
||||
|
[JsonPropertyName("name")] |
||||
|
public virtual string Name { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 指定群主的id。
|
||||
|
/// 如果不指定,系统会随机从userlist中选一人作为群主
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("owner")] |
||||
|
[JsonPropertyName("owner")] |
||||
|
public virtual string Owner { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群成员id列表。
|
||||
|
/// 至少2人,至多2000人
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("userlist")] |
||||
|
[JsonPropertyName("userlist")] |
||||
|
public virtual List<string> Users { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群聊的唯一标志,不能与已有的群重复;
|
||||
|
/// 字符串类型,最长32个字符。
|
||||
|
/// 只允许字符0-9及字母a-zA-Z。
|
||||
|
/// 如果不填,系统会随机生成群id
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("chatid")] |
||||
|
[JsonPropertyName("chatid")] |
||||
|
public virtual string ChatId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
public abstract class WeChatWorkAppChatRequest : WeChatWorkRequest |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 应用标识
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[Newtonsoft.Json.JsonIgnore] |
||||
|
[System.Text.Json.Serialization.JsonIgnore] |
||||
|
public virtual string AgentId { get; set; } |
||||
|
protected WeChatWorkAppChatRequest(string agentId) |
||||
|
{ |
||||
|
AgentId = agentId; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
public class WeChatWorkAppChatUpdateRequest : WeChatWorkAppChatRequest |
||||
|
{ |
||||
|
public WeChatWorkAppChatUpdateRequest( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
string name = null, |
||||
|
string owner = null, |
||||
|
List<string> addUsers = null, |
||||
|
List<string> delUsers = null) |
||||
|
: base(agentId) |
||||
|
{ |
||||
|
Name = name; |
||||
|
Owner = owner; |
||||
|
AddUsers = addUsers; |
||||
|
DelUsers = delUsers; |
||||
|
ChatId = chatId; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 新的群聊名。若不需更新,请忽略此参数。最多50个utf8字符,超过将截断
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("name")] |
||||
|
[JsonPropertyName("name")] |
||||
|
public virtual string Name { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 新群主的id。
|
||||
|
/// 若不需更新,请忽略此参数。课程群聊群主必须在设置的群主列表内
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("owner")] |
||||
|
[JsonPropertyName("owner")] |
||||
|
public virtual string Owner { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 添加成员的id列表
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("add_user_list")] |
||||
|
[JsonPropertyName("add_user_list")] |
||||
|
public virtual List<string> AddUsers { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 踢出成员的id列表
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("del_user_list")] |
||||
|
[JsonPropertyName("del_user_list")] |
||||
|
public virtual List<string> DelUsers { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 群聊id
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("chatid")] |
||||
|
[JsonPropertyName("chatid")] |
||||
|
public virtual string ChatId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Response; |
||||
|
|
||||
|
public class WeChatWorkAppChatCreateResponse : WeChatWorkResponse |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群聊的唯一标志
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("chatid")] |
||||
|
[JsonPropertyName("chatid")] |
||||
|
public virtual string ChatId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Models; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat.Response; |
||||
|
public class WeChatWorkAppChatInfoResponse : WeChatWorkResponse |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 群聊信息
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("chat_info")] |
||||
|
[JsonPropertyName("chat_info")] |
||||
|
public WeChatWorkAppChatInfo ChatInfo { get; set; } |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Response; |
||||
|
using LINGYUN.Abp.WeChat.Work.Features; |
||||
|
using LINGYUN.Abp.WeChat.Work.Token; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Features; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Chat; |
||||
|
|
||||
|
[RequiresFeature(WeChatWorkFeatureNames.Enable)] |
||||
|
public class WeChatWorkAppChatManager : IWeChatWorkAppChatManager, ISingletonDependency |
||||
|
{ |
||||
|
protected IHttpClientFactory HttpClientFactory { get; } |
||||
|
protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } |
||||
|
|
||||
|
public WeChatWorkAppChatManager( |
||||
|
IHttpClientFactory httpClientFactory, |
||||
|
IWeChatWorkTokenProvider weChatWorkTokenProvider) |
||||
|
{ |
||||
|
HttpClientFactory = httpClientFactory; |
||||
|
WeChatWorkTokenProvider = weChatWorkTokenProvider; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<WeChatWorkAppChatCreateResponse> CreateAsync( |
||||
|
WeChatWorkAppChatCreateRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var token = await WeChatWorkTokenProvider.GetTokenAsync(request.AgentId, cancellationToken); |
||||
|
var client = HttpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient); |
||||
|
|
||||
|
using var response = await client.CreateAppChatAsync(token.AccessToken, request, cancellationToken); |
||||
|
return await response.DeserializeObjectAsync<WeChatWorkAppChatCreateResponse>(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<WeChatWorkAppChatInfoResponse> GetAsync( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var token = await WeChatWorkTokenProvider.GetTokenAsync(agentId, cancellationToken); |
||||
|
var client = HttpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient); |
||||
|
|
||||
|
using var response = await client.GetAppChatAsync(token.AccessToken, agentId, cancellationToken); |
||||
|
return await response.DeserializeObjectAsync<WeChatWorkAppChatInfoResponse>(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<WeChatWorkResponse> UpdateAsync( |
||||
|
WeChatWorkAppChatUpdateRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var token = await WeChatWorkTokenProvider.GetTokenAsync(request.AgentId, cancellationToken); |
||||
|
var client = HttpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient); |
||||
|
|
||||
|
using var response = await client.UpdateAppChatAsync(token.AccessToken, request, cancellationToken); |
||||
|
return await response.DeserializeObjectAsync<WeChatWorkAppChatCreateResponse>(); |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Media; |
namespace LINGYUN.Abp.WeChat.Work.Media.Models; |
||||
public class WeChatWorkImageResponse : WeChatWorkResponse |
public class WeChatWorkImageResponse : WeChatWorkResponse |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.Content; |
using Volo.Abp.Content; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Media; |
namespace LINGYUN.Abp.WeChat.Work.Media.Models; |
||||
public class WeChatWorkMediaRequest |
public class WeChatWorkMediaRequest |
||||
{ |
{ |
||||
public string AccessToken { get; set; } |
public string AccessToken { get; set; } |
||||
@ -1,6 +1,6 @@ |
|||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Media; |
namespace LINGYUN.Abp.WeChat.Work.Media.Models; |
||||
public class WeChatWorkMediaResponse : WeChatWorkResponse |
public class WeChatWorkMediaResponse : WeChatWorkResponse |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message; |
||||
|
/// <summary>
|
||||
|
/// 企业微信消息管理器
|
||||
|
/// </summary>
|
||||
|
public interface IWeChatWorkMessageManager |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 撤回应用消息
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/94867
|
||||
|
/// </remarks>
|
||||
|
/// <param name="agentId">应用标识</param>
|
||||
|
/// <param name="messageId">消息ID。从应用发送消息接口 <see cref="IWeChatWorkMessageSender"/> 处获得。</param>
|
||||
|
/// <param name="cancellationToken"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<bool> ReCallMessageAsync(string agentId, string messageId, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 小程序通知消息
|
||||
|
/// </summary>
|
||||
|
public class MiniProgramMessage |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 小程序appid,必须是与当前应用关联的小程序
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("appid")] |
||||
|
[JsonPropertyName("appid")] |
||||
|
public string AppId { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 消息标题,长度限制4-12个汉字(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("title")] |
||||
|
[JsonPropertyName("title")] |
||||
|
public string Title { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 点击消息卡片后的小程序页面,最长1024个字节,仅限本小程序内的页面。该字段不填则消息点击后不跳转。
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("page")] |
||||
|
[JsonPropertyName("page")] |
||||
|
public string Page { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 消息描述,长度限制4-12个汉字(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("description")] |
||||
|
[JsonPropertyName("description")] |
||||
|
public string Description { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 是否放大第一个content_item
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("emphasis_first_item")] |
||||
|
[JsonPropertyName("emphasis_first_item")] |
||||
|
public bool? EmphasisFirstItem { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 消息内容键值对,最多允许10个item
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("content_item")] |
||||
|
[JsonPropertyName("content_item")] |
||||
|
public List<MiniProgramContent> ContentItems{ get; set; } |
||||
|
public MiniProgramMessage() |
||||
|
{ |
||||
|
ContentItems = new List<MiniProgramContent>(); |
||||
|
} |
||||
|
|
||||
|
public MiniProgramMessage( |
||||
|
string appId, |
||||
|
string title, |
||||
|
string page = null, |
||||
|
string description = null, |
||||
|
bool? emphasisFirstItem = null) |
||||
|
{ |
||||
|
AppId = appId; |
||||
|
Page = page; |
||||
|
Title = title; |
||||
|
Description = description; |
||||
|
EmphasisFirstItem = emphasisFirstItem; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class MiniProgramContent |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 长度10个汉字以内
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("key")] |
||||
|
[JsonPropertyName("key")] |
||||
|
public string Key { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 长度30个汉字以内(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("value")] |
||||
|
[JsonPropertyName("value")] |
||||
|
public string Value { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊文件消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatFileMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatFileMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
MediaMessage file) : base(agentId, chatId, "file") |
||||
|
{ |
||||
|
File = file; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 媒体文件
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("file")] |
||||
|
[JsonPropertyName("file")] |
||||
|
public MediaMessage File { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0表示可对外分享,
|
||||
|
/// 1表示不能分享且内容显示水印,
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊图片消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatImageMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatImageMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
MediaMessage image) : base(agentId, chatId, "image") |
||||
|
{ |
||||
|
Image = image; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 图片媒体文件
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("image")] |
||||
|
[JsonPropertyName("image")] |
||||
|
public MediaMessage Image { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0表示可对外分享,
|
||||
|
/// 1表示不能分享且内容显示水印,
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public int Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊markdown消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatMarkdownMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatMarkdownMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
MarkdownMessage markdown) : base(agentId, chatId, "markdown") |
||||
|
{ |
||||
|
Markdown = markdown; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// markdown消息
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("markdown")] |
||||
|
[JsonPropertyName("markdown")] |
||||
|
public MarkdownMessage Markdown { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0不保密
|
||||
|
/// 1保密
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊文本图文消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatMpNewMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatMpNewMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
MpNewMessagePayload mpnews) : base(agentId, chatId, "mpnews") |
||||
|
{ |
||||
|
News = mpnews; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 图文消息(mp)
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("mpnews")] |
||||
|
[JsonPropertyName("mpnews")] |
||||
|
public MpNewMessagePayload News { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0不保密
|
||||
|
/// 1保密
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊文本图文消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatNewMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatNewMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
NewMessagePayload news) : base(agentId, chatId, "news") |
||||
|
{ |
||||
|
News = news; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 图文消息
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("news")] |
||||
|
[JsonPropertyName("news")] |
||||
|
public NewMessagePayload News { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0不保密
|
||||
|
/// 1保密
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊文本卡片消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatTextCardMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatTextCardMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
TextCardMessage textcard) : base(agentId, chatId, "textcard") |
||||
|
{ |
||||
|
TextCard = textcard; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 卡片消息
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("textcard")] |
||||
|
[JsonPropertyName("textcard")] |
||||
|
public TextCardMessage TextCard { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0表示可对外分享,
|
||||
|
/// 1表示不能分享且内容显示水印,
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊文本消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatTextMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatTextMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
TextMessage text) : base(agentId, chatId, "text") |
||||
|
{ |
||||
|
Text = text; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 消息内容,最长不超过2048个字节,超过将截断(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("text")] |
||||
|
[JsonPropertyName("text")] |
||||
|
public TextMessage Text { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0表示可对外分享,
|
||||
|
/// 1表示不能分享且内容显示水印,
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public int Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊语言消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatVideoMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatVideoMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
VideoMessage video) : base(agentId, chatId, "video") |
||||
|
{ |
||||
|
Video = video; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 视频媒体文件
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("video")] |
||||
|
[JsonPropertyName("video")] |
||||
|
public VideoMessage Video { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否是保密消息,
|
||||
|
/// 0表示可对外分享,
|
||||
|
/// 1表示不能分享且内容显示水印,
|
||||
|
/// 默认为0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("safe")] |
||||
|
[JsonPropertyName("safe")] |
||||
|
public byte Safe { get; set; } |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊语言消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkAppChatVoiceMessage : WeChatWorkAppChatMessage |
||||
|
{ |
||||
|
public WeChatWorkAppChatVoiceMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
MediaMessage voice) : base(agentId, chatId, "voice") |
||||
|
{ |
||||
|
Voice = voice; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 语音媒体文件
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("voice")] |
||||
|
[JsonPropertyName("voice")] |
||||
|
public MediaMessage Voice { get; set; } |
||||
|
} |
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信文件消息
|
/// 企业微信文件消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信图片消息
|
/// 企业微信图片消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信markdown消息
|
/// 企业微信markdown消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -0,0 +1,84 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
|
/// <summary>
|
||||
|
/// 企业微信小程序通知消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkMiniProgramMessage |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)。
|
||||
|
/// 特殊情况:指定为"@all",则向该企业应用的全部成员发送
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("touser")] |
||||
|
[JsonPropertyName("touser")] |
||||
|
public virtual string ToUser { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个。
|
||||
|
/// 当touser为"@all"时忽略本参数
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("toparty")] |
||||
|
[JsonPropertyName("toparty")] |
||||
|
public virtual string ToParty { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个。
|
||||
|
/// 当touser为"@all"时忽略本参数
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("totag")] |
||||
|
[JsonPropertyName("totag")] |
||||
|
public virtual string ToTag { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 消息类型
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("msgtype")] |
||||
|
[JsonPropertyName("msgtype")] |
||||
|
public virtual string MsgType { get; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否开启id转译,0表示否,1表示是,默认0。
|
||||
|
/// 仅第三方应用需要用到
|
||||
|
/// 企业自建应用可以忽略。
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("enable_id_trans")] |
||||
|
[JsonPropertyName("enable_id_trans")] |
||||
|
public byte EnableIdTrans { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否开启重复消息检查,0表示否,1表示是,默认0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("enable_duplicate_check")] |
||||
|
[JsonPropertyName("enable_duplicate_check")] |
||||
|
public byte EnableDuplicateCheck { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("duplicate_check_interval")] |
||||
|
[JsonPropertyName("duplicate_check_interval")] |
||||
|
public int DuplicateCheckInterval { get; set; } = 1800; |
||||
|
/// <summary>
|
||||
|
/// 消息内容
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("miniprogram_notice")] |
||||
|
[JsonPropertyName("miniprogram_notice")] |
||||
|
public MiniProgramMessage MiniProgram { get; set; } |
||||
|
public WeChatWorkMiniProgramMessage( |
||||
|
MiniProgramMessage miniProgram, |
||||
|
string toUser = "", |
||||
|
string toParty = "", |
||||
|
string toTag = "", |
||||
|
byte enableIdTrans = 0, |
||||
|
byte enableDuplicateCheck = 0, |
||||
|
int duplicateCheckInterval = 1800) |
||||
|
{ |
||||
|
ToUser = toUser; |
||||
|
ToParty = toParty; |
||||
|
ToTag = toTag; |
||||
|
EnableIdTrans = enableIdTrans; |
||||
|
EnableDuplicateCheck = enableDuplicateCheck; |
||||
|
DuplicateCheckInterval = duplicateCheckInterval; |
||||
|
MiniProgram = miniProgram; |
||||
|
MsgType = "miniprogram_notice"; |
||||
|
} |
||||
|
} |
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信文本图文消息
|
/// 企业微信文本图文消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信文本图文消息
|
/// 企业微信文本图文消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信文本卡片消息
|
/// 企业微信文本卡片消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信文本消息
|
/// 企业微信文本消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信语言消息
|
/// 企业微信语言消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -1,9 +1,8 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using LINGYUN.Abp.WeChat.Work.Message.Models; |
|
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Models; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信语言消息
|
/// 企业微信语言消息
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -0,0 +1,27 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Request; |
||||
|
/// <summary>
|
||||
|
/// 撤回消息请求载体
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkMessageReCallRequest : WeChatWorkRequest |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 调用接口凭证
|
||||
|
/// </summary>
|
||||
|
[System.Text.Json.Serialization.JsonIgnore] |
||||
|
[Newtonsoft.Json.JsonIgnore] |
||||
|
public string AccessToken { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 消息ID
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("msgid")] |
||||
|
[JsonPropertyName("msgid")] |
||||
|
public string MessageId { get; set; } |
||||
|
public WeChatWorkMessageReCallRequest(string accessToken, string messageId) |
||||
|
{ |
||||
|
AccessToken = accessToken; |
||||
|
MessageId = messageId; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Request; |
||||
|
public class WeChatWorkMessageRequest<TMessage> |
||||
|
{ |
||||
|
public string AccessToken { get; set; } |
||||
|
public TMessage Message { get; set; } |
||||
|
public WeChatWorkMessageRequest(string accessToken, TMessage message) |
||||
|
{ |
||||
|
AccessToken = accessToken; |
||||
|
Message = message; |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,7 @@ |
|||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
using System.Text.Json.Serialization; |
using System.Text.Json.Serialization; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
namespace LINGYUN.Abp.WeChat.Work.Message.Response; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信发送消息响应
|
/// 企业微信发送消息响应
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -0,0 +1,28 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
|
||||
|
public abstract class TemplateCard |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 模板卡片类型
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("card_type")] |
||||
|
[JsonPropertyName("card_type")] |
||||
|
public string Type { get; } |
||||
|
/// <summary>
|
||||
|
/// 任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("task_id")] |
||||
|
[JsonPropertyName("task_id")] |
||||
|
public string TaskId { get; set; } |
||||
|
protected TemplateCard(string type, string taskId = "") |
||||
|
{ |
||||
|
Type = type; |
||||
|
TaskId = taskId; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 卡片操作按钮
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardAction |
||||
|
{ |
||||
|
public TemplateCardAction(string key, string text) |
||||
|
{ |
||||
|
Key = key; |
||||
|
Text = text; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 操作key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("key")] |
||||
|
[JsonPropertyName("key")] |
||||
|
public string Key { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 操作的描述文案
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("text")] |
||||
|
[JsonPropertyName("text")] |
||||
|
public string Text { get; set; } |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 卡片右上角更多操作按钮
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardActionMenu |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 卡片副交互辅助文本说明
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("desc")] |
||||
|
[JsonPropertyName("desc")] |
||||
|
public string Description { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 操作列表,列表长度取值范围为 [1, 3]
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("action_list")] |
||||
|
[JsonPropertyName("action_list")] |
||||
|
public List<TemplateCardAction> Actions { get; set;} |
||||
|
public TemplateCardActionMenu(List<TemplateCardAction> actions, string description = "") |
||||
|
{ |
||||
|
Actions = actions; |
||||
|
Description = description; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 整体卡片的点击跳转事件
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardCardAction |
||||
|
{ |
||||
|
public TemplateCardCardAction(string url) |
||||
|
{ |
||||
|
Type = 1; |
||||
|
Url = url; |
||||
|
} |
||||
|
public TemplateCardCardAction(string appid, string pagePath) |
||||
|
{ |
||||
|
Type = 2; |
||||
|
AppId = appid; |
||||
|
PagePath = pagePath; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("type")] |
||||
|
[JsonPropertyName("type")] |
||||
|
public byte Type { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的url,card_action.type是1时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("url")] |
||||
|
[JsonPropertyName("url")] |
||||
|
public string Url { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的小程序的appid,必须是与当前应用关联的小程序,card_action.type是2时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("appid")] |
||||
|
[JsonPropertyName("appid")] |
||||
|
public string AppId { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的小程序的pagepath,card_action.type是2时选填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("pagepath")] |
||||
|
[JsonPropertyName("pagepath")] |
||||
|
public string PagePath { get; set; } |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 关键数据样式
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardEmphasisContent |
||||
|
{ |
||||
|
public TemplateCardEmphasisContent( |
||||
|
string title = "", |
||||
|
string description = "") |
||||
|
{ |
||||
|
Title = title; |
||||
|
Description = description; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 关键数据样式的数据内容,建议不超过14个字
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("title")] |
||||
|
[JsonPropertyName("title")] |
||||
|
public string Title { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 关键数据样式的数据描述内容,建议不超过22个字
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("desc")] |
||||
|
[JsonPropertyName("desc")] |
||||
|
public string Description { get; set; } |
||||
|
} |
||||
@ -0,0 +1,93 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 二级标题+文本
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardHorizontalContent |
||||
|
{ |
||||
|
public static TemplateCardHorizontalContent None(string keyName, string value = "") |
||||
|
{ |
||||
|
return new TemplateCardHorizontalContent( |
||||
|
keyName, 0, value); |
||||
|
} |
||||
|
|
||||
|
public static TemplateCardHorizontalContent FromUrl(string keyName, string url, string value = "") |
||||
|
{ |
||||
|
return new TemplateCardHorizontalContent( |
||||
|
keyName, 1, value, url); |
||||
|
} |
||||
|
|
||||
|
public static TemplateCardHorizontalContent FromMedia(string keyName, string mediaId, string value = "") |
||||
|
{ |
||||
|
return new TemplateCardHorizontalContent( |
||||
|
keyName, 2, value, mediaId: mediaId); |
||||
|
} |
||||
|
|
||||
|
public static TemplateCardHorizontalContent FromUser(string keyName, string userId, string value = "") |
||||
|
{ |
||||
|
return new TemplateCardHorizontalContent( |
||||
|
keyName, 3, value, userId: userId); |
||||
|
} |
||||
|
|
||||
|
public TemplateCardHorizontalContent( |
||||
|
string keyName, |
||||
|
byte type = 0, |
||||
|
string value = "", |
||||
|
string url = "", |
||||
|
string mediaId = "", |
||||
|
string userId = "") |
||||
|
{ |
||||
|
Type = type; |
||||
|
KeyName = keyName; |
||||
|
Value = value; |
||||
|
Url = url; |
||||
|
MediaId = mediaId; |
||||
|
UserId = userId; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 链接类型,0或不填代表不是链接,1 代表跳转url,2 代表下载附件,3 代表点击跳转成员详情
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("type")] |
||||
|
[JsonPropertyName("type")] |
||||
|
public byte Type { get; } |
||||
|
/// <summary>
|
||||
|
/// 二级标题,建议不超过5个字
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("keyname")] |
||||
|
[JsonPropertyName("keyname")] |
||||
|
public string KeyName { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过30个字,(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("value")] |
||||
|
[JsonPropertyName("value")] |
||||
|
public string Value { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 链接跳转的url,horizontal_content_list.type是1时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("url")] |
||||
|
[JsonPropertyName("url")] |
||||
|
public string Url { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 附件的media_id,horizontal_content_list.type是2时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("media_id")] |
||||
|
[JsonPropertyName("media_id")] |
||||
|
public string MediaId { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 成员详情的userid,horizontal_content_list.type是3时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("userid")] |
||||
|
[JsonPropertyName("userid")] |
||||
|
public string UserId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 跳转指引样式
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardJump |
||||
|
{ |
||||
|
public TemplateCardJump(string title, string url) |
||||
|
{ |
||||
|
Type = 1; |
||||
|
Url = url; |
||||
|
Title = title; |
||||
|
} |
||||
|
public TemplateCardJump(string title, string appid, string pagePath) |
||||
|
{ |
||||
|
Type = 2; |
||||
|
AppId = appid; |
||||
|
PagePath = pagePath; |
||||
|
Title = title; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("type")] |
||||
|
[JsonPropertyName("type")] |
||||
|
public byte Type { get; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接样式的文案内容,建议不超过18个字
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("title")] |
||||
|
[JsonPropertyName("title")] |
||||
|
public string Title { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的url,jump_list.type是1时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("url")] |
||||
|
[JsonPropertyName("url")] |
||||
|
public string Url { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的小程序的appid,必须是与当前应用关联的小程序,jump_list.type是2时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("appid")] |
||||
|
[JsonPropertyName("appid")] |
||||
|
public string AppId { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转链接的小程序的pagepath,jump_list.type是2时选填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("pagepath")] |
||||
|
[JsonPropertyName("pagepath")] |
||||
|
public string PagePath { get; set; } |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 卡票标题
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardMainTitle |
||||
|
{ |
||||
|
public TemplateCardMainTitle( |
||||
|
string title = "", |
||||
|
string description = "") |
||||
|
{ |
||||
|
Title = title; |
||||
|
Description = description; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 一级标题,建议不超过36个字,文本通知型卡片本字段非必填,但不可本字段和sub_title_text都不填,(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("title")] |
||||
|
[JsonPropertyName("title")] |
||||
|
public string Title { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 标题辅助信息,建议不超过44个字,(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("desc")] |
||||
|
[JsonPropertyName("desc")] |
||||
|
public string Description { get; set; } |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 引用文献样式
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardQuoteArea |
||||
|
{ |
||||
|
public TemplateCardQuoteArea(string url, string title = "", string text = "") |
||||
|
{ |
||||
|
Type = 1; |
||||
|
Url = url; |
||||
|
Title = title; |
||||
|
Text = text; |
||||
|
} |
||||
|
public TemplateCardQuoteArea(string appid, string pagePath, string title = "", string text = "") |
||||
|
{ |
||||
|
Type = 2; |
||||
|
AppId = appid; |
||||
|
PagePath = pagePath; |
||||
|
Title = title; |
||||
|
Text = text; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("type")] |
||||
|
[JsonPropertyName("type")] |
||||
|
public byte Type { get; } |
||||
|
/// <summary>
|
||||
|
/// 点击跳转的url,quote_area.type是1时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("url")] |
||||
|
[JsonPropertyName("url")] |
||||
|
public string Url { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 点击跳转的小程序的appid,必须是与当前应用关联的小程序,quote_area.type是2时必填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("appid")] |
||||
|
[JsonPropertyName("appid")] |
||||
|
public string AppId { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 点击跳转的小程序的pagepath,quote_area.type是2时选填
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("pagepath")] |
||||
|
[JsonPropertyName("pagepath")] |
||||
|
public string PagePath { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 引用文献样式的标题
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("title")] |
||||
|
[JsonPropertyName("title")] |
||||
|
public string Title { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 引用文献样式的引用文案
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("quote_text")] |
||||
|
[JsonPropertyName("quote_text")] |
||||
|
public string Text { get; set; } |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 来源文字颜色
|
||||
|
/// </summary>
|
||||
|
public enum DescriptionColor |
||||
|
{ |
||||
|
Gray = 0, |
||||
|
Black = 1, |
||||
|
Red = 2, |
||||
|
Green = 3, |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 卡片来源样式信息
|
||||
|
/// </summary>
|
||||
|
public class TemplateCardSource |
||||
|
{ |
||||
|
public TemplateCardSource( |
||||
|
string iconUrl = "", |
||||
|
string description = "", |
||||
|
DescriptionColor descriptionColor = DescriptionColor.Gray) |
||||
|
{ |
||||
|
IconUrl = iconUrl; |
||||
|
Description = description; |
||||
|
DescriptionColor = descriptionColor; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 来源图片的url,来源图片的尺寸建议为72*72
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("icon_url")] |
||||
|
[JsonPropertyName("icon_url")] |
||||
|
public string IconUrl { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 来源图片的描述,建议不超过20个字,(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("desc")] |
||||
|
[JsonPropertyName("desc")] |
||||
|
public string Description { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 来源文字的颜色,目前支持:0(默认) 灰色,1 黑色,2 红色,3 绿色
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("desc_color")] |
||||
|
[JsonPropertyName("desc_color")] |
||||
|
public DescriptionColor DescriptionColor { get; set; } |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 文本模板卡片消息
|
||||
|
/// </summary>
|
||||
|
public class TextTemplateCard : TemplateCard |
||||
|
{ |
||||
|
public TextTemplateCard(TemplateCardCardAction cardAction, string taskId = "") |
||||
|
: base("template_card", taskId) |
||||
|
{ |
||||
|
CardAction = cardAction; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 卡片来源样式信息,不需要来源样式可不填写
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("source")] |
||||
|
[JsonPropertyName("source")] |
||||
|
public TemplateCardSource Source { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 卡片右上角更多操作按钮
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("action_menu")] |
||||
|
[JsonPropertyName("action_menu")] |
||||
|
public TemplateCardActionMenu ActionMenu { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 一级标题
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("main_title")] |
||||
|
[JsonPropertyName("main_title")] |
||||
|
public TemplateCardMainTitle MainTitle { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 二级普通文本,建议不超过160个字,(支持id转译)
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("sub_title_text")] |
||||
|
[JsonPropertyName("sub_title_text")] |
||||
|
public string SubTitle { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 引用文献样式
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("quote_area")] |
||||
|
[JsonPropertyName("quote_area")] |
||||
|
public TemplateCardQuoteArea QuoteArea { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 关键数据样式
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("emphasis_content")] |
||||
|
[JsonPropertyName("emphasis_content")] |
||||
|
public TemplateCardEmphasisContent EmphasisContent { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("horizontal_content_list")] |
||||
|
[JsonPropertyName("horizontal_content_list")] |
||||
|
public List<TemplateCardHorizontalContent> HorizontalContents { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
[JsonProperty("jump_list")] |
||||
|
[JsonPropertyName("jump_list")] |
||||
|
public List<TemplateCardJump> Jumps { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 整体卡片的点击跳转事件,text_notice必填本字段
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("TemplateCardCardAction")] |
||||
|
[JsonPropertyName("TemplateCardCardAction")] |
||||
|
public TemplateCardCardAction CardAction { get; set; } |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message.Templates; |
||||
|
/// <summary>
|
||||
|
/// 企业微信模板卡片消息
|
||||
|
/// </summary>
|
||||
|
public class WeChatWorkTemplateCardMessage : WeChatWorkMessage |
||||
|
{ |
||||
|
public WeChatWorkTemplateCardMessage( |
||||
|
string agentId, |
||||
|
TemplateCard template, |
||||
|
string toUser = "", |
||||
|
string toParty = "", |
||||
|
string toTag = "") : base(agentId, "template_card", toUser, toParty, toTag) |
||||
|
{ |
||||
|
Template = template; |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 模板卡片消息
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("template_card")] |
||||
|
[JsonPropertyName("template_card")] |
||||
|
public TemplateCard Template { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否开启id转译,0表示否,1表示是,默认0。
|
||||
|
/// 仅第三方应用需要用到
|
||||
|
/// 企业自建应用可以忽略。
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("enable_id_trans")] |
||||
|
[JsonPropertyName("enable_id_trans")] |
||||
|
public byte EnableIdTrans { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否开启重复消息检查,0表示否,1表示是,默认0
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("enable_duplicate_check")] |
||||
|
[JsonPropertyName("enable_duplicate_check")] |
||||
|
public byte EnableDuplicateCheck { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 表示是否重复消息检查的时间间隔,默认1800s,最大不超过4小时
|
||||
|
/// </summary>
|
||||
|
[JsonProperty("duplicate_check_interval")] |
||||
|
[JsonPropertyName("duplicate_check_interval")] |
||||
|
public int DuplicateCheckInterval { get; set; } = 1800; |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Newtonsoft.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message; |
||||
|
/// <summary>
|
||||
|
/// 企业微信群聊消息
|
||||
|
/// </summary>
|
||||
|
public abstract class WeChatWorkAppChatMessage : WeChatWorkRequest |
||||
|
{ |
||||
|
protected WeChatWorkAppChatMessage( |
||||
|
string agentId, |
||||
|
string chatId, |
||||
|
string msgType) |
||||
|
{ |
||||
|
AgentId = agentId; |
||||
|
ChatId = chatId; |
||||
|
MsgType = msgType; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 群聊id
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("chatid")] |
||||
|
[JsonPropertyName("chatid")] |
||||
|
public virtual string ChatId { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 消息类型
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
[JsonProperty("msgtype")] |
||||
|
[JsonPropertyName("msgtype")] |
||||
|
public virtual string MsgType { get; protected set; } |
||||
|
/// <summary>
|
||||
|
/// 企业应用的id
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 由于需要换取token, 因此需要传递应用标识
|
||||
|
/// </remarks>
|
||||
|
[NotNull] |
||||
|
[Newtonsoft.Json.JsonIgnore] |
||||
|
[System.Text.Json.Serialization.JsonIgnore] |
||||
|
public virtual string AgentId { get; protected set; } |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Message.Request; |
||||
|
using LINGYUN.Abp.WeChat.Work.Token; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work.Message; |
||||
|
|
||||
|
public class WeChatWorkMessageManager : IWeChatWorkMessageManager, ISingletonDependency |
||||
|
{ |
||||
|
public ILogger<WeChatWorkMessageManager> Logger { get; set; } |
||||
|
|
||||
|
protected IHttpClientFactory HttpClientFactory { get; } |
||||
|
protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } |
||||
|
|
||||
|
public WeChatWorkMessageManager( |
||||
|
IHttpClientFactory httpClientFactory, |
||||
|
IWeChatWorkTokenProvider weChatWorkTokenProvider) |
||||
|
{ |
||||
|
HttpClientFactory = httpClientFactory; |
||||
|
WeChatWorkTokenProvider = weChatWorkTokenProvider; |
||||
|
|
||||
|
Logger = NullLogger<WeChatWorkMessageManager>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<bool> ReCallMessageAsync(string agentId, string messageId, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var token = await WeChatWorkTokenProvider.GetTokenAsync(agentId, cancellationToken); |
||||
|
var client = HttpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient); |
||||
|
|
||||
|
var request = new WeChatWorkMessageReCallRequest( |
||||
|
token.AccessToken, |
||||
|
messageId); |
||||
|
|
||||
|
using var response = await client.ReCallMessageAsync(request, cancellationToken); |
||||
|
var messageResponse = await response.DeserializeObjectAsync<WeChatWorkResponse>(); |
||||
|
|
||||
|
return messageResponse.IsSuccessed; |
||||
|
} |
||||
|
} |
||||
@ -1,11 +0,0 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Message; |
|
||||
public class WeChatWorkMessageRequest |
|
||||
{ |
|
||||
public string AccessToken { get; set; } |
|
||||
public WeChatWorkMessage Message { get; set; } |
|
||||
public WeChatWorkMessageRequest(string accessToken, WeChatWorkMessage message) |
|
||||
{ |
|
||||
AccessToken = accessToken; |
|
||||
Message = message; |
|
||||
} |
|
||||
} |
|
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Security; |
namespace LINGYUN.Abp.WeChat.Work.Security.Models; |
||||
public class WeChatWorkCryptoData |
public class WeChatWorkCryptoData |
||||
{ |
{ |
||||
public string ReceiveId { get; } |
public string ReceiveId { get; } |
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Security; |
namespace LINGYUN.Abp.WeChat.Work.Security.Models; |
||||
public class WeChatWorkCryptoDecryptData : WeChatWorkCryptoData |
public class WeChatWorkCryptoDecryptData : WeChatWorkCryptoData |
||||
{ |
{ |
||||
public string PostData { get; } |
public string PostData { get; } |
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Security; |
namespace LINGYUN.Abp.WeChat.Work.Security.Models; |
||||
public class WeChatWorkCryptoEchoData : WeChatWorkCryptoData |
public class WeChatWorkCryptoEchoData : WeChatWorkCryptoData |
||||
{ |
{ |
||||
public string EchoStr { get; } |
public string EchoStr { get; } |
||||
@ -1,11 +1,32 @@ |
|||||
using System.Threading; |
using LINGYUN.Abp.WeChat.Work.Token.Models; |
||||
|
using System.Threading; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Token |
namespace LINGYUN.Abp.WeChat.Work.Token; |
||||
|
/// <summary>
|
||||
|
/// 企业微信AccessToken接口
|
||||
|
/// </summary>
|
||||
|
public interface IWeChatWorkTokenProvider |
||||
{ |
{ |
||||
public interface IWeChatWorkTokenProvider |
/// <summary>
|
||||
{ |
/// 获取应用Token
|
||||
Task<WeChatWorkToken> GetTokenAsync(string agentId, CancellationToken cancellationToken = default); |
/// </summary>
|
||||
Task<WeChatWorkToken> GetTokenAsync(string corpId, string agentId, CancellationToken cancellationToken = default); |
/// <remarks>
|
||||
} |
/// 参考:https://developer.work.weixin.qq.com/document/path/91039
|
||||
|
/// </remarks>
|
||||
|
/// <param name="agentId">应用标识</param>
|
||||
|
/// <param name="cancellationToken"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<WeChatWorkToken> GetTokenAsync(string agentId, CancellationToken cancellationToken = default); |
||||
|
/// <summary>
|
||||
|
/// 获取应用Token
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 参考:https://developer.work.weixin.qq.com/document/path/91039
|
||||
|
/// </remarks>
|
||||
|
/// <param name="corpId">企业标识</param>
|
||||
|
/// <param name="agentId">应用标识</param>
|
||||
|
/// <param name="cancellationToken"></param>
|
||||
|
/// <returns></returns>
|
||||
|
Task<WeChatWorkToken> GetTokenAsync(string corpId, string agentId, CancellationToken cancellationToken = default); |
||||
} |
} |
||||
|
|||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Token |
namespace LINGYUN.Abp.WeChat.Work.Token.Models |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 企业微信令牌
|
/// 企业微信令牌
|
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Token |
namespace LINGYUN.Abp.WeChat.Work.Token.Models |
||||
{ |
{ |
||||
public class WeChatWorkTokenCacheItem |
public class WeChatWorkTokenCacheItem |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Work.Token |
namespace LINGYUN.Abp.WeChat.Work.Token.Models |
||||
{ |
{ |
||||
public class WeChatWorkTokenRequest |
public class WeChatWorkTokenRequest |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
|
|
||||
namespace LINGYUN.Abp.WeChat.Work.Token |
namespace LINGYUN.Abp.WeChat.Work.Token.Models |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 微信访问令牌返回对象
|
/// 微信访问令牌返回对象
|
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WeChat.Work; |
||||
|
|
||||
|
[Serializable] |
||||
|
public abstract class WeChatWorkRequest |
||||
|
{ |
||||
|
public virtual string SerializeToJson() |
||||
|
{ |
||||
|
return WeChatObjectSerializeExtensions.SerializeToJson(this); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Authorize.Request; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace System.Net.Http |
||||
|
{ |
||||
|
internal static partial class HttpClientWeChatWorkRequestExtensions |
||||
|
{ |
||||
|
public async static Task<HttpResponseMessage> GetUserInfoAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
string code, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/auth/getuserinfo"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
urlBuilder.AppendFormat("&code={0}", code); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage(HttpMethod.Get, urlBuilder.ToString()); |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> GetUserDetailAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
WeChatWorkUserDetailRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/auth/getuserdetail"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Chat.Request; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace System.Net.Http |
||||
|
{ |
||||
|
internal static partial class HttpClientWeChatWorkRequestExtensions |
||||
|
{ |
||||
|
public async static Task<HttpResponseMessage> GetAppChatAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
string chatId, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/appchat/get"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
urlBuilder.AppendFormat("&chatid={0}", chatId); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Get, |
||||
|
urlBuilder.ToString()); |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> CreateAppChatAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
WeChatWorkAppChatCreateRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/appchat/create"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> UpdateAppChatAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
WeChatWorkAppChatUpdateRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/appchat/update"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Media.Models; |
||||
|
using LINGYUN.Abp.WeChat.Work.Utils; |
||||
|
using System.IO; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace System.Net.Http |
||||
|
{ |
||||
|
internal static partial class HttpClientWeChatWorkRequestExtensions |
||||
|
{ |
||||
|
public async static Task<HttpResponseMessage> GetMediaAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string accessToken, |
||||
|
string mediaId, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/media/get"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", accessToken); |
||||
|
urlBuilder.AppendFormat("&media_id={0}", mediaId); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage(HttpMethod.Get, urlBuilder.ToString()); |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> UploadMediaAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
string type, |
||||
|
WeChatWorkMediaRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/media/upload"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", request.AccessToken); |
||||
|
urlBuilder.AppendFormat("&type={0}", type); |
||||
|
|
||||
|
var fileBytes = await request.Content.GetStream().GetAllBytesAsync(); |
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = HttpContentBuildHelper.BuildUploadMediaContent("media", fileBytes, request.Content.FileName) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> UploadImageAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
WeChatWorkMediaRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/media/uploadimg"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", request.AccessToken); |
||||
|
|
||||
|
var fileBytes = await request.Content.GetStream().GetAllBytesAsync(); |
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = HttpContentBuildHelper.BuildUploadMediaContent("file", fileBytes, request.Content.FileName) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work.Message; |
||||
|
using LINGYUN.Abp.WeChat.Work.Message.Request; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace System.Net.Http |
||||
|
{ |
||||
|
internal static partial class HttpClientWeChatWorkRequestExtensions |
||||
|
{ |
||||
|
public async static Task<HttpResponseMessage> SendMessageAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
WeChatWorkMessageRequest<WeChatWorkMessage> request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/message/send"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", request.AccessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.Message.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> SendMessageAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
WeChatWorkMessageRequest<WeChatWorkAppChatMessage> request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/appchat/send"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", request.AccessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.Message.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async static Task<HttpResponseMessage> ReCallMessageAsync( |
||||
|
this HttpMessageInvoker client, |
||||
|
WeChatWorkMessageReCallRequest request, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var urlBuilder = new StringBuilder(); |
||||
|
urlBuilder.Append("/cgi-bin/message/recall"); |
||||
|
urlBuilder.AppendFormat("?access_token={0}", request.AccessToken); |
||||
|
|
||||
|
var httpRequest = new HttpRequestMessage( |
||||
|
HttpMethod.Post, |
||||
|
urlBuilder.ToString()) |
||||
|
{ |
||||
|
Content = new StringContent(request.SerializeToJson()) |
||||
|
}; |
||||
|
|
||||
|
return await client.SendAsync(httpRequest, cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
|
||||
|
namespace System.Net.Http; |
||||
|
internal static class HttpResponseDeserializeExtensions |
||||
|
{ |
||||
|
public async static Task<T> DeserializeObjectAsync<T>(this HttpResponseMessage response) where T : WeChatWorkResponse |
||||
|
{ |
||||
|
if (!response.IsSuccessStatusCode) |
||||
|
{ |
||||
|
throw new AbpRemoteCallException($"Wechat work request error: {response.StatusCode} - {response.ReasonPhrase}"); |
||||
|
} |
||||
|
var responseContent = await response.Content.ReadAsStringAsync(); |
||||
|
|
||||
|
return responseContent.DeserializeObject<T>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
|
||||
|
namespace System; |
||||
|
internal static class WeChatObjectSerializeExtensions |
||||
|
{ |
||||
|
public static string SerializeToJson(this object @object) |
||||
|
{ |
||||
|
return JsonConvert.SerializeObject(@object); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Work; |
||||
|
using Newtonsoft.Json; |
||||
|
|
||||
|
namespace System; |
||||
|
internal static class WeChatWorkResponseDeserializeExtensions |
||||
|
{ |
||||
|
public static T DeserializeObject<T>(this string responseContent) where T : WeChatWorkResponse |
||||
|
{ |
||||
|
return JsonConvert.DeserializeObject<T>(responseContent); |
||||
|
} |
||||
|
} |
||||
@ -1 +1,2 @@ |
|||||
global using Xunit; |
global using Xunit; |
||||
|
global using Shouldly; |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue