Files
Moodle/classes/local/protocol/Signature.php
T

107 lines
3.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace paygw_moneta\local\protocol;
use InvalidArgumentException;
use paygw_moneta\local\Money;
/**
* Три формулы подписи MONETA.Assistant (`MONETA.Assistant.ru.pdf`, гл. 3–5).
*
* Везде MD5 от конкатенации значений без разделителей плюс код проверки
* целостности; отсутствующий параметр — пустая строка. Экземпляр держит код,
* чтобы он не гулял по сигнатурам методов.
*
* @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 Signature
{
private const PATTERN = '/\A[0-9a-f]{32}\z/i';
public function __construct(
#[\SensitiveParameter]
private readonly string $integrityCode,
) {
if ($integrityCode === '') {
throw new InvalidArgumentException('Код проверки целостности не задан.');
}
}
/**
* Формула 1 — платёжная форма (модуль → сервис).
*
* md5(MNT_ID + MNT_TRANSACTION_ID + MNT_AMOUNT + MNT_CURRENCY_CODE + MNT_SUBSCRIBER_ID + MNT_TEST_MODE + КОД)
*/
public function forPaymentForm(
string $accountId,
string $transactionId,
Money $amount,
string $currency,
string $subscriberId,
bool $testMode,
): string {
return $this->hash(
$accountId
. $transactionId
. $amount->toDecimal()
. $currency
. $subscriberId
. AssistantProtocol::testModeFlag($testMode),
);
}
/**
* Формула 2 — входящий запрос на Check URL / Pay URL (сервис → модуль).
*
* md5(MNT_COMMAND + MNT_ID + MNT_TRANSACTION_ID + MNT_OPERATION_ID + MNT_AMOUNT
* + MNT_CURRENCY_CODE + MNT_SUBSCRIBER_ID + MNT_TEST_MODE + КОД)
*
* Значения берутся из запроса как пришли: подпись сверяется с тем, что
* подписал сервис, а не с нашим представлением о заказе.
*/
public function forNotification(CallbackNotification $notification): string
{
return $this->hash(
$notification->getCommand()
. $notification->getAccountId()
. $notification->getTransactionId()
. $notification->getOperationId()
. $notification->getRawAmount()
. $notification->getCurrency()
. $notification->getSubscriberId()
. $notification->getRawTestMode(),
);
}
/**
* Формула 3 — ответ модуля на Check URL и Pay URL.
*
* md5(MNT_RESULT_CODE + MNT_ID + MNT_TRANSACTION_ID + КОД)
*/
public function forResponse(ResultCode $resultCode, string $accountId, string $transactionId): string
{
return $this->hash((string) $resultCode->value . $accountId . $transactionId);
}
/**
* Сравнение без утечки по времени; регистр hex-строки не важен.
*/
public static function equals(string $expected, string $received): bool
{
if (preg_match(self::PATTERN, $received) !== 1) {
return false;
}
return hash_equals(strtolower($expected), strtolower($received));
}
private function hash(string $payload): string
{
return md5($payload . $this->integrityCode);
}
}