diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientExecuteWxaBusinessExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientExecuteWxaBusinessExtensions.cs
index e2e20d30..0c90feff 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientExecuteWxaBusinessExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientExecuteWxaBusinessExtensions.cs
@@ -322,6 +322,68 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
}
#endregion
+ #region License
+ ///
+ /// 异步调用 [POST] /wxa/business/license/activedevice 接口。
+ /// REF: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/hardware-device/activeLicenseDevice.html
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteWxaBusinessLicenseActiveDeviceAsync(this WechatApiClient client, Models.WxaBusinessLicenseActiveDeviceRequest 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, "wxa", "business", "license", "activedevice")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [POST] /wxa/business/license/getdeviceinfo 接口。
+ /// REF: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/hardware-device/getLicenseDeviceInfo.html
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteWxaBusinessLicenseGetDeviceInfoAsync(this WechatApiClient client, Models.WxaBusinessLicenseGetDeviceInfoRequest 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, "wxa", "business", "license", "getdeviceinfo")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [POST] /wxa/business/license/getpkglist 接口。
+ /// REF: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/hardware-device/getLicensePkgList.html
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteWxaBusinessLicenseGetPackageListAsync(this WechatApiClient client, Models.WxaBusinessLicenseGetPackageListRequest 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, "wxa", "business", "license", "getpkglist")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+ #endregion
+
#region LiveBroadcast
///
/// 异步调用 [POST] /wxa/business/applyliveinfo 接口。
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.cs
new file mode 100644
index 00000000..aae9aec6
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/activedevice 接口的请求。
+ ///
+ public class WxaBusinessLicenseActiveDeviceRequest : WechatApiRequest, IInferable
+ {
+ public static class Types
+ {
+ public class Device
+ {
+ ///
+ /// 获取或设置设备型号 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("model_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("model_id")]
+ public string ModelId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置设备序列号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sn")]
+ [System.Text.Json.Serialization.JsonPropertyName("sn")]
+ public string SerialNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置激活码序号。
+ ///
+ [Newtonsoft.Json.JsonProperty("active_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("active_number")]
+ public int ActiveNumber { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置设备列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_list")]
+ public IList DeviceList { get; set; } = new List();
+
+ ///
+ /// 获取或设置资源包类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_type")]
+ public int PackageType { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.cs
new file mode 100644
index 00000000..2510857e
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.cs
@@ -0,0 +1,49 @@
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/activedevice 接口的响应。
+ ///
+ public class WxaBusinessLicenseActiveDeviceResponse : WechatApiResponse
+ {
+ public static class Types
+ {
+ public class Result
+ {
+ ///
+ /// 获取或设置设备型号 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("model_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("model_id")]
+ public string ModelId { get; set; } = default!;
+
+ ///
+ /// 获取或设置设备序列号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sn")]
+ [System.Text.Json.Serialization.JsonPropertyName("sn")]
+ public string SerialNumber { get; set; } = default!;
+
+ ///
+ /// 获取或设置设备过期时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("expire_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("expire_time")]
+ public long? ExpireTimestamp { get; set; }
+
+ ///
+ /// 获取或设置错误码。
+ ///
+ [Newtonsoft.Json.JsonProperty("errcode")]
+ [System.Text.Json.Serialization.JsonPropertyName("errcode")]
+ public int ErrorCode { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置结果列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_list")]
+ public Types.Result[] ResultList { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.cs
new file mode 100644
index 00000000..01a4d8d9
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/getdeviceinfo 接口的请求。
+ ///
+ public class WxaBusinessLicenseGetDeviceInfoRequest : WechatApiRequest, IInferable
+ {
+ public static class Types
+ {
+ public class Device
+ {
+ ///
+ /// 获取或设置设备型号 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("model_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("model_id")]
+ public string ModelId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置设备序列号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sn")]
+ [System.Text.Json.Serialization.JsonPropertyName("sn")]
+ public string SerialNumber { get; set; } = string.Empty;
+ }
+ }
+
+ ///
+ /// 获取或设置设备列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_list")]
+ public IList DeviceList { get; set; } = new List();
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.cs
new file mode 100644
index 00000000..7c7e29ee
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.cs
@@ -0,0 +1,42 @@
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/getdeviceinfo 接口的响应。
+ ///
+ public class WxaBusinessLicenseGetDeviceInfoResponse : WechatApiResponse
+ {
+ public static class Types
+ {
+ public class Device
+ {
+ ///
+ /// 获取或设置设备型号 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("model_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("model_id")]
+ public string ModelId { get; set; } = default!;
+
+ ///
+ /// 获取或设置设备序列号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sn")]
+ [System.Text.Json.Serialization.JsonPropertyName("sn")]
+ public string SerialNumber { get; set; } = default!;
+
+ ///
+ /// 获取或设置设备过期时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("expire_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("expire_time")]
+ public long? ExpireTimestamp { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置设备列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_list")]
+ public Types.Device[] DeviceList { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.cs
new file mode 100644
index 00000000..d45d9e85
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/getpkglist 接口的请求。
+ ///
+ public class WxaBusinessLicenseGetPackageListRequest : WechatApiRequest, IInferable
+ {
+ ///
+ /// 获取或设置资源包类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_type")]
+ public int PackageType { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.cs
new file mode 100644
index 00000000..7f7844dd
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Models/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.cs
@@ -0,0 +1,77 @@
+namespace SKIT.FlurlHttpClient.Wechat.Api.Models
+{
+ ///
+ /// 表示 [POST] /wxa/business/license/getpkglist 接口的响应。
+ ///
+ public class WxaBusinessLicenseGetPackageListResponse : WechatApiResponse
+ {
+ public static class Types
+ {
+ public class Package
+ {
+ ///
+ /// 获取或设置资源包 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_id")]
+ public string PackageId { get; set; } = default!;
+
+ ///
+ /// 获取或设置资源包类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_type")]
+ public int PackageType { get; set; }
+
+ ///
+ /// 获取或设置资源包状态。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_status")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_status")]
+ public int PackageStatus { get; set; }
+
+ ///
+ /// 获取或设置下单时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("start_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("start_time")]
+ public long StartTimestamp { get; set; }
+
+ ///
+ /// 获取或设置过期时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("end_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("end_time")]
+ public long EndTimestamp { get; set; }
+
+ ///
+ /// 获取或设置已使用额度。
+ ///
+ [Newtonsoft.Json.JsonProperty("used")]
+ [System.Text.Json.Serialization.JsonPropertyName("used")]
+ public int UsedQuota { get; set; }
+
+ ///
+ /// 获取或设置资源包总量。
+ ///
+ [Newtonsoft.Json.JsonProperty("all")]
+ [System.Text.Json.Serialization.JsonPropertyName("all")]
+ public int TotalQuota { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置资源包列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("pkg_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("pkg_list")]
+ public Types.Package[] PackageList { get; set; } = default!;
+
+ ///
+ /// 获取或设置最大激活码序号。
+ ///
+ [Newtonsoft.Json.JsonProperty("max_active_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("max_active_number")]
+ public int? MaxActiveNumber { get; set; }
+ }
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.json
new file mode 100644
index 00000000..754696db
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceRequest.json
@@ -0,0 +1,15 @@
+{
+ "pkg_type": 0,
+ "device_list": [
+ {
+ "model_id": "MODEL_ID1",
+ "sn": "SN1",
+ "active_number": 1
+ },
+ {
+ "model_id": "MODEL_ID2",
+ "sn": "SN2",
+ "active_number": 2
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.json
new file mode 100644
index 00000000..0ac4eaa7
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseActiveDeviceResponse.json
@@ -0,0 +1,16 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "device_list": [
+ {
+ "model_id": "MODEL_ID1",
+ "sn": "SN1",
+ "errcode": 0
+ },
+ {
+ "model_id": "MODEL_ID2",
+ "sn": "SN2",
+ "errcode": 0
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.json
new file mode 100644
index 00000000..465b6a22
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoRequest.json
@@ -0,0 +1,12 @@
+{
+ "device_list": [
+ {
+ "model_id": "MODEL_ID1",
+ "sn": "SN1"
+ },
+ {
+ "model_id": "MODEL_ID2",
+ "sn": "SN2"
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.json
new file mode 100644
index 00000000..9cc3f31d
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetDeviceInfoResponse.json
@@ -0,0 +1,16 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "device_list": [
+ {
+ "model_id": "MODEL_ID1",
+ "sn": "SN1",
+ "expire_time": 1630425600
+ },
+ {
+ "model_id": "MODEL_ID2",
+ "sn": "SN2",
+ "expire_time": 1630425600
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.json
new file mode 100644
index 00000000..c6fa034c
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListRequest.json
@@ -0,0 +1,3 @@
+{
+ "pkg_type": 0
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.json
new file mode 100644
index 00000000..a95ee81b
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/ModelSamples/WxaBusiness/License/WxaBusinessLicenseGetPackageListResponse.json
@@ -0,0 +1,25 @@
+{
+ "errcode": 0,
+ "errmsg": "success",
+ "pkg_list": [
+ {
+ "pkg_id": "ZY100000000",
+ "pkg_type": 1,
+ "start_time": 1629907200,
+ "end_time": 1630425600,
+ "pkg_status": 1,
+ "used": 10,
+ "all": 100
+ },
+ {
+ "pkg_id": "ZY100000001",
+ "pkg_type": 2,
+ "start_time": 1629907200,
+ "end_time": 1630425600,
+ "pkg_status": 1,
+ "used": 20,
+ "all": 200
+ }
+ ],
+ "max_active_number": 300
+}