fix(track): send UpsertSmallBag auth via HTTP headers

Track SignatureValidationFilter reads appKey/timestamp/sign from headers, not query. Reverts e642f08 query transport and aligns debug script.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-06-29 12:35:39 +08:00
parent eac7b84f6a
commit bd1288edc9
3 changed files with 25 additions and 22 deletions

View File

@ -1,6 +1,6 @@
# 单独调试 POST /OrderV2/UpsertSmallBag(与 SmallBagTrackOrderClient 一致) # 单独调试 POST /OrderV2/UpsertSmallBag(与 SmallBagTrackOrderClient 一致:鉴权走 Header)
param( param(
[string]$BaseUrl = "http://api.nanafa.com/track", [string]$BaseUrl = "https://api.nanafa.com/track",
[string]$AppKey = "W2606001", [string]$AppKey = "W2606001",
[string]$AppSecret = "ziK8UzlQ39m3kdL346XEBg8nljY8os52", [string]$AppSecret = "ziK8UzlQ39m3kdL346XEBg8nljY8os52",
[string]$OrderNo = "", [string]$OrderNo = "",
@ -40,19 +40,18 @@ $body = @{
} }
} | ConvertTo-Json -Depth 5 -Compress } | ConvertTo-Json -Depth 5 -Compress
$base = $BaseUrl.TrimEnd('/') $url = ($BaseUrl.TrimEnd('/')) + "/OrderV2/UpsertSmallBag"
$url = "$base/OrderV2/UpsertSmallBag?appKey=$([uri]::EscapeDataString($AppKey))&timestamp=$timestamp&sign=$([uri]::EscapeDataString($sign))"
Write-Host "========== UpsertSmallBag Debug ==========" -ForegroundColor Cyan Write-Host "========== UpsertSmallBag Debug ==========" -ForegroundColor Cyan
Write-Host "URL: $url" Write-Host "URL: $url"
Write-Host "Timestamp: $timestamp" Write-Host "Headers: appKey=$AppKey, timestamp=$timestamp, sign=$sign"
Write-Host "Sign: $sign"
Write-Host "Body:" Write-Host "Body:"
Write-Host ($body | ConvertFrom-Json | ConvertTo-Json -Depth 5) Write-Host ($body | ConvertFrom-Json | ConvertTo-Json -Depth 5)
Write-Host "========================================" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan
try { try {
$response = Invoke-WebRequest -Uri $url -Method POST ` $response = Invoke-WebRequest -Uri $url -Method POST `
-Headers @{ appKey = $AppKey; timestamp = "$timestamp"; sign = $sign } `
-ContentType "application/json; charset=utf-8" ` -ContentType "application/json; charset=utf-8" `
-Body ([System.Text.Encoding]::UTF8.GetBytes($body)) ` -Body ([System.Text.Encoding]::UTF8.GetBytes($body)) `
-UseBasicParsing -UseBasicParsing
@ -64,12 +63,12 @@ catch {
$reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream()) $reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
$errBody = $reader.ReadToEnd() $errBody = $reader.ReadToEnd()
Write-Host "HTTP $([int]$_.Exception.Response.StatusCode)" -ForegroundColor Red Write-Host "HTTP $([int]$_.Exception.Response.StatusCode)" -ForegroundColor Red
if ($errBody) { Write-Host $errBody } else { Write-Host "(empty body — 请核对 appKey/appSecret 或联系轨迹平台)" } if ($errBody) { Write-Host $errBody } else { Write-Host "(empty body)" }
} }
else { else {
Write-Host $_.Exception.Message -ForegroundColor Red Write-Host $_.Exception.Message -ForegroundColor Red
} }
Write-Host "" Write-Host ""
Write-Host "Tip: start OMS and POST /order/debug/track-upsert-small-bag with optional body fields." -ForegroundColor Yellow Write-Host "Tip: track SignatureValidationFilter reads appKey/timestamp/sign from HTTP Headers." -ForegroundColor Yellow
exit 1 exit 1
} }

View File

@ -67,13 +67,25 @@ internal sealed class SmallBagTrackOrderClient(
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var sign = SmallBagTrackSignHelper.GenerateSign(appKey, timestamp, settings.AppSecret.Trim()); var sign = SmallBagTrackSignHelper.GenerateSign(appKey, timestamp, settings.AppSecret.Trim());
var body = SmallBagTrackUpsertApiRequest.FromBusinessRequest(request); var body = SmallBagTrackUpsertApiRequest.FromBusinessRequest(request);
var url = SmallBagTrackUpsertApiRequest.BuildRequestUrl(settings.BaseUrl, appKey, timestamp, sign); var url = SmallBagTrackUpsertApiRequest.BuildEndpointUrl(settings.BaseUrl);
var requestJson = JsonSerializer.Serialize(body, JsonOptions); var requestJson = JsonSerializer.Serialize(
new
{
auth = new { appKey, timestamp, sign, transport = "header" },
body
},
JsonOptions);
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
httpRequest.Headers.TryAddWithoutValidation("appKey", appKey);
httpRequest.Headers.TryAddWithoutValidation("timestamp", timestamp.ToString());
httpRequest.Headers.TryAddWithoutValidation("sign", sign);
httpRequest.Content = JsonContent.Create(body, options: JsonOptions);
var client = httpClientFactory.CreateClient(HttpClientName); var client = httpClientFactory.CreateClient(HttpClientName);
client.Timeout = TimeSpan.FromSeconds(Math.Max(5, settings.TimeoutSeconds)); client.Timeout = TimeSpan.FromSeconds(Math.Max(5, settings.TimeoutSeconds));
using var response = await client.PostAsJsonAsync(url, body, cancellationToken); using var response = await client.SendAsync(httpRequest, cancellationToken);
var responseBody = await response.Content.ReadAsStringAsync(cancellationToken); var responseBody = await response.Content.ReadAsStringAsync(cancellationToken);
return new SmallBagTrackUpsertResult return new SmallBagTrackUpsertResult
{ {

View File

@ -1,7 +1,7 @@
namespace Oms.Application.Integrations.SmallBagTrack; namespace Oms.Application.Integrations.SmallBagTrack;
/// <summary> /// <summary>
/// POST /OrderV2/UpsertSmallBag 业务请求体(公共参数 appKey/timestamp/sign 走 Query)。 /// POST /OrderV2/UpsertSmallBag 业务请求体(公共参数 appKey/timestamp/sign 走 HTTP Header)。
/// </summary> /// </summary>
internal sealed class SmallBagTrackUpsertApiRequest internal sealed class SmallBagTrackUpsertApiRequest
{ {
@ -34,14 +34,6 @@ internal sealed class SmallBagTrackUpsertApiRequest
Consignee = request.Consignee Consignee = request.Consignee
}; };
public static string BuildRequestUrl(string baseUrl, string appKey, long timestamp, string sign) public static string BuildEndpointUrl(string baseUrl) =>
{ $"{baseUrl.Trim().TrimEnd('/')}/OrderV2/UpsertSmallBag";
var root = $"{baseUrl.Trim().TrimEnd('/')}/OrderV2/UpsertSmallBag";
var query = string.Join(
'&',
$"appKey={Uri.EscapeDataString(appKey)}",
$"timestamp={timestamp}",
$"sign={Uri.EscapeDataString(sign)}");
return $"{root}?{query}";
}
} }