mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-04-05 17:37:54 +08:00
feat(tenpaybusiness): 升级公共组件
This commit is contained in:
parent
fcc5e91510
commit
43eeb6fe6e
@ -66,9 +66,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events
|
||||
/// 获取或设置支付成功时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("pay_succ_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("pay_succ_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -71,18 +71,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events
|
||||
/// 获取或设置退款成功时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("succeeded_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置退款创建时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("created_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("created_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset CreateTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessEventVerificationException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessEventVerificationException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessEventVerificationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessEventVerificationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessRequestEncryptionException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestEncryptionException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestEncryptionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestEncryptionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessRequestSignatureException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestSignatureException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestSignatureException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestSignatureException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessRequestTimeoutException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestTimeoutException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestTimeoutException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessRequestTimeoutException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessResponseDecryptionException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseDecryptionException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseDecryptionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseDecryptionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Exceptions
|
||||
{
|
||||
public class WechatTenpayBusinessResponseVerificationException : WechatTenpayBusinessException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseVerificationException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseVerificationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatTenpayBusinessResponseVerificationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
{
|
||||
@ -8,11 +8,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>反序列化得到 <see cref="WechatTenpayBusinessEvent"/> 对象。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackJson"></param>
|
||||
/// <param name="webhookJson"></param>
|
||||
/// <returns></returns>
|
||||
public static WechatTenpayBusinessEvent DeserializeEvent(this WechatTenpayBusinessClient client, string callbackJson)
|
||||
public static WechatTenpayBusinessEvent DeserializeEvent(this WechatTenpayBusinessClient client, string webhookJson)
|
||||
{
|
||||
return DeserializeEvent<WechatTenpayBusinessEvent>(client, callbackJson);
|
||||
return DeserializeEvent<WechatTenpayBusinessEvent>(client, webhookJson);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -20,15 +20,15 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// </summary>
|
||||
/// <typeparam name="TEvent"></typeparam>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackJson"></param>
|
||||
/// <param name="webhookJson"></param>
|
||||
/// <returns></returns>
|
||||
public static TEvent DeserializeEvent<TEvent>(this WechatTenpayBusinessClient client, string callbackJson)
|
||||
public static TEvent DeserializeEvent<TEvent>(this WechatTenpayBusinessClient client, string webhookJson)
|
||||
where TEvent : WechatTenpayBusinessEvent
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (string.IsNullOrEmpty(callbackJson)) throw new ArgumentNullException(callbackJson);
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (webhookJson is null) throw new ArgumentNullException(webhookJson);
|
||||
|
||||
return client.JsonSerializer.Deserialize<TEvent>(callbackJson);
|
||||
return client.JsonSerializer.Deserialize<TEvent>(webhookJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,39 +8,37 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackAuthorization"></param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="webhookAuthorization"></param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackAuthorization, string callbackBody)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookAuthorization, string webhookBody)
|
||||
{
|
||||
return VerifyEventSignature(client, callbackAuthorization, callbackBody, out _);
|
||||
return VerifyEventSignature(client, webhookAuthorization, webhookBody, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackAuthorization"></param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="webhookAuthorization"></param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackAuthorization, string callbackBody, out Exception? error)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookAuthorization, string webhookBody, out Exception? error)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (callbackAuthorization == null) throw new ArgumentNullException(nameof(callbackAuthorization));
|
||||
if (callbackBody == null) throw new ArgumentNullException(nameof(callbackBody));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (webhookAuthorization is null) throw new ArgumentNullException(nameof(webhookAuthorization));
|
||||
if (webhookBody is null) throw new ArgumentNullException(nameof(webhookBody));
|
||||
|
||||
bool ret = WechatTenpayBusinessClientSignExtensions.VerifySignature(
|
||||
bool ret = WechatTenpayBusinessClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strAuthorization: callbackAuthorization,
|
||||
strContent: callbackBody,
|
||||
strAuthorization: webhookAuthorization,
|
||||
strContent: webhookBody,
|
||||
out error
|
||||
);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
error = new Exceptions.WechatTenpayBusinessEventVerificationException("Verify signature of event failed. Please see the inner exception for more details.", error);
|
||||
}
|
||||
if (!ret)
|
||||
error ??= new Exception($"Failed to verify webhook event. Maybe the raw signature is invalid.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -49,22 +47,22 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackTimestamp"></param>
|
||||
/// <param name="callbackNonce">。</param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="callbackSignature"></param>
|
||||
/// <param name="callbackSerialNumber"></param>
|
||||
/// <param name="webhookTimestamp"></param>
|
||||
/// <param name="webhookNonce">。</param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <param name="webhookSignature"></param>
|
||||
/// <param name="webhookSerialNumber"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSerialNumber)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSerialNumber)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
callbackTimestamp: callbackTimestamp,
|
||||
callbackNonce: callbackNonce,
|
||||
callbackBody: callbackBody,
|
||||
callbackSignature: callbackSignature,
|
||||
callbackSignatureAlgorithm: Constants.SignAlgorithms.SHA245_WITH_RSA,
|
||||
callbackSerialNumber: callbackSerialNumber,
|
||||
webhookTimestamp: webhookTimestamp,
|
||||
webhookNonce: webhookNonce,
|
||||
webhookBody: webhookBody,
|
||||
webhookSignature: webhookSignature,
|
||||
webhookSignatureAlgorithm: Constants.SignAlgorithms.SHA245_WITH_RSA,
|
||||
webhookSerialNumber: webhookSerialNumber,
|
||||
out _
|
||||
);
|
||||
}
|
||||
@ -73,23 +71,23 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackTimestamp"></param>
|
||||
/// <param name="callbackNonce">。</param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="callbackSignature"></param>
|
||||
/// <param name="callbackSignatureAlgorithm"></param>
|
||||
/// <param name="callbackSerialNumber"></param>
|
||||
/// <param name="webhookTimestamp"></param>
|
||||
/// <param name="webhookNonce">。</param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <param name="webhookSignature"></param>
|
||||
/// <param name="webhookSignatureAlgorithm"></param>
|
||||
/// <param name="webhookSerialNumber"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSignatureAlgorithm, string callbackSerialNumber)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSignatureAlgorithm, string webhookSerialNumber)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
callbackTimestamp: callbackTimestamp,
|
||||
callbackNonce: callbackNonce,
|
||||
callbackBody: callbackBody,
|
||||
callbackSignature: callbackSignature,
|
||||
callbackSignatureAlgorithm: callbackSignatureAlgorithm,
|
||||
callbackSerialNumber: callbackSerialNumber,
|
||||
webhookTimestamp: webhookTimestamp,
|
||||
webhookNonce: webhookNonce,
|
||||
webhookBody: webhookBody,
|
||||
webhookSignature: webhookSignature,
|
||||
webhookSignatureAlgorithm: webhookSignatureAlgorithm,
|
||||
webhookSerialNumber: webhookSerialNumber,
|
||||
out _
|
||||
);
|
||||
}
|
||||
@ -98,24 +96,24 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackTimestamp"></param>
|
||||
/// <param name="callbackNonce">。</param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="callbackSignature"></param>
|
||||
/// <param name="callbackSerialNumber"></param>
|
||||
/// <param name="webhookTimestamp"></param>
|
||||
/// <param name="webhookNonce">。</param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <param name="webhookSignature"></param>
|
||||
/// <param name="webhookSerialNumber"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSerialNumber, out Exception? error)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSerialNumber, out Exception? error)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
callbackTimestamp: callbackTimestamp,
|
||||
callbackNonce: callbackNonce,
|
||||
callbackBody: callbackBody,
|
||||
callbackSignature: callbackSignature,
|
||||
callbackSignatureAlgorithm: Constants.SignAlgorithms.SHA245_WITH_RSA,
|
||||
callbackSerialNumber: callbackSerialNumber,
|
||||
webhookTimestamp: webhookTimestamp,
|
||||
webhookNonce: webhookNonce,
|
||||
webhookBody: webhookBody,
|
||||
webhookSignature: webhookSignature,
|
||||
webhookSignatureAlgorithm: Constants.SignAlgorithms.SHA245_WITH_RSA,
|
||||
webhookSerialNumber: webhookSerialNumber,
|
||||
out error
|
||||
);
|
||||
}
|
||||
@ -124,34 +122,32 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackTimestamp"></param>
|
||||
/// <param name="callbackNonce">。</param>
|
||||
/// <param name="callbackBody"></param>
|
||||
/// <param name="callbackSignature"></param>
|
||||
/// <param name="callbackSignatureAlgorithm"></param>
|
||||
/// <param name="callbackSerialNumber"></param>
|
||||
/// <param name="webhookTimestamp"></param>
|
||||
/// <param name="webhookNonce">。</param>
|
||||
/// <param name="webhookBody"></param>
|
||||
/// <param name="webhookSignature"></param>
|
||||
/// <param name="webhookSignatureAlgorithm"></param>
|
||||
/// <param name="webhookSerialNumber"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSignatureAlgorithm, string callbackSerialNumber, out Exception? error)
|
||||
public static bool VerifyEventSignature(this WechatTenpayBusinessClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSignatureAlgorithm, string webhookSerialNumber, out Exception? error)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
bool ret = WechatTenpayBusinessClientSignExtensions.VerifySignature(
|
||||
bool ret = WechatTenpayBusinessClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strTimestamp: callbackTimestamp,
|
||||
strNonce: callbackNonce,
|
||||
strContent: callbackBody,
|
||||
strSignature: callbackSignature,
|
||||
strSignatureAlgorithm: callbackSignatureAlgorithm,
|
||||
strSerialNumber: callbackSerialNumber,
|
||||
strTimestamp: webhookTimestamp,
|
||||
strNonce: webhookNonce,
|
||||
strContent: webhookBody,
|
||||
strSignature: webhookSignature,
|
||||
strSignatureAlgorithm: webhookSignatureAlgorithm,
|
||||
strSerialNumber: webhookSerialNumber,
|
||||
out error
|
||||
);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
error = new Exceptions.WechatTenpayBusinessEventVerificationException("Verify signature of event failed. Please see the inner exception for more details.", error);
|
||||
}
|
||||
if (!ret)
|
||||
error ??= new Exception($"Failed to verify webhook event. Maybe the raw signature \"{webhookSignature}\" is invalid.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "bill-downloads");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "bill-downloads");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetBillResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetBillResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -41,9 +41,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "bill-downloads", "trans");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "bill-downloads", "trans");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetBillTransactionResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetBillTransactionResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -62,10 +62,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, request.DownloadUrl)
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, request.DownloadUrl)
|
||||
.WithUrl(request.DownloadUrl);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.DownloadBillFileResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.DownloadBillFileResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,20 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
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() + ".png";
|
||||
|
||||
if (request.FileHash == null)
|
||||
if (request.FileHash is null)
|
||||
request.FileHash = BitConverter.ToString(Utilities.SM3Utility.Hash(request.FileBytes)).Replace("-", string.Empty).ToLower();
|
||||
|
||||
if (request.FileContentType == null)
|
||||
if (request.FileContentType is null)
|
||||
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png";
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "file-uploads");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "file-uploads");
|
||||
|
||||
using var httpContent = Utilities.FileHttpContentBuilder.Build(fileName: request.FileName, fileBytes: request.FileBytes, fileContentType: request.FileContentType, fileMetaJson: client.JsonSerializer.Serialize(request));
|
||||
return await client.SendRequestAsync<Models.UploadFileResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsync<Models.UploadFileResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", "app-pay");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", "app-pay");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentAppPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentAppPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -42,9 +42,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", "app-registering-pay");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", "app-registering-pay");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentAppRegisteringPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentAppRegisteringPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -61,9 +61,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", "qrcode-pay");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", "qrcode-pay");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentQrcodePayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentQrcodePayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -80,9 +80,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", "h5-pay");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", "h5-pay");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentH5PayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentH5PayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -99,9 +99,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", "mp-pay");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", "mp-pay");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentMiniProgramPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentMiniProgramPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -121,9 +121,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "payments", request.PaymentId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "payments", request.PaymentId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetPaymentByPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetPaymentByPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -143,9 +143,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "payments", "out-payment-id", request.OutPaymentId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "payments", "out-payment-id", request.OutPaymentId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetPaymentByOutPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetPaymentByOutPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -165,9 +165,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "payments", request.PaymentId, "close");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "payments", request.PaymentId, "close");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.ClosePaymentResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.ClosePaymentResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -187,9 +187,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "redirects");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "redirects");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreatePaymentRedirectLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreatePaymentRedirectLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "product-applications");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "product-applications");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateProductApplicationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateProductApplicationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -41,9 +41,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "product-applications", request.RequestNumber);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "product-applications", request.RequestNumber);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProductApplicationByRequestNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProductApplicationByRequestNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -60,9 +60,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "product-applications", "out-request-no", request.OutRequestNumber);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "product-applications", "out-request-no", request.OutRequestNumber);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProductApplicationByOutRequestNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProductApplicationByOutRequestNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -79,9 +79,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "product-applications", request.RequestNumber, "links");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "product-applications", request.RequestNumber, "links");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateProductApplicationLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateProductApplicationLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.EnterpriseId == null)
|
||||
if (request.EnterpriseId is null)
|
||||
request.EnterpriseId = client.Credentials.EnterpriseId;
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateProfitAllocationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateProfitAllocationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -43,13 +43,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.EnterpriseId == null)
|
||||
if (request.EnterpriseId is null)
|
||||
request.EnterpriseId = client.Credentials.EnterpriseId;
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations", "finish");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations", "finish");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.SetProfitAllocationFinishedResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.SetProfitAllocationFinishedResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -66,9 +66,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", request.AllocationId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", request.AllocationId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProfitAllocationByAllocationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProfitAllocationByAllocationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -85,9 +85,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "out-allocation-id", request.OutAllocationId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "out-allocation-id", request.OutAllocationId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProfitAllocationByOutAllocationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProfitAllocationByOutAllocationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -104,9 +104,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", request.PaymentId, "amounts");
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", request.PaymentId, "amounts");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProfitAllocationAmountByPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProfitAllocationAmountByPaymentIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
#region ReceiverAccount
|
||||
@ -123,18 +123,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.EnterpriseId == null)
|
||||
if (request.EnterpriseId is null)
|
||||
request.EnterpriseId = client.Credentials.EnterpriseId;
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts")
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts")
|
||||
.SetQueryParam("ent_id", request.EnterpriseId);
|
||||
|
||||
if (request.UnifiedSocialCreditCode != null)
|
||||
if (request.UnifiedSocialCreditCode is not null)
|
||||
flurlReq.SetQueryParam("unified_social_credit_code", request.UnifiedSocialCreditCode);
|
||||
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.QueryProfitAllocationReceiverAccountsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.QueryProfitAllocationReceiverAccountsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -150,13 +150,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.EnterpriseId == null)
|
||||
if (request.EnterpriseId is null)
|
||||
request.EnterpriseId = client.Credentials.EnterpriseId;
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations", "receiver-accounts-applications");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "profit-allocations", "receiver-accounts-applications");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateProfitAllocationReceiverAccountApplicationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateProfitAllocationReceiverAccountApplicationResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -173,9 +173,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts-applications", request.ApplicationId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts-applications", request.ApplicationId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProfitAllocationReceiverAccountApplicationByApplicationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProfitAllocationReceiverAccountApplicationByApplicationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -192,9 +192,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts-applications", "out_application_id", request.OutApplicationId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "profit-allocations", "receiver-accounts-applications", "out_application_id", request.OutApplicationId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetProfitAllocationReceiverAccountApplicationByOutApplicationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetProfitAllocationReceiverAccountApplicationByOutApplicationIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "refunds");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "refunds");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateRefundResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateRefundResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -41,9 +41,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "refunds", "refund-id", request.RefundId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "refunds", "refund-id", request.RefundId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetRefundByRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetRefundByRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -60,9 +60,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "refunds", "out-refund-id", request.OutRefundId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "refunds", "out-refund-id", request.OutRefundId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetRefundByOutRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetRefundByOutRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
if (request.EnterpriseId == null)
|
||||
if (request.EnterpriseId is null)
|
||||
request.EnterpriseId = client.Credentials.EnterpriseId;
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "mse-pay", "withdraws");
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "mse-pay", "withdraws");
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.CreateWithdrawResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.CreateWithdrawResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -43,9 +43,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "withdraws", request.WithdrawId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "withdraws", request.WithdrawId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetWithdrawByWithdrawIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetWithdrawByWithdrawIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -61,9 +61,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Get, "mse-pay", "withdraws", "out-withdraw-id", request.OutWithdrawId);
|
||||
.CreateFlurlRequest(request, HttpMethod.Get, "mse-pay", "withdraws", "out-withdraw-id", request.OutWithdrawId);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<Models.GetWithdrawByOutWithdrawIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetWithdrawByOutWithdrawIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,32 +15,32 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
public static TRequest EncryptRequestSensitiveProperty<TRequest>(this WechatTenpayBusinessClient client, TRequest request)
|
||||
where TRequest : WechatTenpayBusinessRequest
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (request == null) throw new ArgumentNullException(nameof(request));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
try
|
||||
{
|
||||
bool requireEncrypt = request.GetType().GetCustomAttributes<WechatTenpayBusinessSensitiveAttribute>(inherit: true).Any();
|
||||
if (requireEncrypt)
|
||||
{
|
||||
if (request.Encryption is null)
|
||||
request.Encryption = new WechatTenpayBusinessRequestEncryption() { Algorithm = client.Credentials.SensitivePropertyEncryptionAlgorithm };
|
||||
if (request.WechatpayEncryption is null)
|
||||
request.WechatpayEncryption = new WechatTenpayBusinessRequestEncryption() { Algorithm = client.Credentials.SensitivePropertyEncryptionAlgorithm };
|
||||
|
||||
if (Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC.Equals(request.Encryption.Algorithm))
|
||||
if (Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC.Equals(request.WechatpayEncryption.Algorithm))
|
||||
{
|
||||
Utilities.ReflectionUtility.ReplacePropertyStringValue(ref request, (target, currentProp, oldValue) =>
|
||||
{
|
||||
var attr = currentProp.GetCustomAttribute<WechatTenpayBusinessSensitivePropertyAttribute>();
|
||||
if (attr == null)
|
||||
if (attr is null)
|
||||
return (false, oldValue);
|
||||
|
||||
string sm4IV = client.Credentials.SensitivePropertyEncryptionSM4IV!;
|
||||
string sm4Key = client.Credentials.SensitivePropertyEncryptionSM4Key!;
|
||||
string sm4EncryptedKey = Utilities.RSAUtility.EncryptWithECB(publicKey: client.Credentials.TBEPCertificatePublicKey, plainText: sm4Key);
|
||||
|
||||
request.Encryption.SerialNumber = client.Credentials.TBEPCertificateSerialNumber;
|
||||
request.Encryption.EncryptedKey = sm4EncryptedKey;
|
||||
request.Encryption.IV = sm4IV;
|
||||
request.WechatpayEncryption.SerialNumber = client.Credentials.TBEPCertificateSerialNumber;
|
||||
request.WechatpayEncryption.EncryptedKey = sm4EncryptedKey;
|
||||
request.WechatpayEncryption.IV = sm4IV;
|
||||
|
||||
string newValue = Utilities.SM4Utility.EncryptWithCBC(key: sm4Key, iv: sm4IV, plainText: oldValue);
|
||||
return (true, newValue);
|
||||
@ -48,13 +48,17 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Unsupported encryption algorithm.");
|
||||
throw new WechatTenpayBusinessException($"Failed to encrypt request. Unsupported encryption algorithm: \"{request.WechatpayEncryption.Algorithm}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Exceptions.WechatTenpayBusinessRequestEncryptionException))
|
||||
catch (WechatTenpayBusinessException)
|
||||
{
|
||||
throw new Exceptions.WechatTenpayBusinessRequestEncryptionException("Failed to encrypt request. Please see the inner exception for more details.", ex);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new WechatTenpayBusinessException("Failed to encrypt request. Please see the inner exception for more details.", ex);
|
||||
}
|
||||
|
||||
return request;
|
||||
|
@ -15,40 +15,40 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
public static TResponse DecryptResponseSensitiveProperty<TResponse>(this WechatTenpayBusinessClient client, TResponse response)
|
||||
where TResponse : WechatTenpayBusinessResponse
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (response == null) throw new ArgumentNullException(nameof(response));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
if (response is null) throw new ArgumentNullException(nameof(response));
|
||||
|
||||
if (!response.IsSuccessful())
|
||||
throw new Exceptions.WechatTenpayBusinessResponseDecryptionException("Failed to decrypt response, because the response is not successful.");
|
||||
throw new WechatTenpayBusinessException("Failed to decrypt response, because the response is not successful.");
|
||||
|
||||
try
|
||||
{
|
||||
bool requireDecrypt = response.GetType().GetCustomAttributes<WechatTenpayBusinessSensitiveAttribute>(inherit: true).Any();
|
||||
if (requireDecrypt)
|
||||
{
|
||||
if (response.Encryption is null)
|
||||
throw new InvalidOperationException("Could not read value of 'TBEP-Encrypt'.");
|
||||
if (response.Encryption.PlatformId != null && response.Encryption.SerialNumber != client.Credentials.PlatformCertificateSerialNumber)
|
||||
throw new Exceptions.WechatTenpayBusinessResponseDecryptionException("Failed to decrypt response, because the platform certificate serial number does not match.");
|
||||
if (response.Encryption.EnterpriseId != null && response.Encryption.SerialNumber != client.Credentials.EnterpriseCertificateSerialNumber)
|
||||
throw new Exceptions.WechatTenpayBusinessResponseDecryptionException("Failed to decrypt response, because the enterprise certificate serial number does not match.");
|
||||
if (response.WechatpayEncryption is null)
|
||||
throw new InvalidOperationException("Failed to decrypt response, because the value of \"TBEP-Encrypt\" is empty.");
|
||||
if (response.WechatpayEncryption.PlatformId is not null && response.WechatpayEncryption.SerialNumber != client.Credentials.PlatformCertificateSerialNumber)
|
||||
throw new WechatTenpayBusinessException($"Failed to decrypt response, because the platform certificate with serial number \"{response.WechatpayEncryption.SerialNumber}\" does not existed.");
|
||||
if (response.WechatpayEncryption.EnterpriseId is not null && response.WechatpayEncryption.SerialNumber != client.Credentials.EnterpriseCertificateSerialNumber)
|
||||
throw new WechatTenpayBusinessException($"Failed to decrypt response, because the enterprise certificate serial number \"{response.WechatpayEncryption.SerialNumber}\" does not existed.");
|
||||
|
||||
if (Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC.Equals(response.Encryption.Algorithm))
|
||||
if (Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC.Equals(response.WechatpayEncryption.Algorithm))
|
||||
{
|
||||
Utilities.ReflectionUtility.ReplacePropertyStringValue(ref response, (target, currentProp, oldValue) =>
|
||||
{
|
||||
var attr = currentProp.GetCustomAttribute<WechatTenpayBusinessSensitivePropertyAttribute>();
|
||||
if (attr == null)
|
||||
if (attr is null)
|
||||
return (false, oldValue);
|
||||
|
||||
string sm4EncryptedKey = response.Encryption.EncryptedKey!;
|
||||
string sm4EncryptedKey = response.WechatpayEncryption.EncryptedKey!;
|
||||
string sm4Key = Utilities.RSAUtility.DecryptWithECB(
|
||||
privateKey: response.Encryption.PlatformId != null ? client.Credentials.PlatformCertificatePrivateKey! :
|
||||
response.Encryption.EnterpriseId != null ? client.Credentials.EnterpriseCertificatePrivateKey! :
|
||||
privateKey: response.WechatpayEncryption.PlatformId is not null ? client.Credentials.PlatformCertificatePrivateKey! :
|
||||
response.WechatpayEncryption.EnterpriseId is not null ? client.Credentials.EnterpriseCertificatePrivateKey! :
|
||||
string.Empty,
|
||||
cipherText: sm4EncryptedKey
|
||||
);
|
||||
string sm4IV = response.Encryption.IV!;
|
||||
string sm4IV = response.WechatpayEncryption.IV!;
|
||||
|
||||
string newValue = Utilities.SM4Utility.DecryptWithCBC(key: sm4Key, iv: sm4IV, cipherText: oldValue);
|
||||
return (true, newValue);
|
||||
@ -56,13 +56,17 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Unsupported decryption algorithm.");
|
||||
throw new WechatTenpayBusinessException($"Failed to decrypt response. Unsupported encryption algorithm: \"{response.WechatpayEncryption.Algorithm}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Exceptions.WechatTenpayBusinessResponseDecryptionException))
|
||||
catch (WechatTenpayBusinessException)
|
||||
{
|
||||
throw new Exceptions.WechatTenpayBusinessResponseDecryptionException("Failed to decrypt response. Please see the inner exception for more details.", ex);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new WechatTenpayBusinessException("Failed to decrypt response. Please see the inner exception for more details.", ex);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
@ -30,18 +30,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
public static bool VerifyResponseSignature<TResponse>(this WechatTenpayBusinessClient client, TResponse response, out Exception? error)
|
||||
where TResponse : WechatTenpayBusinessResponse
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
bool ret = WechatTenpayBusinessClientSignExtensions.VerifySignature(
|
||||
bool ret = WechatTenpayBusinessClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strAuthorization: response.RawHeaders.FirstOrDefault(e => string.Equals(e.Key, "TBEP-Authorization", StringComparison.OrdinalIgnoreCase)).Value,
|
||||
strContent: Encoding.UTF8.GetString(response.RawBytes),
|
||||
strAuthorization: response.GetRawHeaders().GetFirstValueOrEmpty("TBEP-Authorization"),
|
||||
strContent: Encoding.UTF8.GetString(response.GetRawBytes()),
|
||||
out error
|
||||
);
|
||||
|
||||
if (error != null)
|
||||
if (error is not null)
|
||||
{
|
||||
error = new Exceptions.WechatTenpayBusinessResponseVerificationException("Verify signature of response failed. Please see the inner exception for more details.", error);
|
||||
error = new WechatTenpayBusinessException("Verify signature of response failed. Please see the inner exception for more details.", error);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -135,9 +135,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature(this WechatTenpayBusinessClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSignatureAlgorithm, string responseSerialNumber, out Exception? error)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
bool ret = WechatTenpayBusinessClientSignExtensions.VerifySignature(
|
||||
bool ret = WechatTenpayBusinessClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strTimestamp: responseTimestamp,
|
||||
strNonce: responseNonce,
|
||||
@ -148,10 +148,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
out error
|
||||
);
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
error = new Exceptions.WechatTenpayBusinessResponseVerificationException("Verify signature of response failed. Please see the inner exception for more details.", error);
|
||||
}
|
||||
if (!ret)
|
||||
error ??= new Exception($"Failed to verify response. Maybe the raw signature \"{responseSignature}\" is invalid.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
{
|
||||
internal static class WechatTenpayBusinessClientSignExtensions
|
||||
internal static class WechatTenpayBusinessClientSigningExtensions
|
||||
{
|
||||
public static bool VerifySignature(this WechatTenpayBusinessClient client, string strAuthorization, string strContent, out Exception? error)
|
||||
{
|
||||
@ -43,26 +43,26 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
}
|
||||
}
|
||||
|
||||
error = new Exception("Could not read value of 'TBEP-Authorization'.");
|
||||
error = new Exception("The value of \"TBEP-Authorization\" is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool VerifySignature(this WechatTenpayBusinessClient client, string strTimestamp, string strNonce, string strContent, string strSignature, string strSignatureAlgorithm, string strSerialNumber, out Exception? error)
|
||||
{
|
||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
switch (strSignatureAlgorithm)
|
||||
{
|
||||
case Constants.SignAlgorithms.SHA245_WITH_RSA:
|
||||
{
|
||||
if (client.Credentials.TBEPCertificateSerialNumber != null &&
|
||||
client.Credentials.TBEPCertificatePublicKey != null)
|
||||
if (client.Credentials.TBEPCertificateSerialNumber is not null &&
|
||||
client.Credentials.TBEPCertificatePublicKey is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.Equals(client.Credentials.TBEPCertificateSerialNumber, strSerialNumber))
|
||||
{
|
||||
error = new Exception("There is no TBEP public key matched the serial number.");
|
||||
error = new Exception($"There is no TBEP public key matched the serial number \"{strSerialNumber}\".");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
|
||||
default:
|
||||
{
|
||||
error = new Exception("Unsupported sign algorithm.");
|
||||
error = new Exception($"Unsupported sign algorithm: \"{strSignatureAlgorithm}\".");
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Flurl.Http;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Interceptors
|
||||
{
|
||||
using SKIT.FlurlHttpClient.Constants;
|
||||
|
||||
internal class WechatTenpayBusinessRequestSignatureInterceptor : FlurlHttpCallInterceptor
|
||||
internal class WechatTenpayBusinessRequestSigningInterceptor : HttpInterceptor
|
||||
{
|
||||
private const string HTTP_HEADER_PLATFORM_AUTHORIZATION = HttpHeaders.Authorization;
|
||||
private const string HTTP_HEADER_ENTERPRISE_AUTHORIZATION = "Enterprise-Authorization";
|
||||
@ -21,7 +20,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Interceptors
|
||||
private readonly string? _enterpriseCertSn;
|
||||
private readonly string? _enterpriseCertPk;
|
||||
|
||||
public WechatTenpayBusinessRequestSignatureInterceptor(string signAlg, string platformId, string platformCertSn, string platformCertPk, string? enterpriseId, string? enterpriseCertSn, string? enterpriseCertPk)
|
||||
public WechatTenpayBusinessRequestSigningInterceptor(string signAlg, string platformId, string platformCertSn, string platformCertPk, string? enterpriseId, string? enterpriseCertSn, string? enterpriseCertPk)
|
||||
{
|
||||
_signAlg = signAlg;
|
||||
_platformId = platformId;
|
||||
@ -32,35 +31,35 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Interceptors
|
||||
_enterpriseCertPk = enterpriseCertPk;
|
||||
}
|
||||
|
||||
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 (flurlCall.Completed) throw new Exceptions.WechatTenpayBusinessRequestSignatureException("This interceptor must be called before request completed.");
|
||||
if (context is null) throw new ArgumentNullException(nameof(context));
|
||||
if (context.FlurlCall.Completed) throw new WechatTenpayBusinessException("Failed to sign request. This interceptor must be called before request completed.");
|
||||
|
||||
string method = flurlCall.HttpRequestMessage.Method.ToString().ToUpper();
|
||||
string url = flurlCall.HttpRequestMessage.RequestUri?.PathAndQuery ?? string.Empty;
|
||||
string method = context.FlurlCall.HttpRequestMessage.Method.ToString().ToUpper();
|
||||
string url = context.FlurlCall.HttpRequestMessage.RequestUri?.PathAndQuery ?? string.Empty;
|
||||
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
|
||||
string nonce = Guid.NewGuid().ToString("N");
|
||||
string body = string.Empty;
|
||||
|
||||
if (flurlCall.HttpRequestMessage.Content is MultipartFormDataContent formdataContent)
|
||||
if (context.FlurlCall.HttpRequestMessage.Content is MultipartFormDataContent formdataContent)
|
||||
{
|
||||
// NOTICE: multipart/form-data 文件上传请求的待签名参数需特殊处理
|
||||
var httpContent = formdataContent.SingleOrDefault(e => Constants.FormDataFields.FORMDATA_META.Equals(e.Headers.ContentDisposition?.Name?.Trim('\"')));
|
||||
if (httpContent != null)
|
||||
if (httpContent is not null)
|
||||
{
|
||||
body = await httpContent.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
body = flurlCall.RequestBody ?? string.Empty;
|
||||
body = context.FlurlCall.RequestBody ?? string.Empty;
|
||||
}
|
||||
|
||||
string plainText = $"{method}\n{url}\n{timestamp}\n{nonce}\n{body}\n";
|
||||
string signText;
|
||||
|
||||
bool softSignRequired = _enterpriseId != null && _enterpriseCertSn != null && _enterpriseCertPk != null;
|
||||
bool softSignRequired = _enterpriseId is not null && _enterpriseCertSn is not null && _enterpriseCertPk is not null;
|
||||
string? softSignText = null;
|
||||
|
||||
switch (_signAlg)
|
||||
@ -73,31 +72,27 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Interceptors
|
||||
|
||||
if (softSignRequired)
|
||||
{
|
||||
byte[] keyBytes = Convert.FromBase64String(_enterpriseCertPk);
|
||||
byte[] keyBytes = Convert.FromBase64String(_enterpriseCertPk!);
|
||||
byte[] msgBytes = Convert.FromBase64String(signText);
|
||||
softSignText = Convert.ToBase64String(Utilities.RSAUtility.SignWithSHA256(keyBytes, msgBytes));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exceptions.WechatTenpayBusinessRequestSignatureException("Failed to generate signature of request. Please see the inner exception for more details.", ex);
|
||||
throw new WechatTenpayBusinessException("Failed to sign request. Please see the inner exception for more details.", ex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exceptions.WechatTenpayBusinessRequestSignatureException("Unsupported authorization sign algorithm.");
|
||||
throw new WechatTenpayBusinessException($"Failed to sign request. Unsupported signing algorithm: \"{_signAlg}\".");
|
||||
}
|
||||
|
||||
string authString = $"platform_id=\"{_platformId}\",platform_serial_number=\"{_platformCertSn}\",nonce=\"{nonce}\",timestamp=\"{timestamp}\",signature=\"{signText}\",signature_algorithm=\"{_signAlg}\"";
|
||||
flurlCall.Request.Headers.Remove(HTTP_HEADER_PLATFORM_AUTHORIZATION);
|
||||
flurlCall.Request.WithHeader(HttpHeaders.Authorization, authString);
|
||||
context.FlurlCall.Request.WithHeader(HTTP_HEADER_PLATFORM_AUTHORIZATION, $"platform_id=\"{_platformId}\",platform_serial_number=\"{_platformCertSn}\",nonce=\"{nonce}\",timestamp=\"{timestamp}\",signature=\"{signText}\",signature_algorithm=\"{_signAlg}\"");
|
||||
|
||||
if (softSignRequired)
|
||||
{
|
||||
string softAuthString = $"ent_id=\"{_enterpriseId}\",enterprise_serial_number=\"{_enterpriseCertSn}\",signature=\"{softSignText}\",signature_algorithm=\"{_signAlg}\"";
|
||||
flurlCall.Request.Headers.Remove(HTTP_HEADER_ENTERPRISE_AUTHORIZATION);
|
||||
flurlCall.Request.WithHeader(HTTP_HEADER_ENTERPRISE_AUTHORIZATION, softAuthString);
|
||||
context.FlurlCall.Request.WithHeader(HTTP_HEADER_ENTERPRISE_AUTHORIZATION, $"ent_id=\"{_enterpriseId}\",enterprise_serial_number=\"{_enterpriseCertSn}\",signature=\"{softSignText}\",signature_algorithm=\"{_signAlg}\"");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
{
|
||||
/// <summary>
|
||||
@ -7,7 +9,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
{
|
||||
public override bool IsSuccessful()
|
||||
{
|
||||
return base.IsSuccessful() && RawBytes?.Length > 0;
|
||||
return base.IsSuccessful() && GetRawBytes().Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置关单时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("close_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("close_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset CloseTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -163,9 +163,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置下单时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("create_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -254,9 +254,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置过期时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("expire_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("expire_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset ExpireTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -125,9 +125,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置付款时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("pay_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("pay_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置链接过期时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("expire_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("expire_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset ExpireTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置分账成功时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("succeeded_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -117,9 +117,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置分账完成时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("finished_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("finished_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? FinishTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -67,18 +67,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置退款成功时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("succeeded_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置退款创建时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("created_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("created_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset CreateTime { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
|
||||
/// 获取或设置分账成功时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("succeeded_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset? SucceedTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461; net47; netstandard2.0; net6.0</TargetFrameworks>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<TargetFrameworks>net461; net471; netstandard2.0; net6.0</TargetFrameworks>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<NullableReferenceTypes>true</NullableReferenceTypes>
|
||||
</PropertyGroup>
|
||||
@ -14,7 +14,7 @@
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
|
||||
<PackageTags>Flurl.Http Tencent Tenpay FiT 腾讯金融科技服务平台 腾讯金融科技 腾讯金融 腾讯商企付 腾讯微企付 商企付 微企付</PackageTags>
|
||||
<Version>2.2.0</Version>
|
||||
<Version>3.0.0-preview.1</Version>
|
||||
<Description>基于 Flurl.Http 的微企付 API 客户端。</Description>
|
||||
<Authors>Fu Diwei</Authors>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
@ -36,13 +36,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461' Or '$(TargetFramework)' == 'net47'" />
|
||||
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461' Or '$(TargetFramework)' == 'net471'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="'$(TargetFramework)' == 'net461'" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.6.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="3.0.0-preview.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -61,7 +61,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Settings
|
||||
|
||||
internal Credentials(WechatTenpayBusinessClientOptions options)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
if (options is null) throw new ArgumentNullException(nameof(options));
|
||||
|
||||
PlatformId = options.PlatformId;
|
||||
PlatformCertificateSerialNumber = options.PlatformCertificateSerialNumber;
|
||||
|
@ -72,8 +72,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>签名字节数组。</returns>
|
||||
public static byte[] SignWithSHA256(byte[] privateKeyBytes, byte[] msgBytes)
|
||||
{
|
||||
if (privateKeyBytes == null) throw new ArgumentNullException(nameof(privateKeyBytes));
|
||||
if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes));
|
||||
if (privateKeyBytes is null) throw new ArgumentNullException(nameof(privateKeyBytes));
|
||||
if (msgBytes is null) throw new ArgumentNullException(nameof(msgBytes));
|
||||
|
||||
RsaKeyParameters rsaPrivateKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes);
|
||||
return SignWithSHA256(rsaPrivateKeyParams, msgBytes);
|
||||
@ -87,8 +87,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>经 Base64 编码的签名。</returns>
|
||||
public static string SignWithSHA256(string privateKey, string message)
|
||||
{
|
||||
if (privateKey == null) throw new ArgumentNullException(nameof(privateKey));
|
||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||
if (privateKey is null) throw new ArgumentNullException(nameof(privateKey));
|
||||
if (message is null) throw new ArgumentNullException(nameof(message));
|
||||
|
||||
byte[] privateKeyBytes = ConvertPrivateKeyPkcs8PemToByteArray(privateKey);
|
||||
byte[] msgBytes = Encoding.UTF8.GetBytes(message);
|
||||
@ -105,9 +105,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>验证结果。</returns>
|
||||
public static bool VerifyWithSHA256(byte[] publicKeyBytes, byte[] msgBytes, byte[] signBytes)
|
||||
{
|
||||
if (publicKeyBytes == null) throw new ArgumentNullException(nameof(publicKeyBytes));
|
||||
if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes));
|
||||
if (signBytes == null) throw new ArgumentNullException(nameof(signBytes));
|
||||
if (publicKeyBytes is null) throw new ArgumentNullException(nameof(publicKeyBytes));
|
||||
if (msgBytes is null) throw new ArgumentNullException(nameof(msgBytes));
|
||||
if (signBytes is null) throw new ArgumentNullException(nameof(signBytes));
|
||||
|
||||
RsaKeyParameters rsaPublicKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
|
||||
return VerifyWithSHA256(rsaPublicKeyParams, msgBytes, signBytes);
|
||||
@ -122,9 +122,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>验证结果。</returns>
|
||||
public static bool VerifyWithSHA256(string publicKey, string message, string signature)
|
||||
{
|
||||
if (publicKey == null) throw new ArgumentNullException(nameof(publicKey));
|
||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||
if (signature == null) throw new ArgumentNullException(nameof(signature));
|
||||
if (publicKey is null) throw new ArgumentNullException(nameof(publicKey));
|
||||
if (message is null) throw new ArgumentNullException(nameof(message));
|
||||
if (signature is null) throw new ArgumentNullException(nameof(signature));
|
||||
|
||||
byte[] publicKeyBytes = ConvertPublicKeyPkcs8PemToByteArray(publicKey);
|
||||
byte[] msgBytes = Encoding.UTF8.GetBytes(message);
|
||||
@ -141,8 +141,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>解密后的数据字节数组。</returns>
|
||||
public static byte[] DecryptWithECB(byte[] privateKeyBytes, byte[] cipherBytes, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
|
||||
{
|
||||
if (privateKeyBytes == null) throw new ArgumentNullException(nameof(privateKeyBytes));
|
||||
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||
if (privateKeyBytes is null) throw new ArgumentNullException(nameof(privateKeyBytes));
|
||||
if (cipherBytes is null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||
|
||||
RsaKeyParameters rsaPrivateKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes);
|
||||
return DecryptWithECB(rsaPrivateKeyParams, cipherBytes, paddingAlgorithm);
|
||||
@ -157,8 +157,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>解密后的文本数据。</returns>
|
||||
public static string DecryptWithECB(string privateKey, string cipherText, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
|
||||
{
|
||||
if (privateKey == null) throw new ArgumentNullException(nameof(privateKey));
|
||||
if (cipherText == null) throw new ArgumentNullException(nameof(cipherText));
|
||||
if (privateKey is null) throw new ArgumentNullException(nameof(privateKey));
|
||||
if (cipherText is null) throw new ArgumentNullException(nameof(cipherText));
|
||||
|
||||
byte[] privateKeyBytes = ConvertPrivateKeyPkcs8PemToByteArray(privateKey);
|
||||
byte[] cipherBytes = Convert.FromBase64String(cipherText);
|
||||
@ -175,8 +175,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>加密后的数据字节数组。</returns>
|
||||
public static byte[] EncryptWithECB(byte[] publicKeyBytes, byte[] plainBytes, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
|
||||
{
|
||||
if (publicKeyBytes == null) throw new ArgumentNullException(nameof(publicKeyBytes));
|
||||
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
|
||||
if (publicKeyBytes is null) throw new ArgumentNullException(nameof(publicKeyBytes));
|
||||
if (plainBytes is null) throw new ArgumentNullException(nameof(plainBytes));
|
||||
|
||||
RsaKeyParameters rsaPublicKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
|
||||
return EncryptWithECB(rsaPublicKeyParams, plainBytes, paddingAlgorithm);
|
||||
@ -191,8 +191,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>经 Base64 编码的加密数据。</returns>
|
||||
public static string EncryptWithECB(string publicKey, string plainText, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
|
||||
{
|
||||
if (publicKey == null) throw new ArgumentNullException(nameof(publicKey));
|
||||
if (plainText == null) throw new ArgumentNullException(nameof(plainText));
|
||||
if (publicKey is null) throw new ArgumentNullException(nameof(publicKey));
|
||||
if (plainText is null) throw new ArgumentNullException(nameof(plainText));
|
||||
|
||||
byte[] publicKeyBytes = ConvertPublicKeyPkcs8PemToByteArray(publicKey);
|
||||
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
|
||||
|
@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>信息摘要字节数组。</returns>
|
||||
public static byte[] Hash(byte[] bytes)
|
||||
{
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
if (bytes is null) throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
using SHA256 sha = SHA256.Create();
|
||||
return sha.ComputeHash(bytes);
|
||||
@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>信息摘要。</returns>
|
||||
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[] hashBytes = Hash(msgBytes);
|
||||
|
@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>哈希字节数组。</returns>
|
||||
public static byte[] Hash(byte[] bytes)
|
||||
{
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
if (bytes is null) throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
SM3Digest sm3 = new SM3Digest();
|
||||
sm3.BlockUpdate(bytes, 0, bytes.Length);
|
||||
@ -32,7 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>哈希值。</returns>
|
||||
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[] hashBytes = Hash(msgBytes);
|
||||
|
@ -39,8 +39,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>加密后的数据字节数组。</returns>
|
||||
public static byte[] EncryptWithCBC(byte[] keyBytes, byte[] ivBytes, byte[] plainBytes, string paddingMode = SM4_CIPHER_PADDING_PKCS7PADDING)
|
||||
{
|
||||
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
||||
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
|
||||
if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes));
|
||||
if (plainBytes is null) throw new ArgumentNullException(nameof(plainBytes));
|
||||
|
||||
KeyParameter sm4KeyParams = ParameterUtilities.CreateKeyParameter(SM4_ALGORITHM_NAME, keyBytes);
|
||||
ParametersWithIV sm4keyParamsWithIv = new ParametersWithIV(sm4KeyParams, ivBytes);
|
||||
@ -57,8 +57,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>经 Base64 编码的加密数据。</returns>
|
||||
public static string EncryptWithCBC(string key, string iv, string plainText, string paddingMode = SM4_CIPHER_PADDING_PKCS7PADDING)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException(nameof(key));
|
||||
if (plainText == null) throw new ArgumentNullException(nameof(plainText));
|
||||
if (key is null) throw new ArgumentNullException(nameof(key));
|
||||
if (plainText is null) throw new ArgumentNullException(nameof(plainText));
|
||||
|
||||
byte[] keyBytes = Convert.FromBase64String(key);
|
||||
byte[] ivBytes = Convert.FromBase64String(iv);
|
||||
@ -77,8 +77,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>解密后的数据字节数组。</returns>
|
||||
public static byte[] DecryptWithCBC(byte[] keyBytes, byte[] ivBytes, byte[] cipherBytes, string paddingMode = SM4_CIPHER_PADDING_PKCS7PADDING)
|
||||
{
|
||||
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
||||
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||
if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes));
|
||||
if (cipherBytes is null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||
|
||||
KeyParameter sm4KeyParams = ParameterUtilities.CreateKeyParameter(SM4_ALGORITHM_NAME, keyBytes);
|
||||
ParametersWithIV sm4keyParamsWithIv = new ParametersWithIV(sm4KeyParams, ivBytes);
|
||||
@ -95,8 +95,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
/// <returns>解密后的文本数据。</returns>
|
||||
public static string DecryptWithCBC(string key, string iv, string cipherText, string paddingMode = SM4_CIPHER_PADDING_PKCS7PADDING)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException(nameof(key));
|
||||
if (cipherText == null) throw new ArgumentNullException(nameof(cipherText));
|
||||
if (key is null) throw new ArgumentNullException(nameof(key));
|
||||
if (cipherText is null) throw new ArgumentNullException(nameof(cipherText));
|
||||
|
||||
byte[] keyBytes = Convert.FromBase64String(key);
|
||||
byte[] ivBytes = Convert.FromBase64String(iv);
|
||||
|
@ -15,10 +15,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
|
||||
public static MultipartFormDataContent Build(string fileName, byte[] fileBytes, string fileContentType, string fileMetaJson, string formDataName, Action<HttpContent> configureMetaHttpContent, Action<HttpContent> configureFileHttpContent)
|
||||
{
|
||||
if (fileName == null) throw new ArgumentNullException(nameof(fileName));
|
||||
if (fileMetaJson == null) throw new ArgumentNullException(nameof(fileMetaJson));
|
||||
if (formDataName == null) throw new ArgumentNullException(nameof(formDataName));
|
||||
if (configureFileHttpContent == null) throw new ArgumentNullException(nameof(configureFileHttpContent));
|
||||
if (fileName is null) throw new ArgumentNullException(nameof(fileName));
|
||||
if (fileMetaJson is null) throw new ArgumentNullException(nameof(fileMetaJson));
|
||||
if (formDataName is null) throw new ArgumentNullException(nameof(formDataName));
|
||||
if (configureFileHttpContent is null) throw new ArgumentNullException(nameof(configureFileHttpContent));
|
||||
|
||||
fileBytes = fileBytes ?? Array.Empty<byte>();
|
||||
fileContentType = string.IsNullOrEmpty(fileContentType) ? "application/octet-stream" : fileContentType;
|
@ -15,8 +15,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
|
||||
private static void InnerReplacePropertyStringValue<T>(ref T obj, ReplacePropertyStringValueReplacementHandler replacement)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException(nameof(obj));
|
||||
if (replacement == null) throw new ArgumentNullException(nameof(replacement));
|
||||
if (obj is null) throw new ArgumentNullException(nameof(obj));
|
||||
if (replacement is null) throw new ArgumentNullException(nameof(replacement));
|
||||
|
||||
Type objType = obj.GetType();
|
||||
if (!objType.IsClass)
|
||||
@ -82,7 +82,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
Type elementType = element.GetType();
|
||||
if (elementType == typeof(string))
|
||||
{
|
||||
if (currentProp == null)
|
||||
if (currentProp is null)
|
||||
continue;
|
||||
if (!currentProp.CanWrite)
|
||||
continue;
|
||||
@ -121,7 +121,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
Type elementType = element.GetType();
|
||||
if (elementType == typeof(string))
|
||||
{
|
||||
if (currentProp == null)
|
||||
if (currentProp is null)
|
||||
continue;
|
||||
if (!currentProp.CanWrite)
|
||||
continue;
|
||||
@ -160,7 +160,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
|
||||
Type entryValueType = entryValue.GetType();
|
||||
if (entryValueType == typeof(string))
|
||||
{
|
||||
if (currentProp == null)
|
||||
if (currentProp is null)
|
||||
continue;
|
||||
if (!currentProp.CanWrite)
|
||||
continue;
|
@ -35,20 +35,32 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// </summary>
|
||||
/// <param name="options">配置项。</param>
|
||||
public WechatTenpayBusinessClient(WechatTenpayBusinessClientOptions options)
|
||||
: 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 WechatTenpayBusinessClient(WechatTenpayBusinessClientOptions options, HttpClient? httpClient, bool disposeClient = true)
|
||||
: base(httpClient, disposeClient)
|
||||
{
|
||||
if (options is null) throw new ArgumentNullException(nameof(options));
|
||||
|
||||
Credentials = new Settings.Credentials(options);
|
||||
AutoEncryptRequestSensitiveProperty = options.AutoEncryptRequestSensitiveProperty;
|
||||
AutoDecryptResponseSensitiveProperty = options.AutoDecryptResponseSensitiveProperty;
|
||||
|
||||
FlurlClient.BaseUrl = options.Endpoint ?? WechatTenpayBusinessEndpoints.DEFAULT;
|
||||
FlurlClient.Headers.Remove(FlurlHttpClient.Constants.HttpHeaders.Accept);
|
||||
FlurlClient.Headers.Remove(FlurlHttpClient.Constants.HttpHeaders.AcceptLanguage);
|
||||
FlurlClient.WithHeader(FlurlHttpClient.Constants.HttpHeaders.Accept, "application/json");
|
||||
FlurlClient.WithTimeout(TimeSpan.FromMilliseconds(options.Timeout));
|
||||
FlurlClient.Headers.Remove(HttpHeaders.Accept);
|
||||
FlurlClient.Headers.Remove(HttpHeaders.AcceptLanguage);
|
||||
FlurlClient.WithHeader(HttpHeaders.Accept, "application/json");
|
||||
FlurlClient.WithTimeout(options.Timeout <= 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(options.Timeout));
|
||||
|
||||
Interceptors.Add(new Interceptors.WechatTenpayBusinessRequestSignatureInterceptor(
|
||||
Interceptors.Add(new Interceptors.WechatTenpayBusinessRequestSigningInterceptor(
|
||||
signAlg: options.SignAlgorithm,
|
||||
platformId: options.PlatformId,
|
||||
platformCertSn: options.PlatformCertificateSerialNumber,
|
||||
@ -63,27 +75,22 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// 使用当前客户端生成一个新的 <see cref="IFlurlRequest"/> 对象。
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="httpMethod"></param>
|
||||
/// <param name="urlSegments"></param>
|
||||
/// <returns></returns>
|
||||
public IFlurlRequest CreateRequest(WechatTenpayBusinessRequest request, HttpMethod method, params object[] urlSegments)
|
||||
public IFlurlRequest CreateFlurlRequest(WechatTenpayBusinessRequest request, HttpMethod httpMethod, params object[] urlSegments)
|
||||
{
|
||||
IFlurlRequest flurlRequest = FlurlClient.Request(urlSegments).WithVerb(method);
|
||||
IFlurlRequest flurlRequest = base.CreateFlurlRequest(request, httpMethod, urlSegments);
|
||||
|
||||
if (AutoEncryptRequestSensitiveProperty)
|
||||
{
|
||||
this.EncryptRequestSensitiveProperty(request);
|
||||
}
|
||||
|
||||
if (request.Timeout != null)
|
||||
{
|
||||
flurlRequest.WithTimeout(TimeSpan.FromMilliseconds(request.Timeout.Value));
|
||||
}
|
||||
|
||||
if (request.Encryption != null)
|
||||
if (request.WechatpayEncryption is not null)
|
||||
{
|
||||
flurlRequest.Headers.Remove("TBEP-Encrypt");
|
||||
flurlRequest.WithHeader("TBEP-Encrypt", $"enc_key=\"{request.Encryption.EncryptedKey}\",iv=\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(request.Encryption.IV))}\",tbep_serial_number=\"{request.Encryption.SerialNumber}\",algorithm=\"{request.Encryption.Algorithm}\"");
|
||||
flurlRequest.WithHeader("TBEP-Encrypt", $"enc_key=\"{request.WechatpayEncryption.EncryptedKey}\",iv=\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(request.WechatpayEncryption.IV))}\",tbep_serial_number=\"{request.WechatpayEncryption.SerialNumber}\",algorithm=\"{request.WechatpayEncryption.Algorithm}\"");
|
||||
}
|
||||
|
||||
return flurlRequest;
|
||||
@ -97,30 +104,19 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <param name="httpContent"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <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 : WechatTenpayBusinessResponse, new()
|
||||
{
|
||||
if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest));
|
||||
if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest));
|
||||
|
||||
if (httpContent != null)
|
||||
if (httpContent is not null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(httpContent.Headers.ContentType?.MediaType))
|
||||
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using IFlurlResponse flurlResponse = await base.SendRequestAsync(flurlRequest, httpContent, cancellationToken);
|
||||
return await WrapResponseWithJsonAsync<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
catch (FlurlHttpTimeoutException ex)
|
||||
{
|
||||
throw new Exceptions.WechatTenpayBusinessRequestTimeoutException(ex.Message, ex);
|
||||
}
|
||||
catch (FlurlHttpException ex)
|
||||
{
|
||||
throw new WechatTenpayBusinessException(ex.Message, ex);
|
||||
}
|
||||
using IFlurlResponse flurlResponse = await base.SendFlurlRequestAsync(flurlRequest, httpContent, cancellationToken);
|
||||
return await WrapFlurlResponseAsJsonAsync<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -131,36 +127,25 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <param name="data"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <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 : WechatTenpayBusinessResponse, new()
|
||||
{
|
||||
if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest));
|
||||
if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest));
|
||||
|
||||
try
|
||||
{
|
||||
bool isSimpleRequest = data == null ||
|
||||
flurlRequest.Verb == HttpMethod.Get ||
|
||||
flurlRequest.Verb == HttpMethod.Head ||
|
||||
flurlRequest.Verb == HttpMethod.Options;
|
||||
using IFlurlResponse flurlResponse = isSimpleRequest ?
|
||||
await base.SendRequestAsync(flurlRequest, null, cancellationToken) :
|
||||
await base.SendRequestWithJsonAsync(flurlRequest, data, cancellationToken);
|
||||
return await WrapResponseWithJsonAsync<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
catch (FlurlHttpTimeoutException ex)
|
||||
{
|
||||
throw new Exceptions.WechatTenpayBusinessRequestTimeoutException(ex.Message, ex);
|
||||
}
|
||||
catch (FlurlHttpException ex)
|
||||
{
|
||||
throw new WechatTenpayBusinessException(ex.Message, ex);
|
||||
}
|
||||
bool isSimpleRequest = data is null ||
|
||||
flurlRequest.Verb == HttpMethod.Get ||
|
||||
flurlRequest.Verb == HttpMethod.Head ||
|
||||
flurlRequest.Verb == HttpMethod.Options;
|
||||
using IFlurlResponse flurlResponse = isSimpleRequest ?
|
||||
await base.SendFlurlRequestAsync(flurlRequest, null, cancellationToken) :
|
||||
await base.SendFlurlRequestAsJsonAsync(flurlRequest, data, cancellationToken);
|
||||
return await WrapFlurlResponseAsJsonAsync<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
|
||||
private new async Task<TResponse> WrapResponseWithJsonAsync<TResponse>(IFlurlResponse flurlResponse, CancellationToken cancellationToken = default)
|
||||
private new async Task<TResponse> WrapFlurlResponseAsJsonAsync<TResponse>(IFlurlResponse flurlResponse, CancellationToken cancellationToken = default)
|
||||
where TResponse : WechatTenpayBusinessResponse, new()
|
||||
{
|
||||
TResponse result = await base.WrapResponseWithJsonAsync<TResponse>(flurlResponse, cancellationToken);
|
||||
TResponse result = await base.WrapFlurlResponseAsJsonAsync<TResponse>(flurlResponse, cancellationToken);
|
||||
|
||||
string? strEncryption = flurlResponse.Headers.FirstOrDefault("TBEP-Encrypt");
|
||||
if (!string.IsNullOrEmpty(strEncryption))
|
||||
@ -172,13 +157,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
k => k[0],
|
||||
v => v.Length > 1 ? v[1].TrimStart('\"').TrimEnd('\"') : null
|
||||
);
|
||||
result.Encryption = new WechatTenpayBusinessResponseEncryption();
|
||||
result.Encryption.PlatformId = dictEncryption.GetValueOrDefault("platform_id");
|
||||
result.Encryption.EnterpriseId = dictEncryption.GetValueOrDefault("ent_id");
|
||||
result.Encryption.EncryptedKey = dictEncryption.GetValueOrDefault("enc_key");
|
||||
result.Encryption.IV = dictEncryption.GetValueOrDefault("iv");
|
||||
result.Encryption.SerialNumber = dictEncryption.GetValueOrDefault("platform_serial_number") ?? dictEncryption.GetValueOrDefault("enterprise_serial_number");
|
||||
result.Encryption.Algorithm = dictEncryption.GetValueOrDefault("algorithm");
|
||||
result.WechatpayEncryption = new WechatTenpayBusinessResponseEncryption();
|
||||
result.WechatpayEncryption.PlatformId = dictEncryption.GetValueOrDefault("platform_id");
|
||||
result.WechatpayEncryption.EnterpriseId = dictEncryption.GetValueOrDefault("ent_id");
|
||||
result.WechatpayEncryption.EncryptedKey = dictEncryption.GetValueOrDefault("enc_key");
|
||||
result.WechatpayEncryption.IV = dictEncryption.GetValueOrDefault("iv");
|
||||
result.WechatpayEncryption.SerialNumber = dictEncryption.GetValueOrDefault("platform_serial_number") ?? dictEncryption.GetValueOrDefault("enterprise_serial_number");
|
||||
result.WechatpayEncryption.Algorithm = dictEncryption.GetValueOrDefault("algorithm");
|
||||
|
||||
if (AutoDecryptResponseSensitiveProperty && result.IsSuccessful())
|
||||
{
|
||||
|
@ -7,19 +7,25 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置请求超时时间(单位:毫秒)。
|
||||
/// <para>默认值:30000</para>
|
||||
/// <para>
|
||||
/// 默认值:30000
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public int Timeout { get; set; } = 30 * 1000;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置微企付 API 入口点。
|
||||
/// <para>默认值:<see cref="WechatTenpayBusinessEndpoints.DEFAULT"/></para>
|
||||
/// <para>
|
||||
/// 默认值:<see cref="WechatTenpayBusinessEndpoints.DEFAULT"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string Endpoint { get; set; } = WechatTenpayBusinessEndpoints.DEFAULT;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置微企付 API 签名认证方式。
|
||||
/// <para>默认值:<see cref="Constants.SignAlgorithms.SHA245_WITH_RSA"/></para>
|
||||
/// <para>
|
||||
/// 默认值:<see cref="Constants.SignAlgorithms.SHA245_WITH_RSA"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string SignAlgorithm { get; set; } = Constants.SignAlgorithms.SHA245_WITH_RSA;
|
||||
|
||||
@ -63,15 +69,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// </summary>
|
||||
public string TBEPCertificatePublicKey { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否自动加密请求中的敏感字段数据。
|
||||
/// <para>注意:启用该功能需配合 <see cref="SensitivePropertyEncryptionSM4Key"/> 和 <see cref="SensitivePropertyEncryptionSM4IV"/> 使用。</para>
|
||||
/// </summary>
|
||||
public bool AutoEncryptRequestSensitiveProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置自动加密请求重敏感字段数据时使用的算法。
|
||||
/// <para>默认值:<see cref="Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC"/></para>
|
||||
/// <para>
|
||||
/// 默认值:<see cref="Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string SensitivePropertyEncryptionAlgorithm { get; set; } = Constants.EncryptionAlgorithms.RSA_OAEP_WITH_SM4_128_CBC;
|
||||
|
||||
@ -85,6 +87,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// </summary>
|
||||
public string? SensitivePropertyEncryptionSM4IV { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否自动加密请求中的敏感字段数据。
|
||||
/// <para>
|
||||
/// 注意:启用该功能需配合 <see cref="SensitivePropertyEncryptionSM4Key"/> 和 <see cref="SensitivePropertyEncryptionSM4IV"/> 使用。
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public bool AutoEncryptRequestSensitiveProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否自动解密响应中的敏感字段数据。
|
||||
/// </summary>
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
{
|
||||
@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// 表示微企付 API 回调通知事件的基类。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class WechatTenpayBusinessEvent
|
||||
public class WechatTenpayBusinessEvent : ICommonWebhookEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置 API 版本。
|
||||
@ -48,9 +48,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// 获取或设置通知创建时间。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("create_time")]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.Rfc3339DateTimeOffsetConverter))]
|
||||
public DateTimeOffset CreateTime { get; set; }
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
{
|
||||
/// <summary>
|
||||
/// 当调用微企付 API 出错时引发的异常。
|
||||
/// </summary>
|
||||
public class WechatTenpayBusinessException : CommonExceptionBase
|
||||
public class WechatTenpayBusinessException : CommonException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public WechatTenpayBusinessException()
|
||||
|
@ -3,22 +3,15 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <summary>
|
||||
/// 表示微企付 API 请求的基类。
|
||||
/// </summary>
|
||||
public abstract class WechatTenpayBusinessRequest : ICommonRequest
|
||||
public abstract class WechatTenpayBusinessRequest : CommonRequestBase, ICommonRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatTenpayBusinessClient"/> 时的 <see cref="WechatTenpayBusinessClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public virtual int? Timeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置请求使用的微企付敏感字段加密参数。
|
||||
/// <para>如果启用了 <see cref="WechatTenpayBusinessClientOptions.AutoEncryptRequestSensitiveProperty"/> 参数,将由系统自动生成。</para>
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public virtual WechatTenpayBusinessRequestEncryption? Encryption { get; set; }
|
||||
public virtual WechatTenpayBusinessRequestEncryption? WechatpayEncryption { get; set; }
|
||||
}
|
||||
|
||||
public sealed class WechatTenpayBusinessRequestEncryption
|
||||
|
@ -5,62 +5,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
/// <summary>
|
||||
/// 表示微企付 API 响应的基类。
|
||||
/// </summary>
|
||||
public abstract class WechatTenpayBusinessResponse : ICommonResponse
|
||||
public abstract class WechatTenpayBusinessResponse : 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>
|
||||
/// 获取微企付 API 返回的敏感字段加密参数。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public WechatTenpayBusinessResponseEncryption? Encryption { get; internal set; }
|
||||
public WechatTenpayBusinessResponseEncryption? WechatpayEncryption { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取微企付请求链路 ID。
|
||||
@ -77,12 +29,15 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
|
||||
public virtual WechatTenpayBusinessResponseError? Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示调用微企付 API 是否成功(即 HTTP 状态码为 200、202 或 204)。
|
||||
/// 获取一个值,该值指示调用微企付 API 是否成功。
|
||||
/// <para>
|
||||
/// (即 HTTP 状态码为 200/202/204,且 <see cref="Error.Code"/> 值为空)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool IsSuccessful()
|
||||
public override bool IsSuccessful()
|
||||
{
|
||||
return (RawStatus == 200 || RawStatus == 202 || RawStatus == 204) && string.IsNullOrEmpty(Error?.Code);
|
||||
return GetRawStatus() >= 200 && GetRawStatus() <= 204 && string.IsNullOrEmpty(Error?.Code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests
|
||||
{
|
||||
public class CodeAnalyzeTests
|
||||
{
|
||||
[Fact(DisplayName = "代码质量分析")]
|
||||
public void TestCodeAnalyzer()
|
||||
{
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
var options = new TypeDeclarationAnalyzerOptions()
|
||||
{
|
||||
SdkAssembly = Assembly.GetAssembly(typeof(WechatTenpayBusinessClient))!,
|
||||
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models",
|
||||
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models",
|
||||
SdkExecutingExtensionDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness",
|
||||
SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events",
|
||||
ThrowOnNotFoundRequestModelTypes = true,
|
||||
ThrowOnNotFoundResponseModelTypes = true,
|
||||
ThrowOnNotFoundExecutingExtensionTypes = true,
|
||||
ThrowOnNotFoundWebhookEventTypes = 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(WechatTenpayBusinessClient))!,
|
||||
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models",
|
||||
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models",
|
||||
SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events",
|
||||
ProjectSourceRootDirectory = Path.Combine(projdir, "./src/SKIT.FlurlHttpClient.Wechat.TenpayBusiness/"),
|
||||
ProjectTestRootDirectory = Path.Combine(projdir, "./test/SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests/"),
|
||||
ThrowOnNotFoundRequestModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundResponseModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundExecutingExtensionClassCodeFiles = true,
|
||||
ThrowOnNotFoundWebhookEventClassCodeFiles = true,
|
||||
ThrowOnNotFoundRequestModelSerializationSampleFiles = true,
|
||||
ThrowOnNotFoundResponseModelSerializationSampleFiles = true,
|
||||
ThrowOnNotFoundWebhookEventSerializationSampleFiles = true
|
||||
};
|
||||
new SourceFileAnalyzer(options).AssertNoIssues();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -11,22 +11,22 @@
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="ModelSamples/**/*.json" />
|
||||
<Content Include="EventSamples/**/*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.1.0-alpha.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="xunit" Version="2.6.6" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@ -1,26 +0,0 @@
|
||||
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests
|
||||
{
|
||||
public class TestCase_CodeReview
|
||||
{
|
||||
[Fact(DisplayName = "测试用例:代码质量分析")]
|
||||
public void TestCodeAnalyzer()
|
||||
{
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
CodeAnalyzerOptions options = new CodeAnalyzerOptions()
|
||||
{
|
||||
AssemblyName = "SKIT.FlurlHttpClient.Wechat.TenpayBusiness",
|
||||
WorkDirectoryForSourceCode = TestConfigs.WorkDirectoryForSdk,
|
||||
WorkDirectoryForTestSample = TestConfigs.WorkDirectoryForTest
|
||||
};
|
||||
CodeAnalyzer analyzer = new CodeAnalyzer(options);
|
||||
analyzer.Start();
|
||||
analyzer.Assert();
|
||||
analyzer.Flush();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
@ -16,15 +16,12 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests
|
||||
using var stream = File.OpenRead("appsettings.local.json");
|
||||
using var jdoc = JsonDocument.Parse(stream);
|
||||
|
||||
var config = jdoc.RootElement.GetProperty("TestConfig");
|
||||
var config = jdoc.RootElement.GetProperty("TestConfigs");
|
||||
WechatPlatformId = config.GetProperty("PlatformId").GetString()!;
|
||||
WechatPlatformCertSerialNumber = config.GetProperty("PlatformCertSerialNumber").GetString()!;
|
||||
WechatPlatformCertPrivateKey = config.GetProperty("PlatformCertPrivateKey").GetString()!;
|
||||
WechatTBEPCertSerialNumber = config.GetProperty("TBEPCertSerialNumber").GetString()!;
|
||||
WechatTBEPCertPrivateKey = config.GetProperty("TBEPCertPrivateKey").GetString()!;
|
||||
|
||||
WorkDirectoryForSdk = jdoc.RootElement.GetProperty("WorkDirectoryForSdk").GetString()!;
|
||||
WorkDirectoryForTest = jdoc.RootElement.GetProperty("WorkDirectoryForTest").GetString()!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -37,8 +34,5 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests
|
||||
public static readonly string WechatPlatformCertPrivateKey;
|
||||
public static readonly string WechatTBEPCertSerialNumber;
|
||||
public static readonly string WechatTBEPCertPrivateKey;
|
||||
|
||||
public static readonly string WorkDirectoryForSdk;
|
||||
public static readonly string WorkDirectoryForTest;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
{
|
||||
"TestConfig": {
|
||||
"TestConfigs": {
|
||||
"PlatformId": "请在此填写用于测试的微企付商户号",
|
||||
"PlatformCertSerialNumber": "请在此填写用于测试的微企付平台 API 证书序列号",
|
||||
"PlatformCertPrivateKey": "请在此填写用于测试的微企付平台 API 证书私钥(字符串格式)",
|
||||
"TBEPCertSerialNumber": "请在此填写用于测试的微企付证书序列号",
|
||||
"TBEPCertPrivateKey": "请在此填写用于测试的微企付证书私钥(字符串格式)"
|
||||
},
|
||||
"WorkDirectoryForSdk": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.TenpayBusiness\\",
|
||||
"WorkDirectoryForTest": "请输入当前测试项目所在的目录完整路径,如 C:\\Project\\test\\SKIT.FlurlHttpClient.Wechat.TenpayBusiness.UnitTests\\"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user