Files
Антон Н. Николаев 2db9951ff6 Валидация payment_order.recipient.bank.name и payment_order.payment_period.year. Выплаты самозанятым теперь deprecated
Информация про чеки самозанятых в платежах и возвратах удалена - больше не поддерживаем сервисы для самозанятых
Добавлена возможность выставления счета по смс и email
Добавлена поддержка работы со списками выплат
Обновлен Copyright
2026-02-05 15:36:37 +03:00

468 lines
20 KiB
PHP
Raw Permalink 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
/*
* The MIT License
*
* Copyright (c) 2026 "YooMoney", NBСO LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace YooKassa\Request\Payouts;
use YooKassa\Common\AbstractRequest;
use YooKassa\Common\ListObject;
use YooKassa\Common\ListObjectInterface;
use YooKassa\Model\AmountInterface;
use YooKassa\Model\Deal\PayoutDealInfo;
use YooKassa\Model\Metadata;
use YooKassa\Model\MonetaryAmount;
use YooKassa\Request\Payouts\PayoutDestinationData\AbstractPayoutDestinationData;
use YooKassa\Request\Payouts\PayoutDestinationData\PayoutDestinationDataFactory;
use YooKassa\Validator\Constraints as Assert;
/**
* Класс, представляющий модель CreatePayoutRequest.
*
* Класс объекта запроса к API на проведение новой выплаты.
*
* @example 02-builder.php 182 26 Пример использования билдера
*
* @category Class
* @package YooKassa\Request
* @author cms@yoomoney.ru
* @link https://yookassa.ru/developers/api
* @property AmountInterface $amount Сумма создаваемой выплаты
* @property AbstractPayoutDestinationData $payoutDestinationData Данные платежного средства, на которое нужно сделать выплату. Обязательный параметр, если не передан payout_token.
* @property AbstractPayoutDestinationData $payout_destination_data Данные платежного средства, на которое нужно сделать выплату. Обязательный параметр, если не передан payout_token.
* @property string $payoutToken Токенизированные данные для выплаты. Например, синоним банковской карты. Обязательный параметр, если не передан payout_destination_data
* @property string $payout_token Токенизированные данные для выплаты. Например, синоним банковской карты. Обязательный параметр, если не передан payout_destination_data
* @property string $payment_method_id Идентификатор сохраненного способа оплаты, данные которого нужно использовать для проведения выплаты
* @property string $paymentMethodId Идентификатор сохраненного способа оплаты, данные которого нужно использовать для проведения выплаты
* @property PayoutDealInfo $deal Сделка, в рамках которой нужно провести выплату. Необходимо передавать, если вы проводите Безопасную сделку
* @property string $description Описание транзакции (не более 128 символов). Например: «Выплата по договору N»
* @property ListObjectInterface|PayoutPersonalData[] $personal_data Персональные данные получателя выплаты. Только для обычных выплат. Необходимо передавать в этих сценариях: - [выплаты с проверкой получателя](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-check) (только для выплат через СБП); - [выплаты с передачей данных получателя для выписок из реестра](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-data-send). В массиве можно одновременно передать несколько идентификаторов, но только для разных типов данных.
* @property ListObjectInterface|PayoutPersonalData[] $personalData Персональные данные получателя выплаты. Только для обычных выплат. Необходимо передавать в этих сценариях: - [выплаты с проверкой получателя](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-check) (только для выплат через СБП); - [выплаты с передачей данных получателя для выписок из реестра](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-data-send). В массиве можно одновременно передать несколько идентификаторов, но только для разных типов данных.
* @property Metadata $metadata Метаданные привязанные к выплате
*/
class CreatePayoutRequest extends AbstractRequest implements CreatePayoutRequestInterface
{
/** @var int Максимальная длина строки описания сделки. */
public const MAX_LENGTH_DESCRIPTION = 128;
/** @var int Максимальное количество объектов для персональных данных. */
public const MAX_PERSONAL_DATA = 2;
/** @var int Минимальное количество объектов для персональных данных. */
public const MIN_PERSONAL_DATA = 1;
/**
* Сумма создаваемой выплаты
*
* @var AmountInterface|null
*/
#[Assert\NotBlank]
#[Assert\Valid]
#[Assert\Type(MonetaryAmount::class)]
private ?AmountInterface $_amount = null;
/**
* Данные платежного средства, на которое нужно сделать выплату
*
* @var AbstractPayoutDestinationData|null
*/
#[Assert\Valid]
#[Assert\Type(AbstractPayoutDestinationData::class)]
private ?AbstractPayoutDestinationData $_payout_destination_data = null;
/**
* Токенизированные данные для выплаты. Например, синоним банковской карты.
* Обязательный параметр, если не передан `payout_destination_data` или `payment_method_id`.
*
* @var string|null
*/
#[Assert\Type('string')]
private ?string $_payout_token = null;
/**
* Идентификатор сохраненного способа оплаты, данные которого нужно использовать для проведения выплаты.
* [Подробнее о выплатах с использованием идентификатора сохраненного способа оплаты](https://yookassa.ru/developers/payouts/scenario-extensions/multipurpose-token)
* Обязательный параметр, если не передан payout_destination_data или payout_token.
*
* @var string|null
*/
#[Assert\Type('string')]
private ?string $_payment_method_id = null;
/**
* Сделка, в рамках которой нужно провести выплату
*
* @var PayoutDealInfo|null
*/
#[Assert\Valid]
#[Assert\Type(PayoutDealInfo::class)]
private ?PayoutDealInfo $_deal = null;
/**
* Описание транзакции (не более 128 символов). Например: «Выплата по договору 37».
*
* @var string|null
*/
#[Assert\Type('string')]
#[Assert\Length(max: self::MAX_LENGTH_DESCRIPTION)]
private ?string $_description = null;
/**
* Персональные данные получателя выплаты. Только для обычных выплат.
*
* Необходимо передавать в этих сценариях:
* - [выплаты с проверкой получателя](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-check) (только для выплат через СБП);
* - [выплаты с передачей данных получателя для выписок из реестра](https://yookassa.ru/developers/payouts/scenario-extensions/recipient-data-send).
*
* В массиве можно одновременно передать несколько идентификаторов, но только для разных типов данных.
*
* @var PayoutPersonalData[]|ListObjectInterface|null
*/
#[Assert\Valid]
#[Assert\AllType(PayoutPersonalData::class)]
#[Assert\Type(ListObject::class)]
#[Assert\Count(max: self::MAX_PERSONAL_DATA)]
#[Assert\Count(min: self::MIN_PERSONAL_DATA)]
private ?ListObject $_personal_data = null;
/**
* Любые дополнительные данные, которые нужны вам для работы (например, ваш внутренний идентификатор заказа).
*
* @var Metadata|null
*/
#[Assert\Type(Metadata::class)]
private ?Metadata $_metadata = null;
/**
* Возвращает сумму выплаты.
*
* @return AmountInterface|null Сумма выплаты
*/
public function getAmount(): ?AmountInterface
{
return $this->_amount;
}
/**
* Проверяет, была ли установлена сумма выплаты.
*
* @return bool True если сумма выплаты была установлена, false если нет
*/
public function hasAmount(): bool
{
return !empty($this->_amount);
}
/**
* Устанавливает сумму выплаты.
*
* @param AmountInterface|array|null $amount Сумма выплаты
*
* @return self
*/
public function setAmount(mixed $amount): self
{
$this->_amount = $this->validatePropertyValue('_amount', $amount);
return $this;
}
/**
* Возвращает данные для создания метода оплаты.
*
* @return AbstractPayoutDestinationData|null Данные используемые для создания метода оплаты
*/
public function getPayoutDestinationData(): ?AbstractPayoutDestinationData
{
return $this->_payout_destination_data;
}
/**
* Проверяет установлен ли объект с методом оплаты.
*
* @return bool True если объект метода оплаты установлен, false если нет
*/
public function hasPayoutDestinationData(): bool
{
return !empty($this->_payout_destination_data);
}
/**
* Устанавливает объект с информацией для создания метода оплаты.
*
* @param AbstractPayoutDestinationData|array|null $payout_destination_data Объект создания метода оплаты или null
*
* @return self
*/
public function setPayoutDestinationData($payout_destination_data): self
{
if (is_array($payout_destination_data)) {
$payout_destination_data = (new PayoutDestinationDataFactory)->factoryFromArray($payout_destination_data);
}
$this->_payout_destination_data = $this->validatePropertyValue('_payout_destination_data', $payout_destination_data);
return $this;
}
/**
* Возвращает токенизированные данные для выплаты.
*
* @return string|null Токенизированные данные для выплаты
*/
public function getPayoutToken(): ?string
{
return $this->_payout_token;
}
/**
* Проверяет наличие токенизированных данных для выплаты.
*
* @return bool True если токен установлен, false если нет
*/
public function hasPayoutToken(): bool
{
return !empty($this->_payout_token);
}
/**
* Устанавливает токенизированные данные для выплаты.
*
* @param string|null $payout_token Токенизированные данные для выплаты
*
* @return self
*/
public function setPayoutToken(?string $payout_token): self
{
$this->_payout_token = $this->validatePropertyValue('_payout_token', $payout_token);
return $this;
}
/**
* Возвращает идентификатор сохраненного способа оплаты.
*
* @return null|string Идентификатор сохраненного способа оплаты
*/
public function getPaymentMethodId(): ?string
{
return $this->_payment_method_id;
}
/**
* Проверяет наличие идентификатора сохраненного способа оплаты.
*
* @return bool True если идентификатора установлен, false если нет
*/
public function hasPaymentMethodId(): bool
{
return !empty($this->_payment_method_id);
}
/**
* Устанавливает идентификатор сохраненного способа оплаты.
*
* @param null|string $payment_method_id Идентификатор сохраненного способа оплаты
*
* @return self
*/
public function setPaymentMethodId(?string $payment_method_id = null): self
{
$this->_payment_method_id = $this->validatePropertyValue('_payment_method_id', $payment_method_id);
return $this;
}
/**
* Возвращает сделку, в рамках которой нужно провести выплату.
*
* @return PayoutDealInfo|null Сделка, в рамках которой нужно провести выплату
*/
public function getDeal(): ?PayoutDealInfo
{
return $this->_deal;
}
/**
* Проверяет наличие сделки в создаваемой выплате.
*
* @return bool True если сделка есть, false если нет
*/
public function hasDeal(): bool
{
return !empty($this->_deal);
}
/**
* Устанавливает сделку, в рамках которой нужно провести выплату.
*
* @param PayoutDealInfo|array|null $deal Сделка, в рамках которой нужно провести выплату
*
* @return self
*/
public function setDeal(mixed $deal): self
{
$this->_deal = $this->validatePropertyValue('_deal', $deal);
return $this;
}
/**
* Возвращает персональные данные получателя выплаты.
*
* @return PayoutPersonalData[]|ListObjectInterface Персональные данные получателя выплаты
*/
public function getPersonalData(): ListObjectInterface
{
if ($this->_personal_data === null) {
$this->_personal_data = new ListObject(PayoutPersonalData::class);
}
return $this->_personal_data;
}
/**
* Проверяет наличие персональных данных в создаваемой выплате.
*
* @return bool True если персональные данные есть, false если нет
*/
public function hasPersonalData(): bool
{
return !empty($this->_personal_data);
}
/**
* Устанавливает персональные данные получателя выплаты.
*
* @param ListObjectInterface|array|null $personal_data Персональные данные получателя выплаты
*
* @return self
*/
public function setPersonalData(mixed $personal_data = null): self
{
$this->_personal_data = $this->validatePropertyValue('_personal_data', $personal_data);
return $this;
}
/**
* Возвращает описание транзакции.
*
* @return string|null Описание транзакции
*/
public function getDescription(): ?string
{
return $this->_description;
}
/**
* Проверяет наличие описания транзакции в создаваемом платеже.
*
* @return bool True если описание транзакции есть, false если нет
*/
public function hasDescription(): bool
{
return null !== $this->_description;
}
/**
* Устанавливает описание транзакции.
*
* @param string|null $description Описание транзакции
*
* @return self
*/
public function setDescription(?string $description = null): self
{
$this->_description = $this->validatePropertyValue('_description', $description);
return $this;
}
/**
* Возвращает данные оплаты установленные мерчантом.
*
* @return Metadata|null Метаданные, привязанные к выплате
*/
public function getMetadata(): ?Metadata
{
return $this->_metadata;
}
/**
* Проверяет, были ли установлены метаданные выплаты.
*
* @return bool True если метаданные были установлены, false если нет
*/
public function hasMetadata(): bool
{
return !empty($this->_metadata) && $this->_metadata->count() > 0;
}
/**
* Устанавливает метаданные, привязанные к выплате.
*
* @param Metadata|array|null $metadata Метаданные выплаты, устанавливаемые мерчантом
*
* @return $this
*/
public function setMetadata(mixed $metadata = null): self
{
$this->_metadata = $this->validatePropertyValue('_metadata', $metadata);
return $this;
}
/**
* Проверяет на валидность текущий объект
*
* @return bool True если объект запроса валиден, false если нет
*/
public function validate(): bool
{
if (!$this->hasAmount()) {
$this->setValidationError('Amount field is required');
return false;
}
if (
($this->hasPayoutToken() && $this->hasPayoutDestinationData()) ||
($this->hasPayoutToken() && $this->hasPaymentMethodId()) ||
($this->hasPayoutDestinationData() && $this->hasPaymentMethodId())
) {
$this->setValidationError('Both payoutToken, payoutDestinationData and paymentMethodId values are specified');
return false;
}
if (!$this->hasPayoutToken() && !$this->hasPayoutDestinationData() && !$this->hasPaymentMethodId()) {
$this->setValidationError('Both payoutToken, payoutDestinationData and paymentMethodId values are not specified');
return false;
}
return true;
}
/**
* Возвращает билдер объектов запросов создания выплаты.
*
* @return CreatePayoutRequestBuilder Инстанс билдера объектов запросов
*/
public static function builder(): CreatePayoutRequestBuilder
{
return new CreatePayoutRequestBuilder();
}
}