API для онлайн-кассы

ЕКАМ Онлайн — это сервис, который позволяет формировать (регистрировать) фискальные чеки из бэк-офиса любой CMS, CRM и учётной системы по открытому API в полном соответствии с 54-ФЗ. 

Содержание

Назначение сервиса

Согласно новой редакции Федерального закона от 22.05.2003 № 54–ФЗ все интернет-магазины и онлайн-сервисы в России с 01.07.2017 должны применять ККТ независимо от способы оплаты. Поэтому появилась необходимость в сервисе, который бы решал две задачи:

  • Формировать фискальные чеки в момент онлайн-оплаты автоматически (кейс "клиент оплатил онлайн")
  • Печатать кассовые чеки из бэк-офиса магазина вручную (кейс "клиент пришел в магазин и оплатил на месте")

 

Отличительные особенности:

  • Возможность работы нескольких интернет-магазинов и стационарной точки продаж на одной ККТ
  • Автоматическая и ручная печать чеков из бэк-офиса любой внешней системыпо API
  • Гибкий выбор: бумажный чек, электронный чек или оба сразу
  • Балансировка нагрузки на фискальные накопители и ККТ.
  • Умная система мониторинга, отслеживающая сбои, аномальные нагрузки и другие факторы.
  • Экономичное решение с абонентской платой от 800 руб. в месяц

Оборудование

Магазин покупает необходимое количество комплектов оборудования ИНТЕРНЕТ-МАГАЗИН, рекомендуемое число можно уточнить в клиентском отделе ЕКАМ. В комплект входит:

  • ККТ АТОЛ 30Ф
  • Микрокомпьютер EKAM-BOX
  • 1 месяц использования сервиса ЕКАМ Онлайн

С сервисом будет работать любая ККТ из поддерживаемых.

Использование сервиса

В платформе ЕКАМ есть сущность торговая точка, она может быть двух видов:

  • Стационарная точка
  • Интернет-касса

Работа со стационарной точкой происходит с помощью мобильного приложения ЕКАМ Касса на платформе Android. Интернет-касса — это основная сущность сервиса ЕКАМ Онлайн, для неё Android-устройство не требуется. По сути это конкретный интернет-магазин, для которого формируются фискальные документы (чеки и отчёты). На текущий момент у магазина может быть 1 юридическое лицо (в будущем будет реализована поддержка нескольких юридических лиц), а у юридического лица может быть несколько интернет-касс.

Для каждой интернет-кассы указываются микрокомпьютеры EKAM-BOX, которые будут ее обслуживать. ККТ подключаются к EKAM-BOX по USB (1 ККТ = EKAM-BOX). Для каждой интернет-кассы формируется своя очередь фискальных документов, из которой чеки распределяются на ККТ, подключенные к этой интернет-кассе через обслуживающие её микрокомпьютеры EKAM-BOX. Чем больше у магазина интернет-касс и ККТ, тем больше абонентская плата.

Чеки от магазина по API поступают на облако ЕКАМ Онлайн. Веб-сервис записывает их в очередь соответствующей интернет-кассы. Очередь играет роль буфера и увеличивается в размере, если оборудование не подключено или не справляется с нагрузкой. Увеличение количества ККТ приводит к увеличению скорости обработки чеков, что приводит к уменьшению очереди и задержек формирования чеков.

Результат запроса на регистрацию документа можно проверить по API или в бэк-офисе ЕКАМ. Для простоты вместо 'запрос на регистрацию документа' мы говорим просто 'документ' или просто 'чек'. Не забываем, что имеем дело с запросами, которые не всегда превращаются в зарегистрированные документы (только после переходв в статус printed).

Поддерживаемые типы фискальных документов:

  • Чек прихода (выдаётся при продаже)
  • Чек возврата прихода (выдаётся при возврате)
  • Открытие смены (отчёт регистрируется автоматически перед первой первой операцией смены)
  • Закрытие смены / снятие Z-отчёта(отчёт регистрируется в конце смены)

Невозможно закрыть смену, если не открыта. Отсюда следует, что нельзя снять два Z-отчёта подряд.

