Налаштування повного повернення коштів на 1С-Бітрікс
Повне повернення — скасування всього платежу та повернення покупцю повної суми замовлення. Технічно це простіше часткового повернення, але містить кілька нюансів: терміни можливості скасування, різниця між скасуванням передавторизації та поверненням списаних коштів, обов'язковий чек повернення при підключеній касі.
Скасування vs. повернення: у чому різниця
Скасування (void/cancel) — можливе лише до того, як банк провів розрахунок за транзакцією (зазвичай до кінця операційного дня). Кошти повертаються миттєво, оскільки фактично не були списані. У двостадійних платежах — це скасування передавторизації.
Повернення (refund) — після проведеного розрахунку. Гроші спочатку списані, потім надіслано зворотний переказ. Термін зарахування покупцю — 3–10 робочих днів залежно від банку.
Реалізація в обробнику
class MyGatewayHandler extends \Bitrix\Sale\PaySystem\ServiceHandler
implements \Bitrix\Sale\PaySystem\IRefund
{
public function refund(
\Bitrix\Sale\Payment $payment,
$refundableSum
): \Bitrix\Sale\PaySystem\ServiceResult {
$result = new \Bitrix\Sale\PaySystem\ServiceResult();
$externalId = $payment->getField('PS_INVOICE_ID');
// Повне повернення = сума платежу повністю
$fullAmount = $payment->getSum();
// Перевіряємо: сума повернення не перевищує суму платежу
if ($refundableSum > $fullAmount) {
$result->addError(new \Bitrix\Main\Error(
'Сума повернення (' . $refundableSum . ') перевищує суму платежу (' . $fullAmount . ')'
));
return $result;
}
try {
// Спочатку пробуємо скасування (швидше для покупця)
$cancelled = $this->tryCancel($externalId);
if (!$cancelled) {
// Якщо скасування неможливе — повне повернення через refund
$this->gateway->createRefund([
'payment_id' => $externalId,
'amount' => [
'value' => number_format($refundableSum, 2, '.', ''),
'currency' => $payment->getField('CURRENCY'),
],
]);
}
// Оновлюємо статус платежу в 1С-Бітрікс
$payment->setPaid('N');
$payment->setField('PS_STATUS', 'REFUNDED');
$payment->save();
$result->setOperationType(
\Bitrix\Sale\PaySystem\ServiceResult::MONEY_LEAVING
);
} catch (\Exception $e) {
$result->addError(new \Bitrix\Main\Error($e->getMessage()));
}
return $result;
}
private function tryCancel(string $externalId): bool
{
try {
$this->gateway->cancelPayment($externalId);
return true;
} catch (\Exception $e) {
// Якщо скасування неможливе (вже проведено розрахунок) — повертаємо false
return false;
}
}
}
Повне повернення через ЮКасу
// Простe повне повернення
$payment = $yookassaClient->getPaymentInfo($psInvoiceId);
$fullAmount = $payment->getAmount()->getValue();
$refund = $yookassaClient->createRefund([
'payment_id' => $psInvoiceId,
'amount' => ['value' => $fullAmount, 'currency' => 'RUB'],
'receipt' => $fullRefundReceipt, // при підключеній касі
], uniqid('', true));
Чек повернення (фіскальне законодавство)
При повному поверненні чек повинен містити всі позиції вихідного платежу з ознакою payment_mode: full_refund:
// Отримуємо позиції вихідного замовлення
$order = \Bitrix\Sale\Order::load($orderId);
$basket = $order->getBasket();
$refundItems = [];
foreach ($basket->getOrderableItems() as $item) {
$refundItems[] = [
'description' => $item->getField('NAME'),
'quantity' => $item->getQuantity(),
'amount' => ['value' => number_format($item->getPrice(), 2, '.', ''), 'currency' => 'RUB'],
'vat_code' => getVatCode($item),
'payment_subject' => 'commodity',
'payment_mode' => 'full_refund',
];
}
// Додаємо доставку
$delivery = $order->getDeliveryPrice();
if ($delivery > 0) {
$refundItems[] = [
'description' => 'Доставка',
'quantity' => 1,
'amount' => ['value' => number_format($delivery, 2, '.', ''), 'currency' => 'RUB'],
'vat_code' => 1,
'payment_subject' => 'service',
'payment_mode' => 'full_refund',
];
}
Статус замовлення після повернення
Після успішного повернення необхідно оновити статус замовлення:
// Змінюємо статус замовлення на «Скасовано» або «Повернення»
$order->setField('STATUS_ID', 'VD'); // код статусу «Повернення» — налаштовується
$order->save();
// Повертаємо товари на склад за потреби
if ($returnToStock) {
$shipmentCollection = $order->getShipmentCollection();
foreach ($shipmentCollection as $shipment) {
if (!$shipment->isSystem()) {
$shipment->setField('CANCELED', 'Y');
}
}
$order->save();
}
Терміни
| Завдання | Термін |
|---|---|
Метод refund в обробнику + оновлення статусу |
1 день |
| Чек повернення фіскального законодавства | 1 день |
| Тестування сценаріїв скасування та повернення | 0.5 дня |







