Інтеграція з OrangeData для 1С-Бітрікс
OrangeData — хмарний фіскальний реєстратор, що працює за схемою «каса як сервіс». Фізичної каси у магазину немає: OrangeData сам зберігає і обслуговує обладнання, а ви отримуєте API для відправки чеків. Це зручно, поки не починаєте розбиратися в деталях: авторизація через сертифікати X.509, асинхронна фіскалізація, специфічна схема атрибутів чека під 54-ФЗ. Стандартного модуля в Бітрікс немає, все реалізується через кастомний обробник платіжної системи.
Як працює OrangeData API
OrangeData використовує REST API з взаємною TLS-аутентифікацією. Це не просто токен у заголовку — потрібен клієнтський X.509-сертифікат, який видається при реєстрації. Кожен запит до API підписується приватним ключем з цього сертифіката.
Основні ендпоінти:
-
POST /api/v2/documents/— надіслати документ (чек приходу, повернення, коригування) -
GET /api/v2/documents/{id}— отримати результат фіскалізації за ідентифікатором
Важливий момент: фіскалізація асинхронна. Після POST ви отримуєте 202 Accepted, а не готовий чек. Реальний фіскальний ознака з'являється через кілька секунд або хвилин — потрібно опитувати GET-ендпоінт або чекати callback.
Структура запиту на відправку чека
$document = [
'id' => uniqid('', true), // унікальний ідентифікатор документа
'inn' => $inn,
'group' => 'Main',
'key' => $signatureKeyName, // ім'я ключа з особистого кабінету OrangeData
'content' => [
'type' => 1, // 1 - прихід, 2 - повернення приходу
'positions' => $this->buildPositions($payment),
'checkClose' => [
'payments' => [
[
'type' => $this->getPaymentType($payment), // 1-готівка, 2-безнал
'amount' => $payment->getSum(),
],
],
'taxationSystem' => 0, // 0-ЗСО, 1-ССО дохід, 2-ССО дохід-витрати
],
'customerContact' => $this->getCustomerContact($order),
],
];
Поле positions — масив позицій чека. Кожна позиція містить quantity, price, tax (код ставки ПДВ), text (найменування), paymentMethodType і paymentSubjectType. Останні два поля — вимога 54-ФЗ з 2019 року: потрібно явно вказати, що продається (товар, послуга, робота) і яким способом (передоплата, повний розрахунок).
private function buildPositions(\Bitrix\Sale\Payment $payment): array
{
$order = $payment->getOrder();
$basket = $order->getBasket();
$positions = [];
foreach ($basket as $item) {
$positions[] = [
'quantity' => $item->getQuantity(),
'price' => $item->getPrice(),
'tax' => $this->mapVatRate($item->getField('VAT_RATE')),
'text' => $item->getField('NAME'),
'paymentMethodType' => 4, // 4 - повний розрахунок
'paymentSubjectType' => 1, // 1 - товар
];
}
// Доставка як окрема позиція
if ($order->getDeliveryPrice() > 0) {
$positions[] = [
'quantity' => 1,
'price' => $order->getDeliveryPrice(),
'tax' => 6, // без ПДВ
'text' => 'Доставка',
'paymentMethodType' => 4,
'paymentSubjectType' => 4, // 4 - послуга
];
}
return $positions;
}
TLS-аутентифікація: налаштування в PHP
Відправка запитів з клієнтським сертифікатом через cURL:
private function apiRequest(string $method, string $path, array $data = []): array
{
$ch = curl_init('https://api.orangedata.ru:12003' . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_SSLCERT => $this->certPath, // шлях до .crt
CURLOPT_SSLKEY => $this->keyPath, // шлях до .key
CURLOPT_CAINFO => $this->caPath, // кореневий сертифікат OrangeData
CURLOPT_SSL_VERIFYPEER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 202) {
return ['status' => 'queued'];
}
return json_decode($response, true);
}
Сертифікати та ключі зберігаються поза webroot — наприклад, у /local/certs/orangedata/. Шляхи передаються через налаштування обробника платіжної системи. Ніколи не кладіть .key-файл у public_html.
Асинхронна фіскалізація: polling через агентів Бітрікс
Після відправки документа потрібно дочекатися фіскального ознаки. Реалізація через агента:
- Після успішного
POSTзберігаємо вb_sale_order_propsполяORANGEDATA_DOC_IDіORANGEDATA_STATUS = pending. - Агент
OrangeDataCheckAgentзапускається кожну хвилину, вибирає замовлення зORANGEDATA_STATUS = pending, опитуєGET /api/v2/documents/{id}. - Коли статус змінюється на
done— зберігаємо фіскальні дані (fn,fd,fpd, посилання на чек) і змінюємоORANGEDATA_STATUS = done. - Фіскальні дані надсилаються покупцеві по email через подію
SALE_NEW_ORDERабо окремим листом.
public static function run(): string
{
$pendingOrders = self::getPendingOrders();
foreach ($pendingOrders as $orderId => $docId) {
$result = self::checkDocumentStatus($docId);
if (($result['status'] ?? '') === 'done') {
self::saveFiscalData($orderId, $result);
}
}
return __CLASS__ . '::run();';
}
Повернення
При поверненні надсилається документ з type: 2 (повернення приходу). Сума і склад позицій повинні збігатися з оригіналом (при повному поверненні) або містити лише позиції, що повертаються (при частковому). OrangeData не перевіряє зв'язок з вихідним документом за ID — це ваша відповідальність.
Повернення запускається з обробника події OnSaleOrderRefund або з адміністративної частини при ручній обробці повернення.
Тестовий контур
OrangeData надає тестовий API: https://apip.orangedata.ru:12003. Тестові сертифікати видаються окремо. У тестовому режимі фіскалізація проходить через віртуальну касу, реальних ФН немає. Перемикання між контурами — через параметр обробника USE_TEST_API.
Терміни
| Склад | Термін |
|---|---|
| Базова інтеграція (прихід + повернення) | 4–5 днів |
| + Асинхронний polling + email із чеком | +2 дні |
| + Часткові повернення + маппінг ставок ПДВ | +1 день |







