feat(50-allegro-shipment-waybill-push): push waybill to allegro checkout form
Phase 50 complete: - add conditional waybill push for allegro orders only - add retry on ALLEGRO_HTTP_401 and non-critical failure handling - add unit tests and update architecture/changelog docs
This commit is contained in:
@@ -3,13 +3,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Modules\Shipments;
|
||||
|
||||
use App\Core\Exceptions\IntegrationConfigException;
|
||||
use App\Core\Exceptions\ShipmentException;
|
||||
use App\Modules\Orders\OrdersRepository;
|
||||
use App\Modules\Settings\AllegroApiClient;
|
||||
use App\Modules\Settings\AllegroTokenManager;
|
||||
use App\Modules\Settings\CompanySettingsRepository;
|
||||
use RuntimeException;
|
||||
use App\Core\Exceptions\IntegrationConfigException;
|
||||
use App\Core\Exceptions\ShipmentException;
|
||||
use Throwable;
|
||||
|
||||
final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
@@ -35,6 +35,7 @@ final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
{
|
||||
[$accessToken, $env] = $this->tokenManager->resolveToken();
|
||||
$response = $this->apiClient->getDeliveryServices($env, $accessToken);
|
||||
|
||||
return is_array($response['services'] ?? null) ? $response['services'] : [];
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
|
||||
$codAmount = (float) ($formData['cod_amount'] ?? 0);
|
||||
if ($codAmount > 0) {
|
||||
// Allegro WZA manages COD funds internally – iban/ownerName are not accepted
|
||||
// Allegro WZA manages COD funds internally - iban/ownerName are not accepted.
|
||||
$apiPayload['input']['cashOnDelivery'] = [
|
||||
'amount' => number_format($codAmount, 2, '.', ''),
|
||||
'currency' => strtoupper(trim((string) ($formData['cod_currency'] ?? 'PLN'))),
|
||||
@@ -196,14 +197,27 @@ final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
if ($status === 'SUCCESS' && $shipmentId !== '') {
|
||||
$details = $this->apiClient->getShipmentDetails($env, $accessToken, $shipmentId);
|
||||
$trackingNumber = trim((string) ($details['waybill'] ?? ''));
|
||||
$carrierId = trim((string) ($package['carrier_id'] ?? ''));
|
||||
if ($carrierId === '') {
|
||||
$carrierId = trim((string) ($details['carrierId'] ?? ''));
|
||||
}
|
||||
|
||||
$this->packages->update($packageId, [
|
||||
'status' => 'created',
|
||||
'shipment_id' => $shipmentId,
|
||||
'tracking_number' => $trackingNumber !== '' ? $trackingNumber : null,
|
||||
'carrier_id' => $carrierId !== '' ? $carrierId : ($package['carrier_id'] ?? null),
|
||||
'payload_json' => $details,
|
||||
]);
|
||||
|
||||
$this->pushWaybillToAllegroCheckoutForm(
|
||||
(int) ($package['order_id'] ?? 0),
|
||||
$trackingNumber,
|
||||
$carrierId,
|
||||
$accessToken,
|
||||
$env
|
||||
);
|
||||
|
||||
return [
|
||||
'status' => 'created',
|
||||
'shipment_id' => $shipmentId,
|
||||
@@ -268,16 +282,32 @@ final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
'label_path' => 'labels/' . $filename,
|
||||
];
|
||||
|
||||
// Refresh tracking number if not yet saved (may not have been available at creation time)
|
||||
// Refresh tracking number if not yet saved (may not have been available at creation time).
|
||||
if (trim((string) ($package['tracking_number'] ?? '')) === '') {
|
||||
try {
|
||||
$details = $this->apiClient->getShipmentDetails($env, $accessToken, $shipmentId);
|
||||
$trackingNumber = trim((string) ($details['waybill'] ?? ''));
|
||||
$carrierId = trim((string) ($package['carrier_id'] ?? ''));
|
||||
if ($carrierId === '') {
|
||||
$carrierId = trim((string) ($details['carrierId'] ?? ''));
|
||||
}
|
||||
|
||||
if ($trackingNumber !== '') {
|
||||
$updateFields['tracking_number'] = $trackingNumber;
|
||||
if ($carrierId !== '') {
|
||||
$updateFields['carrier_id'] = $carrierId;
|
||||
}
|
||||
|
||||
$this->pushWaybillToAllegroCheckoutForm(
|
||||
(int) ($package['order_id'] ?? 0),
|
||||
$trackingNumber,
|
||||
$carrierId,
|
||||
$accessToken,
|
||||
$env
|
||||
);
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// non-critical – label is still saved
|
||||
// non-critical - label is still saved
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,11 +389,87 @@ final class AllegroShipmentService implements ShipmentProviderInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function pushWaybillToAllegroCheckoutForm(
|
||||
int $orderId,
|
||||
string $trackingNumber,
|
||||
string $carrierId,
|
||||
string $accessToken,
|
||||
string $environment
|
||||
): void {
|
||||
if ($orderId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$waybill = trim($trackingNumber);
|
||||
if ($waybill === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$orderDetails = $this->ordersRepository->findDetails($orderId);
|
||||
if ($orderDetails === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = is_array($orderDetails['order'] ?? null) ? $orderDetails['order'] : [];
|
||||
$source = strtolower(trim((string) ($order['source'] ?? '')));
|
||||
if ($source !== 'allegro') {
|
||||
return;
|
||||
}
|
||||
|
||||
$checkoutFormId = trim((string) ($order['source_order_id'] ?? ''));
|
||||
if ($checkoutFormId === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$normalizedCarrierId = trim($carrierId);
|
||||
if ($normalizedCarrierId === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$carrierName = (string) ($this->packages->resolveCarrierName('allegro_wza', $normalizedCarrierId) ?? '');
|
||||
$carrierName = trim($carrierName);
|
||||
if ($carrierName === '') {
|
||||
$carrierName = $normalizedCarrierId;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->apiClient->addShipmentToOrder(
|
||||
$environment,
|
||||
$accessToken,
|
||||
$checkoutFormId,
|
||||
$waybill,
|
||||
$normalizedCarrierId,
|
||||
$carrierName
|
||||
);
|
||||
} catch (RuntimeException $exception) {
|
||||
if (trim($exception->getMessage()) !== 'ALLEGRO_HTTP_401') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
[$refreshedToken, $refreshedEnvironment] = $this->tokenManager->resolveToken();
|
||||
$this->apiClient->addShipmentToOrder(
|
||||
$refreshedEnvironment,
|
||||
$refreshedToken,
|
||||
$checkoutFormId,
|
||||
$waybill,
|
||||
$normalizedCarrierId,
|
||||
$carrierName
|
||||
);
|
||||
} catch (Throwable) {
|
||||
// non-critical - local shipment remains created
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// non-critical - local shipment remains created
|
||||
}
|
||||
}
|
||||
|
||||
private function generateUuid(): string
|
||||
{
|
||||
$data = random_bytes(16);
|
||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user