Files
zyt/server/app/common/service/pharmacy/EjPharmacyCallbackWorkflow.php
T
2026-07-22 14:50:34 +08:00

83 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
namespace app\common\service\pharmacy;
use Closure;
use DomainException;
use InvalidArgumentException;
use RuntimeException;
use Throwable;
final class EjPharmacyCallbackWorkflow
{
private Closure $loadInbox;
private Closure $createInbox;
private Closure $reloadInbox;
private Closure $process;
private Closure $markFailed;
private Closure $isDuplicateKey;
public function __construct(
callable $loadInbox,
callable $createInbox,
callable $reloadInbox,
callable $process,
callable $markFailed,
callable $isDuplicateKey
) {
$this->loadInbox = Closure::fromCallable($loadInbox);
$this->createInbox = Closure::fromCallable($createInbox);
$this->reloadInbox = Closure::fromCallable($reloadInbox);
$this->process = Closure::fromCallable($process);
$this->markFailed = Closure::fromCallable($markFailed);
$this->isDuplicateKey = Closure::fromCallable($isDuplicateKey);
}
/** @param array<string,mixed> $payload @return array<string,mixed> */
public function handle(array $payload): array
{
$eventId = trim((string) ($payload['event_id'] ?? ''));
if ($eventId === '') {
return ['http_status' => 422, 'message' => 'event_id is required', 'duplicate' => false];
}
$inbox = ($this->loadInbox)($eventId);
if (is_array($inbox) && strtoupper((string) ($inbox['process_status'] ?? '')) === 'PROCESSED') {
return ['http_status' => 200, 'message' => 'ok', 'duplicate' => true];
}
if (!is_array($inbox)) {
try {
$inbox = ($this->createInbox)($payload);
} catch (Throwable $exception) {
if (!(bool) ($this->isDuplicateKey)($exception)) {
return ['http_status' => 500, 'message' => $exception->getMessage(), 'duplicate' => false];
}
$inbox = ($this->reloadInbox)($eventId);
if (!is_array($inbox)) {
return ['http_status' => 500, 'message' => 'callback inbox race could not be reloaded', 'duplicate' => false];
}
if (strtoupper((string) ($inbox['process_status'] ?? '')) === 'PROCESSED') {
return ['http_status' => 200, 'message' => 'ok', 'duplicate' => true];
}
}
}
try {
($this->process)($inbox, $payload);
return ['http_status' => 200, 'message' => 'ok', 'duplicate' => false];
} catch (EjPharmacyCallbackRetryException $exception) {
($this->markFailed)($inbox, $exception->getMessage());
return ['http_status' => 503, 'message' => $exception->getMessage(), 'duplicate' => false];
} catch (InvalidArgumentException|DomainException $exception) {
($this->markFailed)($inbox, $exception->getMessage());
return ['http_status' => 422, 'message' => $exception->getMessage(), 'duplicate' => false];
} catch (Throwable $exception) {
($this->markFailed)($inbox, $exception->getMessage());
return ['http_status' => 500, 'message' => $exception->getMessage(), 'duplicate' => false];
}
}
}