83 lines
3.2 KiB
PHP
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];
|
|
}
|
|
}
|
|
}
|