feat(wxads): 升级公共组件

This commit is contained in:
Fu Diwei 2024-01-29 23:11:47 +08:00 committed by RHQYZ
parent a7484fd89f
commit 54e7ac8266
40 changed files with 230 additions and 336 deletions

View File

@ -1,24 +0,0 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Exceptions
{
public class WechatAdsRequestAgencyTokenException : WechatAdsException
{
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException()
{
}
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException(string message)
: base(message)
{
}
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

View File

@ -1,24 +0,0 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Exceptions
{
public class WechatAdsRequestTimeoutException : WechatAdsException
{
/// <inheritdoc/>
internal WechatAdsRequestTimeoutException()
{
}
/// <inheritdoc/>
internal WechatAdsRequestTimeoutException(string message)
: base(message)
{
}
/// <inheritdoc/>
internal WechatAdsRequestTimeoutException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "adcreatives", "add") .CreateRequest(request, HttpMethod.Post, "adcreatives", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdCreativesAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdCreativesAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "adcreatives", "update") .CreateRequest(request, HttpMethod.Post, "adcreatives", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdCreativesUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdCreativesUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,19 +63,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "adcreatives", "get") .CreateRequest(request, HttpMethod.Get, "adcreatives", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.AdCreativeId != null) if (request.AdCreativeId is not null)
flurlReq.SetQueryParam("adcreative_id", request.AdCreativeId.Value); flurlReq.SetQueryParam("adcreative_id", request.AdCreativeId.Value);
if (request.Filters != null) if (request.Filters is not null)
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.AdCreativesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdCreativesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "adgroups", "add") .CreateRequest(request, HttpMethod.Post, "adgroups", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdGroupsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdGroupsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "adgroups", "update") .CreateRequest(request, HttpMethod.Post, "adgroups", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdGroupsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdGroupsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,19 +63,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "adgroups", "get") .CreateRequest(request, HttpMethod.Get, "adgroups", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.AdGroupId != null) if (request.AdGroupId is not null)
flurlReq.SetQueryParam("adgroup_id", request.AdGroupId.Value); flurlReq.SetQueryParam("adgroup_id", request.AdGroupId.Value);
if (request.Filters != null) if (request.Filters is not null)
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.AdGroupsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdGroupsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -94,7 +94,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "adgroups", "delete") .CreateRequest(request, HttpMethod.Post, "adgroups", "delete")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdGroupsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdGroupsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "ads", "add") .CreateRequest(request, HttpMethod.Post, "ads", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "ads", "update") .CreateRequest(request, HttpMethod.Post, "ads", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,19 +63,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "ads", "get") .CreateRequest(request, HttpMethod.Get, "ads", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.AdId != null) if (request.AdId is not null)
flurlReq.SetQueryParam("ad_id", request.AdId.Value); flurlReq.SetQueryParam("ad_id", request.AdId.Value);
if (request.Filters != null) if (request.Filters is not null)
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.AdsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -94,7 +94,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "ads", "delete") .CreateRequest(request, HttpMethod.Post, "ads", "delete")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "advertiser", "add") .CreateRequest(request, HttpMethod.Post, "advertiser", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdvertiserAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdvertiserAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "advertiser", "update") .CreateRequest(request, HttpMethod.Post, "advertiser", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdvertiserUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdvertiserUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,7 +63,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "advertiser", "get") .CreateRequest(request, HttpMethod.Get, "advertiser", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AdvertiserGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AdvertiserGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -26,7 +26,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "async_tasks", "add") .CreateRequest(request, HttpMethod.Post, "async_tasks", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.AsyncTasksAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AsyncTasksAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -45,16 +45,16 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "async_tasks", "get") .CreateRequest(request, HttpMethod.Get, "async_tasks", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.Filters != null && request.Filters.Any()) if (request.Filters is not null && request.Filters.Any())
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.AsyncTasksGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AsyncTasksGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
#region Files #region Files
@ -76,7 +76,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.SetQueryParam("task_id", request.TaskId) .SetQueryParam("task_id", request.TaskId)
.SetQueryParam("file_id", request.FileId); .SetQueryParam("file_id", request.FileId);
return await client.SendRequestWithJsonAsync<Models.AsyncTaskFilesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.AsyncTaskFilesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
#endregion #endregion
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "campaigns", "add") .CreateRequest(request, HttpMethod.Post, "campaigns", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CampaignsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CampaignsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "campaigns", "update") .CreateRequest(request, HttpMethod.Post, "campaigns", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CampaignsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CampaignsUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,19 +63,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "campaigns", "get") .CreateRequest(request, HttpMethod.Get, "campaigns", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.CampaignId != null) if (request.CampaignId is not null)
flurlReq.SetQueryParam("campaign_id", request.CampaignId.Value); flurlReq.SetQueryParam("campaign_id", request.CampaignId.Value);
if (request.Filters != null) if (request.Filters is not null)
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.CampaignsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CampaignsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -27,13 +27,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.SetQueryParam("bill_year", request.BillYear) .SetQueryParam("bill_year", request.BillYear)
.SetQueryParam("bill_month", request.BillMonth); .SetQueryParam("bill_month", request.BillMonth);
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.CreditBillsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CreditBillsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -26,7 +26,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "custom_audiences", "add") .CreateRequest(request, HttpMethod.Post, "custom_audiences", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CustomAudiencesAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CustomAudiencesAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -45,7 +45,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "custom_audiences", "update") .CreateRequest(request, HttpMethod.Post, "custom_audiences", "update")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.CustomAudiencesUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CustomAudiencesUpdateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -64,16 +64,16 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "custom_audiences", "get") .CreateRequest(request, HttpMethod.Get, "custom_audiences", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.CustomAudienceId != null) if (request.CustomAudienceId is not null)
flurlReq.SetQueryParam("audience_id", request.CustomAudienceId.Value); flurlReq.SetQueryParam("audience_id", request.CustomAudienceId.Value);
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.CustomAudiencesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CustomAudiencesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
#region Files #region Files
@ -104,7 +104,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "custom_audience_files", "add") .CreateRequest(request, HttpMethod.Post, "custom_audience_files", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestAsync<Models.CustomAudienceFilesAddResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsync<Models.CustomAudienceFilesAddResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -123,19 +123,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "custom_audience_files", "get") .CreateRequest(request, HttpMethod.Get, "custom_audience_files", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.CustomAudienceId != null) if (request.CustomAudienceId is not null)
flurlReq.SetQueryParam("audience_id", request.CustomAudienceId.Value); flurlReq.SetQueryParam("audience_id", request.CustomAudienceId.Value);
if (request.CustomAudienceFileId != null) if (request.CustomAudienceFileId is not null)
flurlReq.SetQueryParam("custom_audience_file_id", request.CustomAudienceFileId.Value); flurlReq.SetQueryParam("custom_audience_file_id", request.CustomAudienceFileId.Value);
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.CustomAudienceFilesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.CustomAudienceFilesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
#endregion #endregion
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "estimation", "get") .CreateRequest(request, HttpMethod.Post, "estimation", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.EstimationGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.EstimationGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "fund_transfer", "add") .CreateRequest(request, HttpMethod.Post, "fund_transfer", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.FundTransferAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.FundTransferAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "funds", "get") .CreateRequest(request, HttpMethod.Get, "funds", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.FundsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.FundsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,19 +63,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "fund_statements_detailed", "get") .CreateRequest(request, HttpMethod.Get, "fund_statements_detailed", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.DateRange != null) if (request.DateRange is not null)
flurlReq.SetQueryParam("date_range", client.JsonSerializer.Serialize(request.DateRange)); flurlReq.SetQueryParam("date_range", client.JsonSerializer.Serialize(request.DateRange));
if (request.TradeType != null) if (request.TradeType is not null)
flurlReq.SetQueryParam("trade_type", request.TradeType); flurlReq.SetQueryParam("trade_type", request.TradeType);
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.FundStatementsDetailedGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.FundStatementsDetailedGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -23,17 +23,17 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
if (client is null) throw new ArgumentNullException(nameof(client)); if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request)); if (request is null) throw new ArgumentNullException(nameof(request));
if (request.FileName == null) if (request.FileName is null)
{ {
request.FileName = Guid.NewGuid().ToString("N").ToLower(); request.FileName = Guid.NewGuid().ToString("N").ToLower();
} }
if (request.FileContentType == null) if (request.FileContentType is null)
{ {
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png"; request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png";
} }
if (request.FileHash == null) if (request.FileHash is null)
{ {
request.FileHash = BitConverter.ToString(Utilities.MD5Utility.Hash(request.FileBytes ?? Array.Empty<byte>())).Replace("-", string.Empty); request.FileHash = BitConverter.ToString(Utilities.MD5Utility.Hash(request.FileBytes ?? Array.Empty<byte>())).Replace("-", string.Empty);
} }
@ -49,7 +49,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "images", "add") .CreateRequest(request, HttpMethod.Post, "images", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestAsync<Models.ImagesAddResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsync<Models.ImagesAddResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -68,19 +68,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "images", "get") .CreateRequest(request, HttpMethod.Get, "images", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.ImageId != null) if (request.ImageId is not null)
flurlReq.SetQueryParam("image_id", request.ImageId); flurlReq.SetQueryParam("image_id", request.ImageId);
if (request.Filters != null) if (request.Filters is not null)
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.ImagesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.ImagesGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "qualifications", "add") .CreateRequest(request, HttpMethod.Post, "qualifications", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.QualificationsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.QualificationsAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "qualifications", "get") .CreateRequest(request, HttpMethod.Get, "qualifications", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.QualificationsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.QualificationsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -63,7 +63,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "qualifications", "delete") .CreateRequest(request, HttpMethod.Post, "qualifications", "delete")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.QualificationsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.QualificationsDeleteResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -26,22 +26,22 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "daily_reports", "get") .CreateRequest(request, HttpMethod.Get, "daily_reports", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
if (request.DateRange != null) if (request.DateRange is not null)
flurlReq.SetQueryParam("date_range", client.JsonSerializer.Serialize(request.DateRange)); flurlReq.SetQueryParam("date_range", client.JsonSerializer.Serialize(request.DateRange));
if (request.ReportType != null) if (request.ReportType is not null)
flurlReq.SetQueryParam("report_type", request.ReportType); flurlReq.SetQueryParam("report_type", request.ReportType);
if (request.ReportLevel != null) if (request.ReportLevel is not null)
flurlReq.SetQueryParam("level", request.ReportLevel); flurlReq.SetQueryParam("level", request.ReportLevel);
if (request.PageSize != null) if (request.PageSize is not null)
flurlReq.SetQueryParam("page_size", request.PageSize.Value); flurlReq.SetQueryParam("page_size", request.PageSize.Value);
if (request.Page != null) if (request.Page is not null)
flurlReq.SetQueryParam("page", request.Page.Value); flurlReq.SetQueryParam("page", request.Page.Value);
return await client.SendRequestWithJsonAsync<Models.DailyReportsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.DailyReportsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -62,10 +62,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.SetQueryParam("date", request.DateString) .SetQueryParam("date", request.DateString)
.SetQueryParam("level", request.Level); .SetQueryParam("level", request.Level);
if (request.Filters != null && request.Filters.Any()) if (request.Filters is not null && request.Filters.Any())
flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters)); flurlReq.SetQueryParam("filtering", client.JsonSerializer.Serialize(request.Filters));
return await client.SendRequestWithJsonAsync<Models.RealtimeCostGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.RealtimeCostGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Post, "sp_entrustment", "add") .CreateRequest(request, HttpMethod.Post, "sp_entrustment", "add")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.SpEntrustmentAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.SpEntrustmentAddResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
/// <summary> /// <summary>
@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.CreateRequest(request, HttpMethod.Get, "sp_entrustment", "get") .CreateRequest(request, HttpMethod.Get, "sp_entrustment", "get")
.SetQueryParam("access_token", request.AccessToken); .SetQueryParam("access_token", request.AccessToken);
return await client.SendRequestWithJsonAsync<Models.SpEntrustmentGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.SpEntrustmentGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -26,7 +26,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
.SetQueryParam("access_token", request.AccessToken) .SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("type", request.TagType); .SetQueryParam("type", request.TagType);
return await client.SendRequestWithJsonAsync<Models.TargetingTagsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken); return await client.SendFlurlRequestAsJsonAsync<Models.TargetingTagsGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
} }
} }
} }

