feat: moneta 2.0, MONETA.Assistant payment module for PHPShop 6.7+
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MonetaPhpShop\protocol;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use MonetaPhpShop\Money;
|
||||
|
||||
/**
|
||||
* Âõîäÿùèé çàïðîñ ñåðâèñà íà Check URL (`MNT_COMMAND=CHECK`) èëè Pay URL.
|
||||
*/
|
||||
final class CallbackNotification
|
||||
{
|
||||
private const ACCOUNT_ID_MAX_LENGTH = 20;
|
||||
private const TRANSACTION_ID_MAX_LENGTH = 255;
|
||||
private const OPERATION_ID_MAX_LENGTH = 255;
|
||||
|
||||
/**
|
||||
* Íîìåð îïåðàöèè MONETA.RU â Pay URL — òîëüêî öèôðû
|
||||
*/
|
||||
private const PAY_OPERATION_ID = '/\A[0-9]{1,20}\z/';
|
||||
private const SUBSCRIBER_ID_MAX_LENGTH = 255;
|
||||
private const CURRENCY_LENGTH = 3;
|
||||
private const SIGNATURE_LENGTH = 32;
|
||||
|
||||
/** @var string */
|
||||
private $command;
|
||||
|
||||
/** @var string */
|
||||
private $accountId;
|
||||
|
||||
/** @var string */
|
||||
private $transactionId;
|
||||
|
||||
/** @var string */
|
||||
private $operationId;
|
||||
|
||||
/** @var string */
|
||||
private $rawAmount;
|
||||
|
||||
/** @var Money|null */
|
||||
private $amount;
|
||||
|
||||
/** @var string */
|
||||
private $currency;
|
||||
|
||||
/** @var string */
|
||||
private $subscriberId;
|
||||
|
||||
/** @var string */
|
||||
private $rawTestMode;
|
||||
|
||||
/** @var string */
|
||||
private $signature;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $fields ïàðàìåòðû çàïðîñà ($_POST èëè $_GET — ìåòîä çàäà¸òñÿ â íàñòðîéêàõ ñ÷¸òà)
|
||||
*/
|
||||
public function __construct(array $fields)
|
||||
{
|
||||
$this->command = self::optional($fields, 'MNT_COMMAND', strlen(AssistantProtocol::COMMAND_CHECK));
|
||||
if (($this->command !== '') && ($this->command !== AssistantProtocol::COMMAND_CHECK)) {
|
||||
throw new InvalidArgumentException('Íåèçâåñòíàÿ êîìàíäà óâåäîìëåíèÿ.');
|
||||
}
|
||||
|
||||
$this->accountId = self::required($fields, 'MNT_ID', self::ACCOUNT_ID_MAX_LENGTH);
|
||||
$this->transactionId = self::required($fields, 'MNT_TRANSACTION_ID', self::TRANSACTION_ID_MAX_LENGTH);
|
||||
$this->operationId = self::optional($fields, 'MNT_OPERATION_ID', self::OPERATION_ID_MAX_LENGTH);
|
||||
$this->rawAmount = self::optional($fields, 'MNT_AMOUNT', strlen(Money::MAX));
|
||||
$this->amount = $this->rawAmount === '' ? null : Money::fromDecimal($this->rawAmount);
|
||||
$this->currency = self::required($fields, 'MNT_CURRENCY_CODE', self::CURRENCY_LENGTH);
|
||||
$this->subscriberId = self::optional($fields, 'MNT_SUBSCRIBER_ID', self::SUBSCRIBER_ID_MAX_LENGTH);
|
||||
$this->rawTestMode = self::required($fields, 'MNT_TEST_MODE', 1);
|
||||
if (($this->rawTestMode !== '0') && ($this->rawTestMode !== '1')) {
|
||||
throw new InvalidArgumentException('Íåäîïóñòèìîå çíà÷åíèå MNT_TEST_MODE.');
|
||||
}
|
||||
$this->signature = self::required($fields, 'MNT_SIGNATURE', self::SIGNATURE_LENGTH);
|
||||
|
||||
if (
|
||||
(($this->amount === null) || (preg_match(self::PAY_OPERATION_ID, $this->operationId) !== 1))
|
||||
&& !$this->isCheck()
|
||||
) {
|
||||
throw new InvalidArgumentException('Óâåäîìëåíèþ îá îïëàòå íóæíû ñóììà è íîìåð îïåðàöèè èç öèôð.');
|
||||
}
|
||||
}
|
||||
|
||||
public function isCheck(): bool
|
||||
{
|
||||
return ($this->command === AssistantProtocol::COMMAND_CHECK);
|
||||
}
|
||||
|
||||
public function getCommand(): string
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
public function getAccountId(): string
|
||||
{
|
||||
return $this->accountId;
|
||||
}
|
||||
|
||||
public function getTransactionId(): string
|
||||
{
|
||||
return $this->transactionId;
|
||||
}
|
||||
|
||||
public function getOperationId(): string
|
||||
{
|
||||
return $this->operationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ñóììà êàê ïðèøëà — òîëüêî äëÿ ïîäïèñè; äëÿ ñâåðêè — {@see self::getAmount()}.
|
||||
*/
|
||||
public function getRawAmount(): string
|
||||
{
|
||||
return $this->rawAmount;
|
||||
}
|
||||
|
||||
public function getAmount(): ?Money
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->currency;
|
||||
}
|
||||
|
||||
public function getSubscriberId(): string
|
||||
{
|
||||
return $this->subscriberId;
|
||||
}
|
||||
|
||||
public function getRawTestMode(): string
|
||||
{
|
||||
return $this->rawTestMode;
|
||||
}
|
||||
|
||||
public function isTestMode(): bool
|
||||
{
|
||||
return $this->rawTestMode === '1';
|
||||
}
|
||||
|
||||
public function isSignedBy(Signature $signature): bool
|
||||
{
|
||||
return Signature::equals($signature->forNotification($this), $this->signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $fields
|
||||
*/
|
||||
private static function required(array $fields, string $name, int $maxLength): string
|
||||
{
|
||||
$value = self::optional($fields, $name, $maxLength);
|
||||
if ($value === '') {
|
||||
throw new InvalidArgumentException("Íå ïåðåäàíî ïîëå {$name}.");
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $fields
|
||||
*/
|
||||
private static function optional(array $fields, string $name, int $maxLength): string
|
||||
{
|
||||
if (!array_key_exists($name, $fields)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = $fields[$name];
|
||||
if (!is_string($value)) {
|
||||
throw new InvalidArgumentException("Ïîëå {$name} äîëæíî áûòü ñòðîêîé.");
|
||||
}
|
||||
if (strlen($value) > $maxLength) {
|
||||
throw new InvalidArgumentException("Ïîëå {$name} äëèííåå äîïóñòèìîãî.");
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user