Acquiring SDK позволяет интегрировать Интернет-Эквайринг Tinkoff в мобильные приложения для платформы Android.
Возможности SDK:
- Прием платежей (в том числе рекуррентных);
- Сохранение банковских карт клиента;
- Сканирование и распознавание карт с помощью камеры или NFC;
- Получение информации о клиенте и сохраненных картах;
- Управление сохраненными картами;
- Поддержка локализации;
- Кастомизация экранов SDK;
- Интеграция с онлайн-кассами;
- Поддержка Системы быстрых платежей
- Оплата через Tinkoff Pay
- Оплата через Mir Pay
- Оплата с помощью Yandex Pay
Для работы Tinkoff Acquiring SDK необходим Android версии 7.0 и выше (API level 24).
Для подключения SDK добавьте в build.gradle вашего проекта следующие зависимости:
implementation 'ru.tinkoff.acquiring:ui:$latestVersion'
implementation 'ru.tinkoff.acquiring:threeds-sdk:$latestVersion'
implementation 'ru.tinkoff.acquiring:threeds-wrapper:$latestVersion'
Если вы хотите внедрить сканирование с помощью библиотеки Card-IO, то необходимо добавить в build.gradle
implementation 'ru.tinkoff.acquiring:cardio:$latestVersion'
Так же необходимо добавить в network-security-config содержащий
сертификаты от минцифр и доп. сертификат от тинькофф. Пример можно посмотреть в sample
выглядит он так:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system" />
<certificates src="@raw/acq_tinkoff_root_cert" />
<certificates src="@raw/acq_ministry_of_digital_development_root_cert" />
</trust-anchors>
</base-config>
</network-security-config>
Для начала работы с SDK вам понадобятся:
- Terminal key
- Public key
Которые выдаются после подключения к Интернет-Эквайрингу
Подробнее о настройке Личного кабинета можно прочитать тут
SDK позволяет настроить режим работы (debug/prod). По умолчанию - режим prod. Чтобы настроить debug режим, установите параметры:
AcquiringSdk.isDeveloperMode = true // используется тестовый URL, деньги с карт не списываются
AcquiringSdk.isDebug = true // включение логирования запросов
Кроме того, в некоторых случаях к запросам к API эквайринга есть возможность добавлять некий токен (подпись запроса).
Задание способа генерации токена в случаях, когда это необходимо, может выглядеть следующим образом
(для более подробной информации см. kDoc AcquiringSdk.tokenGenerator
):
AcquiringSdk.tokenGenerator = SampleAcquiringTokenGenerator(password) // генерация токена с использованием пароля
// В целях безопасности не рекомендуется хранить пароль в коде приложения
Для начала необходимо создать TinkoffAcquiring
val tinkoffAcquiring = TinkoffAcquiring(applicationContext, "TERMINAL_KEY", "PUBLIC_KEY") // создание объекта для взаимодействия с SDK и передача данных продавца
Далее необходимо проинициализировать платежные сессии методов оплаты:
tinkoffAcquiring.initSbpPaymentSession()
tinkoffAcquiring.initTinkoffPayPaymentSession()
tinkoffAcquiring.initMirPayPaymentSession()
Примечание Для того чтобы не инициализировать все платежные сессии, можно предварительно вызвать метод TinkoffAcquiring.checkTerminalInfo() для получения списка актуальных способов оплаты и произвести инициализации платежных сессий только для них.
Далее необходимо настроить экран с формой оплаты на обработку конкретного платежа с помощью PaymentOptions которые состоят из настроек проведения оплаты, в том числе данные заказа, данные покупателя и опционально параметры кастомизации экрана оплаты. Так же можно указать модуль для сканирования (свой или CardScannerDelegate). Локализация берется из системы, так же имеется поддержка светлой и тёмной темы. Внешний вид экрана и набор компонентов определяется из доступных методов оплаты, настраивается в личном кабинете.
val paymentOptions =
PaymentOptions().setOptions {
orderOptions { // данные заказа
orderId = "ORDER-ID" // ID заказа в вашей системе
amount = Money.ofRubles(1000) // сумма для оплаты
title = "НАЗВАНИЕ ПЛАТЕЖА" // название платежа, видимое пользователю
description = "ОПИСАНИЕ ПЛАТЕЖА" // описание платежа, видимое пользователю
recurrentPayment = false // флаг определяющий является ли платеж рекуррентным [1]
successURL = "URL" // URL, куда будет переведен покупатель в случае успешной оплаты (см. полную документацию)
failURL = "URL" // URL, куда будет переведен покупатель в случае неуспешной оплаты (см. полную документацию)
}
customerOptions { // данные покупателя
checkType = CheckType.NO.toString() // тип привязки карты
customerKey = "CUSTOMER_KEY" // уникальный ID пользователя для сохранения данных его карты
email = "[email protected]" // E-mail клиента для отправки уведомления об оплате
}
featuresOptions { // настройки визуального отображения и функций экрана оплаты
cameraCardScanner =
CardScannerDelegateImpl() // реализация механизма сканирования карт, можно использовать встроенный CardScannerWrapper
}
}
Затем регистрируем контракт MainFormContract#Contract, и вызываем метод ActivityResultLauncher#launch
val byMainFormPayment = registerForActivityResult(MainFormLauncher.Contract, ActivityResultCallback {})
byMainFormPayment.launch(MainFormContract.StartData(paymentOptions))
Результат платежа вернется в ActivityResultCallback:
- при успешном платеже возвращается MainFormLauncher.Success - содержащий paymentId идентификатор платежа, опционально cardId - id карты, с которой проводился платеж, тип String и опционально rebillId - rebillId карты, если был совершен рекуррентный платеж
- при неуспешном платеже (MainFormLauncher.Error) содержащий Throwable (подробнее о возвращаемых ошибках в документации)
- при отмене платежа (MainFormLauncher.Canceled)
Можно так же передать данные чека, указав параметр receipt в методе PaymentOptions#orderOptions и передать дополнительные параметры additionalData. Эти объекты при их наличии будут переданы на сервер с помощью метода API Init, где можно посмотреть их детальное описание.
val paymentOptions =
PaymentOptions().setOptions {
orderOptions {
receipt = myReceipt
additionalData = dataMap
// другие параметры заказа
}
customerOptions {
// данные покупателя
}
featuresOptions {
// настройки визуального отображения и функций экрана оплаты
}
}
val byMainFormPayment = registerForActivityResult(MainFormContract.Contract)
byMainFormPayment.launch(MainFormContract.StartData(paymentOptions))
[1] Рекуррентный платеж может производиться для дальнейшего списания средств с сохраненной карты, без ввода ее реквизитов. Эта возможность, например, может использоваться для осуществления платежей по подписке.
[2] Безопасная клавиатура используется вместо системной и обеспечивает дополнительную безопасность ввода, т.к. сторонние клавиатуры на устройстве клиента могут перехватывать данные и отправлять их злоумышленнику.
Для запуска экрана привязки карт необходимо зарегестирировать AttachCardLauncher#Contract. В метод также необходимо передать некоторые параметры - тип привязки, данные покупателя и опционально параметры кастомизации (по-аналогии с экраном оплаты):
val attachCardOptions =
AttachCardOptions().setOptions {
setTerminalParams("TERMINAL_KEY", "PUBLIC_KEY")
customerOptions { // данные покупателя
customerKey = "CUSTOMER_KEY" // уникальный ID пользователя для сохранения данных его карты
checkType = CheckType.NO.toString() // тип привязки карты
email = "[email protected]" // E-mail клиента для отправки уведомления о привязке
}
featuresOptions { // настройки визуального отображения и функций экрана оплаты
useSecureKeyboard = true
cameraCardScanner = CameraCardIOScanner()
theme = themeId
}
}
attachCard = registerForActivityResult(AttachCard.Contract, ActivityResultCallback {})
attachCard.launch(options)
Результат вызова метода вернется в ActivityResultCallback в виде AttachCard.Result:
- при успешной привязке (AttachCard.Success) возвращается cardId - id карты, которая была привязана, тип String
- при неуспешной привязке (AttachCard.Error) возвращается ошибка error типа Throwable (подробнее о возвращаемых ошибках в документации)
Включение приема платежей через Систему быстрых платежей осуществляется в Личном кабинете.
Чтобы реализовать оплату с помощью статического QR кода на экране приложения, необходимо:
- Создать соответствующую кнопку приема оплаты в приложении кассира
- Установить слушатель на клик по кнопке и вызвать в нем метод TinkoffAcquiring#openStaticQrScreen Метод openStaticQrScreen принимает параметры: activity, localization - для локализации сообщения на экране, requestCode - для получения ошибки, если таковая возникнет. Результат оплаты товара покупателем по статическому QR коду не отслеживается в SDK, соответственно в onActivityResult вызывающего экран активити может вернуться только ошибка или отмена (закрытие экрана).
Включение приема платежей через Tinkoff Pay осуществляется в Личном кабинете.
Оплату с помощью Tinkoff Pay по кнопке можно настроить двумя способами
- с использованием экранов из SDK;
- с использованием своих экранов и
TpayProcess
из SDK.
Оба варианта содержат общие шаги описанные ниже:
- Для начала необходимо вызвать метод
TinkoffAcquiring.checkTerminalInfo
, в котором можно проверить доступность метода оплаты с помощью расширенияenableTinkoffPay()
. - Если
enableTinkoffPay()
возвращаетtrue
, то можно отобразить кнопку оплаты Tinkoff Pay в вашем приложении в соответствии с Design Guidelines.
- По нажатию на кнопку инициализировать платежную сессию и запустить экран оплаты SDK:
TinkoffAcquiring.initTinkoffPayPaymentSession()
val tpayPayment = registerForActivityResult(TpayLauncher.Contract, ActivityResultCallback {})
// настраиваются по аналогии с экраном оплаты
val paymentOptions = PaymentOptions()
.setOptions {
orderOptions { ... }
customerOptions { ... }
featuresOptions { ... }
setTerminalParams("TERMINAL_KEY", "PUBLIC_KEY")
}
tpayPayment.launch(
StartData(
paymentOptions,
version // берется из ответа метода checkTerminalInfo()
)
)
- Результат оплаты вернется в ActivityResultCallback в виде TpayLauncher.Result
Включение и прием платежей через Mir Pay осуществляется по аналогии с Tinkoff Pay, только для этого используются MirPayLauncher
или MirPayProcess
- По нажатию на кнопку инициализировать платежную сессию
TinkoffAcquiring.initTinkoffPayPaymentSession()
- Запусить свою реализацию экрана оплаты в которой необходимо получить экземпляр
TpayProcess#get
и стартовать процессTpayProcess#start
(параметрversion
можно получить из ответа на шаге 1. Отслеживать статус процесса оплаты можно через полеTpayProcess#state
(под капотом используются корутины, если вы используете что-то другое, воспользуйтесь адаптером), обработать событиеonUiNeeded
и использоватьstate.deepLink
для открытия приложения с формой оплаты. - При необходимости, проверить статус платежа при помощи
TinkoffAcquiring.sdk.getState
(с указаниемpaymentId
полученном вstate.paymentId
на предыдущем шаге); время и частота проверки статуса платежа зависит от нужд клиентского приложения и остается на ваше усмотрение (один из вариантов - проверять статус платежа при возвращении приложения из фона).
AcquiringSdk имеет возможность использовать внутри себя Yandex Pay в качестве хранилища карт.
Если вы хотите использовать Yandex Pay вместе с AcquiringSdk вам необходимо:
- Получить в личном кабинете Yandex значение
YANDEX_CLIENT_ID
- Укажите полученный
YANDEX_CLIENT_ID
в сборочном скрипте build.gradle в качестве значения вmanifestPlaceholders
:
android {
defaultConfig {
manifestPlaceholders = [
// Подставьте ваш yandex_client_id
YANDEX_CLIENT_ID: "12345678901234567890",
]
}
}
- Добавить в build.gradle
implementation 'ru.tinkoff.acquiring:yandexpay:$latestVersion'
Крайне не рекомендуется использовать ru.tinkoff.acquiring:yandexpay
вместе с com.yandex.pay:core
в рамках вашего приложения, так как
могут возникнуть непредвиденные ошибки.
- Включить прием платежей через Yandex Pay в Личном кабинете.
- Проверить Доступ функционала Yandex Pay проверяется через метод
TinkoffAcquiring#checkTerminalInfo
, который возвращает данные обо всех методах оплаты,извлечь данные касательно Yandex Pay расширениеTerminalInfo#mapYandexPayData
. - Кнопка Yandex Pay инкапсулирована во фрагменте
YandexButtonFragment
. Размеры фрагмента-кнопки можете создать самостоятельно, однако если рекомендации по минимальной ширине. Фрагмент можно создать с помощью методаTinkoffAcquiring.createYandexPayButtonFragment
. После выбора карты процесс оплаты запуститься самостоятельно. Возможности кастомизации можно посмотреть в pages.
SDK имеет поддержку 2 локализаций, русскую и английскую.
Для проведения платежа без открытия экрана необходимо создать требуемый процесс для оплаты, передать параметры и написать свою логику обработки состояний платежа.
Для разных способов оплаты существуют разные бизнес сущности процесса оплаты, и разный набор состояний, они лежат в папке ru.tinkoff.acquiring.sdk.payment
Пример запуска платежа:
PaymentByCardProcess.init(sdk, application) // создание процесса платежа
val process = PaymentByCardProcess.get()
process.start(cardData, paymentOptions) // запуск процесса
scope.launch {
process.state.collect { handle(it) } // подписка на события процесса
}
Более подробные варианты использования можно посмотреть в sample проекта.
Для отображения платежной формы и проведения платежа без вызова метода Init можно передать
значение paymentId
в соответствующие Launcher
-ы экранов или если не требуется UI, то в Process
-ы оплаты.
SDK состоит из следующих модулей:
Является базовым модулем для работы с Tinkoff Acquiring API. Модуль реализует протокол взаимодействия с сервером и позволяет не осуществлять прямых обращений в API. Не зависит от Android SDK и может использоваться в standalone Java приложениях.
Основной класс модуля - AcquiringSdk - предоставляет интерфейс для взаимодействия с Tinkoff Acquiring API. Для работы необходимы ключи продавца (см. Подготовка к работе).
Подключение:
implementation 'ru.tinkoff.acquiring:core:$latestVersion'
Содержит классы необходимые для приема платежей через мобильное приложение.
TinkoffAcquiring - позволяет:
- открывать экран оплаты по статическому QR коду
- проверять доступность методов оплаты
TPayLauncher - позволяет открывать экран процесса оплаты через Tinkoff Pay TpayProcess - можно использовать для проведения процесса оплаты используя свой UI
а так же аналогичные классы для возможности проведения оплаты.
Модуль для сканирования карты камерой телефона с помощью библиотеки Card-IO.
Модуль для работы с библиотекой yandexPay
Содержит пример интеграции Tinkoff Acquiring SDK и модуля сканирования Card-IO в мобильное приложение по продаже книг.
-keep class ru.tinkoff.acquiring.sdk.localization.** { *; }
-keep class ru.tinkoff.acquiring.sdk.requests.** { *; }
-keep class ru.tinkoff.acquiring.sdk.models.** { *; }
-keep class ru.tinkoff.acquiring.sdk.yandexpay.models.** { *; } // если подключали яндекс
-keep class ru.rtln.tds.sdk.** { *; }
-keep class org.spongycastle.**
-keep class org.bouncycastle.**
- По возникающим вопросам просьба обращаться на [email protected]
- Баги и feature-реквесты можно направлять в раздел issues
- Полная документация по методам api