View File

@ -1,12 +1,13 @@
using System; using System;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Flurl; using Flurl;
using Flurl.Http; using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors
{ {
internal class WechatAdsRequestAgencyTokenInterceptor : FlurlHttpCallInterceptor internal class WechatAdsRequestAgencyTokenInterceptor : HttpInterceptor
{ {
private readonly string _agencyId; private readonly string _agencyId;
private readonly string _agencyApiKey; private readonly string _agencyApiKey;
@ -17,18 +18,17 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors
_agencyApiKey = agencyApiKey; _agencyApiKey = agencyApiKey;
} }
public override async Task BeforeCallAsync(FlurlCall flurlCall) public override async Task BeforeCallAsync(HttpInterceptorContext context, CancellationToken cancellationToken = default)
{ {
if (flurlCall == null) throw new ArgumentNullException(nameof(flurlCall)); if (context is null) throw new ArgumentNullException(nameof(context));
if (flurlCall.Completed) throw new Exceptions.WechatAdsRequestAgencyTokenException("This interceptor must be called before request completed."); if (context.FlurlCall.Completed) throw new WechatAdsException("Failed to sign request. This interceptor must be called before request completed.");
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString(); string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N"); string nonce = Guid.NewGuid().ToString("N");
string sign = Utilities.MD5Utility.Hash($"{_agencyId}{timestamp}{nonce}{_agencyApiKey}").ToLower(); string sign = Utilities.MD5Utility.Hash($"{_agencyId}{timestamp}{nonce}{_agencyApiKey}").ToLower();
string token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_agencyId},{timestamp},{nonce},{sign}")); string token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_agencyId},{timestamp},{nonce},{sign}"));
flurlCall.Request.RemoveQueryParam("agency_token"); context.FlurlCall.Request.SetQueryParam("agency_token", token);
flurlCall.Request.SetQueryParam("agency_token", token);
await Task.Yield(); await Task.Yield();
} }

View File

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Models namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
{ {
@ -24,14 +24,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("longitude")] [Newtonsoft.Json.JsonProperty("longitude")]
[System.Text.Json.Serialization.JsonPropertyName("longitude")] [System.Text.Json.Serialization.JsonPropertyName("longitude")]
public double Longitude { get; set; } public decimal Longitude { get; set; }
/// <summary> /// <summary>
/// 获取或设置纬度。 /// 获取或设置纬度。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("latitude")] [Newtonsoft.Json.JsonProperty("latitude")]
[System.Text.Json.Serialization.JsonPropertyName("latitude")] [System.Text.Json.Serialization.JsonPropertyName("latitude")]
public double Latitude { get; set; } public decimal Latitude { get; set; }
/// <summary> /// <summary>
/// 获取或设置半径(单位:米)。 /// 获取或设置半径(单位:米)。

View File

@ -30,14 +30,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("longitude")] [Newtonsoft.Json.JsonProperty("longitude")]
[System.Text.Json.Serialization.JsonPropertyName("longitude")] [System.Text.Json.Serialization.JsonPropertyName("longitude")]
public double Longitude { get; set; } public decimal Longitude { get; set; }
/// <summary> /// <summary>
/// 获取或设置纬度。 /// 获取或设置纬度。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("latitude")] [Newtonsoft.Json.JsonProperty("latitude")]
[System.Text.Json.Serialization.JsonPropertyName("latitude")] [System.Text.Json.Serialization.JsonPropertyName("latitude")]
public double Latitude { get; set; } public decimal Latitude { get; set; }
/// <summary> /// <summary>
/// 获取或设置半径(单位:米)。 /// 获取或设置半径(单位:米)。

View File

@ -60,7 +60,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("budget_reach_date")] [Newtonsoft.Json.JsonProperty("budget_reach_date")]
[System.Text.Json.Serialization.JsonPropertyName("budget_reach_date")] [System.Text.Json.Serialization.JsonPropertyName("budget_reach_date")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalStringConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalStringConverter))]
public string? BudgetReachDateString { get; set; } public string? BudgetReachDateString { get; set; }
/// <summary> /// <summary>

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Models.Abstractions namespace SKIT.FlurlHttpClient.Wechat.Ads.Models.Abstractions
{ {
public abstract class CommonFilter public abstract class CommonFilter
@ -29,6 +31,6 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models.Abstractions
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("values")] [Newtonsoft.Json.JsonProperty("values")]
[System.Text.Json.Serialization.JsonPropertyName("values")] [System.Text.Json.Serialization.JsonPropertyName("values")]
public string[] Values { get; set; } = new string[0]; public IList<string> Values { get; set; } = new List<string>();
} }
} }

View File

@ -68,18 +68,18 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
/// 获取或设置最近修改时间戳。 /// 获取或设置最近修改时间戳。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("last_modified_time")] [Newtonsoft.Json.JsonProperty("last_modified_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularDateTimeOffsetConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.BasicDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("last_modified_time")] [System.Text.Json.Serialization.JsonPropertyName("last_modified_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularDateTimeOffsetConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.BasicDateTimeOffsetConverter))]
public DateTimeOffset UpdateTime { get; set; } public DateTimeOffset UpdateTime { get; set; }
/// <summary> /// <summary>
/// 获取或设置创建时间戳。 /// 获取或设置创建时间戳。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("created_time")] [Newtonsoft.Json.JsonProperty("created_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularDateTimeOffsetConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.BasicDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("created_time")] [System.Text.Json.Serialization.JsonPropertyName("created_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularDateTimeOffsetConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.BasicDateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; } public DateTimeOffset CreateTime { get; set; }
} }

View File

@ -96,9 +96,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Models
/// 获取或设置创建时间戳。 /// 获取或设置创建时间戳。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("created_time")] [Newtonsoft.Json.JsonProperty("created_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularDateTimeOffsetConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.BasicDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("created_time")] [System.Text.Json.Serialization.JsonPropertyName("created_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularDateTimeOffsetConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.BasicDateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; } public DateTimeOffset CreateTime { get; set; }
} }

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net6.0</TargetFrameworks> <TargetFrameworks>net461; netstandard2.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion> <LangVersion>10.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes> <NullableReferenceTypes>true</NullableReferenceTypes>
</PropertyGroup> </PropertyGroup>
@ -14,7 +14,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl> <PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
<PackageTags>Flurl.Http Wechat Weixin MicroMessage WechatAds WechatAdvertisting 微信 广告平台 微信广告平台 腾讯广告平台 广点通 微信广点通 腾讯广点通</PackageTags> <PackageTags>Flurl.Http Wechat Weixin MicroMessage WechatAds WechatAdvertisting 微信 广告平台 微信广告平台 腾讯广告平台 广点通 微信广点通 腾讯广点通</PackageTags>
<Version>2.0.0</Version> <Version>3.0.0-preview.1</Version>
<Description>基于 Flurl.Http 的微信广告平台广点通API 客户端。</Description> <Description>基于 Flurl.Http 的微信广告平台广点通API 客户端。</Description>
<Authors>Fu Diwei</Authors> <Authors>Fu Diwei</Authors>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
@ -40,7 +40,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.6.0" /> <PackageReference Include="SKIT.FlurlHttpClient.Common" Version="3.0.0-preview.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
using System; using System;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Settings namespace SKIT.FlurlHttpClient.Wechat.Ads.Settings
{ {
@ -21,7 +21,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Settings
internal Credentials(WechatAdsClientOptions options) internal Credentials(WechatAdsClientOptions options)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); if (options is null) throw new ArgumentNullException(nameof(options));
AgencyId = options.AgencyId; AgencyId = options.AgencyId;
AgencyAppId = options.AgencyAppId; AgencyAppId = options.AgencyAppId;

View File

@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Utilities
/// <returns>信息摘要字节数组。</returns> /// <returns>信息摘要字节数组。</returns>
public static byte[] Hash(byte[] bytes) public static byte[] Hash(byte[] bytes)
{ {
if (bytes == null) throw new ArgumentNullException(nameof(bytes)); if (bytes is null) throw new ArgumentNullException(nameof(bytes));
using MD5 md5 = MD5.Create(); using MD5 md5 = MD5.Create();
return md5.ComputeHash(bytes); return md5.ComputeHash(bytes);
@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Utilities
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>
public static string Hash(string message) public static string Hash(string message)
{ {
if (message == null) throw new ArgumentNullException(nameof(message)); if (message is null) throw new ArgumentNullException(nameof(message));
byte[] msgBytes = Encoding.UTF8.GetBytes(message); byte[] msgBytes = Encoding.UTF8.GetBytes(message);
byte[] hashBytes = Hash(msgBytes); byte[] hashBytes = Hash(msgBytes);

View File

@ -21,14 +21,25 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// </summary> /// </summary>
/// <param name="options">配置项。</param> /// <param name="options">配置项。</param>
public WechatAdsClient(WechatAdsClientOptions options) public WechatAdsClient(WechatAdsClientOptions options)
: base() : this(options, null)
{ {
if (options == null) throw new ArgumentNullException(nameof(options)); }
/// <summary>
///
/// </summary>
/// <param name="options"></param>
/// <param name="httpClient"></param>
/// <param name="disposeClient"></param>
internal protected WechatAdsClient(WechatAdsClientOptions options, HttpClient? httpClient, bool disposeClient = true)
: base(httpClient, disposeClient)
{
if (options is null) throw new ArgumentNullException(nameof(options));
Credentials = new Settings.Credentials(options); Credentials = new Settings.Credentials(options);
FlurlClient.BaseUrl = options.Endpoint ?? WechatAdsEndpoints.DEFAULT; FlurlClient.BaseUrl = options.Endpoint ?? WechatAdsEndpoints.DEFAULT;
FlurlClient.WithTimeout(TimeSpan.FromMilliseconds(options.Timeout)); FlurlClient.WithTimeout(options.Timeout <= 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(options.Timeout));
Interceptors.Add(new Interceptors.WechatAdsRequestAgencyTokenInterceptor( Interceptors.Add(new Interceptors.WechatAdsRequestAgencyTokenInterceptor(
agencyId: options.AgencyId, agencyId: options.AgencyId,
@ -36,34 +47,18 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
)); ));
} }
/// <summary>
/// 用指定的微信广告平台服务商 ID、微信广告平台服务商 AppId、微信广告平台服务商 ApiKey 初始化 <see cref="WechatAdsClient"/> 类的新实例。
/// </summary>
/// <param name="agencyId">微信广告平台服务商 ID。</param>
/// <param name="agencyAppId">微信广告平台服务商 AppId。</param>
/// <param name="agencyApiKey">微信广告平台服务商 ApiKey。</param>
public WechatAdsClient(string agencyId, string agencyAppId, string agencyApiKey)
: this(new WechatAdsClientOptions() { AgencyId = agencyId, AgencyAppId = agencyAppId, AgencyApiKey = agencyApiKey })
{
}
/// <summary> /// <summary>
/// 使用当前客户端生成一个新的 <see cref="IFlurlRequest"/> 对象。 /// 使用当前客户端生成一个新的 <see cref="IFlurlRequest"/> 对象。
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="method"></param> /// <param name="httpMethod"></param>
/// <param name="urlSegments"></param> /// <param name="urlSegments"></param>
/// <returns></returns> /// <returns></returns>
public IFlurlRequest CreateRequest(WechatAdsRequest request, HttpMethod method, params object[] urlSegments) public IFlurlRequest CreateRequest(WechatAdsRequest request, HttpMethod httpMethod, params object[] urlSegments)
{ {
IFlurlRequest flurlRequest = FlurlClient.Request(urlSegments).WithVerb(method); IFlurlRequest flurlRequest = base.CreateFlurlRequest(request, httpMethod, urlSegments);
if (request.Timeout != null) if (request.Version is not null)
{
flurlRequest.WithTimeout(TimeSpan.FromMilliseconds(request.Timeout.Value));
}
if (request.Version != null)
{ {
flurlRequest.SetQueryParam("version", request.Version); flurlRequest.SetQueryParam("version", request.Version);
} }
@ -79,24 +74,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// <param name="httpContent"></param> /// <param name="httpContent"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<T> SendRequestAsync<T>(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default) public async Task<T> SendFlurlRequestAsync<T>(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default)
where T : WechatAdsResponse, new() where T : WechatAdsResponse, new()
{ {
if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest)); if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest));
try using IFlurlResponse flurlResponse = await base.SendFlurlRequestAsync(flurlRequest, httpContent, cancellationToken);
{ return await base.WrapFlurlResponseAsJsonAsync<T>(flurlResponse, cancellationToken);
using IFlurlResponse flurlResponse = await base.SendRequestAsync(flurlRequest, httpContent, cancellationToken);
return await WrapResponseWithJsonAsync<T>(flurlResponse, cancellationToken);
}
catch (FlurlHttpTimeoutException ex)
{
throw new Exceptions.WechatAdsRequestTimeoutException(ex.Message, ex);
}
catch (FlurlHttpException ex)
{
throw new WechatAdsException(ex.Message, ex);
}
} }
/// <summary> /// <summary>
@ -107,30 +91,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<T> SendRequestWithJsonAsync<T>(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default) public async Task<T> SendFlurlRequestAsJsonAsync<T>(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default)
where T : WechatAdsResponse, new() where T : WechatAdsResponse, new()
{ {
if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest)); if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest));
try bool isSimpleRequest = data is null ||
{
bool isSimpleRequest = data == null ||
flurlRequest.Verb == HttpMethod.Get || flurlRequest.Verb == HttpMethod.Get ||
flurlRequest.Verb == HttpMethod.Head || flurlRequest.Verb == HttpMethod.Head ||
flurlRequest.Verb == HttpMethod.Options; flurlRequest.Verb == HttpMethod.Options;
using IFlurlResponse flurlResponse = isSimpleRequest ? using IFlurlResponse flurlResponse = isSimpleRequest ?
await base.SendRequestAsync(flurlRequest, null, cancellationToken) : await base.SendFlurlRequestAsync(flurlRequest, null, cancellationToken) :
await base.SendRequestWithJsonAsync(flurlRequest, data, cancellationToken); await base.SendFlurlRequestAsJsonAsync(flurlRequest, data, cancellationToken);
return await WrapResponseWithJsonAsync<T>(flurlResponse, cancellationToken); return await base.WrapFlurlResponseAsJsonAsync<T>(flurlResponse, cancellationToken);
}
catch (FlurlHttpTimeoutException ex)
{
throw new Exceptions.WechatAdsRequestTimeoutException(ex.Message, ex);
}
catch (FlurlHttpException ex)
{
throw new WechatAdsException(ex.Message, ex);
}
} }
} }
} }

View File

@ -7,13 +7,17 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
{ {
/// <summary> /// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。 /// 获取或设置请求超时时间(单位:毫秒)。
/// <para>默认值30000</para> /// <para>
/// 默认值30000
/// </para>
/// </summary> /// </summary>
public int Timeout { get; set; } = 30 * 1000; public int Timeout { get; set; } = 30 * 1000;
/// <summary> /// <summary>
/// 获取或设置微信广告平台 API 入口点。 /// 获取或设置微信广告平台 API 入口点。
/// <para>默认值:<see cref="WechatAdsEndpoints.DEFAULT"/></para> /// <para>
/// 默认值:<see cref="WechatAdsEndpoints.DEFAULT"/>
/// </para>
/// </summary> /// </summary>
public string Endpoint { get; set; } = WechatAdsEndpoints.DEFAULT; public string Endpoint { get; set; } = WechatAdsEndpoints.DEFAULT;

View File

@ -1,11 +1,11 @@
using System; using System;
namespace SKIT.FlurlHttpClient.Wechat.Ads namespace SKIT.FlurlHttpClient.Wechat.Ads
{ {
/// <summary> /// <summary>
/// 微信广告平台 API 出错时引发的异常。 /// 微信广告平台 API 出错时引发的异常。
/// </summary> /// </summary>
public class WechatAdsException : CommonExceptionBase public class WechatAdsException : CommonException
{ {
/// <inheritdoc/> /// <inheritdoc/>
public WechatAdsException() public WechatAdsException()

View File

@ -3,15 +3,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// <summary> /// <summary>
/// 微信广告平台 API 请求的基类。 /// 微信广告平台 API 请求的基类。
/// </summary> /// </summary>
public abstract class WechatAdsRequest : ICommonRequest public abstract class WechatAdsRequest : CommonRequestBase, ICommonRequest
{ {
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatAdsClient"/> 时的 <see cref="WechatAdsClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public virtual int? Timeout { get; set; }
/// <summary> /// <summary>
/// 获取或设置微信广告平台的 AccessToken。 /// 获取或设置微信广告平台的 AccessToken。
/// </summary> /// </summary>
@ -21,7 +14,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// <summary> /// <summary>
/// 获取或设置微信广告平台的版本号。 /// 获取或设置微信广告平台的版本号。
/// <para>默认值:"v1.0"</para> /// <para>
/// 默认值:"v1.0"
/// </para>
/// </summary> /// </summary>
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]

View File

@ -1,60 +1,10 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Ads namespace SKIT.FlurlHttpClient.Wechat.Ads
{ {
/// <summary> /// <summary>
/// 微信广告平台 API 响应的基类。 /// 微信广告平台 API 响应的基类。
/// </summary> /// </summary>
public abstract class WechatAdsResponse : ICommonResponse public abstract class WechatAdsResponse : CommonResponseBase, ICommonResponse
{ {
/// <summary>
///
/// </summary>
int ICommonResponse.RawStatus { get; set; }
/// <summary>
///
/// </summary>
IDictionary<string, string> ICommonResponse.RawHeaders { get; set; } = default!;
/// <summary>
///
/// </summary>
byte[] ICommonResponse.RawBytes { get; set; } = default!;
/// <summary>
/// 获取原始的 HTTP 响应状态码。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public int RawStatus
{
get { return ((ICommonResponse)this).RawStatus; }
internal set { ((ICommonResponse)this).RawStatus = value; }
}
/// <summary>
/// 获取原始的 HTTP 响应表头集合。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public IDictionary<string, string> RawHeaders
{
get { return ((ICommonResponse)this).RawHeaders; }
internal set { ((ICommonResponse)this).RawHeaders = value; }
}
/// <summary>
/// 获取原始的 HTTP 响应正文。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public byte[] RawBytes
{
get { return ((ICommonResponse)this).RawBytes; }
internal set { ((ICommonResponse)this).RawBytes = value; }
}
/// <summary> /// <summary>
/// 获取微信广告平台 API 返回的错误码。 /// 获取微信广告平台 API 返回的错误码。
/// </summary> /// </summary>
@ -70,12 +20,15 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
public virtual string? ErrorMessage { get; set; } public virtual string? ErrorMessage { get; set; }
/// <summary> /// <summary>
/// 获取一个值,该值指示调用微信广告平台 API 是否成功(即 HTTP 状态码为 200、且 errcode 值为 0 /// 获取一个值,该值指示调用微信广告平台 API 是否成功。
/// <para>
///(即 HTTP 状态码为 200且 <see cref="ErrorCode"/> 值为 0
/// </para>
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public virtual bool IsSuccessful() public override bool IsSuccessful()
{ {
return RawStatus == 200 && ErrorCode == 0; return GetRawStatus() == 200 && ErrorCode == 0;
} }
} }
} }

View File

@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Reflection;
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Ads.UnitTests
{
public class CodeAnalyzeTests
{
[Fact(DisplayName = "代码质量分析")]
public void TestCodeAnalyzer()
{
Assert.Null(Record.Exception(() =>
{
var options = new TypeDeclarationAnalyzerOptions()
{
SdkAssembly = Assembly.GetAssembly(typeof(WechatAdsClient))!,
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Ads.Models",
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Ads.Models",
SdkExecutingExtensionDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Ads",
ThrowOnNotFoundRequestModelTypes = true,
ThrowOnNotFoundResponseModelTypes = true,
ThrowOnNotFoundExecutingExtensionTypes = true
};
new TypeDeclarationAnalyzer(options).AssertNoIssues();
}));
Assert.Null(Record.Exception(() =>
{
string workdir = Environment.CurrentDirectory;
string projdir = Path.Combine(workdir, "../../../../../");
var options = new SourceFileAnalyzerOptions()
{
SdkAssembly = Assembly.GetAssembly(typeof(WechatAdsClient))!,
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Ads.Models",
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.Ads.Models",
ProjectSourceRootDirectory = Path.Combine(projdir, "./src/SKIT.FlurlHttpClient.Wechat.Ads/"),
ProjectTestRootDirectory = Path.Combine(projdir, "./test/SKIT.FlurlHttpClient.Wechat.Ads.UnitTests/"),
ThrowOnNotFoundRequestModelClassCodeFiles = true,
ThrowOnNotFoundResponseModelClassCodeFiles = true,
ThrowOnNotFoundExecutingExtensionClassCodeFiles = true,
ThrowOnNotFoundRequestModelSerializationSampleFiles = true,
ThrowOnNotFoundResponseModelSerializationSampleFiles = true
};
new SourceFileAnalyzer(options).AssertNoIssues();
}));
}
}
}

View File

@ -11,21 +11,21 @@
<ItemGroup> <ItemGroup>
<None Remove=".gitignore" /> <None Remove=".gitignore" />
<Content Include="appsettings.json"> <Content Include="appsettings.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</Content>
<Content Include="ModelSamples/**/*.json" /> <Content Include="ModelSamples/**/*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.1.0-alpha.1" /> <PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.3.0-preview.1" />
<PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View File

@ -1,28 +0,0 @@
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Ads.UnitTests
{
public class TestCase_CodeReview
{
[Fact(DisplayName = "测试用例:代码质量分析")]
public void TestCodeAnalyzer()
{
Assert.Null(Record.Exception(() =>
{
CodeAnalyzerOptions options = new CodeAnalyzerOptions()
{
AssemblyName = "SKIT.FlurlHttpClient.Wechat.Ads",
WorkDirectoryForSourceCode = TestConfigs.WorkDirectoryForSdk,
WorkDirectoryForTestSample = TestConfigs.WorkDirectoryForTest,
AllowNotFoundEventTypes = true,
AllowNotFoundEventSamples = true
};
CodeAnalyzer analyzer = new CodeAnalyzer(options);
analyzer.Start();
analyzer.Assert();
analyzer.Flush();
}));
}
}
}

View File

@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
@ -17,14 +17,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.UnitTests
using var stream = File.OpenRead("appsettings.local.json"); using var stream = File.OpenRead("appsettings.local.json");
using var jdoc = JsonDocument.Parse(stream); using var jdoc = JsonDocument.Parse(stream);
var config = jdoc.RootElement.GetProperty("TestConfig"); var config = jdoc.RootElement.GetProperty("TestConfigs");
WechatAgencyId = config.GetProperty("AgencyId").GetString()!; WechatAgencyId = config.GetProperty("AgencyId").GetString()!;
WechatAgencyAppId = config.GetProperty("AgencyAppId").GetString()!; WechatAgencyAppId = config.GetProperty("AgencyAppId").GetString()!;
WechatAgencyApiKey = config.GetProperty("AgencyApiKey").GetString()!; WechatAgencyApiKey = config.GetProperty("AgencyApiKey").GetString()!;
WechatAccessToken = config.GetProperty("AccessToken").GetString()!; WechatAccessToken = config.GetProperty("AccessToken").GetString()!;
WorkDirectoryForSdk = jdoc.RootElement.GetProperty("WorkDirectoryForSdk").GetString()!;
WorkDirectoryForTest = jdoc.RootElement.GetProperty("WorkDirectoryForTest").GetString()!;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -36,8 +33,5 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.UnitTests
public static readonly string WechatAgencyAppId; public static readonly string WechatAgencyAppId;
public static readonly string WechatAgencyApiKey; public static readonly string WechatAgencyApiKey;
public static readonly string WechatAccessToken; public static readonly string WechatAccessToken;
public static readonly string WorkDirectoryForSdk;
public static readonly string WorkDirectoryForTest;
} }
} }

View File

@ -1,10 +1,8 @@
{ {
"TestConfig": { "TestConfigs": {
"AgencyId": "请在此填写用于测试的微信广告 AgencyId", "AgencyId": "请在此填写用于测试的微信广告 AgencyId",
"AgencyAppId": "请在此填写用于测试的微信广告 AgencyAppId", "AgencyAppId": "请在此填写用于测试的微信广告 AgencyAppId",
"AgencyApiKey": "请在此填写用于测试的微信广告 AgencyApiKey", "AgencyApiKey": "请在此填写用于测试的微信广告 AgencyApiKey",
"AccessToken": "请在此填写用于测试的微信广告 AccessToken" "AccessToken": "请在此填写用于测试的微信广告 AccessToken"
}, }
"WorkDirectoryForSdk": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.Ads\\",
"WorkDirectoryForTest": "请输入当前测试项目所在的目录完整路径,如 C:\\Project\\test\\SKIT.FlurlHttpClient.Wechat.Ads.UnitTests\\"
} }