Skip to main content

Операции платёжного терминала

Общая информация

LIFE POS Checkout может принимать оплату по банковской карте через платежный терминал, например через QPOS mini. Для этого модуль periphery-models, подключаемый через build.gradle, содержит набор классов результатов выполнения операций через платежный терминал.

Для каждого действия action используется своя модель результата операции, смотрите таблицу соответствия операций и моделей.

Модели передаются и получаются в виде json строки, которая является сериализованным представлением модели. Чтобы сериализовать модель в json строку используйте метод toJSON().

Для десериализации json строки в соответствующую модель используйте метод fromJSON() с указанием нужного класса модели:

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

Соответствие операций и моделей

Таблица соответствия операций и моделей:

Название операцииДействие (action)Модель результата операции
Оплатаru.lifepay.checkout.payment_terminal.transaction.payPTTransaction
Возвратru.lifepay.checkout.payment_terminal.transaction.refundPTTransaction
Отменаru.lifepay.checkout.payment_terminal.transaction.cancelPTTransaction
Получение результата оплаты/возврата/отменыru.lifepay.checkout.payment_terminal.transaction.get_resultPTTransaction
Сверка итоговru.lifepay.checkout.payment_terminal.close_shiftPTSummaryShiftReport

Поддерживаемые платежные терминалы и операции

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

Платежные терминалы и поддерживаемые операции

Платежный терминалТип подключенияОплата/Возврат/ОтменаПолучение результата оплаты/возврата/отменыСверка итогов
Lifepay QPOSBluetooth++Выполняется сервером в 00:00

Оплата

Действие: ru.lifepay.checkout.payment_terminal.transaction.pay

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

НазваниеТипОбязательностьЗначение/описание
request_idStringнетУникальный идентификатор запроса. Возвращается в ответе. Некоторые виды терминалов поддерживают операцию получения результата оплаты по request_id. Логику работы смотрите в разделе Получение результата оплаты/возврата/отмены.
metadataHashMap<String, String>нетДополнительные пользовательские данные. Возвращаются в ответе. Смотрите раздел Передача дополнительных данных.
amountLongдаСумма оплаты в копейках.

Дополнительные параметры

НазваниеТипОбязательностьЗначение/описание
loginStringдаЛогин пользователя в системе Lifepay.
passwordStringдаПароль пользователя в системе Lifepay.
sign_on_screenStringнет"1" - да, "0" - нет. По умолчанию "0". Необходимо ли выводить экран для ввода подписи покупателя на смартфоне в случае необходимости подтвердить транзакцию подписью.
emailStringнетПочта на которую будет отправлен электронный СЛИП чек оплаты.
phoneStringнетТелефон на который будет отправлено SMS с электронным СЛИП чеком оплаты.
recipient_innStringнетИНН получателя платежа.

Пример выполнения запроса

Пример выполнения запроса на Kotlin:

fun pay(
requestId: String,
metadata: HashMap\<String, String>?,
amount: Long
) {
val lifepaySpecificData = LifepaySpecificDataRepository.getData()
sendRequest(
intent = Intent(Actions.ru.lifepay.checkout.payment_terminal.transaction.pay)
.putExtra("request_id", requestId)
.putExtra("metadata", metadata)
.putExtra("amount", amount)

.apply {
putExtra("sign_on_screen", if (lifepaySpecificData.signOnScreen) "1" else "0")
if (!lifepaySpecificData.login.isNullOrEmpty()) {
putExtra("login", lifepaySpecificData.login)
}
if (!lifepaySpecificData.password.isNullOrEmpty()) {
putExtra("password", lifepaySpecificData.password)
}
if (!lifepaySpecificData.email.isNullOrEmpty()) {
putExtra("email", lifepaySpecificData.email)
}
if (!lifepaySpecificData.phone.isNullOrEmpty()) {
putExtra("phone", lifepaySpecificData.phone)
}
if (!lifepaySpecificData.recipientInn.isNullOrEmpty()) {
putExtra("recipient_inn", lifepaySpecificData.recipientInn)
}
}
)
}

