LIFE POS Checkout

Документация по интеграции с приложением LIFE POS Checkout. Все примеры кода приведены на языке программирования Kotlin.

Исходники приложения для демонстрации интеграции

1. Настройка проекта

В build.gradle файле проекта прописать maven репозиторий:

allprojects {
    repositories {
        maven { 
            url 'https://lifepaycloudplatform.pkgs.visualstudio.com/Common/_packaging/external/maven/v1' 
        }
    }
}

В build.gradle файле модуля приложения подключить зависимости:

implementation "ru.lifepay:periphery-models:$lifepayPeripheryVersion"

Последняя версия моделей:

ext {
    lifepayPeripheryVersion = '0.0.48' 
}

2. Фискализация

2.1. Запуск LIFE POS Checkout

Для фискализации при помощи приложения LIFE POS Checkout необходимо создать в своем приложении экземпляр класса Intent с packageName = "ru.lifepay.checkout" и action = "fiscal" и сбросить все флаги через setFlags(0).

val lifepayIntent = (getPackageManager()
    ?.getLaunchIntentForPackage("ru.lifepay.checkout") 
    ?: throw IllegalStateException("Приложение LIFE POS Checkout не установлено."))
    .setFlags(0)
    .setAction("fiscal")

Для отправки запроса в приложение LIFE POS Checkout необходимо использовать метод startActivityForResult(...) класса Activity:

startActivityForResult(lifepayIntent, 5555)

Для получения результата операции необходимо перегрузить метод onActivityResult(...) класса Activity:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    //обработка
}

Параметры запроса необходимо передавать при помощи метода putExtra(...) класса Intent. Например:

lifepayIntent.putExtra("document_type", "receipt")

2.2. Параметры входящего запроса

2.2.1. Базовые поля

В таблице 2.1 приводится список базовых полей любого запроса на фискализацию.

Таблица 2.1. Базовые поля

Название Тип Обязательность Описание
request_id String да Уникальный идентификатор запроса. Логику работы смотрите в разделе 2.4. Защита от дублирования.
document_type String да Тип документа: обычный чек, чек коррекции, …
data String в зависимости от типа документа сериализованные в json строку параметры документа.

Поле data заполняется в зависимости от типа документа document_type. Подключенный модуль periphery-models содержит набор классов (моделей) параметров фискальных чеков. Для каждого типа документа используется своя модель. В разделе 2.2.2. Полный список полей для каждого типа документа указана соответствующая ему модель. Чтобы сериализовать модель в json строку для передачи параметром запроса, необходимо использовать метод toJSON().

В зависимости от типа документа и используемого типа фискального регистратора (ФР) в запросе могут быть дополнительные поля. Тип используемого ФР выбирается вручную из приложения LIFE POS Checkout. В первой версии приложения доступен только только один тип ФР - облачная касса. Он же установлен по умолчанию, выбирать вручную его не нужно. Для использования облачной кассы необходимо передавать дополнительные поля приведенные в таблице 2.2.

Таблица 2.2. Дополнительные поля для облачной кассы

Название Тип Обязательность Описание
apikey String да АПИ-ключ компании в системе Lifepay. Узнать свой АПИ-ключ можно в личном кабинете Lifepay.
target_serial String нет Серийный номер принтера, на котором необходимо фискализировать данные. Если не задан, чек будет фискализирован на одном из подключенных (активных) фискальных принтеров.

2.2.2. Полный список полей

Таблица 2.3. Кассовый чек (облачная касса)

Название Тип Обязательность Значение/описание
request_id String да Генерация данного параметра должна быть встроена в логику вашего приложения. Подробнее в разделе 2.4. Защита от дублирования.
document_type String да receipt
data String да Экземпляр класса FCRegisterReceiptParams сериализованный в json.
print Boolean нет true/false - необходимо ли печатать чек на фискальном регистраторе. По умолчанию - true. В случае false, необходимо заполнять поле customerContacts модели FCRegisterReceiptParams (поле data).
apikey String да АПИ-ключ компании в системе Lifepay. Узнать свой АПИ-ключ можно в личном кабинете Lifepay.
target_serial String нет Серийный номер принтера, на котором необходимо фискализировать данные. Если не задан, чек будет фискализирован на одном из подключенных (активных) фискальных принтеров.

Таблица 2.4. Кассовый чек коррекции (облачная касса)

Название Тип Обязательность Значение/описание
request_id String да Генерация данного параметра должна быть встроена в логику вашего приложения. Подробнее в разделе 2.4. Защита от дублирования.
document_type String да receipt_of_correction
data String да Экземпляр класса FCRegisterReceiptOfCorrectionParams сериализованный в json.
apikey String да АПИ-ключ компании в системе Lifepay. Узнать свой АПИ-ключ можно в личном кабинете Lifepay.
target_serial String нет Серийный номер принтера, на котором необходимо фискализировать данные. Если не задан, чек будет фискализирован на одном из подключенных (активных) фискальных принтеров.

2.3. Параметры результата запроса

В случае успешной обработки запроса приложение LIFE POS Checkout возвращает resultCode = Activity.RESULT_OK (-1) и экземпляр класса Intent с action = "fiscal". Если resultCode отличается от Activity.RESULT_OK или intent == null, то следует рассматривать данную ситуацию как ошибку с error_type = unknown_result_error. (Смотрите таблицу 2.7. Поля ошибки и раздел 2.4. Защита от дублирования.)

