fix(track): forward Authorization Bearer to UpsertSmallBag
Track gateway requires the logged-in user JWT in addition to appKey/timestamp/sign headers. Capture token before async enqueue so background sync still works. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
bd1288edc9
commit
3046f26837
@ -1,8 +1,9 @@
|
|||||||
# 单独调试 POST /OrderV2/UpsertSmallBag(与 SmallBagTrackOrderClient 一致:鉴权走 Header)
|
# 单独调试 POST /OrderV2/UpsertSmallBag(与 SmallBagTrackOrderClient 一致:鉴权走 Header + Bearer)
|
||||||
param(
|
param(
|
||||||
[string]$BaseUrl = "https://api.nanafa.com/track",
|
[string]$BaseUrl = "https://api.nanafa.com/track",
|
||||||
[string]$AppKey = "W2606001",
|
[string]$AppKey = "W2606001",
|
||||||
[string]$AppSecret = "ziK8UzlQ39m3kdL346XEBg8nljY8os52",
|
[string]$AppSecret = "ziK8UzlQ39m3kdL346XEBg8nljY8os52",
|
||||||
|
[string]$Authorization = "",
|
||||||
[string]$OrderNo = "",
|
[string]$OrderNo = "",
|
||||||
[string]$Client = "TEST001"
|
[string]$Client = "TEST001"
|
||||||
)
|
)
|
||||||
@ -45,13 +46,25 @@ $url = ($BaseUrl.TrimEnd('/')) + "/OrderV2/UpsertSmallBag"
|
|||||||
Write-Host "========== UpsertSmallBag Debug ==========" -ForegroundColor Cyan
|
Write-Host "========== UpsertSmallBag Debug ==========" -ForegroundColor Cyan
|
||||||
Write-Host "URL: $url"
|
Write-Host "URL: $url"
|
||||||
Write-Host "Headers: appKey=$AppKey, timestamp=$timestamp, sign=$sign"
|
Write-Host "Headers: appKey=$AppKey, timestamp=$timestamp, sign=$sign"
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($Authorization)) {
|
||||||
|
Write-Host "Headers: Authorization=<provided>"
|
||||||
|
}
|
||||||
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 {
|
||||||
|
$headers = @{
|
||||||
|
appKey = $AppKey
|
||||||
|
timestamp = "$timestamp"
|
||||||
|
sign = $sign
|
||||||
|
}
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($Authorization)) {
|
||||||
|
$headers.Authorization = $Authorization
|
||||||
|
}
|
||||||
|
|
||||||
$response = Invoke-WebRequest -Uri $url -Method POST `
|
$response = Invoke-WebRequest -Uri $url -Method POST `
|
||||||
-Headers @{ appKey = $AppKey; timestamp = "$timestamp"; sign = $sign } `
|
-Headers $headers `
|
||||||
-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
|
||||||
@ -69,6 +82,6 @@ catch {
|
|||||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||||
}
|
}
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Tip: track SignatureValidationFilter reads appKey/timestamp/sign from HTTP Headers." -ForegroundColor Yellow
|
Write-Host "Tip: track gateway requires Authorization Bearer from logged-in user, plus appKey/timestamp/sign headers." -ForegroundColor Yellow
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Oms.Application.Integrations.SmallBagTrack;
|
namespace Oms.Application.Integrations.SmallBagTrack;
|
||||||
@ -7,6 +9,7 @@ namespace Oms.Application.Integrations.SmallBagTrack;
|
|||||||
internal sealed class SmallBagTrackOrderClient(
|
internal sealed class SmallBagTrackOrderClient(
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
ISmallBagTrackConfigProvider configProvider,
|
ISmallBagTrackConfigProvider configProvider,
|
||||||
|
IHttpContextAccessor httpContextAccessor,
|
||||||
ILogger<SmallBagTrackOrderClient> logger) : ISmallBagTrackOrderClient
|
ILogger<SmallBagTrackOrderClient> logger) : ISmallBagTrackOrderClient
|
||||||
{
|
{
|
||||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||||
@ -68,10 +71,18 @@ internal sealed class SmallBagTrackOrderClient(
|
|||||||
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.BuildEndpointUrl(settings.BaseUrl);
|
var url = SmallBagTrackUpsertApiRequest.BuildEndpointUrl(settings.BaseUrl);
|
||||||
|
var authorization = ResolveAuthorization(request);
|
||||||
var requestJson = JsonSerializer.Serialize(
|
var requestJson = JsonSerializer.Serialize(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
auth = new { appKey, timestamp, sign, transport = "header" },
|
auth = new
|
||||||
|
{
|
||||||
|
appKey,
|
||||||
|
timestamp,
|
||||||
|
sign,
|
||||||
|
transport = "header",
|
||||||
|
authorizationForwarded = !string.IsNullOrWhiteSpace(authorization)
|
||||||
|
},
|
||||||
body
|
body
|
||||||
},
|
},
|
||||||
JsonOptions);
|
JsonOptions);
|
||||||
@ -80,6 +91,7 @@ internal sealed class SmallBagTrackOrderClient(
|
|||||||
httpRequest.Headers.TryAddWithoutValidation("appKey", appKey);
|
httpRequest.Headers.TryAddWithoutValidation("appKey", appKey);
|
||||||
httpRequest.Headers.TryAddWithoutValidation("timestamp", timestamp.ToString());
|
httpRequest.Headers.TryAddWithoutValidation("timestamp", timestamp.ToString());
|
||||||
httpRequest.Headers.TryAddWithoutValidation("sign", sign);
|
httpRequest.Headers.TryAddWithoutValidation("sign", sign);
|
||||||
|
ApplyAuthorization(httpRequest, authorization);
|
||||||
httpRequest.Content = JsonContent.Create(body, options: JsonOptions);
|
httpRequest.Content = JsonContent.Create(body, options: JsonOptions);
|
||||||
|
|
||||||
var client = httpClientFactory.CreateClient(HttpClientName);
|
var client = httpClientFactory.CreateClient(HttpClientName);
|
||||||
@ -98,6 +110,26 @@ internal sealed class SmallBagTrackOrderClient(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? ResolveAuthorization(SmallBagTrackUpsertRequest request)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(request.Authorization))
|
||||||
|
{
|
||||||
|
return request.Authorization.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpContextAccessor.HttpContext?.Request.Headers.Authorization.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyAuthorization(HttpRequestMessage httpRequest, string? authorization)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(authorization))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpRequest.Headers.Authorization = AuthenticationHeaderValue.Parse(authorization);
|
||||||
|
}
|
||||||
|
|
||||||
private static SmallBagTrackUpsertResult Skipped(string reason) =>
|
private static SmallBagTrackUpsertResult Skipped(string reason) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,6 +20,11 @@ public class SmallBagTrackUpsertRequest
|
|||||||
public string ApiCode { get; set; } = string.Empty;
|
public string ApiCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
public SmallBagTrackConsigneeRequest Consignee { get; set; } = new();
|
public SmallBagTrackConsigneeRequest Consignee { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转发到轨迹网关的 Authorization(异步入队前从当前 HTTP 请求捕获)。
|
||||||
|
/// </summary>
|
||||||
|
public string? Authorization { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SmallBagTrackConsigneeRequest
|
public class SmallBagTrackConsigneeRequest
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Fake.Application;
|
using Fake.Application;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Oms.Application.Dtos.Channels;
|
using Oms.Application.Dtos.Channels;
|
||||||
using Oms.Application.Dtos.Orders;
|
using Oms.Application.Dtos.Orders;
|
||||||
@ -1444,6 +1445,18 @@ public partial class OrderService
|
|||||||
OrderParcelReceiverInput? receiver)
|
OrderParcelReceiverInput? receiver)
|
||||||
{
|
{
|
||||||
var request = await BuildSmallBagTrackUpsertRequestAsync(order, receiver);
|
var request = await BuildSmallBagTrackUpsertRequestAsync(order, receiver);
|
||||||
|
var authorization = LazyServiceProvider
|
||||||
|
.GetRequiredService<IHttpContextAccessor>()
|
||||||
|
.HttpContext?
|
||||||
|
.Request
|
||||||
|
.Headers
|
||||||
|
.Authorization
|
||||||
|
.ToString();
|
||||||
|
if (!string.IsNullOrWhiteSpace(authorization))
|
||||||
|
{
|
||||||
|
request.Authorization = authorization;
|
||||||
|
}
|
||||||
|
|
||||||
SmallBagTrackOrderNotifier.Enqueue(request);
|
SmallBagTrackOrderNotifier.Enqueue(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user