feat(work): 新增会议高级布局管理相关接口

This commit is contained in:
Fu Diwei
2023-06-20 19:54:56 +08:00
parent 1e368a81f0
commit e6c76b1eab
25 changed files with 944 additions and 19 deletions

View File

@@ -153,11 +153,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
len = IPAddress.NetworkToHostOrder(len);
byte[] bMsg = new byte[len];
byte[] bCorpId = new byte[btmpMsg.Length - 20 - len];
byte[] bAppId = new byte[btmpMsg.Length - 20 - len];
Array.Copy(btmpMsg, 20, bMsg, 0, len);
Array.Copy(btmpMsg, 20 + len, bCorpId, 0, btmpMsg.Length - 20 - len);
Array.Copy(btmpMsg, 20 + len, bAppId, 0, btmpMsg.Length - 20 - len);
appId = Encoding.UTF8.GetString(bCorpId);
appId = Encoding.UTF8.GetString(bAppId);
return Encoding.UTF8.GetString(bMsg);
}
@@ -180,15 +180,15 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
string randCode = CreateRandCode(16);
byte[] bRand = Encoding.UTF8.GetBytes(randCode);
byte[] bCorpId = Encoding.UTF8.GetBytes(appId);
byte[] bAppId = Encoding.UTF8.GetBytes(appId);
byte[] bMsgTmp = Encoding.UTF8.GetBytes(plainText);
byte[] bMsgLen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bMsgTmp.Length));
byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bCorpId.Length + bMsgTmp.Length];
byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppId.Length + bMsgTmp.Length];
Array.Copy(bRand, bMsg, bRand.Length);
Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
Array.Copy(bMsgTmp, 0, bMsg, bRand.Length + bMsgLen.Length, bMsgTmp.Length);
Array.Copy(bCorpId, 0, bMsg, bRand.Length + bMsgLen.Length + bMsgTmp.Length, bCorpId.Length);
Array.Copy(bAppId, 0, bMsg, bRand.Length + bMsgLen.Length + bMsgTmp.Length, bAppId.Length);
return AESEncrypt(keyBytes: keyBytes, ivBytes: ivBytes, plainBytes: bMsg);
}

View File

