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; } + } +}