Files
2026-09-15 10:35:56 +08:00

89 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\LingxingErp\Model\Order;
use Esun\LingxingErp\Model\Api\ApiException;
use Esun\LingxingErp\Model\Api\Client;
use Esun\LingxingErp\Model\Api\Endpoint;
use Esun\LingxingErp\Model\Config;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Store\Model\StoreManagerInterface;
class OrderExporter
{
public function __construct(
private readonly Client $client,
private readonly Config $config,
private readonly OrderPayloadBuilder $payloadBuilder,
private readonly StoreManagerInterface $storeManager
) {
}
public function export(OrderInterface $order, ?array $payload = null): array
{
$payload ??= $this->payloadBuilder->build($order);
$websiteId = (int)$this->storeManager->getStore((int)$order->getStoreId())->getWebsiteId();
try {
$response = $this->client->post(Endpoint::ORDER_CREATE, $payload);
} catch (ApiException $exception) {
// The ERP may have committed the order even if the response was lost. Reconcile before retrying.
try {
$existing = $this->findExisting((string)$order->getIncrementId(), $websiteId);
} catch (\Throwable) {
throw $exception;
}
if ($existing !== null) {
return [
'payload' => $payload,
'response' => $exception->getResponse(),
'global_order_no' => $existing,
];
}
throw $exception;
}
$successes = $response['data']['success_details'] ?? [];
foreach (is_array($successes) ? $successes : [] as $success) {
if ((string)($success['platform_order_no'] ?? '') === (string)$order->getIncrementId()
&& (string)($success['global_order_no'] ?? '') !== '') {
return ['payload' => $payload, 'response' => $response, 'global_order_no' => (string)$success['global_order_no']];
}
}
$existing = $this->findExisting((string)$order->getIncrementId(), $websiteId);
if ($existing !== null) {
return ['payload' => $payload, 'response' => $response, 'global_order_no' => $existing];
}
$errors = $response['data']['error_details'] ?? [];
$message = is_array($errors) && $errors !== []
? implode('; ', array_filter(array_map(static fn(array $error): string => (string)($error['error_message'] ?? ''), $errors)))
: 'Lingxing did not return a success record for this order.';
throw new ApiException($message, 'order_not_created', $response);
}
private function findExisting(string $incrementId, int $websiteId): ?string
{
$response = $this->client->post(Endpoint::ORDER_LIST, [
'offset' => 0,
'length' => 20,
'store_id' => [$this->config->getLingxingStoreId($websiteId)],
'platform_code' => [$this->config->getPlatformCode($websiteId)],
'platform_order_nos' => [$incrementId],
]);
foreach (($response['data']['list'] ?? []) as $order) {
foreach (($order['platform_info'] ?? []) as $platformInfo) {
if ((string)($platformInfo['platform_order_no'] ?? '') === $incrementId) {
return (string)($order['global_order_no'] ?? '') ?: null;
}
}
foreach (($order['item_info'] ?? []) as $item) {
if ((string)($item['platform_order_no'] ?? '') === $incrementId) {
return (string)($order['global_order_no'] ?? '') ?: null;
}
}
}
return null;
}
}