Успешная обработка запроса еще не означает успешной фискализации документа. Для определения факта успешной/неуспешной фискализации следует ориентироваться на поле code. В таблице 2.5 представлен список полей в случае успешной фискализации.

Таблица 2.5. Поля результата запроса в случае успешной фискализации

Название Тип Обязательность Значение/описание
code Int да 0 - успешная фискализация документа.
request_id String да Значение request_id, которое было передано в запросе.
document_type String да Значение document_type, которое было передано в запросе.
data String да сериализованные в json строку данные фискализации.

Значения полей можно извлекать из экземпляра класса Bundle получаемого из свойства extra класса Intent при помощи методов extras.getInt(...) и extras.getString(...). Значение поля data зависит от типа документа document_type. Для результатов запроса (также как и для входящего запроса) имеется набор классов (моделей) для каждого типа документа в модуле periphery-models. В таблице 2.6 представлен список соотвествия типов документов и моделей из библиотеки.

Таблица 2.6. Соответствие типов документов и моделей

Название типа документа Тип документа Входящая модель Исходящая модель
Кассовый чек receipt FCRegisterReceiptParams FDReceipt
Кассовый чек коррекции receipt_of_correction FCRegisterReceiptOfCorrectionParams FDReceiptOfCorrection

Для десериализации строкового значения поля data в соответствующую модель следует использовать следующий метод:

GSONConverter.fromJSON(data, FDReceipt::class.java)

В таблице 2.7 представлен список полей в случае завершения запроса с ошибкой.

Таблица 2.7. Поля ошибки

Название Тип Обязательность Значение/описание
code Int да Отличное от нуля значение. Означает, что произошла ошибка.
request_id String да Значение request_id, которое было передано в запросе.
error_type String да Тип ошибки. Каждый тип имеет свою собственную логику обработки. Смотрите таблицу 2.8. Типы ошибок.
message String да Текст ошибки для вывода пользователю.
log String нет Дополнительная информация об ошибке для разработчиков. Для пользователей ее выводить не нужно. Может быть полезной на этапе интеграции и тестирования. Может иметь большой размер.

Таблицу 2.8. Типы ошибок

Тип ошибки (error_type) Описание
default_error Обычная ошибка.
unknown_result_error Результат запроса неизвестен. Логику обработки смотрите в разделе 2.4. Защита от дублирования.

2.4. Защита от дублирования

Каждый запрос в приложение LIFE POS Checkout должен содержать обязательный параметр request_id. Как написано в описании это уникальный идентификатор запроса. Данный идентификатор используется локально в приложении LIFE POS Checkout и необходим для работы механизма защиты от дублирования.

Логика работы следующая: У стороннего приложения имеются данные кассового чека, которые необходимо зафискализировать. Стороннее приложение локально генерирует request_id и отсылает запрос на фискализацию в LIFE POS Checkout вместе с этим request_id. 1) Если в результате выполнения запроса происходит успешная фискализация (code == 0), то повторный запрос в LIFE POS Checkout с тем же request_id будет выдавать успешный результат с теми же данными, без выполнения фискализации. При этом нужно понимать, что этот механизм будет работать только локально на этом android устройстве. Если отправить запрос с тем же request_id с другого android устройства, то такой чек будет зафискализирован. Данный механизм нужен, чтобы защититься от дублей локально, в определенное ограниченное время. К примеру для облачной кассы запоминается локально 50 последних запросов. 2) Если в результате выполнения запроса происходит ошибка с error_type == unknown_result_error, то это означает что результат запроса неизвестен, он может быть как успешным, так и нет. В этом случае при следующей попытке фискализации этого чека необходимо отсылать запрос с тем же request_id, что и первоначальный. Это необходимо делать либо до получения успешного результата, либо до получения ошибки с другим error_type. 3) Если в результате выполнения запроса происходит ошибка с error_type != unknown_result_error, то для следующей попытки фискализации этого чека необходимо сгенерировать новый request_id. Т.к. старый request_id с большой долей вероятности в этом случае выдаст ошибку.

Не используйте для этих целей какие либо внутренние глобальные идентификаторы заказа из своей системы. Т.к во первых как описано выше для одного и того же чека может потребоваться изменять request_id. И также иногда может требоваться для одного заказа фискализация нескольких разных чеков.

Если вам требуется передавать внутренний глобальный идентификатор заказа вместе с чеком смотрите раздел 2.5. Передача дополнительных данных

2.5. Передача дополнительных данных

Приложение LIFE POS Checkout позволяет передавать вместе с кассовый чеком и кассовым чеком коррекции чеком дополнительные данные. Например это может быть уникальный идентификатор заказа из вашей системы.

При использовании облачной кассы это дает возможность находить чеки в личном кабинете Lifepay по переданным данным.

Для реализации этого механизма необходимо передавать в моделях FCRegisterReceiptParams и FCRegisterReceiptOfCorrectionParams параметр:

var additionalAttributes: List<FCAdditionalAttribute>?

Класс FCAdditionalAttribute выглядит следующим образом:

class FCAdditionalAttribute(
    var name: String,
    var value: String
) 

Пример заполнения параметра additionalAttributes:

additionalAttributes = listOf(FCAdditionalAttribute(
                name = "OperationId",
                value = "12345"))

Никаких проверок на дублирование для данного параметра не производится.