54 lines
2.2 KiB
PHP
54 lines
2.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace paygw_moneta\local\protocol;
|
|
|
|
use core_date;
|
|
use DateTimeImmutable;
|
|
|
|
/**
|
|
* `MNT_TRANSACTION_ID` — идентификатор заказа, который модуль отдаёт в платёжной
|
|
* форме и получает обратно в Check URL, Pay URL и на странице возврата: UUID заказа
|
|
* плюс метка времени, `0192b4c1-…_20260924143005MSK`. Метка — только для людей
|
|
* (в личном кабинете Moneta и в переписке с поддержкой по ней видно, когда открыта форма),
|
|
* поэтому она в часовом поясе сайта, а не в UTC; обратно она не читается, parse()
|
|
* берёт только UUID.
|
|
*
|
|
* @package paygw_moneta
|
|
* @copyright 2026 Moneta Labs {@link https://moneta.ru/}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
final class AssistantTransactionId
|
|
{
|
|
/**
|
|
* Номер заказа — UUID в нижнем регистре ({@see \paygw_moneta\local\order\TransactionRepository::create()}).
|
|
* Фрагмент шаблона без якорей: его же проверяет
|
|
* {@see \paygw_moneta\local\order\TransactionRepository::isMerchantOrderId()}.
|
|
*/
|
|
public const ORDER_ID = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
|
|
|
|
public const SEPARATOR = '_';
|
|
|
|
private const PATTERN = '/\A
|
|
(?<id>' . self::ORDER_ID . ') # UUID заказа
|
|
' . self::SEPARATOR . ' # разделитель
|
|
[0-9]{14} # метка времени YmdHis
|
|
(?:[A-Z0-9+\-]{1,6})? # пояс: MSK, +03 — не обязателен
|
|
\z/x';
|
|
|
|
private function __construct() {}
|
|
|
|
public static function build(string $orderId, ?DateTimeImmutable $now = null): string
|
|
{
|
|
$now ??= new DateTimeImmutable('now', core_date::get_server_timezone_object());
|
|
|
|
return $orderId . self::SEPARATOR . $now->format('YmdHisT');
|
|
}
|
|
|
|
public static function parse(string $raw): ?string
|
|
{
|
|
return preg_match(self::PATTERN, $raw, $matches) === 1 ? $matches['id'] : null;
|
|
}
|
|
}
|