Browse Source

Merge pull request #1343 from colinin/wecom-webhook-message

feat(wechat): wecom webhook message integrate
pull/1351/head
yx lin 5 months ago
committed by GitHub
parent
commit
0283b37b12
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 23
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Features/WeChatWorkFeatureDefinitionProvider.cs
  2. 17
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Features/WeChatWorkFeatureNames.cs
  3. 14
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/IWeChatWorkMessageSender.cs
  4. 75
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardAction.cs
  5. 35
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardEmphasisContent.cs
  6. 111
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardHorizontalContent.cs
  7. 35
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardImage.cs
  8. 119
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardImageTextArea.cs
  9. 99
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardJump.cs
  10. 35
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardMainTitle.cs
  11. 111
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardQuoteArea.cs
  12. 81
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardSource.cs
  13. 35
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardVerticalContent.cs
  14. 3
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TextMessage.cs
  15. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookFileMessage.cs
  16. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookImageMessage.cs
  17. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookMarkdownMessage.cs
  18. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookMarkdownV2Message.cs
  19. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookNewsMessage.cs
  20. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookTemplateCardMessage.cs
  21. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookTextMessage.cs
  22. 27
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookVoiceMessage.cs
  23. 26
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookFileMessage.cs
  24. 35
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookImageMessage.cs
  25. 29
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookMarkdownMessage.cs
  26. 33
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookMarkdownV2Message.cs
  27. 88
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookNewsMessage.cs
  28. 72
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookNewsNoticeCardMessage.cs
  29. 100
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTemplateCardMessage.cs
  30. 45
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTextMessage.cs
  31. 63
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTextNoticeCardMessage.cs
  32. 26
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookVoiceMessage.cs
  33. 25
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/WeChatWorkMessageSender.cs
  34. 22
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/WeChatWorkWebhookMessage.cs
  35. 20
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Message.cs

23
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Features/WeChatWorkFeatureDefinitionProvider.cs

@ -21,6 +21,7 @@ public class WeChatWorkFeatureDefinitionProvider : FeatureDefinitionProvider
AddMessageFeature(wechatWorkFeature);
AddAppChatFeature(wechatWorkFeature);
AddWebhookFeature(wechatWorkFeature);
}
protected virtual void AddMessageFeature(FeatureDefinition wechatWorkFeature)
@ -67,6 +68,28 @@ public class WeChatWorkFeatureDefinitionProvider : FeatureDefinitionProvider
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 1000)));
}
protected virtual void AddWebhookFeature(FeatureDefinition wechatWorkFeature)
{
var messageEnableFeature = wechatWorkFeature.CreateChild(
name: WeChatWorkFeatureNames.Webhook.Enable,
defaultValue: "false",
displayName: L("Features:WebhookMessageEnable"),
description: L("Features:WebhookMessageEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
messageEnableFeature.CreateChild(
name: WeChatWorkFeatureNames.Webhook.Limit,
defaultValue: "20",
displayName: L("Features:WebhookMessage.Limit"),
description: L("Features:WebhookMessage.LimitDesc"),
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 20000)));
messageEnableFeature.CreateChild(
name: WeChatWorkFeatureNames.Webhook.LimitInterval,
defaultValue: "1",
displayName: L("Features:WebhookMessage.LimitInterval"),
description: L("Features:WebhookMessage.LimitIntervalDesc"),
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 1000)));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<WeChatWorkResource>(name);

17
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Features/WeChatWorkFeatureNames.cs

@ -44,4 +44,21 @@ public static class WeChatWorkFeatureNames
public const string LimitInterval = GroupName + ".LimitInterval";
}
}
public static class Webhook
{
public const string GroupName = WeChatWorkFeatureNames.GroupName + ".Webhook";
/// <summary>
/// 启用消息推送
/// </summary>
public const string Enable = GroupName + ".Enable";
/// <summary>
/// 发送次数上限
/// </summary>
public const string Limit = GroupName + ".Limit";
/// <summary>
/// 发送次数上限时长
/// </summary>
public const string LimitInterval = GroupName + ".LimitInterval";
}
}

14
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/IWeChatWorkMessageSender.cs

@ -32,4 +32,18 @@ public interface IWeChatWorkMessageSender
Task<WeChatWorkResponse> SendAsync(
WeChatWorkAppChatMessage message,
CancellationToken cancellationToken = default);
/// <summary>
/// 发送Webhook消息
/// </summary>
/// <remarks>
/// 参考:https://developer.work.weixin.qq.com/document/path/99110
/// </remarks>
/// <param name="webhookKey">消息推送的webhook Key</param>
/// <param name="message">继承自 <see cref="WeChatWorkWebhookMessage"/> 的企业微信Webhook消息载体</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<WeChatWorkResponse> SendAsync(
string webhookKey,
WeChatWorkWebhookMessage message,
CancellationToken cancellationToken = default);
}

75
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardAction.cs

