diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Extensions/WechatAdsClientExecuteAdvertiserExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Extensions/WechatAdsClientExecuteAdvertiserExtensions.cs new file mode 100644 index 00000000..f8f2705c --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Extensions/WechatAdsClientExecuteAdvertiserExtensions.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Flurl; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.Ads +{ + public static class WechatAdsClientExecuteAdvertiserExtensions + { + /// + /// 异步调用 [POST] /advertiser/add 接口。 + /// + /// + /// + /// + /// + public static async Task ExecuteAdvertiserAddAsync(this WechatAdsClient client, Models.AdvertiserAddRequest 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(HttpMethod.Post, "advertiser", "add") + .SetOptions(request) + .SetQueryParam("access_token", request.AccessToken); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /advertiser/update 接口。 + /// + /// + /// + /// + /// + public static async Task ExecuteAdvertiserUpdateAsync(this WechatAdsClient client, Models.AdvertiserUpdateRequest 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(HttpMethod.Post, "advertiser", "update") + .SetOptions(request) + .SetQueryParam("access_token", request.AccessToken); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [GET] /advertiser/get 接口。 + /// + /// + /// + /// + /// + public static async Task ExecuteAdvertiserGetAsync(this WechatAdsClient client, Models.AdvertiserGetRequest 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(HttpMethod.Get, "advertiser", "get") + .SetOptions(request) + .SetQueryParam("access_token", request.AccessToken); + + return await client.SendRequestAsync(flurlReq, cancellationToken: cancellationToken); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddRequest.cs new file mode 100644 index 00000000..a6d56954 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddRequest.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [POST] /advertiser/add 接口的请求。 + /// + public class AdvertiserAddRequest : WechatAdsRequest + { + /// + /// 获取或设置行业 ID。 + /// + [Newtonsoft.Json.JsonProperty("system_industry_id")] + [System.Text.Json.Serialization.JsonPropertyName("system_industry_id")] + public int IndustryId { get; set; } + + /// + /// 获取或设置联系人姓名。 + /// + [Newtonsoft.Json.JsonProperty("contact_person")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person")] + public string ContactPerson { get; set; } = string.Empty; + + /// + /// 获取或设置联系人电话号码。 + /// + [Newtonsoft.Json.JsonProperty("contact_person_telephone")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person_telephone")] + public string ContactTeleNumber { get; set; } = string.Empty; + + /// + /// 获取或设置经营性质类型。 + /// + [Newtonsoft.Json.JsonProperty("business_type")] + [System.Text.Json.Serialization.JsonPropertyName("business_type")] + public string? BusinessType { get; set; } + + /// + /// 获取或设置经营内容。 + /// + [Newtonsoft.Json.JsonProperty("business_content")] + [System.Text.Json.Serialization.JsonPropertyName("business_content")] + public string? BusinessContent { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddResponse.cs new file mode 100644 index 00000000..4235477c --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserAddResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [POST] /advertiser/add 接口的响应。 + /// + public class AdvertiserAddResponse : WechatAdsResponse + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetRequest.cs new file mode 100644 index 00000000..a6f5f1c3 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [GET] /advertiser/get 接口的请求。 + /// + public class AdvertiserGetRequest : WechatAdsRequest + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetResponse.cs new file mode 100644 index 00000000..00d8f2d5 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserGetResponse.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [GET] /advertiser/get 接口的响应。 + /// + public class AdvertiserGetResponse : WechatAdsResponse + { + public static class Types + { + public class Data + { + /// + /// 获取或设置公众号名称。 + /// + [Newtonsoft.Json.JsonProperty("wechat_account_name")] + [System.Text.Json.Serialization.JsonPropertyName("wechat_account_name")] + public string WechatAccountNickname { get; set; } = default!; + + /// + /// 获取或设置系统状态。 + /// + [Newtonsoft.Json.JsonProperty("system_status")] + [System.Text.Json.Serialization.JsonPropertyName("system_status")] + public string SystemStatus { get; set; } = default!; + + /// + /// 获取或设置行业 ID。 + /// + [Newtonsoft.Json.JsonProperty("industry_id")] + [System.Text.Json.Serialization.JsonPropertyName("industry_id")] + public int IndustryId { get; set; } + + /// + /// 获取或设置联系人姓名。 + /// + [Newtonsoft.Json.JsonProperty("contact_person")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person")] + public string ContactPerson { get; set; } = default!; + + /// + /// 获取或设置联系人电话号码。 + /// + [Newtonsoft.Json.JsonProperty("contact_person_telephone")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person_telephone")] + public string ContactTeleNumber { get; set; } = default!; + + /// + /// 获取或设置经营性质类型。 + /// + [Newtonsoft.Json.JsonProperty("business_type")] + [System.Text.Json.Serialization.JsonPropertyName("business_type")] + public string? BusinessType { get; set; } + + /// + /// 获取或设置经营内容。 + /// + [Newtonsoft.Json.JsonProperty("business_content")] + [System.Text.Json.Serialization.JsonPropertyName("business_content")] + public string? BusinessContent { get; set; } + } + } + + /// + /// 获取或设置返回数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateRequest.cs new file mode 100644 index 00000000..f9c981cb --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateRequest.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [POST] /advertiser/update 接口的请求。 + /// + public class AdvertiserUpdateRequest : WechatAdsRequest + { + /// + /// 获取或设置行业 ID。 + /// + [Newtonsoft.Json.JsonProperty("system_industry_id")] + [System.Text.Json.Serialization.JsonPropertyName("system_industry_id")] + public int? IndustryId { get; set; } + + /// + /// 获取或设置联系人姓名。 + /// + [Newtonsoft.Json.JsonProperty("contact_person")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person")] + public string? ContactPerson { get; set; } + + /// + /// 获取或设置联系人电话号码。 + /// + [Newtonsoft.Json.JsonProperty("contact_person_telephone")] + [System.Text.Json.Serialization.JsonPropertyName("contact_person_telephone")] + public string? ContactTeleNumber { get; set; } + + /// + /// 获取或设置经营性质类型。 + /// + [Newtonsoft.Json.JsonProperty("business_type")] + [System.Text.Json.Serialization.JsonPropertyName("business_type")] + public string? BusinessType { get; set; } + + /// + /// 获取或设置经营内容。 + /// + [Newtonsoft.Json.JsonProperty("business_content")] + [System.Text.Json.Serialization.JsonPropertyName("business_content")] + public string? BusinessContent { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateResponse.cs new file mode 100644 index 00000000..77e750a1 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/Models/Advertiser/AdvertiserUpdateResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.Models +{ + /// + /// 表示 [POST] /advertiser/update 接口的响应。 + /// + public class AdvertiserUpdateResponse : WechatAdsResponse + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.Ads/WechatAdsEndpoints.cs b/src/SKIT.FlurlHttpClient.Wechat.Ads/WechatAdsEndpoints.cs index 380a8b99..92743284 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Ads/WechatAdsEndpoints.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Ads/WechatAdsEndpoints.cs @@ -10,6 +10,6 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads /// /// 主域名(默认)。 /// - public const string DEFAULT = "https://api.weixin.qq.com"; + public const string DEFAULT = "https://api.weixin.qq.com/marketing"; } } diff --git a/test/SKIT.FlurlHttpClient.Wechat.Ads.UnitTests/WechatAdsDeclarationTests.cs b/test/SKIT.FlurlHttpClient.Wechat.Ads.UnitTests/WechatAdsDeclarationTests.cs new file mode 100644 index 00000000..ed6e0317 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.Ads.UnitTests/WechatAdsDeclarationTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace SKIT.FlurlHttpClient.Wechat.Ads.UnitTests +{ + public class WechatAdsDeclarationTests + { + private static readonly Assembly _assembly = Assembly.Load("SKIT.FlurlHttpClient.Wechat.Ads"); + + [Fact(DisplayName = "验证 API 模型命名")] + public void ApiModelsNamingTest() + { + TestAssertUtil.VerifyApiModelsNaming(_assembly, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "验证 API 模型定义")] + public void ApiModelsDefinitionTest() + { + string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples"); + Assert.True(Directory.Exists(workdir)); + + TestAssertUtil.VerifyApiModelsDefinition(_assembly, workdir, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "验证 API 接口命名")] + public void ApiExtensionsNamingTest() + { + TestAssertUtil.VerifyApiExtensionsNaming(_assembly, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "验证代码规范")] + public void CodeStyleTest() + { + string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory); + Assert.True(Directory.Exists(workdir)); + + TestAssertUtil.VerifySourceCodeStyle(workdir, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + } +}