Выгрузка счетов¶
Вы можете присылать в платёжный шлюз R1.pay список счетов на оплату. Эти счета будут разосланы в информационные системы управляющих компаний, чтобы попасть к конечным потребителям.
Процесс обработки счетов¶
- Поставщик услуг отправляет пакет счетов через
POST /api/v1/invoices/push - Шлюз проверяет каждый счет:
- Проверяет на дубликаты комбинаций
account+periodв пакете. Несколько счетов за один период быть не должно. - Проверяет форматы и диапазоны всех полей.
- Ищет в базе данных соответствующего счёту агента (управляющую компанию).
- Проверяет на дубликаты комбинаций
- Шлюз возвращает
push_id(при успехе) или отклоняет пакет с деталями ошибок. - Если счета валидны, шлюз присылает ответ, что счета приняты, и далее асинхронно рассылает их соответствующим агентам.
- По завершении операции поставщик услуг получит вебхук-уведомление со статусом рассылки и возможными ошибками.
- При необходимости статус рассылки счетов можно проверить самостоятельно через запрос к
POST /api/v1/invoices/status
Информация о запросах¶
Базовый URL: https://paygw.robstor.ru/api/v1/
Метод: POST
Заголовки запросов:¶
| Имя заголовка | Значение |
|---|---|
| Content-Type | application/json |
| R1-Token | <ваш_секретный_токен> |
Аутентификация¶
Используйте в разделе header запроса ключ R1-Token, содержащий ваш токен поставщика услуг. Получите токен у администратора платформы R1.pay. На нашей стороне ваш токен хранится в зашифрованном виде и проверяется при каждом обращении к сервису.
Пример CURL запроса с использованием токена для аутентификации:
curl -X POST https://paygw.robstor.ru/api/v1/invoices/push \
-H "Content-Type: application/json" \
-H "R1-Token: <ваш_секретный_токен>" \
-d '{
"invoices": [
{
"account": "3494987",
"period": 202607,
"date": "2026-07-01",
"calculated": 500,
"amount": 1500
}
]
}'
Коды состояния HTTP¶
Коды, которые мы отдаём в ответах на запросы.
- 200 OK — запрос принят и обработан (включая случаи с ошибками валидации, отклонением счетов)
- 401 Unauthorized — запрос отклонён, потому что указан неверный токен
- 500 Internal Server Error — только в случае серверных сбоев на стороне шлюза
1. Отправка счетов¶
POST /invoices/push
Отправка пакета счетов на оплату для распределения по управляющим компаниям.
Запрос¶
Структура запроса¶
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
invoices |
array | Да | Список счетов для отправки (поля счёта описываются далее) |
account |
string | Да | Номер лицевого счёта клиента (макс. 64 символа) |
period |
integer | Да | Период в виде числа в формате YYYYMM (например, 202607 для июля 2026). Месяц должен быть 01–12, год в диапазоне 2000-2050 |
date |
string | Да | Дата счёта в формате YYYY-MM-DD. |
calculated |
integer | Да | Рассчитанная/начисленная сумма (в копейках). Строго больше нуля. |
amount |
integer | Да | Итоговая сумма к оплате (в копейках). Строго больше нуля. |
fields |
array | Нет | Дополнительные поля счёта (массив объектов { "field": "имя", "value": "значение" }). Обратите внимание: данный массив содержит ТОЛЬКО текстовую информацию (поля "field" и "value" обязательно имеют строковый тип данных, записываются в кавычках) |
Пример запроса¶
{
"invoices": [
{
"account": "3494987",
"period": 202607,
"date": "2026-07-01",
"calculated": 500,
"amount": 1500,
"fields": []
},
{
"account": "3494988",
"period": 202607,
"date": "2026-07-01",
"calculated": 300,
"amount": 900,
"fields": [
{
"field": "имя необязательного дополнительного поля",
"value": "значение дополнительного поля"
}
]
}
]
}
Ответ¶
Правила формирования ответа¶
- Ответ на данный запрос указывает на количество принятых к обработке или отклонённых счетов после первоначальной проверки (валидации). Но после инициализации рассылки счетов агенты могут отклонить тот или иной счёт или он может быть не доставлен по другим причинам. Окончательная информация о статусе рассылки счетов может быть получена позже через вебхук или через запрос статуса.
- Если хотя бы один счёт в пакете имеет ошибки, весь пакет отклоняется. В ответе указываются детали по каждому отклонённому счёту и причине отклонения, чтобы вы могли исправить данные и отправить повторно.
Структура ответа¶
| Поле | Тип | Описание |
|---|---|---|
msg |
string | Сообщение о статусе обработки |
push_id |
int64 | Идентификатор запроса загрузки счетов (для отслеживания статуса) |
status |
string | Общий статус: in_progress, completed, completed_with_errors, failed |
total |
integer | Общее количество счетов в пакете |
accepted |
integer | Количество принятых счетов |
rejected |
integer | Количество отклонённых счетов |
rejected_invoices |
array | Список отклонённых счетов (пустой при успехе) |
Поля в rejected_invoices¶
| Поле | Тип | Описание |
|---|---|---|
account |
string | Номер лицевого счёта, который не был принят |
error_code |
integer | Код ошибки (см. документацию по ошибкам) |
error |
string | Текстовое описание ошибки |
Примеры ответов¶
- Все счета приняты к рассылке
{
"msg": "We’ve received the invoices. Distribution to agents is now in progress.",
"push_id": 12345,
"status": "in_progress",
"total": 2,
"accepted": 2,
"rejected": 0,
"rejected_invoices": []
}
- Запрос отклонён из-за части неверных счетов
{
"msg": "Errors detected in one or more invoice entries. Request rejected.",
"push_id": 0,
"status": "failed",
"total": 2,
"accepted": 1,
"rejected": 1,
"rejected_invoices": [
{
"account": "3494988",
"error_code": 401,
"error": "Account not found"
}
]
}
2. Узнать статус загрузки счетов¶
POST /invoices/status
Позволяет проверить текущий статус ранее отправленного пакета счетов.
Запрос¶
Структура запроса¶
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
push_id |
integer | Да | Идентификатор запроса, полученный при отправке счетов через /api/v1/invoices/push |
Пример запроса¶
{
"push_id": 12345
}
Ответ¶
Структура ответа¶
| Поле | Тип | Описание |
|---|---|---|
msg |
string | Сообщение о статусе запроса |
push_id |
int64 | Идентификатор запроса загрузки |
status |
string | Статус рассылки: in_progress, completed, completed_with_errors, failed |
total |
integer | Общее количество счетов в пакете |
accepted |
integer | Количество принятых агентами счетов |
rejected |
integer | Количество отклонённых счетов |
rejected_invoices |
array | Список отклонённых счетов с деталями ошибок. Список может быть пустым в случае отсутствия ошибок |
Примеры ответов¶
- Все счета успешно разосланы
{
"msg": "Invoices delivery status information",
"push_id": 12345,
"status": "completed",
"total": 2,
"accepted": 2,
"rejected": 0,
"rejected_invoices": []
}
- Счета частично разосланы
{
"msg": "Invoices delivery status information",
"push_id": 12345,
"status": "completed_with_errors",
"total": 5,
"accepted": 4,
"rejected": 1,
"rejected_invoices": [
{
"account": "3494988",
"error_code": 401,
"error": "Account not found"
}
]
}
ℹ️ Примечание: Статус
completed_with_errorsговорит о том, что рассылка счетов по управляющим компаниям завершена, но не все счета успешно разосланы и приняты. Список непринятых счетов с указанием ошибок можно посмотреть вrejected_invoices.
- Запись с указанным
push_idне найдена для данного поставщика
ℹ️ Примечание: Запрос должен поступать от того же поставщика услуг, который ранее инициировал загрузку
{
"msg": "No record for merchant with the push_id",
"push_id": 12345,
"status": "",
"total": 0,
"accepted": 0,
"rejected": 0,
"rejected_invoices": []
}
Важные замечания по ответам¶
Логика работы шлюза¶
При отправке счетов каждый счёт проходит следующие проверки:
| Правило | Код ошибки | Сообщение об ошибке |
|---|---|---|
account пустой |
303 | "Empty account field" |
Длина account > 64 |
301 | "Account number exceeds maximum length of 64" |
Период в period невалидный (месяц не 01–12 или год выходит за рамки 2000-2050) |
302 | "Error in period: Invalid period format" |
calculated < 0 |
304 | "Calculated value cannot be negative" |
amount < 0 |
304 | "Amount value cannot be negative" |
Формат date не YYYY-MM-DD |
305 | "Invalid date format (expected YYYY-MM-DD)" |
Дубликат account+period в пакете |
306 | "Duplicate account-period entry" |
| Счёт не зарегистрирован у агента | 401 | "Account not found" |
Коды ошибок при доставке (error_code в rejected_invoices)¶
| Код | Ошибка (EN) | Перевод | Описание |
|---|---|---|---|
| 301 | Account number exceed maximum length of 64 | Номер лицевого счёта превысил максимальную длину в 64 символа | Указан слишком длинный номер лицевого счёта. Если номер действительно очень длинный, необходимо обратиться к администратору платёжной системы |
| 302 | Error in period: ... | Ошибка в периоде:... | после двоеточия указана более точная причина ошибки, например, неверный формат данных |
| 303 | Empty account field | Лицевой счёт пустой | Ошибка возникает, если лицевой счёт в счёте на оплату не указан |
| 304 | Calculated (Amount) value cannot be nagative | Значение поля Calculated (Amount) не может быть отрицательным | Эта ошибка может возникнуть, если сумма отрицательная |
| 305 | Invalid date format (expected YYYY-MM-DD) | Неверный формат даты (ожидается в формате ГГГГ-ММ-ДД) | Дата счёта указана не в принятом формате |
| 306 | Duplicate account-period entry | Повторная запись "лицевой счет - период" | В одном пакете не должна быть передано более одного раза запись, касающаяся одного лицевого счёта за один период |
| 401 | Account not found | Лицевой счёт не найден | Лицевой счёт не найден в базе платёжной системы. Это могло произойти, если лицевой счёт не был добавлен пользователем (и в базе данных не создалась запись об этом счёте), но поставщик услуг пытается присылать счета на оплату по данном лицевому счёту |
| 501 | Server Errors | Ошибки сервера | Ошибки, не связанные с передаваемыми данными, возникающие в результате сбоев на стороне сервера шлюза или серверов агентов: - Cannot get active agents from DB — сервис не смог получить список активных агентов из БД. - Failed to marshal invoice payload — сервис не смог сформировать данные для отправки агенту. - Agent internal error, code= — агент вернул ошибку, сообщается её код |
| 504 | Failed to deliver to agent after several retries | Ошибка доставки к агенту после нескольких попыток | Возможно, сервер агента не доступен или неверно настроен, поэтому сервис не может доставить счета. |
Вебхук-уведомления о статусе загрузки счетов¶
После завершения асинхронной рассылки счетов агентам (управляющим компаниям), шлюз отправляет вам вебхук-уведомление с финальным статусом и детальной статистикой. Вы самостоятельно указываете администратору платёжного шлюза R1.pay базовый URL вебхук-эндпоинта. Если URL не установлен, вебхук-уведомления отправляться не будут.
Вебхук-URL: https://ВАШ_BASE_WEBHOOK_URL/invoices/status
Метод: POST
Заголовки запросов:¶
| Имя заголовка | Значение |
|---|---|
| Content-Type | application/json |
| R1-Token | <ваш_секретный_токен> |
Аутентификация¶
Шлюз отправляет заголовок R1-Token с вашим токеном, который вам нужно предварительно передать представителю R1.pay защищённым способом. Вам следует проверять этот токен для подтверждения, что запрос исходит от доверенного шлюза. Обычно такую проверку внедряют в middleware, подключённому к защищаемым роутам.
Пример части кода на Python, реализующего такую проверку:
EXPECTED_TOKEN = os.environ.get("R1_Token")
token = request.headers.get("R1-Token")
if not token:
abort(401)
received = token.encode("utf-8")
expected = EXPECTED_TOKEN.encode("utf-8")
if not hmac.compare_digest(received, expected):
abort(401)
Важно: В целях безопасности токены рекомендуется хранить в зашифрованном виде, чтобы в случае взлома эти чувствительные данные не попали в руки злоумышленников. Если выявлен факт утечки, следует незамедлительно сгенерировать новый токен для нашей системы.
Функционал обработчика вебхука¶
- Принять JSON-тело запроса со статусом рассылки
- Проверить заголовок
R1-Tokenдля подтверждения, что запрос от доверенного шлюза - Обработать полученные данные (сохранить в вашу базу, обновить статусы счетов, отправить уведомления клиентам и т.д.)
- Вернуть HTTP 200 OK с любым валидным JSON-ответом
⚠️ Важно: Шлюз ожидает ответ
200 OKв течение ограниченного времени. Долгая обработка может привести к таймауту, но шлюз повторит попытку (см. retry-логику ниже).
Запрос¶
Структура запроса¶
| Поле | Тип | Описание |
|---|---|---|
msg |
string | Сообщение о статусе уведомления |
push_id |
int64 | Идентификатор запроса загрузки (тот же, что был возвращён при /api/v1/invoices/push) |
status |
string | Финальный статус рассылки: completed, completed_with_errors, failed |
total |
integer | Общее количество счетов в пакете |
accepted |
integer | Количество счетов, принятых агентами |
rejected |
integer | Количество отклонённых/недоставленных счетов |
rejected_invoices |
array | Список отклонённых счетов с деталями ошибок (пустой массив при полном успехе) |
Поля в rejected_invoices¶
| Поле | Тип | Описание |
|---|---|---|
account |
string | Номер лицевого счёта, который не был принят |
error_code |
integer | Код ошибки (см. документацию по ошибкам ) |
error |
string | Текстовое описание ошибки |
Пример запроса¶
{
"msg": "Webhook notification about invoices delivery status",
"push_id": 12345,
"status": "completed_with_errors",
"total": 5,
"accepted": 3,
"rejected": 2,
"rejected_invoices": [
{
"account": "3494988",
"error_code": 401,
"error": "Account not found"
},
{
"account": "3494990",
"error_code": 501,
"error": "Agent internal error"
}
]
}
Ответ¶
Ваш обработчик должен вернуть HTTP 200 OK с любым валидным JSON-ответом, например:
{
"status": "received",
"push_id": 12345
}
Шлюз не проверяет содержимое вашего ответа, ему важен код состояния 200.
Retry-логика¶
Если шлюз не получает ответ 200 OK или получает ошибку HTTP, он повторяет отправку вебхука.
3 попытки отправки — если все оказались неудачными, шлюз больше не повторяет отправку для этого
push_id. В таком случае используйтеPOST /api/v1/invoices/statusдля ручной проверки статуса.