@ -0,0 +1,75 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 卡片的点击跳转事件
/// </summary>
public class TemplateCardAction
{
/// <summary>
/// 卡片跳转类型,1 代表跳转url,2 代表打开小程序。text_notice模版卡片中该字段取值范围为[1,2]
/// </summary>
[NotNull]
[JsonProperty("type")]
[JsonPropertyName("type")]
public int Type { get; set; }
/// <summary>
/// 跳转链接的url,type是1时必填
/// </summary>
[CanBeNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 点击跳转的小程序的appid,type是2时必填
/// </summary>
[CanBeNull]
[JsonProperty("appid")]
[JsonPropertyName("appid")]
public string AppId { get; set; }
/// <summary>
/// 点击跳转的小程序的pagepath,type是2时选填
/// </summary>
[CanBeNull]
[JsonProperty("pagepath")]
[JsonPropertyName("pagepath")]
public string PagePath { get; set; }
private TemplateCardAction(
int type,
string url = null,
string appId = null,
string pagePath = null)
{
Type = type;
Url = url;
AppId = appId;
PagePath = pagePath;
}
/// <summary>
/// 创建一个跳转链接卡片事件
/// </summary>
/// <param name="url">跳转链接的url</param>
/// <returns></returns>
public static TemplateCardAction Link(string url)
{
Check.NotNullOrWhiteSpace(url, nameof(url));
return new TemplateCardAction(1, url);
}
/// <summary>
/// 创建一个跳转小程序卡片事件
/// </summary>
/// <param name="appId">小程序的appid</param>
/// <param name="pagePath">小程序的pagePath</param>
/// <returns></returns>
public static TemplateCardAction MiniProgram(string appId, string pagePath)
{
Check.NotNullOrWhiteSpace(appId, nameof(appId));
Check.NotNullOrWhiteSpace(pagePath, nameof(pagePath));
return new TemplateCardAction(2, appId: appId, pagePath: pagePath);
}
}

35
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardEmphasisContent.cs

@ -0,0 +1,35 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 关键数据样式
/// </summary>
public class TemplateCardEmphasisContent
{
/// <summary>
/// 关键数据样式的数据内容,建议不超过10个字
/// </summary>
[CanBeNull]
[JsonProperty("title")]
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// 关键数据样式的数据描述内容,建议不超过15个字
/// </summary>
[CanBeNull]
[JsonProperty("desc")]
[JsonPropertyName("desc")]
public string Description { get; set; }
/// <summary>
/// 创建一个关键数据样式
/// </summary>
/// <param name="title">关键数据样式的数据内容</param>
/// <param name="description">关键数据样式的数据描述内容</param>
public TemplateCardEmphasisContent(string title, string description = null)
{
Title = title;
Description = description;
}
}

111
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardHorizontalContent.cs

@ -0,0 +1,111 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 二级标题+文本
/// </summary>
public class TemplateCardHorizontalContent
{
/// <summary>
/// 模版卡片的二级标题信息内容支持的类型,1是url,2是文件附件,3 代表点击跳转成员详情
/// </summary>
[CanBeNull]
[JsonProperty("type")]
[JsonPropertyName("type")]
public int? Type { get; set; }
/// <summary>
/// 二级标题,建议不超过5个字
/// </summary>
[NotNull]
[JsonProperty("keyname")]
[JsonPropertyName("keyname")]
public string KeyName { get; set; }
/// <summary>
/// 二级文本,如果type是2,该字段代表文件名称(要包含文件类型),建议不超过26个字
/// </summary>
[CanBeNull]
[JsonProperty("value")]
[JsonPropertyName("value")]
public string Value { get; set; }
/// <summary>
/// 链接跳转的url,type是1时必填
/// </summary>
[CanBeNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 附件的media_id,type是2时必填
/// </summary>
[CanBeNull]
[JsonProperty("media_id")]
[JsonPropertyName("media_id")]
public string MediaId { get; set; }
/// <summary>
/// 成员详情的userid,type是3时必填
/// </summary>
[CanBeNull]
[JsonProperty("userid")]
[JsonPropertyName("userid")]
public string UserId { get; set; }
private TemplateCardHorizontalContent(
string keyName,
int? type = null,
string value = null,
string url = null,
string mediaId = null,
string userId = null)
{
Type = type;
KeyName = keyName;
Value = value;
Url = url;
MediaId = mediaId;
UserId = userId;
}
/// <summary>
/// 创建一个跳转链接的二级标题+文本
/// </summary>
/// <param name="keyName">二级标题</param>
/// <param name="url">链接跳转的url</param>
/// <param name="value">二级文本</param>
/// <returns></returns>
public static TemplateCardHorizontalContent Link(string keyName, string url, string value = null)
{
Check.NotNullOrWhiteSpace(keyName, nameof(keyName));
Check.NotNullOrWhiteSpace(url, nameof(url));
return new TemplateCardHorizontalContent(keyName, 1, value: value, url: url);
}
/// <summary>
/// 创建一个引用文件的二级标题+文本
/// </summary>
/// <param name="keyName">二级标题</param>
/// <param name="fileName">文件名称</param>
/// <param name="mediaId">附件的mediaId</param>
/// <returns></returns>
public static TemplateCardHorizontalContent File(string keyName, string fileName, string mediaId)
{
Check.NotNullOrWhiteSpace(keyName, nameof(keyName));
Check.NotNullOrWhiteSpace(fileName, nameof(fileName));
Check.NotNullOrWhiteSpace(mediaId, nameof(mediaId));
return new TemplateCardHorizontalContent(keyName, 2, value: fileName, mediaId: mediaId);
}
/// <summary>
/// 创建一个成员详情的二级标题+文本
/// </summary>
/// <param name="keyName">二级标题</param>
/// <param name="userId">成员的userid</param>
/// <returns></returns>
public static TemplateCardHorizontalContent UserInfo(string keyName, string userId)
{
Check.NotNullOrWhiteSpace(keyName, nameof(keyName));
Check.NotNullOrWhiteSpace(userId, nameof(userId));
return new TemplateCardHorizontalContent(keyName, 3, userId: userId);
}
}

35
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardImage.cs

@ -0,0 +1,35 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 图片样式
/// </summary>
public class TemplateCardImage
{
/// <summary>
/// 图片的url
/// </summary>
[NotNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 图片的宽高比,宽高比要小于2.25,大于1.3,不填该参数默认1.3
/// </summary>
[CanBeNull]
[JsonProperty("aspect_ratio")]
[JsonPropertyName("aspect_ratio")]
public float? AspectRatio { get; set; }
/// <summary>
/// 创建一个图片样式
/// </summary>
/// <param name="url">图片的url</param>
/// <param name="aspectRatio">图片的宽高比,不填该参数默认1.3</param>
public TemplateCardImage(string url, float? aspectRatio = 1.3f)
{
Url = url;
AspectRatio = aspectRatio;
}
}

119
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardImageTextArea.cs

@ -0,0 +1,119 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 左图右文样式
/// </summary>
public class TemplateCardImageTextArea
{
/// <summary>
/// 左图右文样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
/// </summary>
[CanBeNull]
[JsonProperty("type")]
[JsonPropertyName("type")]
public int? Type { get; set; }
/// <summary>
/// 左图右文样式的图片url
/// </summary>
[NotNull]
[JsonProperty("image_url")]
[JsonPropertyName("image_url")]
public string ImageUrl { get; set; }
/// <summary>
/// 点击跳转的url,type是1时必填
/// </summary>
[NotNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 点击跳转的小程序的appid,type是2时必填
/// </summary>
[CanBeNull]
[JsonProperty("appid")]
[JsonPropertyName("appid")]
public string AppId { get; set; }
/// <summary>
/// 点击跳转的小程序的pagepath,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("desc")]
[JsonPropertyName("desc")]
public string Description { get; set; }
private TemplateCardImageTextArea(
string imageUrl,
int? type = null,
string url = null,
string appId = null,
string pagePath = null,
string title = null,
string description = null)
{
Type = type;
ImageUrl = imageUrl;
Url = url;
AppId = appId;
PagePath = pagePath;
Title = title;
Description = description;
}
/// <summary>
/// 创建一个跳转链接左图右文样式
/// </summary>
/// <param name="imageUrl">左图右文样式的图片url</param>
/// <param name="url">点击跳转的url</param>
/// <param name="title">左图右文样式的标题</param>
/// <param name="description">左图右文样式的描述</param>
/// <returns></returns>
public static TemplateCardImageTextArea Link(
string imageUrl,
string url,
string title = null,
string description = null)
{
Check.NotNullOrWhiteSpace(imageUrl, nameof(imageUrl));
Check.NotNullOrWhiteSpace(url, nameof(url));
return new TemplateCardImageTextArea(imageUrl, 1, url: url, title: title, description: description);
}
/// <summary>
/// 创建一个跳转小程序左图右文样式
/// </summary>
/// <param name="imageUrl">左图右文样式的图片url</param>
/// <param name="appId">小程序AppId</param>
/// <param name="pagePath">小程序PagePath</param>
/// <param name="title">左图右文样式的标题</param>
/// <param name="description">左图右文样式的描述</param>
/// <returns></returns>
public static TemplateCardImageTextArea MiniProgram(
string imageUrl,
string appId,
string pagePath,
string title = null,
string description = null)
{
Check.NotNullOrWhiteSpace(imageUrl, nameof(imageUrl));
Check.NotNullOrWhiteSpace(appId, nameof(appId));
Check.NotNullOrWhiteSpace(pagePath, nameof(pagePath));
return new TemplateCardImageTextArea(imageUrl, 2, appId: appId, pagePath: pagePath, title: title, description: description);
}
}

99
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardJump.cs

@ -0,0 +1,99 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 跳转指引样式
/// </summary>
public class TemplateCardJump
{
/// <summary>
/// 跳转链接类型,0或不填代表不是链接,1 代表跳转url,2 代表跳转小程序
/// </summary>
[CanBeNull]
[JsonProperty("type")]
[JsonPropertyName("type")]
public int? Type { get; set; }
/// <summary>
/// 跳转链接样式的文案内容,建议不超过13个字
/// </summary>
[NotNull]
[JsonProperty("title")]
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// 跳转链接的url,type是1时必填
/// </summary>
[CanBeNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 点击跳转的小程序的appid,type是2时必填
/// </summary>
[CanBeNull]
[JsonProperty("appid")]
[JsonPropertyName("appid")]
public string AppId { get; set; }
/// <summary>
/// 点击跳转的小程序的pagepath,type是2时选填
/// </summary>
[CanBeNull]
[JsonProperty("pagepath")]
[JsonPropertyName("pagepath")]
public string PagePath { get; set; }
private TemplateCardJump(
string title,
int? type = null,
string url = null,
string appId = null,
string pagePath = null)
{
Type = type;
Title = title;
Url = url;
AppId = appId;
PagePath = pagePath;
}
/// <summary>
/// 创建一个默认指引样式
/// </summary>
/// <param name="title">跳转链接样式的文案内容</param>
/// <returns></returns>
public static TemplateCardJump Default(string title)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
return new TemplateCardJump(title);
}
/// <summary>
/// 创建一个跳转链接的指引样式
/// </summary>
/// <param name="title">跳转链接样式的文案内容</param>
/// <param name="url">跳转链接的url</param>
/// <returns></returns>
public static TemplateCardJump Link(string title, string url)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
Check.NotNullOrWhiteSpace(url, nameof(url));
return new TemplateCardJump(title, 1, url);
}
/// <summary>
/// 创建一个跳转小程序的指引样式
/// </summary>
/// <param name="title">跳转链接样式的文案内容</param>
/// <param name="appId">跳转链接的小程序的appid</param>
/// <param name="pagePath">跳转链接的小程序的pagepath</param>
/// <returns></returns>
public static TemplateCardJump MiniProgram(string title, string appId, string pagePath)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
Check.NotNullOrWhiteSpace(appId, nameof(appId));
Check.NotNullOrWhiteSpace(pagePath, nameof(pagePath));
return new TemplateCardJump(title, 2, appId: appId, pagePath: pagePath);
}
}

35
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardMainTitle.cs

@ -0,0 +1,35 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 模版卡片的主要内容
/// </summary>
public class TemplateCardMainTitle
{
/// <summary>
/// 一级标题,建议不超过26个字。模版卡片主要内容的一级标题main_title.title和二级普通文本sub_title_text必须有一项填写
/// </summary>
[CanBeNull]
[JsonProperty("title")]
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// 标题辅助信息,建议不超过30个字
/// </summary>
[CanBeNull]
[JsonProperty("desc")]
[JsonPropertyName("desc")]
public string Description { get; set; }
/// <summary>
/// 创建一个模版卡片的主要内容
/// </summary>
/// <param name="title">一级标题</param>
/// <param name="description">标题辅助信息</param>
public TemplateCardMainTitle(string title, string description = null)
{
Title = title;
Description = description;
}
}

111
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardQuoteArea.cs

@ -0,0 +1,111 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 引用文献
/// </summary>
public class TemplateCardQuoteArea
{
/// <summary>
/// 引用文献样式区域点击事件,0或不填代表没有点击事件,1 代表跳转url,2 代表跳转小程序
/// </summary>
[CanBeNull]
[JsonProperty("type")]
[JsonPropertyName("type")]
public int? Type { get; set; }
/// <summary>
/// 点击跳转的url,type是1时必填
/// </summary>
[CanBeNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 点击跳转的小程序的appid,type是2时必填
/// </summary>
[CanBeNull]
[JsonProperty("appid")]
[JsonPropertyName("appid")]
public string AppId { get; set; }
/// <summary>
/// 点击跳转的小程序的pagepath,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 QuoteText { get; set; }
private TemplateCardQuoteArea(
string title,
int? type = null,
string url = null,
string appId = null,
string pagePath = null,
string quoteText = null)
{
Title = title;
QuoteText = quoteText;
Type = type;
Url = url;
AppId = appId;
PagePath = pagePath;
}
/// <summary>
/// 创建一个默认引用文献
/// </summary>
/// <param name="title">引用文献样式的标题</param>
/// <param name="quoteText">引用文献样式的引用文案</param>
/// <returns></returns>
public static TemplateCardQuoteArea Default(string title, string quoteText = null)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
return new TemplateCardQuoteArea(title, quoteText: quoteText);
}
/// <summary>
/// 创建一个跳转链接的引用文献
/// </summary>
/// <param name="title">引用文献样式的标题</param>
/// <param name="url">点击跳转的url</param>
/// <param name="quoteText">引用文献样式的引用文案</param>
/// <returns></returns>
public static TemplateCardQuoteArea Link(string title, string url, string quoteText = null)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
Check.NotNullOrWhiteSpace(url, nameof(url));
return new TemplateCardQuoteArea(title, 1, url, quoteText: quoteText);
}
/// <summary>
/// 创建一个跳转小程序的引用文献
/// </summary>
/// <param name="title">引用文献样式的标题</param>
/// <param name="appId">跳转链接的小程序的appid</param>
/// <param name="pagePath">跳转链接的小程序的pagepath</param>
/// <param name="quoteText">引用文献样式的引用文案</param>
/// <returns></returns>
public static TemplateCardQuoteArea MiniProgram(string title, string appId, string pagePath, string quoteText = null)
{
Check.NotNullOrWhiteSpace(title, nameof(title));
Check.NotNullOrWhiteSpace(appId, nameof(appId));
Check.NotNullOrWhiteSpace(pagePath, nameof(pagePath));
return new TemplateCardQuoteArea(title, 2, appId: appId, pagePath: pagePath, quoteText: quoteText);
}
}

81
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardSource.cs

@ -0,0 +1,81 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 卡片来源样式信息
/// </summary>
public class TemplateCardSource
{
/// <summary>
/// 来源图片的url
/// </summary>
[CanBeNull]
[JsonProperty("icon_url")]
[JsonPropertyName("icon_url")]
public string IconUrl { get; set; }
/// <summary>
/// 来源图片的描述,建议不超过13个字
/// </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 int? DescriptionColor { get; set; }
private TemplateCardSource(
string iconUrl = null,
string description = null,
int? descriptionColor = 0)
{
IconUrl = iconUrl;
Description = description;
DescriptionColor = descriptionColor;
}
/// <summary>
/// 创建一个灰色卡片来源样式
/// </summary>
/// <param name="iconUrl">来源图片的url</param>
/// <param name="description">来源图片的描述</param>
/// <returns></returns>
public static TemplateCardSource Grey(string iconUrl, string description = null)
{
return new TemplateCardSource(iconUrl, description, 0);
}
/// <summary>
/// 创建一个黑色卡片来源样式
/// </summary>
/// <param name="iconUrl">来源图片的url</param>
/// <param name="description">来源图片的描述</param>
/// <returns></returns>
public static TemplateCardSource Black(string iconUrl, string description = null)
{
return new TemplateCardSource(iconUrl, description, 1);
}
/// <summary>
/// 创建一个红色卡片来源样式
/// </summary>
/// <param name="iconUrl">来源图片的url</param>
/// <param name="description">来源图片的描述</param>
/// <returns></returns>
public static TemplateCardSource Red(string iconUrl, string description = null)
{
return new TemplateCardSource(iconUrl, description, 2);
}
/// <summary>
/// 创建一个绿色卡片来源样式
/// </summary>
/// <param name="iconUrl">来源图片的url</param>
/// <param name="description">来源图片的描述</param>
/// <returns></returns>
public static TemplateCardSource Green(string iconUrl, string description = null)
{
return new TemplateCardSource(iconUrl, description, 3);
}
}

35
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TemplateCardVerticalContent.cs

@ -0,0 +1,35 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 卡片二级垂直内容
/// </summary>
public class TemplateCardVerticalContent
{
/// <summary>
/// 卡片二级标题,建议不超过26个字
/// </summary>
[CanBeNull]
[JsonProperty("title")]
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// 二级普通文本,建议不超过112个字
/// </summary>
[CanBeNull]
[JsonProperty("desc")]
[JsonPropertyName("desc")]
public string Description { get; set; }
/// <summary>
/// 创建一个卡片二级垂直内容
/// </summary>
/// <param name="title">卡片二级标题</param>
/// <param name="description">二级普通文本</param>
public TemplateCardVerticalContent(string title, string description = null)
{
Title = title;
Description = description;
}
}

3
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/TextMessage.cs

@ -1,6 +1,7 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
@ -10,7 +11,7 @@ public class TextMessage
{
public TextMessage(string content)
{
Content = content;
Content = Check.NotNullOrWhiteSpace(content, nameof(content), 2048);
}
/// <summary>

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookFileMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook文件消息
/// </summary>
public class WeChatWorkWebhookFileMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 文件消息体
/// </summary>
[NotNull]
[JsonProperty("file")]
[JsonPropertyName("file")]
public WebhookFileMessage File { get; set; }
/// <summary>
/// 创建一个企业微信Webhook文件消息
/// </summary>
/// <param name="file">文件消息体</param>
public WeChatWorkWebhookFileMessage(WebhookFileMessage file)
: base("file")
{
File = file;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookImageMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook图片消息
/// </summary>
public class WeChatWorkWebhookImageMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 图片消息体
/// </summary>
[NotNull]
[JsonProperty("image")]
[JsonPropertyName("image")]
public WebhookImageMessage Image { get; set; }
/// <summary>
/// 创建一个企业微信Webhook图片消息
/// </summary>
/// <param name="image">图片消息体</param>
public WeChatWorkWebhookImageMessage(WebhookImageMessage image)
: base("image")
{
Image = image;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookMarkdownMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook Markdown消息
/// </summary>
public class WeChatWorkWebhookMarkdownMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// Markdown消息体
/// </summary>
[NotNull]
[JsonProperty("markdown")]
[JsonPropertyName("markdown")]
public WebhookMarkdownMessage Markdown { get; set; }
/// <summary>
/// 创建一个企业微信Webhook Markdown消息
/// </summary>
/// <param name="markdown">Markdown消息体</param>
public WeChatWorkWebhookMarkdownMessage(WebhookMarkdownMessage markdown)
: base("markdown")
{
Markdown = markdown;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookMarkdownV2Message.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook MarkdownV2消息
/// </summary>
public class WeChatWorkWebhookMarkdownV2Message : WeChatWorkWebhookMessage
{
/// <summary>
/// markdown_v2消息体
/// </summary>
[NotNull]
[JsonProperty("markdown_v2")]
[JsonPropertyName("markdown_v2")]
public WebhookMarkdownV2Message Markdown { get; set; }
/// <summary>
/// 创建一个企业微信Webhook MarkdownV2消息
/// </summary>
/// <param name="markdown">markdown_v2消息体</param>
public WeChatWorkWebhookMarkdownV2Message(WebhookMarkdownV2Message markdown)
: base("markdown_v2")
{
Markdown = markdown;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookNewsMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook图文消息
/// </summary>
internal class WeChatWorkWebhookNewsMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 图文消息体
/// </summary>
[NotNull]
[JsonProperty("news")]
[JsonPropertyName("news")]
public WebhookNewsMessage News { get; set; }
/// <summary>
/// 创建一个企业微信Webhook图文消息
/// </summary>
/// <param name="markdown">图文消息体</param>
public WeChatWorkWebhookNewsMessage(WebhookNewsMessage news)
: base("news")
{
News = news;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookTemplateCardMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook模版卡片消息
/// </summary>
public class WeChatWorkWebhookTemplateCardMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 模版卡片消息体
/// </summary>
[NotNull]
[JsonProperty("template_card")]
[JsonPropertyName("template_card")]
public WebhookTemplateCardMessage TemplateCard { get; set; }
/// <summary>
/// 创建一个企业微信Webhook模版卡片消息
/// </summary>
/// <param name="templateCard">模版卡片消息体</param>
public WeChatWorkWebhookTemplateCardMessage(WebhookTemplateCardMessage templateCard)
: base("template_card")
{
TemplateCard = templateCard;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookTextMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook文本消息
/// </summary>
public class WeChatWorkWebhookTextMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 文本消息体
/// </summary>
[NotNull]
[JsonProperty("text")]
[JsonPropertyName("text")]
public WebhookTextMessage Text { get; set; }
/// <summary>
/// 创建一个企业微信Webhook文本消息
/// </summary>
/// <param name="templateCard">文本消息体</param>
public WeChatWorkWebhookTextMessage(WebhookTextMessage text)
: base("text")
{
Text = text;
}
}

27
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WeChatWorkWebhookVoiceMessage.cs

@ -0,0 +1,27 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// 企业微信Webhook语音消息
/// </summary>
public class WeChatWorkWebhookVoiceMessage : WeChatWorkWebhookMessage
{
/// <summary>
/// 语音消息体
/// </summary>
[NotNull]
[JsonProperty("voice")]
[JsonPropertyName("voice")]
public WebhookVoiceMessage Voice { get; set; }
/// <summary>
/// 创建一个企业微信Webhook语音消息
/// </summary>
/// <param name="voice">语音消息体</param>
public WeChatWorkWebhookVoiceMessage(WebhookVoiceMessage voice)
: base("voice")
{
Voice = voice;
}
}

26
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookFileMessage.cs

@ -0,0 +1,26 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook文件消息体
/// </summary>
public class WebhookFileMessage
{
/// <summary>
/// 文件id,通过下文的文件上传接口获取
/// </summary>
[NotNull]
[JsonProperty("media_id")]
[JsonPropertyName("media_id")]
public string MediaId { get; set; }
/// <summary>
/// 创建一个Webhook文件消息体
/// </summary>
/// <param name="mediaId">文件id,通过下文的文件上传接口获取</param>
public WebhookFileMessage(string mediaId)
{
MediaId = mediaId;
}
}

35
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookImageMessage.cs

@ -0,0 +1,35 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook图片消息体
/// </summary>
public class WebhookImageMessage
{
/// <summary>
/// 图片内容的base64编码
/// </summary>
[NotNull]
[JsonProperty("base64")]
[JsonPropertyName("base64")]
public string Base64 { get; set; }
/// <summary>
/// 图片的md5
/// </summary>
[NotNull]
[JsonProperty("md5")]
[JsonPropertyName("md5")]
public string Md5 { get; set; }
/// <summary>
/// 创建一个Webhook图片消息体
/// </summary>
/// <param name="base64">图片内容的base64编码</param>
/// <param name="md5">图片的md5</param>
public WebhookImageMessage(string base64, string md5)
{
Base64 = base64;
Md5 = md5;
}
}

29
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookMarkdownMessage.cs

@ -0,0 +1,29 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook Markdown消息体
/// </summary>
public class WebhookMarkdownMessage
{
/// <summary>
/// markdown内容,最长不超过4096个字节,必须是utf8编码
/// </summary>
[NotNull]
[StringLength(4096)]
[JsonProperty("content")]
[JsonPropertyName("content")]
public string Content { get; set; }
/// <summary>
/// 创建一个Webhook Markdown消息体
/// </summary>
/// <param name="content">markdown内容,最长不超过4096个字节,必须是utf8编码</param>
public WebhookMarkdownMessage(string content)
{
Content = Check.NotNullOrWhiteSpace(content, nameof(content), 4096);
}
}

33
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookMarkdownV2Message.cs

@ -0,0 +1,33 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook MarkdownV2消息体
/// </summary>
public class WebhookMarkdownV2Message
{
/// <summary>
/// markdown_v2内容,最长不超过4096个字节,必须是utf8编码。
/// </summary>
/// <remarks>
/// 1. markdown_v2不支持字体颜色、@群成员的语法, 具体支持的语法可参考下面说明<br />
/// 2. 消息内容在客户端 4.1.36 版本以下(安卓端为4.1.38以下) 消息表现为纯文本,建议使用最新客户端版本体验
/// </remarks>
[NotNull]
[StringLength(4096)]
[JsonProperty("content")]
[JsonPropertyName("content")]
public string Content { get; set; }
/// <summary>
/// 创建一个Webhook MarkdownV2消息体
/// </summary>
/// <param name="content">markdown_v2内容,最长不超过4096个字节,必须是utf8编码</param>
public WebhookMarkdownV2Message(string content)
{
Content = Check.NotNullOrWhiteSpace(content, nameof(content), 4096);
}
}

88
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookNewsMessage.cs

@ -0,0 +1,88 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook图文消息体
/// </summary>
public class WebhookNewsMessage
{
/// <summary>
/// 图文消息,一个图文消息支持1到8条图文
/// </summary>
[NotNull]
[JsonProperty("articles")]
[JsonPropertyName("articles")]
public List<WebhookArticleMessage> Articles { get; set; }
/// <summary>
/// 创建一个Webhook图文消息体
/// </summary>
/// <param name="articles">图文消息列表</param>
/// <exception cref="ArgumentException"></exception>
public WebhookNewsMessage(List<WebhookArticleMessage> articles)
{
Articles = Check.NotNull(articles, nameof(articles));
if (Articles.Count < 1 || Articles.Count > 8)
{
throw new ArgumentException("One image-text message supports 1 to 8 image-text messages!");
}
}
}
public class WebhookArticleMessage
{
/// <summary>
/// 标题,不超过128个字节,超过会自动截断
/// </summary>
[NotNull]
[StringLength(128)]
[JsonProperty("title")]
[JsonPropertyName("title")]
public string Title { get; set; }
/// <summary>
/// 描述,不超过512个字节,超过会自动截断
/// </summary>
[CanBeNull]
[StringLength(512)]
[JsonProperty("description")]
[JsonPropertyName("description")]
public string Description { get; set; }
/// <summary>
/// 点击后跳转的链接。
/// </summary>
[NotNull]
[JsonProperty("url")]
[JsonPropertyName("url")]
public string Url { get; set; }
/// <summary>
/// 图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图 1068*455,小图150*150。
/// </summary>
[CanBeNull]
[JsonProperty("picurl")]
[JsonPropertyName("picurl")]
public string PictureUrl { get; set; }
/// <summary>
/// 创建一个图文消息
/// </summary>
/// <param name="title">标题</param>
/// <param name="url">点击后跳转的链接</param>
/// <param name="description">描述</param>
/// <param name="pictureUrl">图文消息的图片链接</param>
public WebhookArticleMessage(
string title,
string url,
string description = "",
string pictureUrl = "")
{
Title = Check.NotNullOrWhiteSpace(title, nameof(title), 128);
Url = Check.NotNullOrWhiteSpace(url, nameof(url));
Description = Check.Length(description, nameof(description), 512);
PictureUrl = pictureUrl;
}
}

72
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookNewsNoticeCardMessage.cs

@ -0,0 +1,72 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook 图文展示模版卡片消息体
/// </summary>
public class WebhookNewsNoticeCardMessage : WebhookTemplateCardMessage
{
/// <summary>
/// 创建一个Webhook 图文展示模版卡片消息体
/// </summary>
/// <param name="cardImage">图片样式</param>
/// <param name="action">整体卡片的点击跳转事件</param>
/// <param name="mainTitle">模版卡片的主要内容</param>
/// <param name="imageTextArea">左图右文样式</param>
/// <param name="source">卡片来源样式信息</param>
/// <param name="quoteArea">引用文献样式</param>
/// <param name="horizontalContents">二级标题+文本列表,列表长度不超过6</param>
/// <param name="verticalContents">卡片二级垂直内容,列表长度不超过4</param>
/// <param name="jumps">跳转指引样式的列表,列表长度不超过3</param>
/// <exception cref="ArgumentException"></exception>
public WebhookNewsNoticeCardMessage(
TemplateCardImage cardImage,
TemplateCardAction action,
TemplateCardMainTitle mainTitle,
TemplateCardImageTextArea imageTextArea = null,
TemplateCardSource source = null,
TemplateCardQuoteArea quoteArea = null,
List<TemplateCardHorizontalContent> horizontalContents = null,
List<TemplateCardVerticalContent> verticalContents = null,
List<TemplateCardJump> jumps = null)
: base("news_notice", action, mainTitle, source, quoteArea, horizontalContents, jumps)
{
Check.NotNull(mainTitle, nameof(mainTitle));
Check.NotNull(cardImage, nameof(cardImage));
CardImage = cardImage;
ImageTextArea = imageTextArea;
VerticalContents = verticalContents;
if (verticalContents != null && verticalContents.Count > 4)
{
throw new ArgumentException("The length of the secondary vertical content list on the card cannot exceed 4!");
}
}
/// <summary>
/// 图片样式
/// </summary>
[NotNull]
[JsonProperty("aspect_ratio")]
[JsonPropertyName("aspect_ratio")]
public TemplateCardImage CardImage { get; set; }
/// <summary>
/// 左图右文样式
/// </summary>
[CanBeNull]
[JsonProperty("image_text_area")]
[JsonPropertyName("image_text_area")]
public TemplateCardImageTextArea ImageTextArea { get; set; }
/// <summary>
/// 卡片二级垂直内容,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过4
/// </summary>
[CanBeNull]
[JsonProperty("vertical_content_list")]
[JsonPropertyName("vertical_content_list")]
public List<TemplateCardVerticalContent> VerticalContents { get; set; }
}

100
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTemplateCardMessage.cs

@ -0,0 +1,100 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook模板卡片消息体
/// </summary>
public abstract class WebhookTemplateCardMessage
{
/// <summary>
/// 模版卡片的模版类型
/// </summary>
[CanBeNull]
[JsonProperty("card_type")]
[JsonPropertyName("card_type")]
public string CardType { get; set; }
/// <summary>
/// 卡片来源样式信息,不需要来源样式可不填写
/// </summary>
[CanBeNull]
[JsonProperty("source")]
[JsonPropertyName("source")]
public TemplateCardSource Source { get; set; }
/// <summary>
/// 模版卡片的主要内容,包括一级标题和标题辅助信息
/// </summary>
[CanBeNull]
[JsonProperty("main_title")]
[JsonPropertyName("main_title")]
public TemplateCardMainTitle MainTitle { get; set; }
/// <summary>
/// 引用文献样式,建议不与关键数据共用
/// </summary>
[CanBeNull]
[JsonProperty("quote_area")]
[JsonPropertyName("quote_area")]
public TemplateCardQuoteArea QuoteArea { 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>
[CanBeNull]
[JsonProperty("card_action")]
[JsonPropertyName("card_action")]
public TemplateCardAction Action { get; set; }
/// <summary>
/// 创建一个Webhook模板卡片消息体
/// </summary>
/// <param name="action">整体卡片的点击跳转事件</param>
/// <param name="mainTitle">模版卡片的主要内容</param>
/// <param name="source">卡片来源样式信息</param>
/// <param name="quoteArea">引用文献样式</param>
/// <param name="horizontalContents">二级标题+文本列表,列表长度不超过6</param>
/// <param name="jumps">跳转指引样式的列表,列表长度不超过3</param>
/// <exception cref="ArgumentException"></exception>
protected WebhookTemplateCardMessage(
string cardType,
TemplateCardAction action,
TemplateCardMainTitle mainTitle = null,
TemplateCardSource source = null,
TemplateCardQuoteArea quoteArea = null,
List<TemplateCardHorizontalContent> horizontalContents = null,
List<TemplateCardJump> jumps = null)
{
CardType = Check.NotNullOrWhiteSpace(cardType, nameof(cardType));
Action = Check.NotNull(action, nameof(action));
MainTitle = mainTitle;
Source = source;
QuoteArea = quoteArea;
HorizontalContents = horizontalContents;
Jumps = jumps;
if (horizontalContents != null && horizontalContents.Count > 6)
{
throw new ArgumentException("The length of the secondary title and the text list should not exceed 6!");
}
if (jumps != null && jumps.Count > 3)
{
throw new ArgumentException("The length of the list in the style of jump guidance should not exceed 3!");
}
}
}

45
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTextMessage.cs

@ -0,0 +1,45 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook文本消息体
/// </summary>
public class WebhookTextMessage
{
/// <summary>
/// 消文本内容,最长不超过2048个字节,必须是utf8编码
/// </summary>
[NotNull]
[StringLength(2048)]
[JsonProperty("content")]
[JsonPropertyName("content")]
public string Content { get; set; }
/// <summary>
/// userid的列表,提醒群中的指定成员(@某个成员),@all表示提醒所有人,如果开发者获取不到userid,可以使用mentioned_mobile_list
/// </summary>
[NotNull]
[JsonProperty("mentioned_list")]
[JsonPropertyName("mentioned_list")]
public List<string> MentionedList { get; set; }
/// <summary>
/// 手机号列表,提醒手机号对应的群成员(@某个成员),@all表示提醒所有人
/// </summary>
[NotNull]
[StringLength(2048)]
[JsonProperty("mentioned_mobile_list")]
[JsonPropertyName("mentioned_mobile_list")]
public List<string> MentionedMobileList { get; set; }
/// <summary>
/// 创建一个Webhook文本消息体
/// </summary>
/// <param name="content">消息内容</param>
public WebhookTextMessage(string content)
{
Content = Check.NotNullOrWhiteSpace(content, nameof(content), 2048);
}
}

63
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookTextNoticeCardMessage.cs

@ -0,0 +1,63 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook 文本通知模版卡片消息体
/// </summary>
public class WebhookTextNoticeCardMessage : WebhookTemplateCardMessage
{
/// <summary>
/// 二级普通文本,建议不超过112个字。模版卡片主要内容的一级标题main_title.title和二级普通文本sub_title_text必须有一项填写
/// </summary>
[CanBeNull]
[JsonProperty("sub_title_text")]
[JsonPropertyName("sub_title_text")]
public string SubTitleText { get; set; }
/// <summary>
/// 关键数据样式
/// </summary>
[CanBeNull]
[JsonProperty("emphasis_content")]
[JsonPropertyName("emphasis_content")]
public TemplateCardEmphasisContent EmphasisContent { get; set; }
/// <summary>
/// 创建一个Webhook 文本通知模版卡片消息体
/// </summary>
/// <param name="action">整体卡片的点击跳转事件</param>
/// <param name="mainTitle">模版卡片的主要内容</param>
/// <param name="subTitleText">二级普通文本</param>
/// <param name="emphasisContent">关键数据样式</param>
/// <param name="source">卡片来源样式信息</param>
/// <param name="quoteArea">引用文献样式</param>
/// <param name="horizontalContents">二级标题+文本列表,列表长度不超过6</param>
/// <param name="jumps">跳转指引样式的列表,列表长度不超过3</param>
/// <exception cref="ArgumentException"></exception>
public WebhookTextNoticeCardMessage(
TemplateCardAction action,
TemplateCardMainTitle mainTitle = null,
string subTitleText = null,
TemplateCardEmphasisContent emphasisContent = null,
TemplateCardSource source = null,
TemplateCardQuoteArea quoteArea = null,
List<TemplateCardHorizontalContent> horizontalContents = null,
List<TemplateCardJump> jumps = null)
: base("text_notice", action, mainTitle, source, quoteArea, horizontalContents, jumps)
{
MainTitle = mainTitle;
SubTitleText = subTitleText;
EmphasisContent = emphasisContent;
Source = source;
QuoteArea = quoteArea;
HorizontalContents = horizontalContents;
Jumps = jumps;
if (mainTitle == null && subTitleText.IsNullOrWhiteSpace())
{
throw new ArgumentException("One of the primary title mainTitle and the secondary ordinary text subTitleText of the main content of the template card must be filled in!");
}
}
}

26
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/Models/WebhookVoiceMessage.cs

@ -0,0 +1,26 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages.Models;
/// <summary>
/// Webhook语音消息体
/// </summary>
public class WebhookVoiceMessage
{
/// <summary>
/// 语音文件id,通过下文的文件上传接口获取
/// </summary>
[NotNull]
[JsonProperty("media_id")]
[JsonPropertyName("media_id")]
public string MediaId { get; set; }
/// <summary>
/// 创建一个Webhook语音消息体
/// </summary>
/// <param name="mediaId">语音文件id</param>
public WebhookVoiceMessage(string mediaId)
{
MediaId = mediaId;
}
}

25
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/WeChatWorkMessageSender.cs

@ -76,7 +76,30 @@ public class WeChatWorkMessageSender : IWeChatWorkMessageSender, ISingletonDepen
if (!messageResponse.IsSuccessed)
{
Logger.LogWarning("Send wechat work message failed");
Logger.LogWarning("Send wechat work app chat message failed");
Logger.LogWarning($"Error code: {messageResponse.ErrorCode}, message: {messageResponse.ErrorMessage}");
}
return messageResponse;
}
[RequiresFeature(WeChatWorkFeatureNames.Webhook.Enable)]
[RequiresLimitFeature(
WeChatWorkFeatureNames.Webhook.Limit,
WeChatWorkFeatureNames.Webhook.LimitInterval,
LimitPolicy.Minute)]
// 消息发送频率限制: https://developer.work.weixin.qq.com/document/path/99110#%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E9%A2%91%E7%8E%87%E9%99%90%E5%88%B6
public async virtual Task<WeChatWorkResponse> SendAsync(string webhookKey, WeChatWorkWebhookMessage message, CancellationToken cancellationToken = default)
{
var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken);
var client = HttpClientFactory.CreateClient(AbpWeChatWorkGlobalConsts.ApiClient);
using var response = await client.SendMessageAsync(webhookKey, message, cancellationToken);
var messageResponse = await response.DeserializeObjectAsync<WeChatWorkResponse>();
if (!messageResponse.IsSuccessed)
{
Logger.LogWarning("Send wechat work webhook message failed");
Logger.LogWarning($"Error code: {messageResponse.ErrorCode}, message: {messageResponse.ErrorMessage}");
}

22
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Messages/WeChatWorkWebhookMessage.cs

@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace LINGYUN.Abp.WeChat.Work.Messages;
/// <summary>
/// 企业微信Webhook消息结构体
/// </summary>
public abstract class WeChatWorkWebhookMessage : WeChatWorkRequest
{
/// <summary>
/// 消息类型
/// </summary>
[NotNull]
[JsonProperty("msgtype")]
[JsonPropertyName("msgtype")]
public string MsgType { get; set; }
protected WeChatWorkWebhookMessage(string msgType)
{
MsgType = msgType;
}
}

20
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Message.cs

@ -64,4 +64,24 @@ internal static partial class HttpClientWeChatWorkRequestExtensions
return await client.SendAsync(httpRequest, cancellationToken);
}
public async static Task<HttpResponseMessage> SendMessageAsync(
this HttpMessageInvoker client,
string webhookKey,
WeChatWorkWebhookMessage request,
CancellationToken cancellationToken = default)
{
var urlBuilder = new StringBuilder();
urlBuilder.Append("/cgi-bin/webhook/send");
urlBuilder.AppendFormat("?key={0}", webhookKey);
var httpRequest = new HttpRequestMessage(
HttpMethod.Post,
urlBuilder.ToString())
{
Content = new StringContent(request.SerializeToJson())
};
return await client.SendAsync(httpRequest, cancellationToken);
}
}

Loading…
Cancel
Save