Skip to content

Commit

Permalink
fix(microapp): 修复小游戏支付签名生成错误的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
fudiwei committed Jul 14, 2024
1 parent a3bda94 commit 9c455b8
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,48 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Flurl;
using Flurl.Http;

namespace SKIT.FlurlHttpClient.ByteDance.MicroApp
{
public static class DouyinMicroAppClientExecuteLegacyAppsGameExtensions
{
private static string GenerateRequestSignature<TRequest>(DouyinMicroAppClient client, TRequest request, string httpMethod, string httpLocation)
where TRequest : Models.AppsGameWalletRequestBase
private static T PreprocessRequest<T>(DouyinMicroAppClient client, ref T request)
where T : Models.AppsGameWalletRequestBase, new()
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (client is null) throw new ArgumentNullException(nameof(request));
if (request is null) throw new ArgumentNullException(nameof(request));

/*
* REF: https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/api/payment/payment-signature-generation-algorithm
*/
if (request.AppId is null)
{
request.AppId = client.Credentials.AppId;
}

IDictionary<string, string> paramMap = new SortedDictionary<string, string>(
new Dictionary<string, string>()
if (request.Timestamp is null)
{
request.Timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds();
}

if (request.Signature is null)
{
string json = client.JsonSerializer.Serialize(request);
IDictionary<string, string> paramMap = new SortedDictionary<string, string>(Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, string>>(json)!, StringComparer.Ordinal);
foreach (var entry in paramMap)
{
{ "access_token", HttpUtility.UrlEncode(request.AccessToken ?? string.Empty) },
{ "appid", HttpUtility.UrlEncode(request.AppId ?? string.Empty) },
{ "openid", HttpUtility.UrlEncode(request.OpenId ?? string.Empty) },
{ "zone_id", HttpUtility.UrlEncode(request.ZoneId ?? string.Empty) },
{ "pf", HttpUtility.UrlEncode(request.Platform ?? string.Empty) },
{ "ts", request.Timestamp.ToString()! }
},
StringComparer.Ordinal
);
string plainText = string.Join("&", paramMap.Select(e => $"{e.Key}={e.Value}"))
+ $"&org_loc={httpLocation}"
+ $"&method={httpMethod.ToUpper()}";
return Utilities.HMACUtility.HashWithSHA256(client.Credentials.ECPaySalt ?? string.Empty, plainText).Value!.ToLower();
if (entry.Key == "mp_sig")
paramMap.Remove(entry.Key);
if (entry.Value is null)
paramMap.Remove(entry.Key);
}

string message = string.Join("&", paramMap.Select(e => $"{e.Key}={e.Value}"))
+ $"&org_loc={request.GetRequestPath()}"
+ $"&method={request.GetRequestMethod()}";
request.Signature = Utilities.HMACUtility.HashWithSHA256(client.Credentials.ECPaySalt!, message).Value!.ToLower();
}

return request;
}

/// <summary>
Expand All @@ -56,14 +64,7 @@ private static string GenerateRequestSignature<TRequest>(DouyinMicroAppClient cl
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));

if (request.AppId is null)
request.AppId = client.Credentials.AppId;

if (request.Timestamp is null)
request.Timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds();

if (request.Signature is null)
request.Signature = GenerateRequestSignature(client, request, HttpMethod.Post.Method, "/api/apps/game/wallet/get_balance");
PreprocessRequest(client, ref request);

IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "api", "apps", "game", "wallet", "get_balance")
Expand All @@ -88,14 +89,7 @@ private static string GenerateRequestSignature<TRequest>(DouyinMicroAppClient cl
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));

if (request.AppId is null)
request.AppId = client.Credentials.AppId;

if (request.Timestamp is null)
request.Timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds();

if (request.Signature is null)
request.Signature = GenerateRequestSignature(client, request, HttpMethod.Post.Method, "/api/apps/game/wallet/game_pay");
PreprocessRequest(client, ref request);

IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "api", "apps", "game", "wallet", "game_pay")
Expand All @@ -120,14 +114,7 @@ private static string GenerateRequestSignature<TRequest>(DouyinMicroAppClient cl
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));

if (request.AppId is null)
request.AppId = client.Credentials.AppId;

if (request.Timestamp is null)
request.Timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds();

if (request.Signature is null)
request.Signature = GenerateRequestSignature(client, request, HttpMethod.Post.Method, "/api/apps/game/wallet/add_coin");
PreprocessRequest(client, ref request);

IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "api", "apps", "game", "wallet", "add_coin")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
{
/// <summary>
/// <para>表示 [POST] /api/apps/game/wallet/add_coin 接口的请求。</para>
Expand All @@ -18,5 +18,15 @@ public class AppsGameWalletAddCoinRequest : AppsGameWalletRequestBase
[Newtonsoft.Json.JsonProperty("present_counts")]
[System.Text.Json.Serialization.JsonPropertyName("present_counts")]
public int PresentAmount { get; set; }

protected internal override string GetRequestMethod()
{
return "POST";
}

protected internal override string GetRequestPath()
{
return "/api/apps/game/wallet/add_coin";
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
{
/// <summary>
/// <para>表示 [POST] /api/apps/game/wallet/game_pay 接口的请求。</para>
Expand Down Expand Up @@ -32,5 +32,15 @@ public class AppsGameWalletGamePayRequest : AppsGameWalletRequestBase
[Newtonsoft.Json.JsonProperty("app_remark")]
[System.Text.Json.Serialization.JsonPropertyName("app_remark")]
public string? Remark { get; set; }

protected internal override string GetRequestMethod()
{
return "POST";
}

protected internal override string GetRequestPath()
{
return "/api/apps/game/wallet/game_pay";
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
namespace SKIT.FlurlHttpClient.ByteDance.MicroApp.Models
{
/// <summary>
/// <para>表示 [POST] /api/apps/game/wallet/get_balance 接口的请求。</para>
/// </summary>
public class AppsGameWalletGetBalanceRequest : AppsGameWalletRequestBase
{
protected internal override string GetRequestMethod()
{
return "POST";
}

protected internal override string GetRequestPath()
{
return "/api/apps/game/wallet/get_balance";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,9 @@ public abstract class AppsGameWalletRequestBase : DouyinMicroAppRequest
[Newtonsoft.Json.JsonProperty("mp_sig")]
[System.Text.Json.Serialization.JsonPropertyName("mp_sig")]
public string? Signature { get; set; }

protected internal abstract string GetRequestMethod();

protected internal abstract string GetRequestPath();
}
}

0 comments on commit 9c455b8

Please sign in to comment.