$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 $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 $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; } }