Возврат

Действие: ru.lifepay.checkout.payment_terminal.transaction.refund

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

НазваниеТипОбязательностьЗначение/описание
request_idStringнетУникальный идентификатор запроса. Возвращается в ответе. Некоторые виды терминалов поддерживают операцию получения результата возврата по request_id. Логику работы смотрите в разделе Получение результата оплаты/возврата/отмены.
metadataHashMap<String, String>нетДополнительные пользовательские данные. Возвращаются в ответе. Смотрите раздел Передача дополнительных данных.
amountLongдаСумма возврата в копейках.
primary_transactionStringдаСериализованный в json строку объект PTTransaction полученный в результатах оплаты.

Дополнительные параметры

НазваниеТипОбязательностьЗначение/описание
loginStringдаЛогин пользователя в системе Lifepay.
passwordStringдаПароль пользователя в системе Lifepay.
sign_on_screenStringнет"1" - да, "0" - нет. По умолчанию "0". Необходимо ли выводить экран для ввода подписи покупателя на смартфоне в случае необходимости подтвердить транзакцию подписью.

Пример выполнения запроса

Пример выполнения запроса на Kotlin:

fun refund(
requestId: String,
amount: Long,
primaryTransaction: PTTransaction
) {
val lifepaySpecificData = LifepaySpecificDataRepository.getData()
sendRequest(
intent = Intent(Actions.ru.lifepay.checkout.payment_terminal.transaction.refund)
.putExtra("request_id", requestId)
.putExtra("amount", amount)
.putExtra("primary_transaction", primaryTransaction.toJSON())

.apply {
putExtra("sign_on_screen", if (lifepaySpecificData.signOnScreen) "1" else "0")
if (!lifepaySpecificData.login.isNullOrEmpty()) {
putExtra("login", lifepaySpecificData.login)
}
if (!lifepaySpecificData.password.isNullOrEmpty()) {
putExtra("password", lifepaySpecificData.password)
}
}
)
}

Отмена

Действие: ru.lifepay.checkout.payment_terminal.transaction.cancel

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

НазваниеТипОбязательностьЗначение/описание
request_idStringнетУникальный идентификатор запроса. Возвращается в ответе. Некоторые виды терминалов поддерживают операцию получения результата отмены по request_id. Логику работы смотрите в разделе Получение результата оплаты/возврата/отмены.
metadataHashMap<String, String>нетДополнительные пользовательские данные. Возвращаются в ответе. Смотрите раздел Передача дополнительных данных
amountLongдаСумма отмены в копейках.
primary_transactionStringдаСериализованный в json строку объект PTTransaction полученный в результатах оплаты.

Дополнительные параметры

НазваниеТипОбязательностьЗначение/описание
loginStringдаЛогин пользователя в системе Lifepay.
passwordStringдаПароль пользователя в системе Lifepay.
sign_on_screenStringнет"1" - да, "0" - нет. По умолчанию "0". Необходимо ли выводить экран для ввода подписи покупателя на смартфоне в случае необходимости подтвердить транзакцию подписью.

Пример выполнения запроса

Пример выполнения запроса на Kotlin:

fun cancel(
requestId: String,
amount: Long,
primaryTransaction: PTTransaction
) {
val lifepaySpecificData = LifepaySpecificDataRepository.getData()
sendRequest(
intent = Intent(Actions.ru.lifepay.checkout.payment_terminal.transaction.cancel)
.putExtra("request_id", requestId)
.putExtra("amount", amount)
.putExtra("primary_transaction", primaryTransaction.toJSON())

.apply {
putExtra("sign_on_screen", if (lifepaySpecificData.signOnScreen) "1" else "0")
if (!lifepaySpecificData.login.isNullOrEmpty()) {
putExtra("login", lifepaySpecificData.login)
}
if (!lifepaySpecificData.password.isNullOrEmpty()) {
putExtra("password", lifepaySpecificData.password)
}
}
)
}

