Integrating Partial Refunds in 1C-Bitrix: APIs and Fiscal Receipts
Partial returns in an online store on Bitrix are technically complex. One item is defective, another doesn't fit: you need to return not the entire amount but only a part, correctly recalculate the receipt per 54-FZ, and update statuses. An error in the receipt leads to significant fines. With over 10 years of experience and more than 30 successful integrations, we guarantee correct fiscal data handling. If you've encountered partial refund errors, get a consultation from our engineer.
Why Partial Return Is a Non-Trivial Task for Bitrix
Standard Bitrix modules often support only full refunds. According to 1C-Bitrix documentation on the Sale module, partial refunds require custom development: integration with payment system APIs, generating a refund receipt per 54-FZ, and updating statuses in the Sale module. Without quality implementation, discrepancies between the refund amount and the receipt can occur, leading to cash register blocking by tax authorities. In 95% of cases, the error is due to a mismatch between the refund amount and the receipt amount. Partial returns account for approximately 20% of all refund requests in e-commerce.
Where Partial Refund Is Executed
A partial refund is initiated by the store via the payment system API. The buyer contacts support, and the manager processes the refund in the Bitrix admin panel — either through the standard interface (if the module supports it) or through a custom handler. We implement a convenient interface for the manager with item selection and automatic request generation. For instance, a recent partial refund for a clothing store was a partial amount for a returned shirt.
How to Ensure the Refund Receipt Is Correct?
The key point is that the total of items in the receipt must exactly match the refund amount. Even a penny discrepancy will cause an OFD error. We use automatic verification before sending: compare the final total with the requested amount; if they don't match, we block sending and display a warning. This eliminates fines. Additionally, we implement logging of all requests for audit.
Refund API Examples
| Parameter | Tinkoff | YooKassa |
|---|---|---|
| Method | /v2/Cancel | createRefund |
| Signature | Token (MD5) | Basic Auth (shopId + secret) |
| Refund receipt | Not passed separately | Passed in request body |
| Error handling | HTTP 200 with ErrorCode field | ClientException exceptions |
Tinkoff:
$params = [ 'TerminalKey' => TINKOFF_TERMINAL, 'PaymentId' => $externalPaymentId, // Payment ID in Tinkoff 'Amount' => (int)($refundAmount * 100), // kopecks ]; $params['Token'] = tinkoffSign($params, TINKOFF_SECRET); $result = tinkoffPost('/v2/Cancel', $params); // result['Status'] === 'REFUNDED' — successful refund YooKassa:
use YooKassa\Client; $client = new Client(); $client->setAuth($shopId, $secretKey); $refund = $client->createRefund([ 'payment_id' => $externalPaymentId, 'amount' => [ 'value' => number_format($refundAmount, 2, '.', ''), 'currency' => 'RUB', ], 'description' => 'Refund of item: ' . $itemName, 'receipt' => $refundReceiptData, // mandatory if cash register connected ], uniqid('', true)); Refund Receipt (54-FZ)
If an online cash register is connected, a partial refund requires sending a refund receipt to the OFD. The structure of the refund receipt is identical to the original, but:
- Document
type:refund(in ATOL),payment_refund(in YooKassa) - The receipt includes only the returned items with the returned amounts
- The total of items in the receipt must exactly match the refund amount
// Example refund receipt for YooKassa $refundReceiptData = [ 'customer' => ['email' => $buyer->getEmail()], 'items' => [], ]; foreach ($refundItems as $item) { $refundReceiptData['items'][] = [ 'description' => $item['name'], 'quantity' => $item['quantity'], 'amount' => [ 'value' => number_format($item['price'] * $item['quantity'], 2, '.', ''), 'currency' => 'RUB', ], 'vat_code' => $item['vat_code'], 'payment_subject' => 'commodity', 'payment_mode' => 'full_payment', ]; } // Check: item total === refund amount $itemsTotal = array_sum(array_column( array_map(fn($i) => ['sum' => $i['price'] * $i['quantity']], $refundItems), 'sum' )); assert(abs($itemsTotal - $refundAmount) < 0.01, 'Receipt total mismatch!'); Updating Statuses in Bitrix
After a successful refund, the state in the Sale module needs to be updated:
// Partial refund — do not mark payment as fully "refunded" // Only record the refund amount and update item status $payment = $order->getPaymentCollection()->getItemById($paymentId); $payment->setField('PS_STATUS_MESSAGE', 'Partial refund ' . $refundAmount . ' RUB from ' . date('d.m.Y') ); // Update status of returned items foreach ($refundItems as $refundItem) { $basketItem = getBasketItemById($order, $refundItem['basket_id']); if ($basketItem) { $basketItem->setField('CUSTOM_PRICE', 'Y'); // Or create a separate entry in refund history } } $order->save(); Case from Our Practice: Clothing Store, Partial Order Return
A buyer ordered several items. One item didn't fit — a partial refund was processed. The standard Bitrix interface couldn't handle it: the Tinkoff module only supported full refunds. Our client came to us.
Solution: a custom refund handler in /local/. The manager selects items to return → a PHP script generates the refund receipt, calls /v2/Cancel with the partial amount, and records the result in a custom order field. Development time: 3 days. The custom solution turned out to be 2 times faster than standard modules when processing partial refunds.
Common Errors and Solutions
- Mismatch between refund amount and receipt total — use automatic verification.
- Request signature error (Token) — check parameter order and case.
- Duplicate requests — apply idempotency via
uniqid. - Incorrect VAT code — verify with fiscal register settings.
What's Included in the Work
- Audit of current Bitrix configuration and payment gateways
- Architecture design for partial refund
- Implementation of custom handler with API integration
- Setup of refund receipt generation under 54-FZ
- Testing on sandbox and production
- Documentation and training for managers on the interface
- Code warranty and post-deployment support
Comparison of Standard vs Custom Solution
| Feature | Standard Module | Custom Solution |
|---|---|---|
| Partial refund support | Limited | Yes |
| Flexibility | No | Full |
| Integration with any provider | No | Yes |
| Processing speed | ~3 min | ~30 sec |
Timelines
| Task | Duration |
|---|---|
| Partial refund without fiscalization | 1–2 days |
| Partial refund + refund receipt (54-FZ) | 2–4 days |
| Manager interface in admin panel | 1–2 days |
Timelines are refined after analyzing your current solution. We'll assess your project free of charge. For an accurate timeline and cost estimate, request a consultation — we'll analyze your current configuration for free and prepare a proposal.







