Read Parcel2Go label hash from order links when Hash is empty
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 26s
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 26s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
504a867351
commit
51c6748894
@@ -225,8 +225,9 @@ class ShippingController extends Controller
|
|||||||
abort_unless(ctype_digit($orderLineId), 404);
|
abort_unless(ctype_digit($orderLineId), 404);
|
||||||
$orders = $parcel2Go->fetch('me/orders/detail')['Orders'] ?? [];
|
$orders = $parcel2Go->fetch('me/orders/detail')['Orders'] ?? [];
|
||||||
$order = collect($orders)->first(fn ($order) => (string) ($order['OrderLineId'] ?? '') === $orderLineId);
|
$order = collect($orders)->first(fn ($order) => (string) ($order['OrderLineId'] ?? '') === $orderLineId);
|
||||||
abort_unless($order && ! empty($order['Hash']), 404);
|
$hash = $order ? $parcel2Go->labelHash($order) : null;
|
||||||
$pdf = $parcel2Go->labelPdf($orderLineId, $order['Hash']);
|
abort_unless($hash, 404);
|
||||||
|
$pdf = $parcel2Go->labelPdf($orderLineId, $hash);
|
||||||
|
|
||||||
return response($pdf, 200, [
|
return response($pdf, 200, [
|
||||||
'Content-Type' => 'application/pdf',
|
'Content-Type' => 'application/pdf',
|
||||||
|
|||||||
@@ -163,6 +163,25 @@ class Parcel2Go
|
|||||||
])->throw()->json() ?? [];
|
])->throw()->json() ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parcel2Go leaves the order's Hash empty and puts the label hash in its "labels-a4" link instead.
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $order
|
||||||
|
*/
|
||||||
|
public function labelHash(array $order): ?string
|
||||||
|
{
|
||||||
|
if (filled($order['Hash'] ?? null)) {
|
||||||
|
return (string) $order['Hash'];
|
||||||
|
}
|
||||||
|
$link = collect($order['Links'] ?? [])->first(fn ($link): bool => is_array($link) && str_starts_with((string) ($link['Name'] ?? ''), 'labels-a4'))['Link'] ?? null;
|
||||||
|
if (! is_string($link)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
parse_str((string) parse_url($link, PHP_URL_QUERY), $query);
|
||||||
|
|
||||||
|
return filled($query['hash'] ?? null) ? (string) $query['hash'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
public function labelPdf(string $reference, string $hash): string
|
public function labelPdf(string $reference, string $hash): string
|
||||||
{
|
{
|
||||||
$token = $this->profileConnected() ? $this->profileAccessToken() : $this->accessToken();
|
$token = $this->profileConnected() ? $this->profileAccessToken() : $this->accessToken();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<div class="p-6"><h3 class="text-lg font-semibold">Existing shipments</h3><p class="mt-1 text-sm text-slate-400">Current Parcel2Go progress and labels from your account history.</p></div>
|
<div class="p-6"><h3 class="text-lg font-semibold">Existing shipments</h3><p class="mt-1 text-sm text-slate-400">Current Parcel2Go progress and labels from your account history.</p></div>
|
||||||
<table class="w-full min-w-[800px] text-left text-sm"><thead class="border-y border-slate-800 text-slate-400"><tr><th class="p-4">Order</th><th class="p-4">Courier</th><th class="p-4">Service</th><th class="p-4">Progress</th><th class="p-4">Estimated delivery</th><th class="p-4">Recipient</th><th class="p-4">Destination</th><th class="p-4">Label</th></tr></thead><tbody class="divide-y divide-slate-800">
|
<table class="w-full min-w-[800px] text-left text-sm"><thead class="border-y border-slate-800 text-slate-400"><tr><th class="p-4">Order</th><th class="p-4">Courier</th><th class="p-4">Service</th><th class="p-4">Progress</th><th class="p-4">Estimated delivery</th><th class="p-4">Recipient</th><th class="p-4">Destination</th><th class="p-4">Label</th></tr></thead><tbody class="divide-y divide-slate-800">
|
||||||
@forelse(($orders['Orders'] ?? []) as $order)
|
@forelse(($orders['Orders'] ?? []) as $order)
|
||||||
<tr><td class="p-4">{{ $order['OrderLineId'] ?? '—' }}</td><td class="p-4">{{ $order['Courier'] ?? '—' }}</td><td class="p-4">{{ $order['Service'] ?? '—' }}</td><td class="p-4"><span @class(['rounded-full px-2 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $order['Tracking']['Delivered'] ?? false, 'bg-sky-500/10 text-sky-300' => ! ($order['Tracking']['Delivered'] ?? false)])>{{ ($order['Tracking']['Delivered'] ?? false) ? 'Delivered' : 'In transit' }}</span></td><td class="p-4">{{ app(\App\Services\Display::class)->dateTime($order['EstimatedDeliveryDate'] ?? null) }}</td><td class="p-4">{{ $order['DeliveryAddress']['ContactName'] ?? '—' }}</td><td class="p-4">{{ app(\App\Services\Display::class)->flag($order['DeliveryAddress'] ?? []) }}</td><td class="p-4">@if(! empty($order['Hash']) && ! empty($order['OrderLineId']))<a class="font-semibold text-brand hover:underline" href="{{ route('shipping.label', $order['OrderLineId']) }}">Download PDF</a>@else<span class="text-slate-500">Unavailable</span>@endif</td></tr>
|
<tr><td class="p-4">{{ $order['OrderLineId'] ?? '—' }}</td><td class="p-4">{{ $order['Courier'] ?? '—' }}</td><td class="p-4">{{ $order['Service'] ?? '—' }}</td><td class="p-4"><span @class(['rounded-full px-2 py-1 text-xs font-semibold', 'bg-emerald-500/10 text-emerald-300' => $order['Tracking']['Delivered'] ?? false, 'bg-sky-500/10 text-sky-300' => ! ($order['Tracking']['Delivered'] ?? false)])>{{ ($order['Tracking']['Delivered'] ?? false) ? 'Delivered' : 'In transit' }}</span></td><td class="p-4">{{ app(\App\Services\Display::class)->dateTime($order['EstimatedDeliveryDate'] ?? null) }}</td><td class="p-4">{{ $order['DeliveryAddress']['ContactName'] ?? '—' }}</td><td class="p-4">{{ app(\App\Services\Display::class)->flag($order['DeliveryAddress'] ?? []) }}</td><td class="p-4">@if(app(\App\Services\Parcel2Go::class)->labelHash($order) && ! empty($order['OrderLineId']))<a class="font-semibold text-brand hover:underline" href="{{ route('shipping.label', $order['OrderLineId']) }}">Download PDF</a>@else<span class="text-slate-500">Unavailable</span>@endif</td></tr>
|
||||||
@empty<tr><td colspan="8" class="p-6 text-slate-400">{{ $historyAvailable ? 'No shipments in Parcel2Go account history.' : 'Shipment history is unavailable. Check the Client Credentials in Settings.' }}</td></tr>@endforelse
|
@empty<tr><td colspan="8" class="p-6 text-slate-400">{{ $historyAvailable ? 'No shipments in Parcel2Go account history.' : 'Shipment history is unavailable. Check the Client Credentials in Settings.' }}</td></tr>@endforelse
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
</section>@endsection
|
</section>@endsection
|
||||||
|
|||||||
@@ -191,6 +191,25 @@ class IntegrationsTest extends TestCase
|
|||||||
Http::assertSent(fn ($request) => str_contains($request->url(), '/labels/123') && str_contains($request->url(), 'hash=order-hash'));
|
Http::assertSent(fn ($request) => str_contains($request->url(), '/labels/123') && str_contains($request->url(), 'hash=order-hash'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_shipping_label_uses_the_hash_from_order_links_when_hash_field_is_empty(): void
|
||||||
|
{
|
||||||
|
Http::preventStrayRequests();
|
||||||
|
Http::fake([
|
||||||
|
'https://auth.example.test/token' => Http::response(['access_token' => 'test-token']),
|
||||||
|
'https://shipping.example.test/api/me/orders/detail' => Http::response(['Orders' => [[
|
||||||
|
'OrderLineId' => 123, 'Hash' => null,
|
||||||
|
'Links' => [['Name' => 'labels-a4', 'Link' => 'https://www.parcel2go.com/label/orderline?media=0&orderlineid=123&hash=link%2Bhash%3D']],
|
||||||
|
]]]),
|
||||||
|
'https://shipping.example.test/api/labels/123*' => Http::response(['Base64EncodedLabels' => [base64_encode('%PDF-1.4 test label')]]),
|
||||||
|
]);
|
||||||
|
config()->set('services.parcel2go', ['client_id' => 'id', 'client_secret' => 'secret', 'auth_url' => 'https://auth.example.test/token', 'base_url' => 'https://shipping.example.test/api']);
|
||||||
|
|
||||||
|
$admin = User::factory()->create(['role' => 'admin']);
|
||||||
|
$this->actingAs($admin)->get(route('shipping'))->assertSee(route('shipping.label', 123), false);
|
||||||
|
$this->actingAs($admin)->get(route('shipping.label', 123))->assertOk()->assertSee('%PDF-1.4 test label');
|
||||||
|
Http::assertSent(fn ($request) => str_contains($request->url(), '/labels/123') && str_contains($request->url(), 'hash=link%2Bhash%3D'));
|
||||||
|
}
|
||||||
|
|
||||||
public function test_collection_booking_uses_quoted_service_and_available_date(): void
|
public function test_collection_booking_uses_quoted_service_and_available_date(): void
|
||||||
{
|
{
|
||||||
$this->pendingEtsyOrder();
|
$this->pendingEtsyOrder();
|
||||||
|
|||||||
Reference in New Issue
Block a user