diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Events/KfMessage/KfMessageEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Events/KfMessage/KfMessageEvent.cs
new file mode 100644
index 00000000..0dc807da
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Events/KfMessage/KfMessageEvent.cs
@@ -0,0 +1,16 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Events
+{
+ ///
+ /// 表示 kf_msg_or_event 事件的数据。
+ /// REF: https://open.work.weixin.qq.com/api/doc/90000/90135/94670
+ /// REF: https://open.work.weixin.qq.com/api/doc/90001/90143/94699
+ ///
+ public class KfMessageEvent : WechatWorkEvent, WechatWorkEvent.Types.IXmlSerializable
+ {
+ ///
+ /// 获取或设置调用拉取消息的 Token。
+ ///
+ [System.Xml.Serialization.XmlElement("Content")]
+ public string Token { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinKfExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinKfExtensions.cs
index 47253ced..63a80db8 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinKfExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinKfExtensions.cs
@@ -373,5 +373,26 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
}
+
+ ///
+ /// 异步调用 [POST] /cgi-bin/kf/sync_msg 接口。
+ /// REF: https://open.work.weixin.qq.com/api/doc/90000/90135/94670
+ /// REF: https://open.work.weixin.qq.com/api/doc/90001/90143/94699
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCgibinKfSyncMessageAsync(this WechatWorkClient client, Models.CgibinKfSyncMessageRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "cgi-bin", "kf", "sync_msg")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSendMessageRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSendMessageRequest.cs
index bdb74d45..5f9dafaf 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSendMessageRequest.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSendMessageRequest.cs
@@ -57,7 +57,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Models
///
[Newtonsoft.Json.JsonProperty("thumb_media_id")]
[System.Text.Json.Serialization.JsonPropertyName("thumb_media_id")]
- public string ThumbnailMediaId { get; set; }= string.Empty;
+ public string ThumbnailMediaId { get; set; } = string.Empty;
}
public class MiniProgramMessage
@@ -88,7 +88,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Models
///
[Newtonsoft.Json.JsonProperty("thumb_media_id")]
[System.Text.Json.Serialization.JsonPropertyName("thumb_media_id")]
- public string ThumbnailMediaId { get; set; }= string.Empty;
+ public string ThumbnailMediaId { get; set; } = string.Empty;
}
public class MenuMessage
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageRequest.cs
new file mode 100644
index 00000000..ec574dc3
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageRequest.cs
@@ -0,0 +1,29 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/kf/sync_msg 接口的请求。
+ ///
+ public class CgibinKfSyncMessageRequest : WechatWorkRequest
+ {
+ ///
+ /// 获取或设置同步消息的 Token。
+ ///
+ [Newtonsoft.Json.JsonProperty("token")]
+ [System.Text.Json.Serialization.JsonPropertyName("token")]
+ public string Token { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置翻页标记。
+ ///
+ [Newtonsoft.Json.JsonProperty("cursor")]
+ [System.Text.Json.Serialization.JsonPropertyName("cursor")]
+ public string? NextCursor { get; set; }
+
+ ///
+ /// 获取或设置翻页每页数量。
+ ///
+ [Newtonsoft.Json.JsonProperty("limit")]
+ [System.Text.Json.Serialization.JsonPropertyName("limit")]
+ public int? Limit { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageResponse.cs
new file mode 100644
index 00000000..c8a243cc
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinKf/CgibinKfSyncMessageResponse.cs
@@ -0,0 +1,283 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/kf/sync_msg 接口的响应。
+ ///
+ public class CgibinKfSyncMessageResponse : WechatWorkResponse
+ {
+ public static class Types
+ {
+ public class Message
+ {
+ public static class Types
+ {
+ public class TextMessage : CgibinKfSendMessageRequest.Types.TextMessage
+ {
+ ///
+ /// 获取或设置客户点击菜单的菜单项 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("menu_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("menu_id")]
+ public string? MenuId { get; set; }
+ }
+
+ public class ImageMessage : CgibinKfSendMessageRequest.Types.ImageMessage
+ {
+ }
+
+ public class VoiceMessage : CgibinKfSendMessageRequest.Types.VoiceMessage
+ {
+ }
+
+ public class VideoMessage : CgibinKfSendMessageRequest.Types.VideoMessage
+ {
+ }
+
+ public class FileMessage : CgibinKfSendMessageRequest.Types.FileMessage
+ {
+ }
+
+ public class BusinessCardMessage
+ {
+ ///
+ /// 获取或设置名片的 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("userid")]
+ public string UserId { get; set; } = default!;
+ }
+
+ public class LinkMessage : CgibinKfSendMessageRequest.Types.LinkMessage
+ {
+ ///
+ /// 获取或设置图文封面的 URL。
+ ///
+ [Newtonsoft.Json.JsonProperty("pic_url")]
+ [System.Text.Json.Serialization.JsonPropertyName("pic_url")]
+ public string ThumbnailUrl { get; set; } = default!;
+ }
+
+ public class MiniProgramMessage : CgibinKfSendMessageRequest.Types.MiniProgramMessage
+ {
+ }
+
+ public class MenuMessage : CgibinKfSendMessageRequest.Types.MenuMessage
+ {
+ }
+
+ public class LocationMessage : CgibinKfSendMessageRequest.Types.LocationMessage
+ {
+ }
+
+ public class EventMessage
+ {
+ ///
+ /// 获取或设置事件类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("event_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("event_type")]
+ public string EventType { get; set; } = default!;
+
+ ///
+ /// 获取或设置客户账号 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("open_kfid")]
+ [System.Text.Json.Serialization.JsonPropertyName("open_kfid")]
+ public string? OpenKfId { get; set; }
+
+ ///
+ /// 获取或设置外部联系人账号。
+ ///
+ [Newtonsoft.Json.JsonProperty("external_userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("external_userid")]
+ public string? ExternalUserId { get; set; }
+
+ ///
+ /// 获取或设置专员的 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("servicer_userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("servicer_userid")]
+ public string? ServicerUserId { get; set; }
+
+ ///
+ /// 获取或设置场景值。
+ ///
+ [Newtonsoft.Json.JsonProperty("scene")]
+ [System.Text.Json.Serialization.JsonPropertyName("scene")]
+ public string? Scene { get; set; }
+
+ ///
+ /// 获取或设置场景参数。
+ ///
+ [Newtonsoft.Json.JsonProperty("scene_param")]
+ [System.Text.Json.Serialization.JsonPropertyName("scene_param")]
+ public string? SceneParameter { get; set; }
+
+ ///
+ /// 获取或设置欢迎语。
+ ///
+ [Newtonsoft.Json.JsonProperty("welcome_code")]
+ [System.Text.Json.Serialization.JsonPropertyName("welcome_code")]
+ public string? WelcomeCode { get; set; }
+
+ ///
+ /// 获取或设置状态。
+ ///
+ [Newtonsoft.Json.JsonProperty("status")]
+ [System.Text.Json.Serialization.JsonPropertyName("status")]
+ public int? Status { get; set; }
+
+ ///
+ /// 获取或设置发送失败的消息 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("fail_msgid")]
+ [System.Text.Json.Serialization.JsonPropertyName("fail_msgid")]
+ public string? FailedMessageId { get; set; }
+
+ ///
+ /// 获取或设置发送失败的类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("fail_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("fail_type")]
+ public int? FailedType { get; set; }
+
+ ///
+ /// 获取或设置变更类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("change_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("change_type")]
+ public int? ChangeType { get; set; }
+
+ ///
+ /// 获取或设置旧的专员 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("old_servicer_userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("old_servicer_userid")]
+ public string? OldServicerUserId { get; set; }
+
+ ///
+ /// 获取或设置新的专员 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("new_servicer_userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("new_servicer_userid")]
+ public string? NewServicerUserId { get; set; }
+
+ ///
+ /// 获取或设置用于发送事件响应消息的 Code。
+ ///
+ [Newtonsoft.Json.JsonProperty("msg_code")]
+ [System.Text.Json.Serialization.JsonPropertyName("msg_code")]
+ public string? MessageCode { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置消息 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("msgid")]
+ [System.Text.Json.Serialization.JsonPropertyName("msgid")]
+ public string MessageId { get; set; } = default!;
+
+ ///
+ /// 获取或设置消息类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("msgtype")]
+ [System.Text.Json.Serialization.JsonPropertyName("msgtype")]
+ public string MessageType { get; set; } = default!;
+
+ ///
+ /// 获取或设置文本消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("text")]
+ [System.Text.Json.Serialization.JsonPropertyName("text")]
+ public Types.TextMessage? MessageContentForText { get; set; }
+
+ ///
+ /// 获取或设置图片消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("image")]
+ [System.Text.Json.Serialization.JsonPropertyName("image")]
+ public Types.ImageMessage? MessageContentForImage { get; set; }
+
+ ///
+ /// 获取或设置语音消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("voice")]
+ [System.Text.Json.Serialization.JsonPropertyName("voice")]
+ public Types.VoiceMessage? MessageContentForVoice { get; set; }
+
+ ///
+ /// 获取或设置视频消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("video")]
+ [System.Text.Json.Serialization.JsonPropertyName("video")]
+ public Types.VideoMessage? MessageContentForVideo { get; set; }
+
+ ///
+ /// 获取或设置文件消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("file")]
+ [System.Text.Json.Serialization.JsonPropertyName("file")]
+ public Types.FileMessage? MessageContentForFile { get; set; }
+
+ ///
+ /// 获取或设置名片消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("business_card")]
+ [System.Text.Json.Serialization.JsonPropertyName("business_card")]
+ public Types.BusinessCardMessage? MessageContentForBusinessCard { get; set; }
+
+ ///
+ /// 获取或设置图文消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("link")]
+ [System.Text.Json.Serialization.JsonPropertyName("link")]
+ public Types.LinkMessage? MessageContentForLink { get; set; }
+
+ ///
+ /// 获取或设置小程序消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("miniprogram")]
+ [System.Text.Json.Serialization.JsonPropertyName("miniprogram")]
+ public Types.MiniProgramMessage? MessageContentForMiniProgram { get; set; }
+
+ ///
+ /// 获取或设置菜单消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("msgmenu")]
+ [System.Text.Json.Serialization.JsonPropertyName("msgmenu")]
+ public Types.MenuMessage? MessageContentForMenu { get; set; }
+
+ ///
+ /// 获取或设置地理位置消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("location")]
+ [System.Text.Json.Serialization.JsonPropertyName("location")]
+ public Types.LocationMessage? MessageContentForLocation { get; set; }
+
+ ///
+ /// 获取或设置事件消息信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("event")]
+ [System.Text.Json.Serialization.JsonPropertyName("event")]
+ public Types.EventMessage? MessageContentForEvent { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置是否还有更多数据。
+ ///
+ [Newtonsoft.Json.JsonProperty("has_more")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("has_more")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))]
+ public bool HasMore { get; set; } = default!;
+
+ ///
+ /// 获取或设置翻页标记。
+ ///
+ [Newtonsoft.Json.JsonProperty("cursor")]
+ [System.Text.Json.Serialization.JsonPropertyName("cursor")]
+ public string? NextCursor { get; set; }
+ }
+}