Получение результата оплаты/возврата/отмены

Действие: ru.lifepay.checkout.payment_terminal.transaction.get_result

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

НазваниеТипОбязательностьЗначение/описание
request_idStringдаЗначение request_id, которое было передано при первоначальном проведении операции.
metadataHashMap<String, String>нетЗначение metadata, которое было передано при первоначальном проведении операции.

Дополнительные параметры

НазваниеТипОбязательностьЗначение/описание
loginStringдаЛогин пользователя в системе Lifepay.
passwordStringдаПароль пользователя в системе Lifepay.

Пример выполнения запроса

Пример выполнения запроса на Kotlin:

fun getResult(
requestId: String,
metadata: Serializable?
) {
val lifepaySpecificData = LifepaySpecificDataRepository.getData()
sendRequest(
intent = Intent(Actions.ru.lifepay.checkout.payment_terminal.transaction.get_result)
.putExtra("request_id", requestId)
.putExtra("metadata", metadata)

.apply {
if (!lifepaySpecificData.login.isNullOrEmpty()) {
putExtra("login", lifepaySpecificData.login)
}
if (!lifepaySpecificData.password.isNullOrEmpty()) {
putExtra("password", lifepaySpecificData.password)
}
}
)
}

Сверка итогов

Действие: ru.lifepay.checkout.payment_terminal.close_shift

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

НазваниеТипОбязательностьЗначение/описание
request_idStringнетУникальный идентификатор запроса. Возвращается в ответе.
metadataHashMap<String, String>нетДополнительные пользовательские данные. Возвращаются в ответе.

Пример выполнения запроса

Пример выполнения запроса на Kotlin:

fun closeShift() {
sendRequest(Intent(Actions.ru.lifepay.checkout.payment_terminal.close_shift))
}

private fun sendRequest(intent: Intent) {
Logger.logRequest(intent)
try {
activity.startActivityForResult(intent, 5555) //число 5555 взято просто так, можно использовать другое число.
} catch (e: ActivityNotFoundException) {
errorCallback.invoke("Приложение LIFE POS Checkout не установлено на устройстве. Необходимо установить приложение.")
} catch (e: Throwable) {
errorCallback.invoke(e.message)
}
}

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

При успешном запросе Checkout возвращает resultCode = Activity.RESULT_OK (-1) и экземпляр класса Intent с действием action, которое было указано во входящем интенте.

При ошибке Checkout вернёт resultCode со значением отличным от Activity.RESULT_OK или intent будет содержать null.

Для определения факта успешной операции проверяйте значение параметра code:

  • значение 0 — операция выполнена успешно;
  • значение отличное от 0 — произошла ошибка.

Параметры результата при успешном выполнении операции

НазваниеТипОбязательностьЗначение/описание
codeIntда0 - операция проведена успешно.
dataStringдаСериализованный в json строку результат операции. Смотрите таблицу соответствия операций и моделей.
request_idStringдаЗначение request_id, которое было передано в запросе. Если значение не было передано в запросе, то оно генерируется автоматически.
metadataHashMap<String, String>нетЗначение metadata, которое было передано в запросе. Извлекается через extras.getSerializable("metadata").

Значения полей можно извлекать из экземпляра класса Bundle получаемого из свойства extras класса Intent при помощи методов extras.getInt(...) и extras.getString(...).

Параметры результата при ошибке

НазваниеТипОбязательностьЗначение/описание
codeIntдаОтличное от нуля значение. Означает, что произошла ошибка.
request_idStringдаЗначение request_id, которое было передано в запросе. Если значение не было передано в запросе, то оно генерируется автоматически.
metadataHashMap<String, String>нетЗначение metadata, которое было передано в запросе. Извлекается через extras.getSerializable("metadata").
error_typeStringдаТип ошибки. Каждый тип имеет свою собственную логику обработки. Смотрите Типы ошибок.
messageStringдаТекст ошибки для вывода пользователю.

