diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersRedPackExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersRedPackExtensions.cs index 541137b2..7842e79a 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersRedPackExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersRedPackExtensions.cs @@ -1,8 +1,10 @@ -using System; +using System; +using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Flurl.Http; +using SKIT.FlurlHttpClient.Wechat.TenpayV2.Settings; namespace SKIT.FlurlHttpClient.Wechat.TenpayV2 { @@ -89,5 +91,60 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2 return await client.SendRequestWithXmlAsync(flurlReq, data: request, cancellationToken: cancellationToken); } + + #region WeWork + /// + /// 异步调用 [POST] /mmpaymkttransfers/sendworkwxredpack 接口。 + /// REF: https://developer.work.weixin.qq.com/document/path/96697 + /// + /// + /// + /// + /// + public static async Task ExecuteSendPayMarketingTransfersWeWorkRedPackAsync(this WechatTenpayClient client, Models.SendPayMarketingTransfersWeWorkRedPackRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + if (request.WeWorkSign == null) + { + if (request.MerchantId == null) + { + request.MerchantId = client.Credentials.MerchantId; + } + + if (request.AppId == null) + { + request.AppId = client.Credentials.AppId; + } + + if (request.NonceString == null) + { + request.NonceString = Guid.NewGuid().ToString("N"); + } + + request.WeWorkSign = Utilities.RequestSigner.Sign( + paramsMap: new Dictionary() + { + { "act_name", request.ActivityName }, + { "mch_billno", request.MerchantBillNumber }, + { "mch_id", request.MerchantId }, + { "nonce_str", request.NonceString }, + { "re_openid", request.OpenId }, + { "total_amount", request.TotalAmount.ToString() }, + { "wxappid", request.AppId } + }, + secretKey: "secret", + secretValue: client.Credentials.WeWorkPaymentSecret!, + signType: Constants.SignTypes.MD5 + ); + } + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "mmpaymkttransfers", "sendworkwxredpack"); + + return await client.SendRequestWithXmlAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + #endregion } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersTransferExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersTransferExtensions.cs index cb819ad1..be0df026 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersTransferExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecutePayMarketingTransfersTransferExtensions.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -45,5 +46,61 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2 return await client.SendRequestWithXmlAsync(flurlReq, data: request, cancellationToken: cancellationToken); } + + #region WeWork + /// + /// 异步调用 [POST] /mmpaymkttransfers/promotion/paywwsptrans2pocket 接口。 + /// REF: https://developer.work.weixin.qq.com/document/path/96697 + /// + /// + /// + /// + /// + public static async Task ExecuteCreatePayMarketingTransfersPromotionWeWorkTransferAsync(this WechatTenpayClient client, Models.CreatePayMarketingTransfersPromotionWeWorkTransferRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + if (request.WeWorkSign == null) + { + if (request.MerchantId == null) + { + request.MerchantId = client.Credentials.MerchantId; + } + + if (request.AppId == null) + { + request.AppId = client.Credentials.AppId; + } + + if (request.NonceString == null) + { + request.NonceString = Guid.NewGuid().ToString("N"); + } + + request.WeWorkSign = Utilities.RequestSigner.Sign( + paramsMap: new Dictionary() + { + { "amount", request.Amount.ToString() }, + { "appid", request.AppId }, + { "desc", request.Description }, + { "mch_id", request.MerchantId }, + { "nonce_str", request.NonceString }, + { "openid", request.OpenId }, + { "partner_trade_no", request.PartnerTradeNumber }, + { "ww_msg_type", request.MessageType } + }, + secretKey: "secret", + secretValue: client.Credentials.WeWorkPaymentSecret!, + signType: Constants.SignTypes.MD5 + ); + } + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "mmpaymkttransfers", "promotion", "paywwsptrans2pocket"); + + return await client.SendRequestWithXmlAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + #endregion } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.cs new file mode 100644 index 00000000..7b01cc4b --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.cs @@ -0,0 +1,100 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Models +{ + /// + /// 表示 [POST] /mmpaymkttransfers/sendworkwxredpack 接口的请求。 + /// + public class SendPayMarketingTransfersWeWorkRedPackRequest : WechatTenpaySignableRequest + { + /// + /// + /// + [Newtonsoft.Json.JsonProperty("mch_id")] + [System.Text.Json.Serialization.JsonPropertyName("mch_id")] + public override string? MerchantId { get; set; } + + /// + /// + /// + [Newtonsoft.Json.JsonProperty("wxappid")] + [System.Text.Json.Serialization.JsonPropertyName("wxappid")] + public override string? AppId { get; set; } + + /// + /// 获取或设置商户订单号。 + /// + [Newtonsoft.Json.JsonProperty("mch_billno")] + [System.Text.Json.Serialization.JsonPropertyName("mch_billno")] + public string MerchantBillNumber { get; set; } = string.Empty; + + /// + /// 获取或设置接受红包的用户 OpenId。 + /// + [Newtonsoft.Json.JsonProperty("re_openid")] + [System.Text.Json.Serialization.JsonPropertyName("re_openid")] + public string OpenId { get; set; } = string.Empty; + + /// + /// 获取或设置红包发送者名称。与字段 二选一。 + /// + [Newtonsoft.Json.JsonProperty("sender_name")] + [System.Text.Json.Serialization.JsonPropertyName("sender_name")] + public string? SenderName { get; set; } + + /// + /// 获取或设置红包发送者头像 MediaId。 + /// + [Newtonsoft.Json.JsonProperty("sender_header_media_id")] + [System.Text.Json.Serialization.JsonPropertyName("sender_header_media_id")] + public string? SenderHeadImageMediaId { get; set; } + + /// + /// 获取或设置发送红包的应用 ID。与字段 二选一。 + /// + [Newtonsoft.Json.JsonProperty("agentid")] + [System.Text.Json.Serialization.JsonPropertyName("agentid")] + public int? AgentId { get; set; } + + /// + /// 获取或设置红包金额(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("total_amount")] + [System.Text.Json.Serialization.JsonPropertyName("total_amount")] + [System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)] + public int TotalAmount { get; set; } + + /// + /// 获取或设置红包祝福语。 + /// + [Newtonsoft.Json.JsonProperty("wishing")] + [System.Text.Json.Serialization.JsonPropertyName("wishing")] + public string? Wishing { get; set; } + + /// + /// 获取或设置活动名称。 + /// + [Newtonsoft.Json.JsonProperty("act_name")] + [System.Text.Json.Serialization.JsonPropertyName("act_name")] + public string? ActivityName { get; set; } + + /// + /// 获取或设置备注。 + /// + [Newtonsoft.Json.JsonProperty("remark")] + [System.Text.Json.Serialization.JsonPropertyName("remark")] + public string? Remark { get; set; } + + /// + /// 获取或设置场景 ID。 + /// + [Newtonsoft.Json.JsonProperty("scene_id")] + [System.Text.Json.Serialization.JsonPropertyName("scene_id")] + public string? SceneId { get; set; } + + /// + /// 获取或设置企业微信支付接口签名。如果不指定将由系统自动生成。 + /// + [Newtonsoft.Json.JsonProperty("workwx_sign")] + [System.Text.Json.Serialization.JsonPropertyName("workwx_sign")] + public string? WeWorkSign { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.cs new file mode 100644 index 00000000..0784140c --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.cs @@ -0,0 +1,65 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Models +{ + /// + /// 表示 [POST] /mmpaymkttransfers/sendworkwxredpack 接口的响应。 + /// + public class SendPayMarketingTransfersWeWorkRedPackResponse : WechatTenpaySignableResponse + { + /// + /// + /// + [Newtonsoft.Json.JsonProperty("mch_id")] + [System.Text.Json.Serialization.JsonPropertyName("mch_id")] + public override string? MerchantId { get; set; } + + /// + /// + /// + [Newtonsoft.Json.JsonProperty("wxappid")] + [System.Text.Json.Serialization.JsonPropertyName("wxappid")] + public override string? AppId { get; set; } + + /// + /// 获取或设置商户订单号。 + /// + [Newtonsoft.Json.JsonProperty("mch_billno")] + [System.Text.Json.Serialization.JsonPropertyName("mch_billno")] + public string MerchantBillNumber { get; set; } = default!; + + /// + /// 获取或设置接受红包的用户 OpenId。 + /// + [Newtonsoft.Json.JsonProperty("re_openid")] + [System.Text.Json.Serialization.JsonPropertyName("re_openid")] + public string OpenId { get; set; } = default!; + + /// + /// 获取或设置红包金额(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("total_amount")] + [System.Text.Json.Serialization.JsonPropertyName("total_amount")] + [System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)] + public int TotalAmount { get; set; } + + /// + /// 获取或设置微信红包订单号。 + /// + [Newtonsoft.Json.JsonProperty("send_listid")] + [System.Text.Json.Serialization.JsonPropertyName("send_listid")] + public string PaymentNumber { get; set; } = default!; + + /// + /// 获取或设置红包发送者名称。 + /// + [Newtonsoft.Json.JsonProperty("sender_name")] + [System.Text.Json.Serialization.JsonPropertyName("sender_name")] + public string? SenderName { get; set; } + + /// + /// 获取或设置红包发送者头像 MediaId。 + /// + [Newtonsoft.Json.JsonProperty("sender_header_media_id")] + [System.Text.Json.Serialization.JsonPropertyName("sender_header_media_id")] + public string? SenderHeadImageMediaId { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.cs new file mode 100644 index 00000000..1fe7921a --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.cs @@ -0,0 +1,123 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Models +{ + /// + /// 表示 [POST] /mmpaymkttransfers/promotion/paywwsptrans2pocket 接口的请求。 + /// + public class CreatePayMarketingTransfersPromotionWeWorkTransferRequest : WechatTenpaySignableRequest + { + /// + /// + /// + [Newtonsoft.Json.JsonProperty("mch_id")] + [System.Text.Json.Serialization.JsonPropertyName("mch_id")] + public override string? MerchantId { get; set; } + + /// + /// + /// + [Newtonsoft.Json.JsonProperty("appid")] + [System.Text.Json.Serialization.JsonPropertyName("appid")] + public override string? AppId { get; set; } + + /// + /// 获取或设置商户付款单号。 + /// + [Newtonsoft.Json.JsonProperty("partner_trade_no")] + [System.Text.Json.Serialization.JsonPropertyName("partner_trade_no")] + public string PartnerTradeNumber { get; set; } = string.Empty; + + /// + /// 获取或设置用户的 OpenId。 + /// + [Newtonsoft.Json.JsonProperty("openid")] + [System.Text.Json.Serialization.JsonPropertyName("openid")] + public string OpenId { get; set; } = string.Empty; + + /// + /// 获取或设置付款的应用 ID。 + /// + [Newtonsoft.Json.JsonProperty("agentid")] + [System.Text.Json.Serialization.JsonPropertyName("agentid")] + public int? AgentId { get; set; } + + /// + /// 获取或设置终端设备号。 + /// + [Newtonsoft.Json.JsonProperty("device_info")] + [System.Text.Json.Serialization.JsonPropertyName("device_info")] + public string? DeviceInfo { get; set; } + + /// + /// 获取或设置金额(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("amount")] + [System.Text.Json.Serialization.JsonPropertyName("amount")] + [System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)] + public int Amount { get; set; } + + /// + /// 获取或设置备注。 + /// + [Newtonsoft.Json.JsonProperty("desc")] + [System.Text.Json.Serialization.JsonPropertyName("desc")] + public string? Description { get; set; } + + /// + /// 获取或设置校验用户姓名选项。 + /// 默认值:FORCE_CHECK + /// + [Newtonsoft.Json.JsonProperty("check_name")] + [System.Text.Json.Serialization.JsonPropertyName("check_name")] + public string CheckNameType { get; set; } = "FORCE_CHECK"; + + /// + /// 获取或设置收款用户姓名。 + /// + [Newtonsoft.Json.JsonProperty("re_user_name")] + [System.Text.Json.Serialization.JsonPropertyName("re_user_name")] + public string? UserName { get; set; } + + /// + /// 获取或设置用户终端 IP。 + /// + [Newtonsoft.Json.JsonProperty("spbill_create_ip")] + [System.Text.Json.Serialization.JsonPropertyName("spbill_create_ip")] + public string ClientIp { get; set; } = string.Empty; + + /// + /// 获取或设置付款消息类型。 + /// 默认值:NORMAL_MSG + /// + [Newtonsoft.Json.JsonProperty("ww_msg_type")] + [System.Text.Json.Serialization.JsonPropertyName("ww_msg_type")] + public string MessageType { get; set; } = "NORMAL_MSG"; + + /// + /// 获取或设置审批单号。 + /// + [Newtonsoft.Json.JsonProperty("approval_number")] + [System.Text.Json.Serialization.JsonPropertyName("approval_number")] + public string? ApprovalNumber { get; set; } + + /// + /// 获取或设置审批类型。 + /// + [Newtonsoft.Json.JsonProperty("approval_type")] + [System.Text.Json.Serialization.JsonPropertyName("approval_type")] + public int? ApprovalType { get; set; } + + /// + /// 获取或设置活动名称。 + /// + [Newtonsoft.Json.JsonProperty("act_name")] + [System.Text.Json.Serialization.JsonPropertyName("act_name")] + public string? ActivityName { get; set; } + + /// + /// 获取或设置企业微信支付接口签名。如果不指定将由系统自动生成。 + /// + [Newtonsoft.Json.JsonProperty("workwx_sign")] + [System.Text.Json.Serialization.JsonPropertyName("workwx_sign")] + public string? WeWorkSign { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.cs new file mode 100644 index 00000000..ececabab --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.cs @@ -0,0 +1,54 @@ +using System; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Models +{ + /// + /// 表示 [POST] /mmpaymkttransfers/promotion/paywwsptrans2pocket 接口的响应。 + /// + public class CreatePayMarketingTransfersPromotionWeWorkTransferResponse : WechatTenpaySignableResponse + { + /// + /// + /// + [Newtonsoft.Json.JsonProperty("mch_id")] + [System.Text.Json.Serialization.JsonPropertyName("mch_id")] + public override string? MerchantId { get; set; } + + /// + /// + /// + [Newtonsoft.Json.JsonProperty("appid")] + [System.Text.Json.Serialization.JsonPropertyName("appid")] + public override string? AppId { get; set; } + + /// + /// 获取或设置商户付款单号。 + /// + [Newtonsoft.Json.JsonProperty("partner_trade_no")] + [System.Text.Json.Serialization.JsonPropertyName("partner_trade_no")] + public string PartnerTradeNumber { get; set; } = default!; + + /// + /// 获取或设置微信付款单号。 + /// + [Newtonsoft.Json.JsonProperty("payment_no")] + [System.Text.Json.Serialization.JsonPropertyName("payment_no")] + public string PaymentNumber { get; set; } = default!; + + /// + /// 获取或设置付款成功时间。 + /// + [Newtonsoft.Json.JsonProperty("payment_time")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularNullableDateTimeOffsetConverter))] + [System.Text.Json.Serialization.JsonPropertyName("payment_time")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularNullableDateTimeOffsetConverter))] + public DateTimeOffset? SuccessTime { get; set; } + + /// + /// 获取或设置终端设备号。 + /// + [Newtonsoft.Json.JsonProperty("device_info")] + [System.Text.Json.Serialization.JsonPropertyName("device_info")] + public string? DeviceInfo { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Settings/Credentials.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Settings/Credentials.cs index dc2df5b7..66eb93bf 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Settings/Credentials.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Settings/Credentials.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Settings { @@ -29,6 +29,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Settings /// public string? AppId { get; } + /// + /// 初始化客户端时 的副本。 + /// + public string? WeWorkPaymentSecret { get; } + internal Credentials(WechatTenpayClientOptions options) { if (options == null) throw new ArgumentNullException(nameof(options)); @@ -38,6 +43,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Settings MerchantCertificateBytes = options.MerchantCertificateBytes; MerchantCertificatePassword = options.MerchantCertificatePassword; AppId = options.AppId; + WeWorkPaymentSecret = options.WeWorkPaymentSecret; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/RequestSigner.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/RequestSigner.cs index ed62d748..f3beddd3 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/RequestSigner.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/RequestSigner.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; @@ -6,24 +6,41 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities { internal static class RequestSigner { + private const string DEFAULT_SECRET_KEY = "key"; + public static string Sign(IDictionary paramsMap, string secret, string? signType = null) + { + return Sign(paramsMap: paramsMap, secretKey: DEFAULT_SECRET_KEY, secretValue: secret, signType: signType); + } + + public static string Sign(IDictionary paramsMap, string secretKey, string secretValue, string? signType = null) { if (paramsMap == null) throw new ArgumentNullException(nameof(paramsMap)); IDictionary sortedParamsMap = new SortedDictionary(paramsMap, StringComparer.OrdinalIgnoreCase); string sortedQueryString = string.Join("&", sortedParamsMap.Where(e => !string.IsNullOrEmpty(e.Value)).Select(e => $"{e.Key}={e.Value}")); - return SignFromSortedQueryString(sortedQueryString, secret, signType); + return SignFromSortedQueryString(queryString: sortedQueryString, secretKey: secretKey, secretValue: secretValue, signType: signType); } public static string SignFromJson(string json, string secret, string? signType = null) { - return SignFromSortedQueryString(JsonUtility.ParseToSortedQueryString(json), secret, signType); + return SignFromJson(json: json, secretKey: DEFAULT_SECRET_KEY, secretValue: secret, signType: signType); + } + + public static string SignFromJson(string json, string secretKey, string secretValue, string? signType = null) + { + return SignFromSortedQueryString(queryString: JsonUtility.ParseToSortedQueryString(json), secretKey: secretKey, secretValue: secretValue, signType: signType); } public static string SignFromSortedQueryString(string queryString, string secret, string? signType = null) + { + return SignFromSortedQueryString(queryString: queryString, secretKey: DEFAULT_SECRET_KEY, secretValue: secret, signType: signType); + } + + public static string SignFromSortedQueryString(string queryString, string secretKey, string secretValue, string? signType = null) { signType = signType ?? Constants.SignTypes.MD5; - queryString = queryString + $"&key={secret}"; + queryString = queryString + $"&{secretKey}={secretValue}"; switch (signType) { @@ -34,7 +51,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities case Constants.SignTypes.HMAC_SHA256: { - return HMACUtility.HashWithSHA256(secret, queryString).ToUpper(); + return HMACUtility.HashWithSHA256(secretValue, queryString).ToUpper(); } default: diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/WechatTenpayClientOptions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/WechatTenpayClientOptions.cs index c2e8762a..c2410798 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/WechatTenpayClientOptions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/WechatTenpayClientOptions.cs @@ -1,4 +1,4 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV2 +namespace SKIT.FlurlHttpClient.Wechat.TenpayV2 { /// /// 一个用于构造 时使用的配置项。 @@ -42,5 +42,10 @@ /// 获取或设置微信 AppId。若一个商户号下关联多个 AppId 的,该参数可以置空,改为在请求时传入。 /// public string? AppId { get; set; } + + /// + /// 获取或设置企业微信企业支付密钥。 + /// + public string? WeWorkPaymentSecret { get; set; } } } diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.json new file mode 100644 index 00000000..fd6f583c --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackRequest.json @@ -0,0 +1,15 @@ +{ + "nonce_str": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS", + "sign": "C380BEC2BFD727A4B6845133519F3AD6", + "mch_billno": "123456", + "mch_id": "10000098", + "wxappid": "wx8888888888888888", + "sender_name": "XX活动", + "sender_header_media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0", + "re_openid": "oxTWIuGaIt6gTKsQRLau2M0yL16E", + "total_amount": "1000", + "wishing": "感谢您参加猜灯谜活动,祝您元宵节快乐!", + "act_name": "猜灯谜抢红包活动", + "remark": "猜越多得越多,快来抢!", + "workwx_sign": "99BCDAFF065A4B95628E3DB468A874A8" +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.json new file mode 100644 index 00000000..e168132e --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersRedPack/WeWork/SendPayMarketingTransfersWeWorkRedPackResponse.json @@ -0,0 +1,14 @@ +{ + "return_code": "SUCCESS", + "return_msg": "ok", + "sign": "C380BEC2BFD727A4B6845133519F3AD6", + "result_code": "SUCCESS", + "mch_billno": "123456", + "mch_id": "10000098", + "wxappid": "wx8888888888888888", + "re_openid": "oxTWIuGaIt6gTKsQRLau2M0yL16E", + "total_amount": "1000", + "send_listid": "235785324578098", + "sender_name": "XX活动", + "sender_header_media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0" +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.json new file mode 100644 index 00000000..0f4f3963 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferRequest.json @@ -0,0 +1,17 @@ +{ + "appid": "wxe062425f740c8888", + "mch_id": "1900000109", + "device_info": "013467007045764", + "nonce_str": "3PG2J4ILTKCH16CQ2502SI8ZNMTM67VS", + "sign": "C97BDBACF37622775366F38B629F45E3", + "partner_trade_no": "100000982017072019616", + "openid": "ohO4Gt7wVPxIT1A9GjFaMYMiZY1s", + "check_name": "NO_CHECK", + "re_user_name": "张三", + "amount": "100", + "desc": "六月出差报销费用", + "spbill_create_ip": "10.2.3.10", + "workwx_sign": "99BCDAFF065A4B95628E3DB468A874A8", + "ww_msg_type": "NORMAL_MSG", + "act_name": "示例项目" +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.json new file mode 100644 index 00000000..3401058c --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/ModelSamples/PayMarketingTransfersTransfer/WeWork/CreatePayMarketingTransfersPromotionWeWorkTransferResponse.json @@ -0,0 +1,12 @@ +{ + "return_code": "SUCCESS", + "return_msg": "ok", + "appid": "wxec38b8ff840b8888", + "mch_id": "1900000109", + "device_info": "013467007045764", + "nonce_str": "lxuDzMnRjpcXzxLx0q", + "result_code": "SUCCESS", + "partner_trade_no": "100000982017072019616", + "payment_no": "1000018301201505190181489473", + "payment_time": "2017-07-20 22:05:59" +}