@@ -159,7 +159,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
string cipher = Utilities.WxMsgCryptor.AESEncrypt(
plainText: json,
encodingAESKey: client.Credentials.PushEncodingAESKey!,
corpOrSuiteId: string.IsNullOrEmpty(client.Credentials.SuiteId) ? client.Credentials.CorpId : client.Credentials.SuiteId!
corpId: string.IsNullOrEmpty(client.Credentials.SuiteId) ? client.Credentials.CorpId : client.Credentials.SuiteId!
);
string sign = Utilities.WxMsgCryptor.GenerateSignature(
sToken: client.Credentials.PushToken!,
@@ -215,7 +215,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
string cipher = Utilities.WxMsgCryptor.AESEncrypt(
plainText: xml,
encodingAESKey: client.Credentials.PushEncodingAESKey!,
corpOrSuiteId: string.IsNullOrEmpty(client.Credentials.SuiteId) ? client.Credentials.CorpId : client.Credentials.SuiteId!
corpId: string.IsNullOrEmpty(client.Credentials.SuiteId) ? client.Credentials.CorpId : client.Credentials.SuiteId!
);
xml = Utilities.WxMsgCryptor.WrapXml(sToken: client.Credentials.PushToken!, sMsgEncrypt: cipher);

View File

@@ -577,6 +577,106 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingLayoutSetDefaultResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/add 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98861 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingAdvancedLayoutAddResponse> ExecuteCgibinMeetingAdvancedLayoutAddAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutAddRequest 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", "meeting", "advanced_layout", "add")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/update 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98868 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingAdvancedLayoutUpdateResponse> ExecuteCgibinMeetingAdvancedLayoutUpdateAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutUpdateRequest 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", "meeting", "advanced_layout", "update")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/apply 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98869 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingAdvancedLayoutApplyResponse> ExecuteCgibinMeetingAdvancedLayoutApplyAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutApplyRequest 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", "meeting", "advanced_layout", "apply")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutApplyResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/list 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98862 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingAdvancedLayoutListResponse> ExecuteCgibinMeetingAdvancedLayoutListAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutListRequest 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", "meeting", "advanced_layout", "list")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutListResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/get_user_layout 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98865 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingAdvancedLayoutGetUserLayoutResponse> ExecuteCgibinMeetingAdvancedLayoutGetUserLayoutAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutGetUserLayoutRequest 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", "meeting", "advanced_layout", "get_user_layout")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutGetUserLayoutResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/meeting/advanced_layout/batch_delete 接口。</para>
/// <para>REF: https://developer.work.weixin.qq.com/document/path/98866 </para>
@@ -585,7 +685,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinMeetingLayoutBatchDeleteResponse> ExecuteCgibinMeetingLayoutBatchDeleteAsync(this WechatWorkClient client, Models.CgibinMeetingLayoutBatchDeleteRequest request, CancellationToken cancellationToken = default)
public static async Task<Models.CgibinMeetingAdvancedLayoutBatchDeleteResponse> ExecuteCgibinMeetingAdvancedLayoutBatchDeleteAsync(this WechatWorkClient client, Models.CgibinMeetingAdvancedLayoutBatchDeleteRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
@@ -594,7 +694,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
.CreateRequest(request, HttpMethod.Post, "cgi-bin", "meeting", "advanced_layout", "batch_delete")
.SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingLayoutBatchDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
return await client.SendRequestWithJsonAsync<Models.CgibinMeetingAdvancedLayoutBatchDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>

View File

@@ -0,0 +1,170 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/add 接口的请求。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutAddRequest : WechatWorkRequest
{
public static class Types
{
public class Layout
{
public static class Types
{
public class Page
{
public static class Types
{
public class PollingSettings
{
/// <summary>
/// 获取或设置轮询间隔时间类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_interval_unit")]
[System.Text.Json.Serialization.JsonPropertyName("polling_interval_unit")]
public int PollingIntervalUnitType { get; set; }
/// <summary>
/// 获取或设置轮询间隔时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_interval")]
[System.Text.Json.Serialization.JsonPropertyName("polling_interval")]
public int PollingInterval { get; set; }
/// <summary>
/// 获取或设置是否忽略没开启视频成员。
/// </summary>
[Newtonsoft.Json.JsonProperty("ignore_user_novideo")]
[System.Text.Json.Serialization.JsonPropertyName("ignore_user_novideo")]
public bool IsIgnoreUserNoVideo { get; set; }
/// <summary>
/// 获取或设置设置是否忽略未入会成员。
/// </summary>
[Newtonsoft.Json.JsonProperty("ignore_user_absence")]
[System.Text.Json.Serialization.JsonPropertyName("ignore_user_absence")]
public bool IsIgnoreUserAbsence { get; set; }
}
public class UserSeat
{
public static class Types
{
public class User
{
/// <summary>
/// 获取或设置参会的成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("userid")]
[System.Text.Json.Serialization.JsonPropertyName("userid")]
public string? UserId { get; set; }
/// <summary>
/// 获取或设置参会的成员临时 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("tmp_openid")]
[System.Text.Json.Serialization.JsonPropertyName("tmp_openid")]
public string? TempOpenId { get; set; }
/// <summary>
/// 获取或设置昵称。
/// </summary>
[Newtonsoft.Json.JsonProperty("nick_name")]
[System.Text.Json.Serialization.JsonPropertyName("nick_name")]
public string? Nickname { get; set; }
}
}
/// <summary>
/// 获取或设置宫格 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("grid_id")]
[System.Text.Json.Serialization.JsonPropertyName("grid_id")]
public string GridId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置宫格类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("grid_type")]
[System.Text.Json.Serialization.JsonPropertyName("grid_type")]
public int GridType { get; set; }
/// <summary>
/// 获取或设置视频画面来源。
/// </summary>
[Newtonsoft.Json.JsonProperty("video_type")]
[System.Text.Json.Serialization.JsonPropertyName("video_type")]
public int? VideoType { get; set; }
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public IList<Types.User>? UserList { get; set; }
}
}
/// <summary>
/// 获取或设置布局模板 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_template_id")]
[System.Text.Json.Serialization.JsonPropertyName("layout_template_id")]
public string LayoutTemplateId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置是否开启轮询。
/// </summary>
[Newtonsoft.Json.JsonProperty("enable_polling")]
[System.Text.Json.Serialization.JsonPropertyName("enable_polling")]
public bool? EnablePolling { get; set; }
/// <summary>
/// 获取或设置轮询配置信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_setting")]
[System.Text.Json.Serialization.JsonPropertyName("polling_setting")]
public Types.PollingSettings? PollingSettings { get; set; }
/// <summary>
/// 获取或设置用户座次列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_seat_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_seat_list")]
public IList<Types.UserSeat> UserSeatList { get; set; } = new List<Types.UserSeat>();
}
}
/// <summary>
/// 获取或设置布局名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_name")]
[System.Text.Json.Serialization.JsonPropertyName("layout_name")]
public string? LayoutName { get; set; }
/// <summary>
/// 获取或设置布局单页列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("page_list")]
[System.Text.Json.Serialization.JsonPropertyName("page_list")]
public IList<Types.Page> PageList { get; set; } = new List<Types.Page>();
}
}
/// <summary>
/// 获取或设置会议 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("meetingid")]
[System.Text.Json.Serialization.JsonPropertyName("meetingid")]
public string MeetingId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置布局列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_list")]
[System.Text.Json.Serialization.JsonPropertyName("layout_list")]
public IList<Types.Layout> LayoutList { get; set; } = new List<Types.Layout>();
}
}

