8. Работа с чеками 54-ФЗ
Источник: https://docs.paykeeper.ru/dokumentatsiya-json-api/rabota-s-chekami-54-fz/
PayKeeper поддерживает автоматическую генерацию чеков по 54-ФЗ.
Список запросов
| # | URI | Назначение |
|---|---|---|
| 8.1 | /info/receipts/bydate/ | Реестр чеков за период с фильтрами |
| 8.2 | /info/receipts/bydatecount/ | Счёт чеков за период по типам |
| 8.3 | /info/receipts/bypaymentid/ | Чеки по платежу |
| 8.4 | /info/receipts/byid/ | Чек по внутреннему номеру |
| 8.5 | /info/receipts/search/ | Поиск чеков по фискальным атрибутам |
| 8.6 | RESERVED | зарезервировано |
| 8.7 | RESERVED | зарезервировано |
| 8.8 | /info/itemcode/check/ | Проверка кода маркировки в Честном Знаке |
| 8.9 | RESERVED | зарезервировано |
| 8.10 | RESERVED | зарезервировано |
| 8.11 | /change/receipt/print/ | Печать чека по платежу или произвольным атрибутам |
| 8.12 | RESERVED | проверка статуса чека у кассы |
| 8.13 | Callback | Оповещение при переходе чека в финальный статус |
8.1 Реестр чеков /info/receipts/bydate/
Тип: GET
Формат: /info/receipts/bydate/?start=2021-01-28&end=2021-02-28&sum_type[0]=sum_cashless&sum_type[1]=sum_cash&status[0]=created&status[1]=success
Параметры запроса:
| # | Параметр | Назначение |
|---|---|---|
| 1 | start | Опц. Начало периода (YYYY-MM-DD) |
| 2 | end | Опц. Конец периода (YYYY-MM-DD) |
| 3 | status | Опц. Массив. Фильтр по статусу (created, request_sent, success, failed, timeout) |
| 4 | receipt_type | Обяз. Массив. Фильтр по типу (sale, refund, correction) |
| 5 | sum_type | Обяз. Массив. Фильтр по способу оплаты (sum_cashless, sum_cash, sum_advance, sum_credit) |
| 6 | sort | Опц. По умолчанию request_datetime. Поле сортировки: payment_id, refund_id, request_datetime, obtain_datetime, status |
| 7 | direction | Опц. ASC / DESC. По умолчанию DESC |
| 8 | from | Опц. По умолчанию 0 |
| 9 | limit | Опц. По умолчанию 10 |
Поля массива receipts:
| # | Параметр | Назначение |
|---|---|---|
| 1 | id | ID чека |
| 2 | payment_id | Номер платежа (может быть пустым) |
| 3 | type | sale / refund |
| 4 | is_post_sale | Чек окончательного расчёта |
| 5 | refund_id | Порядковый номер возврата |
| 6 | status | created, request_sent, success, timeout, failed |
| 7 | contact | Email/телефон плательщика |
| 8 | sum_cashless | Безнал |
| 9 | sum_cash | Наличные |
| 10 | sum_advance | Зачёт аванса |
| 11 | sum_credit | Кредит |
| 12 | cart | Корзина (JSON-строка) |
| 13 | receipt_properties | Доп. свойства (JSON-строка) |
| 14 | fpd | ФПД |
| 15 | fnd | Номер ФД |
| 16 | fn | Номер ФН |
| 17 | ts | Время формирования (YYYYMMDDTHHmm) |
| 18 | rnkkt | Регистрационный номер ККТ |
| 19 | shift_number | Номер смены |
| 20 | receipt_number | Номер чека в смене |
| 21 | obtain_datetime | Дата оплаты |
| 22 | request_datetime | Дата оповещения магазина |
| 23 | fop_receipt_key | Ключ чека (часть URL страницы) |
| 24 | fop_uuid | Уникальный ID запроса к кассе |
| 25 | fop_url | Содержимое QR-кода |
Счётчики counts:
| Параметр | Назначение |
|---|---|
status | Число чеков по статусу |
receipt_type | Число по типу |
sum_type | Число по способу оплаты |
page_size | Всего найдено на странице |
totals.sum_type | Группировка по способу |
totals.status | Группировка по статусу |
totals.receipt_type | Группировка по типу |
totals.total | Всего по запросу без пагинации |
Пример ответа:
{
"receipts": [
{
"id": "2107145011",
"payment_id": "0",
"type": "sale",
"is_post_sale": "0",
"refund_id": "0",
"status": "request_sent",
"contact": "",
"sum_cashless": "1.00",
"sum_cash": "0.00",
"sum_advance": "0.00",
"sum_credit": "0.00",
"cart": "[{\"item_type\":\"goods\",\"payment_type\":\"prepay\",\"sku\":\"\",\"name\":\"Lorem ipsum\",\"price\":\"1\",\"quantity\":\"1\",\"item_code\":\"\",\"tax\":\"none\",\"sum\":1,\"agent\":{\"type\":\"other\"},\"supplier\":{\"phones\":[\"+79101234567\"],\"inn\":\"5544332219\",\"name\":\"ООО ТЕСТ\"}}]",
"receipt_properties": "{\"client\":null,\"agent\":{\"type\":\"other\"},\"supplier\":{\"phones\":[\"+79101234567\"],\"inn\":\"5544332219\",\"name\":\"ООО ТЕСТ\"}}",
"fpd": null,
"fnd": null,
"fn": null,
"ts": null,
"rnkkt": null,
"shift_number": null,
"receipt_number": null,
"request_datetime": "2021-10-12 11:27:12",
"obtain_datetime": null,
"fop_receipt_key": "XjtaLpCw_kqfiiI",
"fop_uuid": "27e80723-21e7-418b-9806-00f1a7e6aef8",
"fop_url": null
}
],
"counts": {
"status": {"request_sent": 4},
"receipt_type": {"sale": 4},
"sum_type": {"sum_cashless": 4},
"page_size": 4,
"totals": {
"sum_type": {"sum_cashless": 4, "sum_cash": 0, "sum_advance": 0, "sum_credit": 0},
"status": {"created": 0, "request_sent": 4, "success": 0, "failed": 0, "timeout": 0},
"receipt_type": {"sale": 4, "refund": 0, "expense": 0, "expense_refund": 0, "correction": 0},
"total": 4
}
}
}8.2 Количество чеков /info/receipts/bydatecount/
Тип: GET
Формат: /info/receipts/bydatecount/?start=2020-10-18&end=2021-10-18
Параметры: start, end.
Пример:
{
"sum_type": {"sum_cashless": 15, "sum_cash": 0, "sum_advance": 5, "sum_credit": 0},
"status": {"created": 1, "request_sent": 11, "success": 7, "failed": 1, "timeout": 0},
"receipt_type": {"sale": 20, "refund": 0, "expense": 0, "expense_refund": 0, "correction": 0},
"total": 20
}8.3 Чеки по платежу /info/receipts/bypaymentid/
Тип: GET
Формат: /info/receipts/bypaymentid/?payment_id=2211
Параметры: payment_id.
Показывает чеки окончательного расчёта и произвольные чеки, сгенерированные для платежа. Первичный чек при получении платежа здесь не отображается.
8.4 Чек по ID /info/receipts/byid/
Тип: GET
Формат: /info/receipts/byid/?id=4201
Параметры: id.
Параметры ответа:
| # | Параметр | Назначение |
|---|---|---|
| 1 | id | ID чека |
| 2 | payment_id | Номер платежа |
| 3 | type | sale / refund / expense / expense-refund |
| 4 | is_post_sale | Признак окончательного расчёта ("0"/"1") |
| 5 | is_correction | Чек коррекции по ФФД 1.2 ("0"/"1") |
| 6 | refund_id | Порядковый номер возврата |
| 7 | status | created, sending, rejected, request_sent, success, timeout, failed |
| 8 | contact | Email/телефон |
| 9 | sum_cashless | Безнал |
| 10 | sum_cash | Наличные |
| 11 | sum_advance | Зачёт аванса |
| 12 | sum_credit | Кредит |
| 13 | sum_counter_payment | Встречное предоставление |
| 14 | cart | Корзина (JSON-строка) |
| 15 | receipt_properties | Доп. свойства (JSON-строка) |
| 16 | fpd | ФПД |
| 17 | fnd | Номер ФД |
| 18 | fn | Номер ФН |
| 19 | ts | Время формирования |
| 20 | rnkkt | Регистрационный номер |
| 21 | shift_number | Смена |
| 22 | receipt_number | Номер в смене |
| 23 | obtain_datetime | Дата оплаты |
| 24 | request_datetime | Дата запроса |
| 25 | fop_receipt_key | Ключ чека |
| 26 | fop_uuid | Уникальный ID запроса |
| 27 | fop_url | QR-контент |
| 28 | custom_params | JSON с доп. атрибутами (для коррекции) |
| 29 | error | JSON с описанием ошибки (если rejected/failed) |
Статусы чеков
| Статус | Описание | Финальный |
|---|---|---|
created | Принят, ожидает отправки | Нет |
sending | Отправляется балансировщику | Нет |
rejected | Отклонён балансировщиком (детали в error) | Да |
request_sent | Принят балансировщиком, будет отправлен кассе | Нет |
success | Чек сформирован | Да |
timeout | Долго в очереди без результата, удалён | Да |
failed | Касса отклонила (детали в error) | Да |
Поля custom_params (ФФД 1.2 коррекция)
| Поле | Назначение |
|---|---|
correction_type | self / by_order |
correction_operation_date | Дата исходной операции (YYYY-MM-DD, тег 1178) |
correction_document_number | Номер предписания ФНС (тег 1179, до 32 симв.) |
Поле error
| Поле | Назначение |
|---|---|
type | syntax_error, ffd_error, item_code_error, print_error, queue_error |
message | Описание |
error_id | ID события в логе |
Типы ошибок
| Тип | Описание |
|---|---|
syntax_error | Синтаксическая ошибка в запросе, отбраковка до передачи в ФН |
ffd_error | Запрещённые по ФФД теги или их комбинация, отбраковка при передаче в ФН |
item_code_error | Код «Честного знака» не прошёл проверку; устройство настроено отклонять такие чеки |
print_error | Общая ошибка при обработке на ККТ |
queue_error | Ошибка постановки в очередь до передачи ККТ |
Пример ответа:
{
"id": "4201",
"payment_id": "2098",
"type": "sale",
"is_post_sale": "1",
"is_correction": "1",
"refund_id": null,
"status": "success",
"contact": "client@mail.ru",
"sum_cashless": "0.00",
"sum_cash": "0.00",
"sum_advance": "15529.10",
"sum_credit": "0.00",
"sum_counter_payment": "0.00",
"cart": "[{\"name\":\"TEST 3\",\"quantity\":1,\"price\":15529.10,\"sum\":15529.10,\"tax\":\"none\",\"payment_type\":\"full\"}]",
"receipt_properties": "null",
"fpd": "2020473855",
"fnd": "8930",
"fn": "9999078900001341",
"ts": "20190621T1638",
"rnkkt": "0000000400054952",
"shift_number": "7123",
"receipt_number": "6162",
"obtain_datetime": "2019-05-11 09:12:22",
"request_datetime": "2019-05-11 09:12:01",
"fop_receipt_key": "VhamK7kl",
"fop_uuid": "6ee-cs-130",
"fop_url": "t=20190511T0912&s=15529.10&fn=9999078900001341&i=8930&fp=2020473855&n=1",
"custom_params": "{\"correction_type\":\"self\",\"correction_operation_date\":\"2022-04-11\"}",
"error": null
}8.5 Поиск чеков /info/receipts/search/
Тип: GET
Формат: /info/receipts/search/?start=2020-10-18&end=2021-10-18&query=12345
Параметры:
| Параметр | Назначение |
|---|---|
start | Начало (YYYY-MM-DD) |
end | Конец (YYYY-MM-DD) |
query | Подстрока (ищется в id, payment_id, contact) |
Формат ответа как в 8.1.
8.6 / 8.7 / 8.9 / 8.10 RESERVED
Не используется.
8.8 Проверка кода маркировки /info/itemcode/check
Для режима разрешений валидация допустимости продажи товара при добавлении кода маркировки. Результат добавляется к чеку.
Тип: GET
Формат: /info/itemcode/check
Параметры:
| Параметр | Назначение |
|---|---|
item_code | Код маркировки без GS-символов (эвристика по позициям байтов) |
item_code_b64 | Точное значение кода с GS-символами, base64 |
Передаётся один из двух. Если оба — используется item_code_b64.
8.11 Печать чека /change/receipt/print/
Тип: POST
Формат: /change/receipt/print/
Печать асинхронная — отправить запрос и проверять результат позже (рекомендуется через 2+ минуты).
Параметры:
| # | Параметр | Назначение |
|---|---|---|
| 1 | payment_id | Номер платежа (может быть пустой строкой ''). Обязателен |
| 2 | type | sale / refund / expense / expense-refund |
| 3 | is_post_sale | Признак окончательного расчёта (true/false). Не отправляется для type=refund |
| 4 | is_correction | Чек коррекции ФФД 1.2 (true/false) |
| 5 | refund_id | Порядковый номер возврата (можно '') |
| 6 | contact | Email или телефон (+79101234567) |
| 7 | sum_cashless | Безнал |
| 8 | sum_cash | Наличные |
| 9 | sum_advance | Аванс |
| 10 | sum_credit | Кредит |
| 11 | sum_counter_payment | Встречное предоставление |
| 12 | cart | Корзина (JSON-строка) |
| 13 | receipt_properties | Доп. свойства (JSON-объект) |
| 14 | receipt_key | Уникальный ключ (минимум 6 симв.) |
Ответ:
{"receipt_id": 816}Поля для чека коррекции (ФФД 1.2)
Дополнительные поля при is_correction=true:
| Поле | Назначение |
|---|---|
correction_type | self / by_order |
correction_operation_date | Дата исходной операции (YYYY-MM-DD, тег 1178) |
correction_document_number | Номер предписания ФНС (тег 1179, до 32 симв.) |
additional_receipt_data | Номер исправляемого чека (тег 1192) |
8.12 RESERVED
Не используется. Планируется: проверка статуса чека у кассы и получение фискальных атрибутов, если они отсутствуют.
8.13 Callback о финальном статусе чека
При достижении чеком финального статуса (см. 8.4) PayKeeper шлёт POST-оповещение на сайт ТСП один раз, без подтверждения доставки.
Тело содержит все параметры из ответа 8.4 + подпись:
sign— цифровая подпись запроса
Вычисление подписи
Все параметры (включая пустые) сортируются по ключу лексикографически, значения конкатенируются через ;. Берётся HMAC-SHA256 с секретным словом в качестве ключа.
Проверка на PHP
<?php
$request = $_POST;
$pk_key = "Secret client key";
unset($request['sign']);
ksort($request);
$to_hash = implode(';', $request);
$sign = hash_hmac('sha256', $to_hash, $pk_key);
if(strtoupper($sign) == strtoupper($_POST['sign']))
{
// подпись валидна
}
?>