Типы ошибок

Тип ошибки (error_type)Описание
default_errorОбычная ошибка.
unknown_result_errorРезультат операции неизвестен. Выдается только для терминалов и операций поддерживающих операцию получения результата оплаты/возврата/отмены. Логику обработки смотрите в разделе Получение результата оплаты/возврата/отмены.
duplicate_request_errorПовторный запрос с одним и тем же request_id. Выдается только для терминалов и операций поддерживающих операцию получения результата оплаты/возврата/отмены. Логику обработки смотрите в разделе Получение результата оплаты/возврата/отмены.
result_not_found_errorРезультат операции не найден. Выдается только на запрос получения результата оплаты/возврата/отмены. Подробнее в разделе Получение результата оплаты/возврата/отмены.

Получение результата оплаты, возврата, отмены

Для каждого запроса в Checkout можно передавать параметр request_id. В случае если его не передать, то он будет сгенерирован автоматически и вернется в ответе.

request_id это уникальный идентификатор запроса в приложении LIFE POS Checkout для получения результата операции при необходимости. Для этого отправьте запрос в Checkout на получение результата оплаты/возврата/отмены. В результате выполнения вы получите такой же ответ, как и в запросе на выполнение операций оплаты/возврата/отмены. Смотрите раздел Параметры результата запроса.

Для терминалов и операций оплаты, возврата, отмены в параметре ошибки error_type могут возвращаться значения unknown_result_error и duplicate_request_error. Их поддерживают не все терминалы и типы операций. Смотрите таблицу платежные терминалы и поддерживаемые операции. Если терминал или операция не поддерживают получение результата, то эти ошибки не возвращаются.

Получение результата операции доступно ограниченное время после проведения операции. Например, LIFE PAY QPOS запоминает 500 последних запросов.

Алгоритм обработки ошибок unknown_result_error и duplicate_request_error

  1. Если в результате проведения операции происходит ошибка unknown_result_error, то результат операции неизвестен. Он может быть как успешным, так и неуспешным. В этом случае можно проверьте результат операции, отправив запрос получения результата оплаты/возврата/отмены в LIFE POS Checkout.
info

Не отправляйте этот запрос автоматически после получения ошибки. Эта ошибка может произойти из-за того, что терминал потерял связь со смартфоном или сел.

Мы рекомендуем предупредить кассира и предложить ему запросить результат операции нажатием на кнопку. Пример такой реализации смотрите в демонстрационном приложении в классе ResponseHandler.

  1. Запрос получения результата оплаты/возврата/отмены также может закончиться ошибкой с типом unknown_result_error. Например, если не удалось соединиться с терминалом или отсутствует связь с интернетом. В этом случае можно повторите алгоритм из пункта 1.

  2. Если запрос получения результата оплаты/возврата/отмены заканчивается ошибкой с типом отличным от unknown_result_error, тогда обновите request_id для проведения операции заново.

  3. Если в результате проведения операции оплаты/возврата/отмены происходит ошибка с duplicate_request_error, то повторите пункт 1 алгоритма. Эта ошибка возникает при попытке провести операцию с тем же request_id, что и ранее. А значит, что по предыдущей операции не был получен результат и request_id не был изменен.

info

Не используйте в качестве request_id какие-либо внутренние глобальные идентификаторы заказа/покупки/продажи из своего приложения. Для одной и той же операции может потребоваться изменять request_id в процессе попыток ее проведения.

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

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

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

При использовании Lifepay QPOS это даёт возможность получать оповещение стороннего сервера о транзакции, если в ЛК Lifepay указан URL для уведомлений.

Для передачи дополнительных параметров используйте metadata в параметрах запросов. Никаких проверок на дублирование для этого параметра не выполняется. Пример заполнения параметра metadata:

val metadata = HashMap\<String, String>().apply {
put("OrderId", "12345")
}
intent.putExtra("metadata", metadata)