View File

@@ -0,0 +1,72 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/add 接口的响应。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutAddResponse : WechatWorkResponse
{
public static class Types
{
public class Layout : CgibinMeetingAdvancedLayoutListResponse.Types.Layout
{
public static new class Types
{
public class Page : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page
{
public static new class Types
{
public class PollingSettings : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.PollingSettings
{
}
public class UserSeat : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.UserSeat
{
public static new class Types
{
public class User : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.UserSeat.Types.User
{
}
}
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public new Types.User[] UserList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置轮询配置信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_setting")]
[System.Text.Json.Serialization.JsonPropertyName("polling_setting")]
public new Types.PollingSettings? PollingSettings { get; set; }
/// <summary>
/// 获取或设置用户座次列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_seat_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_seat_list")]
public new Types.UserSeat[] UserSeatList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置布局单页列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("page_list")]
[System.Text.Json.Serialization.JsonPropertyName("page_list")]
public new Types.Page[] PageList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置布局列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_list")]
[System.Text.Json.Serialization.JsonPropertyName("layout_list")]
public Types.Layout[] LayoutList { get; set; } = default!;
}
}

View File

@@ -0,0 +1,44 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/apply 接口的请求。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutApplyRequest : WechatWorkRequest
{
public static class Types
{
public class User
{
/// <summary>
/// 获取或设置参会的成员临时 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("tmp_openid")]
[System.Text.Json.Serialization.JsonPropertyName("tmp_openid")]
public string TempOpenId { get; set; } = string.Empty;
}
}
/// <summary>
/// 获取或设置会议 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("meetingid")]
[System.Text.Json.Serialization.JsonPropertyName("meetingid")]
public string MeetingId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置布局 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_id")]
[System.Text.Json.Serialization.JsonPropertyName("layout_id")]
public string LayoutId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public IList<Types.User> UserList { get; set; } = new List<Types.User>();
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/apply 接口的响应。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutApplyResponse : WechatWorkResponse
{
}
}

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Models
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/batch_delete 接口的请求。</para>
/// </summary>
public class CgibinMeetingLayoutBatchDeleteRequest : WechatWorkRequest
public class CgibinMeetingAdvancedLayoutBatchDeleteRequest : WechatWorkRequest
{
/// <summary>
/// 获取或设置会议 ID。

View File

@@ -3,7 +3,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Models
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/batch_delete 接口的响应。</para>
/// </summary>
public class CgibinMeetingLayoutBatchDeleteResponse : WechatWorkResponse
public class CgibinMeetingAdvancedLayoutBatchDeleteResponse : WechatWorkResponse
{
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/get_user_layout 接口的请求。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutGetUserLayoutRequest : WechatWorkRequest
{
/// <summary>
/// 获取或设置会议 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("meetingid")]
[System.Text.Json.Serialization.JsonPropertyName("meetingid")]
public string MeetingId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置参会的成员临时 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("tmp_openid")]
[System.Text.Json.Serialization.JsonPropertyName("tmp_openid")]
public string TempOpenId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置终端设备类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("instance_id")]
[System.Text.Json.Serialization.JsonPropertyName("instance_id")]
public int InstanceId { get; set; }
}
}

View File

@@ -0,0 +1,80 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/get_user_layout 接口的响应。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutGetUserLayoutResponse : WechatWorkResponse
{
public static class Types
{
public class Page : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page
{
public static new class Types
{
public class PollingSettings : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.PollingSettings
{
}
public class UserSeat : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.UserSeat
{
public static new class Types
{
public class User : CgibinMeetingAdvancedLayoutListResponse.Types.Layout.Types.Page.Types.UserSeat.Types.User
{
}
}
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public new Types.User[] UserList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置轮询配置信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_setting")]
[System.Text.Json.Serialization.JsonPropertyName("polling_setting")]
public new Types.PollingSettings? PollingSettings { get; set; }
/// <summary>
/// 获取或设置用户座次列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_seat_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_seat_list")]
public new Types.UserSeat[] UserSeatList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置布局 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("selected_layout_id")]
[System.Text.Json.Serialization.JsonPropertyName("selected_layout_id")]
public string LayoutId { get; set; } = default!;
/// <summary>
/// 获取或设置布局名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_name")]
[System.Text.Json.Serialization.JsonPropertyName("layout_name")]
public string LayoutName { get; set; } = default!;
/// <summary>
/// 获取或设置布局类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_type")]
[System.Text.Json.Serialization.JsonPropertyName("layout_type")]
public int LayoutType { get; set; }
/// <summary>
/// 获取或设置布局单页列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("page_list")]
[System.Text.Json.Serialization.JsonPropertyName("page_list")]
public Types.Page[]? PageList { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/list 接口的请求。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutListRequest : WechatWorkRequest
{
/// <summary>
/// 获取或设置会议 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("meetingid")]
[System.Text.Json.Serialization.JsonPropertyName("meetingid")]
public string MeetingId { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,128 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/list 接口的响应。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutListResponse : WechatWorkResponse
{
public static class Types
{
public class Layout
{
public static class Types
{
public class Page
{
public static class Types
{
public class PollingSettings : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page.Types.PollingSettings
{
}
public class UserSeat
{
public static class Types
{
public class User : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page.Types.UserSeat.Types.User
{
}
}
/// <summary>
/// 获取或设置宫格 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("grid_id")]
[System.Text.Json.Serialization.JsonPropertyName("grid_id")]
public string GridId { get; set; } = default!;
/// <summary>
/// 获取或设置宫格类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("grid_type")]
[System.Text.Json.Serialization.JsonPropertyName("grid_type")]
public int GridType { get; set; }
/// <summary>
/// 获取或设置视频画面来源。
/// </summary>
[Newtonsoft.Json.JsonProperty("video_type")]
[System.Text.Json.Serialization.JsonPropertyName("video_type")]
public int VideoType { get; set; }
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public Types.User[] UserList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置布局模板 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_template_id")]
[System.Text.Json.Serialization.JsonPropertyName("layout_template_id")]
public string LayoutTemplateId { get; set; } = default!;
/// <summary>
/// 获取或设置是否开启轮询。
/// </summary>
[Newtonsoft.Json.JsonProperty("enable_polling")]
[System.Text.Json.Serialization.JsonPropertyName("enable_polling")]
public bool EnablePolling { get; set; }
/// <summary>
/// 获取或设置轮询配置信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_setting")]
[System.Text.Json.Serialization.JsonPropertyName("polling_setting")]
public Types.PollingSettings? PollingSettings { get; set; }
/// <summary>
/// 获取或设置用户座次列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_seat_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_seat_list")]
public Types.UserSeat[] UserSeatList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置布局 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_id")]
[System.Text.Json.Serialization.JsonPropertyName("layout_id")]
public string LayoutId { get; set; } = default!;
/// <summary>
/// 获取或设置布局名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_name")]
[System.Text.Json.Serialization.JsonPropertyName("layout_name")]
public string LayoutName { get; set; } = default!;
/// <summary>
/// 获取或设置布局单页列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("page_list")]
[System.Text.Json.Serialization.JsonPropertyName("page_list")]
public Types.Page[] PageList { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置会议应用的布局 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("selected_layout_id")]
[System.Text.Json.Serialization.JsonPropertyName("selected_layout_id")]
public string SelectedLayoutId { get; set; } = default!;
/// <summary>
/// 获取或设置布局列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_list")]
[System.Text.Json.Serialization.JsonPropertyName("layout_list")]
public Types.Layout[] LayoutList { get; set; } = default!;
}
}

View File

@@ -0,0 +1,82 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/update 接口的请求。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutUpdateRequest : WechatWorkRequest
{
public static class Types
{
public class Page : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page
{
public static new class Types
{
public class PollingSettings : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page.Types.PollingSettings
{
}
public class UserSeat : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page.Types.UserSeat
{
public static new class Types
{
public class User : CgibinMeetingAdvancedLayoutAddRequest.Types.Layout.Types.Page.Types.UserSeat.Types.User
{
}
}
/// <summary>
/// 获取或设置用户列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_list")]
public new IList<Types.User>? UserList { get; set; }
}
}
/// <summary>
/// 获取或设置轮询配置信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("polling_setting")]
[System.Text.Json.Serialization.JsonPropertyName("polling_setting")]
public new Types.PollingSettings? PollingSettings { get; set; }
/// <summary>
/// 获取或设置用户座次列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_seat_list")]
[System.Text.Json.Serialization.JsonPropertyName("user_seat_list")]
public new IList<Types.UserSeat> UserSeatList { get; set; } = new List<Types.UserSeat>();
}
}
/// <summary>
/// 获取或设置会议 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("meetingid")]
[System.Text.Json.Serialization.JsonPropertyName("meetingid")]
public string MeetingId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置布局 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_id")]
[System.Text.Json.Serialization.JsonPropertyName("layout_id")]
public string LayoutId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置布局名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("layout_name")]
[System.Text.Json.Serialization.JsonPropertyName("layout_name")]
public string? LayoutName { get; set; }
/// <summary>
/// 获取或设置布局单页列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("page_list")]
[System.Text.Json.Serialization.JsonPropertyName("page_list")]
public IList<Types.Page> PageList { get; set; } = new List<Types.Page>();
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/meeting/advanced_layout/update 接口的响应。</para>
/// </summary>
public class CgibinMeetingAdvancedLayoutUpdateResponse : WechatWorkResponse
{
}
}

View File

@@ -136,9 +136,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
/// </summary>
/// <param name="cipherText">企业微信推送来的加密文本内容(即 `Encrypt` 字段的值)。</param>
/// <param name="encodingAESKey">企业微信后台设置的 EncodingAESKey。</param>
/// <param name="corpOrSuiteId">企业微信 CorpId 或第三方应用的 SuiteId。</param>
/// <param name="corpId">企业微信 CorpId 或第三方应用的 SuiteId。</param>
/// <returns>解密后的文本内容。</returns>
public static string AESDecrypt(string cipherText, string encodingAESKey, out string corpOrSuiteId)
public static string AESDecrypt(string cipherText, string encodingAESKey, out string corpId)
{
if (cipherText == null) throw new ArgumentNullException(nameof(cipherText));
if (encodingAESKey == null) throw new ArgumentNullException(nameof(encodingAESKey));
@@ -157,7 +157,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
Array.Copy(btmpMsg, 20, bMsg, 0, len);
Array.Copy(btmpMsg, 20 + len, bCorpId, 0, btmpMsg.Length - 20 - len);
corpOrSuiteId = Encoding.UTF8.GetString(bCorpId);
corpId = Encoding.UTF8.GetString(bCorpId);
return Encoding.UTF8.GetString(bMsg);
}
@@ -166,13 +166,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
/// </summary>
/// <param name="plainText">返回给企业微信的原始文本内容。</param>
/// <param name="encodingAESKey">企业微信后台设置的 EncodingAESKey。</param>
/// <param name="corpOrSuiteId">企业微信 CorpId 或第三方应用的 SuiteId。</param>
/// <param name="corpId">企业微信 CorpId 或第三方应用的 SuiteId。</param>
/// <returns>加密后的文本内容。</returns>
public static string AESEncrypt(string plainText, string encodingAESKey, string corpOrSuiteId)
public static string AESEncrypt(string plainText, string encodingAESKey, string corpId)
{
if (plainText == null) throw new ArgumentNullException(nameof(plainText));
if (encodingAESKey == null) throw new ArgumentNullException(nameof(encodingAESKey));
if (corpOrSuiteId == null) throw new ArgumentNullException(nameof(corpOrSuiteId));
if (corpId == null) throw new ArgumentNullException(nameof(corpId));
byte[] keyBytes = Convert.FromBase64String(encodingAESKey + "=");
byte[] ivBytes = new byte[16];
@@ -180,7 +180,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
string randCode = CreateRandCode(16);
byte[] bRand = Encoding.UTF8.GetBytes(randCode);
byte[] bCorpId = Encoding.UTF8.GetBytes(corpOrSuiteId);
byte[] bCorpId = Encoding.UTF8.GetBytes(corpId);
byte[] bMsgTmp = Encoding.UTF8.GetBytes(plainText);
byte[] bMsgLen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bMsgTmp.Length));
byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bCorpId.Length + bMsgTmp.Length];

View File

@@ -0,0 +1,34 @@
{
"meetingid": "MEETINGID",
"layout_list": [
{
"layout_name": "testmictest",
"page_list": [
{
"layout_template_id": "3",
"enable_polling": true,
"polling_setting": {
"polling_interval_unit": 1,
"polling_interval": 10,
"ignore_user_novideo": false,
"ignore_user_absence": false
},
"user_seat_list": [
{
"grid_id": "1",
"grid_type": 1,
"video_type": 3,
"user_list": [
{
"userid": "USERID",
"tmp_openid": "TMPOPENID1",
"nick_name": "bmlja25hbWUK"
}
]
}
]
}
]
}
]
}

View File

@@ -0,0 +1,36 @@
{
"errcode": 0,
"errmsg": "ok",
"layout_list": [
{
"layout_id": "LAYOUTID1",
"layout_name": "testmictest",
"page_list": [
{
"layout_template_id": "3",
"enable_polling": true,
"polling_setting": {
"polling_interval_unit": 1,
"polling_interval": 10,
"ignore_user_absence": false,
"ignore_user_novideo": false
},
"user_seat_list": [
{
"grid_id": "1",
"grid_type": 1,
"video_type": 3,
"user_list": [
{
"userid": "USERID",
"tmp_openid": "TMPOPENID1",
"nick_name": "bmlja25hbWUK"
}
]
}
]
}
]
}
]
}

View File

@@ -0,0 +1,9 @@
{
"meetingid": "MEETINGID",
"layout_id": "LAYOUTID1",
"user_list": [
{
"tmp_openid": "TMPOPENID1"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"meetingid": "MEETINGID",
"tmp_openid": "TMPOPENID1",
"instance_id": 1
}

View File

@@ -0,0 +1,31 @@
{
"errcode": 0,
"errmsg": "ok",
"selected_layout_id": "LAYOUTID1",
"layout_name": "testmictest",
"layout_type": 2,
"page_list": [
{
"layout_template_id": "3",
"enable_polling": true,
"polling_setting": {
"polling_interval_unit": 1,
"polling_interval": 10,
"ignore_user_absence": false,
"ignore_user_novideo": false
},
"user_seat_list": [
{
"grid_id": "1",
"grid_type": 1,
"video_type": 3,
"user_list": [
{
"tmp_openid": "TMPOPENID1"
}
]
}
]
}
]
}

View File

@@ -0,0 +1,37 @@
{
"errcode": 0,
"errmsg": "ok",
"selected_layout_id": "LAYOUTID1",
"layout_list": [
{
"layout_id": "LAYOUTID1",
"layout_name": "testmictest",
"page_list": [
{
"layout_template_id": "3",
"enable_polling": true,
"polling_setting": {
"polling_interval_unit": 1,
"polling_interval": 10,
"ignore_user_absence": false,
"ignore_user_novideo": false
},
"user_seat_list": [
{
"grid_id": "1",
"grid_type": 1,
"video_type": 3,
"user_list": [
{
"userid": "USERID",
"tmp_openid": "TMPOPENID1",
"nick_name": "dGVzdF9uaWNr"
}
]
}
]
}
]
}
]
}

View File

@@ -0,0 +1,30 @@
{
"meetingid": "MEETINGID",
"layout_id": "LAYOUTID1",
"layout_name": "testmictest",
"page_list": [
{
"layout_template_id": "3",
"enable_polling": true,
"polling_setting": {
"polling_interval_unit": 1,
"polling_interval": 10,
"ignore_user_novideo": false,
"ignore_user_absence": false
},
"user_seat_list": [
{
"grid_id": "1",
"grid_type": 1,
"video_type": 3,
"user_list": [
{
"userid": "USERID",
"tmp_openid": "TMPOPENID1"
}
]
}
]
}
]
}