Если на ККТ поступает запрсо на регистрацию чека, а смена длится больше 24 часов, то ККТ сначала автоматически закрывает смену, а затем печатает запрошенный чек.

Создание и подключение приложения

  1. Приложение может быть написано на любом языке программирования, диалог с сервером ведется с помощью HTTP-запросов со стороны приложения. Данные передаются в формате JSON.
  2. Разработчик обращается в техподдержку ЕКАМ (support@ekam.ru), сообщает о желании создать приложение, предоставляет свои контакты и данные о системе, с которой планирует произвести интеграцию.
  3. Техподдержка сообщает разработчику 2 параметра: Client ID и Client Secret Key.
  4. Разработчик генерирует токен для доступа к API вручную или через OAuth2.



Генерация токена вручную

Если вы разрабатываете приложение под ваш собственный сайт/сервис (единичная интеграция), то это самый простой способ получения токена.

Чтобы сгенерировать токен, перейдите в раздел бэк-офиса Торговые точки, добавьте новую интернет-кассу, выбрав приложение ЕКАМ API и введя в диалоге Client ID и Client Secret Key вашего приложения.

После создания интернет-кассы нажмите в контекстном меню интернет-кассы на кнопку Токен доступа – токен будет сгенерирован заново, старый перестанет действовать.



Генерация токена через OAuth2

Если вы разрабатываете приложение под множество клиентов и хотите, чтобы установка проходила без вашего участия, то следует выбрать способ получения токена через OAuth2.

Разработчик создаёт установщик шлюза для работы с интернет-кассой. Создание шлюза происходит по протоколу OAuth2 с участием пользователя. Для этого нужно перенаправить пользователя на

https://app.ekam.ru/oauth?client_id={<Client ID>}&redirect_url={<Redirect URL>}&state={<State>}
  • <Client ID> — полученный от техподдержки ЕКАМ параметр Client ID.
  • <Redirect URL> — адрес, на который пользователь будет перенаправлен после успешной установки приложения.
  • <State> — случайно сгенерированная разработчиком приложения строка (например, в base64). Используется для проверки безопасности на разных этапах.

В случае ошибки в параметрах или отсутствия приложения с такими параметрами, пользователь увидит сообщение "Приложение не найдено"

Если URL и параметры верные, пользователь попадёт на форму входа/регистрации в ЕКАМ. После входа система попросит его выбрать аккаунт и интернет-кассу. По завершению этих действий создается шлюз (связка приложения с интернет-кассой), а пользователь перенаправляется на

<Redirect URL>?auth_code=<Auth Code>&state=<State>
  • <Auth Code> — авторизационный код шлюза, необходимый для получения токена.
  • <State> — переданный ранее State.

Для дальнейшей работы с интернет-кассой по API необходим токен. Если пройти ту же процедуру и создать шлюз на ту же интернет-кассу, то будет выдан новый токен, а старый будет отозван. 

Для получения токена необходимо отправить POST-запрос на

https://app.ekam.ru/oauth

с телом

{
  "auth_code":  "0b2f0eb695fa1",    # полученный на предыдущем шаге Auth Code
  "client_id" : "f53bd9e1a05f2",    # полученный от техподдержки Client ID
  "client_secret": "b3sl33fskl"     # полученный от техподдержки Client Secret Key
}


В ответе придет либо ошибка 400, либо ответ с токеном:

{
  "access_token" : "23dl3fjls3"     # токен для работы с интернет-кассой по API
}

Созданные с помощью токена чеки попадут в очередь соответствующей ему интернет-кассы.

Токен можно получить одним запросом из Линукса:

curl -H 'Content-Type: application/json' -X POST -d '{"auth_code":"***","client_id":"***","client_secret":"***"}'
     https://app.ekam.ru/oauth

Алгоритм взаимодействия с сервисом

Взаимодействие с сервером происходит с помощью запросов POST и GET.

POST-запросы направляют на сервер задания на ККТ (печать чека, Z-отчёт). В ответ сервер присылает клиенту идентификатор запрошенной операции.

GET-запросы получают информацию от сервера о состоянии интернет-кассы или выданному ранее идентификатору операции. Сервер возвращает клиенту либо статус (документ в очереди), либо ошибку (неверный формат), либо запрошенную информацию (реквизитами фискализации).

Авторизация

В целях авторизации при всех запросах к API необходимо в заголовке HTTP-запроса X-Access-Token указывать полученный ранее токен.

curl -X GET --header 'Accept: application/json' --header 'X-Access-Token: <Token ID>'
     'https://app.ekam.ru/api/online/v1/receipt_requests'

Пример:

curl -X GET --header 'Accept: application/json' --header 'X-Access-Token: sdf339fjlie3l4ji3lsijsl22'
     'https://app.ekam.ru/api/online/v1/receipt_requests'

Обработка ошибок

В случае успешного выполнения операции сервер возвращает статус 200 или 201.

Если метод API вызван без токена или в запросе передан недействительный токен, сервер возвращает статус 403.

В поисковых запросах при невозможности найти запрашиваемый элемент возвращается ошибка 404.

Если переданы не все параметры (обязательные обозначены звёздочкой *) или они переданы в неверном формате – статус 422.

Если сервис временно не отвечает (например, из-за профилактических работ) – статус 500.

Формализованная спецификация

Самая актуальная формализованная спецификация с возможностью отправлять запросы и получать ответы сервера доступна в Swagger по этой ссылке.

Описание методов

1. Регистрация чека

Описание

Метод служит для регистрации чека в ККТ (прихода или возврата прихода)

Запрос

Метод: POST

https://app.ekam.ru/api/online/v1/receipt_requests

Тело запроса должно содержать документ в формате JSON, пример:

{
  "order_id": "91421af3",
  "order_number": "1014",
  "type": "sale",
  "email": "info@contact.ru",
  "phone_number": "79650000000",
  "should_print": true,
  "cash_amount": 201.1,
  "electron_amount": 0,
  "cashier_name": "string",
  "draft": true,
  "lines": [
    {
      "price": 10,
      "quantity": 2,
      "title": "Плюшевый мишка",
      "total_price": 20,
      "vat_rate": null
    }
  ]
}
  • order_id — уникальный внутри магазина идентификатор заказа или оплаты (если для одного заказа поддерживается несколько оплат). Передавать можно любую строку до 50 символов или может не быть задан вовсе. Больше одного чека одного типа с заданным order_id зарегистрировать нельзя (чеки со статусом "Ошибка" не в счёт).
  • order_number — номер заказа для печати на бумажном чеке, может быть любой строкой.
  • type * — тип чека: 'sale' – чек прихода, 'return' – чек возврата прихода.
  • email — электронная почта покупателя, на которую должен быть отправлен электронный чек.
  • phone_number — номер телефона покупателя в международном формате, на который должен быть отправлен электронный чек.
  • should_print * — печатать (true) или не печатать (false) бумажный чек (по умолчанию – false).
  • cash_amount * — итого оплачено наличными.
  • electron_amount — итого оплачено электронно.
  • cashier_name — имя кассира.
  • draft — черновик (true) или чек для оформления (false).
  • lines * — массив позиций чека.
  • price * — цена 1 единицы товара (если НДС задан, то с учётом НДС), точность до двух знаков после запятой.
  • quantity * — количество товара, точность до трех знаков.
  • title * — название товара.
  • total_price * — сумма по строке, цена * кол-во (если НДС задан, то с учётом НДС), точность до двух знаков после запятой.
  • vat_rate * — ставка НДС: null – без НДС, 0 – 0%, 10 – 10%, 18 – 18%.

Важно: сумма полей total_price по всем позициям чека должна равняться сумме cash_amount + electron_amount. Иначе – ошибка 422.

Пример запроса

 

https://app.ekam.ru/api/online/v1/cashbox

 

Ответ на запрос

Код ответа Результат Пример ответа
201 Ответ получен
{
  "id": 39,
  "order_id": 91421af3,
  "type": "SaleReceiptRequest",
  "status": "pending",
  "kkt_receipt_id": null,
  "amount": "10.0",
  "cash_amount": null,
  "electron_amount": null,
  "lines": [
    {
      "id": 40,
      "title": "Fsdfsdf",
      "quantity": "1.0",
      "total_price": "10.0",
      "price": "10.0",
      "vat_rate": 0,
      "vat_amount": "0.0"
    }
  ],
  "email": null,
  "phone_number": null,
  "should_print": true,
  "created_at": "2017-05-29T15:33:31.470820Z",
  "updated_at": "2017-05-29T15:33:31.470820Z",
  "error": null,
  "error_at" null
}
403 Доступ запрещён  
422 Неверный формат
{
  "error": "string"
}

  • id — идентификатор запроса на регистрацию документа.
  • order_id — уникальный идентификатор заказа учётной системы (источника заказов).
  • type — тип документа: SaleReceiptRequest – чек прихода, ReturnReceiptRequest – чек возврата прихода, ReturnReceiptRequest – отчёт о закрытии смены (Z-отчёт).
  • status — статус запроса на регистрацию: pending – документ в очереди на регистрацию, printed – документ успешно зарегистрирован в ККТ, error – произошла ошибка (документ точно не будет зарегистрирован).
  • kkt_receipt_id — идентификатор зарегистрированного документа (номер чека ККТ в ЕКАМ).
  • amount — общая сумма документа.
  • cash_amount — итого оплачено наличными.
  • electron_amount — итого оплачено электронно.
  • lines — массив позиций чека.
  • id (в составе чека) — идентификатор позиции в чеке.
  • title — название товара.
  • quantity — количество товара, точность до трех знаков.
  • total_price — сумма по строке, цена * кол-во (если НДС задан, то с учётом НДС).
  • price — цена 1 единицы товара (если НДС задан, то с учётом НДС).
  • vat_rate — ставка НДС: null – без НДС, 0 – 0%, 10 – 10%, 18 – 18%.
  • vat_amount — сумма НДС по строке.
  • email — электронная почта покупателя, на которую должен быть отправлен электронный чек.
  • phone_number — номер телефона покупателя в международном формате, на который должен быть отправлен электронный чек.
  • should_print — печатать (true) или не печатать (false) бумажный чек.
  • created_at — время создания запроса на регистрацию документа.
  • updated_at — время изменения запроса на регистрацию документа.
  • error — сообщение об ошибке при статусе error.
  • error_at — время появления ошибки при статусе error.

Оплата несколькими способами одновременно невозможна. Чек может быть сформирован только на оплату 100% наличными или на оплату 100% электронно.

Онлайн-кассир (форма подтверждения чека)

Вместо моментального оформления чека можно перенаправить пользователя на форму подтверждения/корректировки. Для этого необходимо отправить запрос на чек с флагом draft=true, получить в ответ параметр с веб-адресом online_cashier_url и перенаправить на него пользователя. Пользователь должен подтвердить чек в течение 15 минут.

2. Получение информациии о чеках

Описание

Метод служит для получения списка чеков с возможностью фильтрации.

Сортировка чеков в результатах отбора идёт по полю updated_at.

Запрос

Метод: GET

https://app.ekam.ru/api/online/v1/receipt_requests?updated_since=<Updated Since>&after=<After>&limit=<Limit>&type=<Type>&status=<Status>
  • <Type> — тип чека: 'sale' – чек прихода, 'return' – чек возврата прихода. Будут отобраны только документы указанного типа.
  • <Status> — статус запроса на регистрацию: pending – документ в очереди на регистрацию, printed – документ успешно зарегистрирован в ККТ, error – произошла ошибка (документ точно не будет зарегистрирован). Будут отобраны только документы с указанным статусом.
  • <Limit> — максимальное число документов в результете отбора. Параметр может использоваться в пагинации.
  • <Updated Since> — фильтрация по времени, будут отобраны только те документы, которые были обновлены не раньше указанного времени. Параметр может использоваться в пагинации.
  • <After> — параметр не используется.

Пример запроса

 

https://app.ekam.ru/api/online/v1/receipt_requests?after=1&limit=2&type=sales&status=pending

 

Ответ на запрос

Код ответа Результат Пример ответа
200 Ответ получен
{
  "items": [
    {
      "id": 596,
      "type": "SaleReceiptRequest",
      "status": "printed",
      "kkt_receipt_id": 74,
      "amount": "10000.0",
      "cash_amount": "10000.0",
      "electron_amount": "0.0",
      "lines": [
        {
          "id": 614,
          "title": "Смартфон",
          "quantity": "1.0",
          "total_price": "10000.0",
          "vat_rate": 0,
          "vat_amount": "0.0"
        }
      ],
      "email": null,
      "phone_number": "+79012345678",
      "should_print": true,
      "order_id": "11126010",
      "order_number": "1",
      "created_at": "2017-06-02T12:56:27.149506Z",
      "updated_at": "2017-06-02T13:24:13.094088Z",
      "kkt_receipt_exists": true,
      "fiscal_data": {
        "receipt_number": 1,
        "model_number": 61,
        "factory_kkt_number": "00106106050261",
        "factory_fn_number": "9999078900006741",
        "registration_number": "0000000001014591",
        "fn_expired_period": 13,
        "fd_number": "15",
        "fpd": "1525842555",
        "registration_date": "2017-05-23T00:00:00.000000Z",
        "fn_expired_at": null
      },
      "receipt_url": "https://s61.ekam.ru/r/6589afea-1579-433d-b03b-aa19a928f338"
    }
  ],
  "next_page_url": "https://s61.ekam.ru/api/online/v1/receipt_requests?after=596&limit=1&updated_since=2017-06-02+16%3A24%3A13+%2B0300"
}
403 Доступ запрещён  
422 Неверный формат  

Пагинация

Для первого запроса можно использовать limit и updated_since, дальше в ответе помимо массива items будет присутствовать поле next_page_url, содержащее ссылку на следующую страницу. 
Для получения следующей страницы можно пользоваться полученным next_page_url.

3. Закрытие смены

Описание

Метод служит для закрытие кассовой смены (снятия Z-отчёта).

Запрос

Метод: POST

https://app.ekam.ru/api/online/v1/receipt_requests/close_retail_shift

Пример запроса

https://app.ekam.ru/api/online/v1/receipt_requests/close_retail_shift

Ответ на запрос

Код ответа Результат Пример ответа
201 Ответ получен
{
  "id": 49,
  "type": "CloseRetailShiftRequest",
  "status": "pending",
  "kkt_receipt_id": null,
  "amount": "0.0",
  "cash_amount": null,
  "electron_amount": null,
  "email": null,
  "phone_number": null,
  "should_print": false,
  "created_at": "2017-05-29T21:22:50.072464Z",
  "updated_at": "2017-05-29T21:22:50.072464Z"
}
403 Доступ запрещён  
422 Неверный формат
{
  "error": "string"
}

  • id — идентификатор запроса на регистрацию документа.
  • type — тип документа: SaleReceiptRequest – чек прихода, SaleReceiptRequest – чек возврата прихода, ReturnReceiptRequest – отчёт о закрытии смены (Z-отчёт).
  • status — статус запроса на регистрацию: pending – документ в очереди на регистрацию, printed – документ успешно зарегистрирован в ККТ, error – произошла ошибка (документ точно не будет зарегистрирован).
  • kkt_receipt_id — идентификатор зарегистрированного документа (номер чека ККТ в ЕКАМ).
  • amount — для кассовых отчётов параметр не используется.
  • cash_amount — для кассовых отчётов параметр не используется.
  • electron_amount — для кассовых отчётов параметр не используется.
  • email — для кассовых отчётов параметр не используется.
  • phone_number — для кассовых отчётов параметр не используется.
  • should_print — для кассовых отчётов параметр не используется.
  • created_at — время создания запроса на регистрацию документа.
  • updated_at — время изменения запроса на регистрацию документа.
  • error — сообщение об ошибке при статусе error.
  • error_at — время появления ошибки при статусе error.