Integrating Partial Refunds in 1C-Bitrix: APIs and Fiscal Receipts

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 st

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1415
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    995
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    733
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    862
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    772
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1134

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
  1. Mismatch between refund amount and receipt total — use automatic verification.
  2. Request signature error (Token) — check parameter order and case.
  3. Duplicate requests — apply idempotency via uniqid.
  4. 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.