CloudKassir Integration for 1C-Bitrix
CloudKassir is a cloud fiscal receipt service operating under Federal Law No. 54-FZ. It works on the same model as OrangeData and ATOL Online: the hardware is on the service's side, you pay per receipt processed, and you do not worry about maintaining physical cash registers. The CloudKassir API is simpler than its competitors — authentication is via login/password with Basic Auth, and there is no client certificate requirement. This lowers the entry threshold but does not eliminate the main challenges: VAT rate mapping, asynchrony, and correct line item formatting under 54-FZ.
CloudKassir API: Structure
Base URL: https://api.cloudkassir.ru/v1/. Authentication: Basic Auth, login and password from the personal account.
Key methods:
-
POST /receipts— submit a receipt -
GET /receipts/{id}— receipt processing status -
POST /receipts/correction— correction receipt
The response to POST /receipts returns an id — the internal task identifier. The receipt itself is not in the response; you need to poll GET /receipts/{id}.
Receipt Structure
$receipt = [
'external_id' => 'order-' . $orderId . '-' . time(),
'receipt' => [
'client' => [
'email' => $customerEmail, // email or phone required
],
'company' => [
'email' => $shopEmail,
'sno' => 'osn', // osn, usn_income, usn_income_outcome
'inn' => $inn,
'payment_address' => $siteUrl,
],
'items' => $this->buildItems($payment),
'payments' => [
[
'type' => 2, // 1-cash, 2-electronic
'sum' => $payment->getSum(),
],
],
'total' => $payment->getSum(),
],
'timestamp' => date('d.m.Y H:i:s'),
'type' => 'sell', // sell, sell_return
'url' => $callbackUrl,
];
The url field is the callback address after fiscalisation. CloudKassir will send a POST with the receipt data: fn, fd, fpd, QR code. This is more convenient than polling if you have a public IP address.
Building Receipt Line Items
private function buildItems(\Bitrix\Sale\Payment $payment): array
{
$order = $payment->getOrder();
$items = [];
foreach ($order->getBasket() as $basketItem) {
$items[] = [
'name' => mb_substr($basketItem->getField('NAME'), 0, 128),
'price' => $basketItem->getPrice(),
'quantity' => $basketItem->getQuantity(),
'sum' => $basketItem->getFinalPrice(),
'payment_method' => 'full_payment', // prepayment / full payment
'payment_object' => 'commodity', // goods, service, work
'vat' => $this->getVatTag($basketItem->getField('VAT_RATE')),
];
}
if ($order->getDeliveryPrice() > 0) {
$items[] = [
'name' => 'Delivery',
'price' => $order->getDeliveryPrice(),
'quantity' => 1.0,
'sum' => $order->getDeliveryPrice(),
'payment_method' => 'full_payment',
'payment_object' => 'service',
'vat' => 'none',
];
}
return $items;
}
The name length is limited to 128 characters — mb_substr is mandatory. The vat field accepts: none, vat0, vat10, vat110, vat20, vat120. Mapping from the Bitrix VAT rate to a CloudKassir string:
private function getVatTag(?float $vatRate): string
{
return match(true) {
$vatRate === null || $vatRate == 0 => 'none',
$vatRate == 0.1 => 'vat10',
$vatRate == 0.2 => 'vat20',
default => 'none',
};
}
Bitrix Payment System Handler
The integration is implemented as a handler in /local/php_interface/include/sale_payment/cloudkassir/. The class extends \Bitrix\Sale\PaySystem\ServiceHandler.
The receipt is sent in the processRequest() method — after receiving confirmation from the payment system (bank). Not when the order is created, but specifically after confirming the fact of payment.
public function processRequest(
\Bitrix\Sale\Payment $payment,
\Bitrix\Main\Request $request
): \Bitrix\Sale\PaySystem\ServiceResult {
$result = new \Bitrix\Sale\PaySystem\ServiceResult();
// First mark the payment as paid
$result->setOperationType(\Bitrix\Sale\PaySystem\ServiceResult::MONEY_COMING);
// Then send the receipt
$this->sendReceipt($payment);
return $result;
}
Sending the receipt before payment confirmation is a violation of 54-FZ: the receipt must be generated at the moment of settlement.
Callback and Saving Fiscal Data
When a callback is received from CloudKassir (after successful fiscalisation), save the data to the order properties:
public function handleCallback(array $callbackData): void
{
$orderId = $this->extractOrderId($callbackData['external_id']);
$order = \Bitrix\Sale\Order::load($orderId);
$propCollection = $order->getPropertyCollection();
$propCollection->getItemByOrderPropertyCode('CLOUDKASSIR_FN')
->setValue($callbackData['fn']);
$propCollection->getItemByOrderPropertyCode('CLOUDKASSIR_FD')
->setValue($callbackData['fd']);
$propCollection->getItemByOrderPropertyCode('CLOUDKASSIR_FPD')
->setValue($callbackData['fpd']);
$order->save();
}
The order properties CLOUDKASSIR_FN, CLOUDKASSIR_FD, and CLOUDKASSIR_FPD are created manually in the admin panel before launching the integration.
Refunds: Type sell_return
When processing a payment refund, a receipt with type: sell_return is submitted. The line item composition must match the original receipt. CloudKassir does not automatically link receipts by ID — the correctness of the line items is your responsibility.
For partial refunds (only some items returned) — only the returned items are passed in items with their actual quantities and amounts.
Specifics When Working with Prepayments
If the store accepts prepayments (50% at order, 50% at delivery), two receipts must be sent:
- On the first payment: line items with
payment_method: prepayment(oradvance), typesell - When closing the settlement: line items with
payment_method: full_payment, typesell
This is a requirement of 54-FZ. CloudKassir supports it; Bitrix does not out of the box. The two-receipt logic must be implemented custom, based on order statuses and payment type.
Testing
CloudKassir provides a test environment: https://demo.cloudkassir.ru. Test credentials are issued upon registration. In test mode, receipts are not transmitted to the tax authority — you can safely debug the request structure.
Timeline
| Scope | Duration |
|---|---|
| Income + refund, Basic Auth | 3–4 days |
| + Callback handler + saving fiscal data | +1 day |
| + Prepayment scheme (two receipts) | +2 days |







