Acquiring SDK позволяет интегрировать Интернет-Эквайринг в мобильные приложения для платформы iOS.
Для работы Tinkoff Acquiring SDK необходимо:
Для подключения добавьте в файл Podfile
зависимости:
pod 'TinkoffASDKCore'
pod 'TinkoffASDKUI'
Package.swift
Чтобы интегрировать AcquiringSdk в ваш проект используя Package.swift
нужно указать зависимость:
dependencies: [
.package(url: "https://github.com/Tinkoff/AcquiringSdk_IOS.git", .upToNextMajor(from: "2.10.1"))
]
File -> Add packages -> https://github.com/Tinkoff/AcquiringSdk_IOS.git
Выберите нужные библиотеки:
TinkoffASDKCore - если вам нужен только Core функционал без UI части.
TinkoffASDKUI - уже включает в себя Core часть. Полное sdk - Core + UI часть.
:warning: Необходимо хранить сильную ссылку на экземпляр AcquiringUISDK
Для начала работы с SDK вам понадобятся:
Данные выдаются в личном кабинете после подключения к Интернет-Эквайрингу.
Подробнее о настройке Личного кабинета можно прочитать тут
Для корректно работы с сертификатами минцифры, необходимо добавить в Info.plist свойство: "App Transport Security Settings" c флагом "Allow Arbitrary Loads" = true
Можно просто скопировать source code и вставить в Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
В начале нужно создать конфигурацию, используем объект AcquiringSdkConfiguration, обязательные параметры:
Дополнительные параметры которые можно установить:
После инициализации SDK им можно пользоваться и вызывать форму для оплаты, и список карт.
Для проведения оплаты в модуле TinkoffASDKUI/AcquiringUISDK реализованы методы для различных сценариев оплаты. Доступны:
Для работы со списком сохраненных карты реализован метод:
Если ваш терминал поддерживает валидацию токена, присылаемого в запросах к API эквайринга, то необходимо реализовать протокол ITokenProvider
и передать его в AcquiringSdkConfiguration
:
func provideToken(
forRequestParameters parameters: [String: String], // Параметры, участвующие в генерации токена
completion: @escaping (Result<String, Error>) -> Void // Замыкание, которое необходимо вызвать, передав результат генерации токена
)
Для генерации токена необходимо:
Password
В простейшем случае реализация может выглядеть следующим образом:
func provideToken(
forRequestParameters parameters: [String: String],
completion: @escaping (Result<String, Error>) -> Void
) {
let sourceString = parameters
.merging(["Password": password]) { $1 }
.sorted { $0.key < $1.key }
.map(\.value)
.joined()
let hashingResult = Result {
try SHA256.hash(from: sourceString)
}
completion(hashingResult)
}
:warning: Реализация выше приведена исключительно в качестве примера. В целях безопасности не стоит хранить и как бы то ни было взаимодействовать с паролем от терминала в коде мобильного приложения. Наиболее подходящий сценарий - передавать полученные параметры на бекенд, где будет происходить генерация токена на основе параметров и пароля
Для отображения формы оплаты необходимо вызвать метод AcquiringUISDK.presentPaymentView
:
public func presentPaymentView(
on presentingViewController: UIViewController,
customerKey: String? = nil,
acquiringPaymentStageConfiguration: AcquiringPaymentStageConfiguration,
configuration: AcquiringViewConfiguration,
tinkoffPayDelegate: TinkoffPayDelegate? = nil,
completionHandler: @escaping PaymentCompletionHandler
)
По завершении платежа будет вызван completionHandler
с Result<PaymentStatusResponse, Error>
, в котором в случае успеха будут содержаться данные:
В методе выбор стадии платежа осуществляется с помощью AcquiringPaymentStageConfiguration
. Далее рассмотрим доступные стадии
В этом сценарии ASDK самостоятельно вызывает метод Init
API эквайринга при совершении оплаты, передавая информацию о платеже, заданных в PaymentInitData:
312
. Параметр должен быть равен сумме всех товаров в чекеtrue
, то регистрирует платёж как рекуррентный (родительский)JSON
объект, содержащий дополнительные параметры в виде [Key: Value]
.Key: String
– 20 знаков, Value: String
– 100 знаков. Максимальное количество пар параметров не может превышать 20let paymentData: PaymentInitData = ...
let paymentStageConfiguration = AcquiringPaymentStageConfiguration(paymentStage: .`init`(paymentData: paymentData))
paymentId
В этом сценарии метод Init
API эквайринга вызывается вне SDK, например на бекенде клиентского приложения. Затем в SDK эквайринга полученный paymentId
передается с помощью:
let paymentId: Int64 = ...
let paymentStageConfiguration = AcquiringPaymentStageConfiguration(paymentStage: .finish(paymentId: paymentId))
Для работы с TinkoffPay необходимо добавить в Info.plist в массив по ключу LSApplicationQueriesSchemes
значение tinkoffbank
.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>tinkoffbank</string>
</array>
При открытии экрана оплаты SDK проверит наличие возможности оплаты через TinkoffPay и, в зависимости от результата, отобразит кнопку оплаты.
Отключить отображение кнопки программно можно с помощью параметра tinkoffPayEnabled
в featuresOptions
в конфигурации AcquiringViewConfiguration
.
Совершить платеж можно через общий экран оплаты, вызвав метод у экземпляра AcquiringUISDK
.
func presentPaymentView(
on presentingViewController: UIViewController,
acquiringPaymentStageConfiguration: AcquiringPaymentStageConfiguration,
configuration: AcquiringViewConfiguration,
tinkoffPayDelegate: TinkoffPayDelegate?,
completionHandler: @escaping PaymentCompletionHandler
)
В момент показа экрана оплаты, будет совершен запрос, который проверит, доступна ли оплата через TinkoffPay для вашего терминала и в случае доступности отобразится кнопка для совершения оплаты.
Для определения возможности оплаты через TinkoffPay SDK посылает запрос на https://securepay.tinkoff.ru/v2/TinkoffPay/terminals/$terminalKey/status.
Ответ на запрос кэшируется на некоторое время. Значение по-умолчанию 300 секунд. Его можно сконфигурировать через параметр tinkoffPayStatusCacheLifeTime
у объектаAcquiringSdkConfiguration
, который используется при инициализации AcquiringUISDK
.
Посредством реализации протокола TinkoffPayDelegate
можно получит сообщение о том, что оплата через Tinkoff Pay недоступна.
Можно сконфигурировать стиль кнопки TinkoffPay через параметр tinkoffPayButtonStyle
у AcquiringViewConfiguration
.
Для отображения кнопки оплаты через Tinkoff Pay внутри вашего приложения (вне экрана оплаты, предоставляемого SDK) необходимо:
func getTinkoffPayStatus(completion: @escaping (Result<GetTinkoffPayStatusResponse, Error>) -> Void)
При наличии возможности оплаты отобразить кнопку оплаты через Tinkoff Pay в вашем приложении
По нажатию кнопки вызвать метод(параметр GetTinkoffPayStatusResponse.Status.Version
получен на 1 шаге) и показать полученный из метода ViewController
func tinkoffPayViewController(
acquiringPaymentStageConfiguration: AcquiringPaymentStageConfiguration,
configuration: AcquiringViewConfiguration,
version: GetTinkoffPayStatusResponse.Status.Version,
completionHandler: PaymentCompletionHandler? = nil) -> UIViewController
)
Задача по закрытию ViewController, полученный из метода, ложится на плечи пользователя в момент вызова completionHandler
.
Если необходимо использовать отдельно методы API для TinkoffPay:
У экземпляра AcquiringSdk
можно вызвать:
Для проверки доступности TinkoffPay на терминале
func getTinkoffPayStatus(completion: @escaping (Result<GetTinkoffPayStatusResponse, Error>) -> Void)
Для получения deeplink
func getTinkoffPayLink(
paymentId: Int64,
version: GetTinkoffPayStatusResponse.Status.Version,
completion: @escaping (Result<GetTinkoffLinkResponse, Error>) -> Void
)
Для отрисовки кнопки существует класс TinkoffPayButton
.
При инициализации можно указать требуемый стиль кнопки.
При использовании этого инициализатора, у кнопки будет фиксированный стиль.
init(style: TinkoffPayButton.Style)
В случае использовании этого инициализатора, можно указать отдельно стиль для светлой и темной темы.
init(dynamicStyle: TinkoffPayButton.DynamicStyle)
для сканера нужно использовать любое стороннее решение, подключение сканера к SDK осуществляется через AcquiringViewConfiguration.scaner - это ссылка на объект который реализует протокол CardRequisitesScanerProtocol
protocol CardRequisitesScanerProtocol: class {
func startScanner(completion: @escaping (_ number: String?, _ yy: Int?, _ mm: Int?) -> Void)
}
Пример использования:
extension RootViewController: AcquiringScanerProtocol {
func presentScanner(completion: @escaping (_ number: String?, _ yy: Int?, _ mm: Int?) -> Void) -> UIViewController? {
if let viewController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "CardScanerViewController") as? CardScanerViewController {
viewController.onScannerResult = { (numbres) in
completion(numbres, nil, nil)
}
return viewController
}
return nil
}
}
public func presentCardList(
on presentingViewController: UIViewController,
customerKey: String,
configuration: AcquiringViewConfiguration
)
// терминал
let credential = AcquiringSdkCredential(terminalKey: ASDKStageTestData.terminalKey, publicKey: ASDKStageTestData.testPublicKey)
// конфигурация для старта sdk
let acquiringSDKConfiguration = AcquiringSdkConfiguration(credential: credential)
// включаем логи, результаты работы запросов пишутся в консоль
acquiringSDKConfiguration.logger = AcquiringLoggerDefault()
if let sdk = try? AcquiringUISDK.init(configuration: acquiringSDKConfiguration) {
// SDK проинициализировалось, можно приступать к работе
}
AcquiringViewConfiguration
let viewConfiguration = AcquiringViewConfiguration()
// подключаем сканер
viewConfiguration.scaner = scaner
// Формируем поля для экрана оплаты
viewConfiguration.fields = []
// Заголовок в UINavigationBar, для случая когда экран оплаты раскрыт на весь экран
viewConfiguration.viewTitle = NSLocalizedString("title.pay", comment: "Оплата")
// 1. Заголовок экрана "Оплата на сумму хх.хх руб."
let title = NSAttributedString(string: NSLocalizedString("title.payment", comment: "Оплата"), attributes: [.font: UIFont.boldSystemFont(ofSize: 22)])
let amountString = Utils.formatAmount(NSDecimalNumber(floatLiteral: productsAmount()))
let amountTitle = NSAttributedString(string: "\(NSLocalizedString("text.totalAmount", comment: "на сумму")) \(amountString)", attributes: [.font : UIFont.systemFont(ofSize: 17)])
// fields.append
viewConfiguration.fields.append(AcquiringViewConfiguration.InfoFields.amount(title: title, amount: amountTitle))
// 2. Описание товаров которые оплачиваем
let productsDetails = NSMutableAttributedString()
productsDetails.append(NSAttributedString(string: "Книги\n", attributes: [.font : UIFont.systemFont(ofSize: 17)]))
let productsDetails = products.map { (product) -> String in
return product.name
}.joined(separator: ", ")
productsDetails.append(NSAttributedString(string: productsDetails, attributes: [.font : UIFont.systemFont(ofSize: 13), .foregroundColor: UIColor(red: 0.573, green: 0.6, blue: 0.635, alpha: 1)]))
viewConfiguration.fields.append(AcquiringViewConfiguration.InfoFields.detail(title: productsDetails))
// 3. Добавляем поле email
if AppSetting.shared.showEmailField {
viewConfiguration.fields.append(AcquiringViewConfiguration.InfoFields.email(value: nil, placeholder: NSLocalizedString("placeholder.email", comment: "Отправить квитанцию по адресу")))
}
// 4. Кнопка для оплаты используя Систему Быстрых Платежей
if AppSetting.shared.paySBP {
viewConfiguration.fields.append(AcquiringViewConfiguration.InfoFields.buttonPaySPB)
}
Для того что бы кастомизировать UI компонента(цвет кнопки оплатить и т.д.), необходимо реализовать протокол Style
и передать его экземпляр как параметр style
при инициализации объекта SDK.
import TinkoffASDKUI
struct MyAwesomeStyle: Style {
...
}
let sdk = try AcquiringUISDK(configuration: acquiringSDKConfiguration style: MyAwesomeStyle())
Содержит пример интеграции Tinkoff Acquiring SDK в мобильное приложение по продаже книг. Главный экран список заготовок товаров. Второй экран - детали товара и выбор способа оплаты.
link |
Stars: 25 |
Last commit: 11 hours ago |
Changed
Fixed
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics