TinkoffASDKUI 3.1.1

TinkoffASDKUI 3.1.1

Grigory SerebryaniyBazarov IvanDmitry Overchuk 维护。



  • Tinkoff

Tinkoff iOS 收款 SDK

Acquiring SDK 允许在 iOS 平台上将互联网收单集成到移动应用程序中。

模块

Acquiring SDK 包括三个模块,您可以根据需要将它们连接到您的应用程序

  • TinkoffASDKCore - 是一个低级模块,用于形成和发起对 收单 API 的网络请求,并用于配置网络安全数据传输
  • TinkoffASDKUI - 包含将各种用户接收支付场景集成到您的应用程序所需的所有逻辑。在大多数情况下,您只需连接它
  • TinkoffASDKYandexPay - 是一个辅助模块,封装了与 YandexPaySDK 的所有操作。如果需要连接设置了通过 Tinkoff Cash Desk 接收支付按钮的 YandexPay,请连接它

连接

Cocoapods

要使用Cocoapods连接,请在Podfile文件中添加所需的依赖项

pod 'TinkoffASDKCore'
pod 'TinkoffASDKUI'
pod 'TinkoffASDKYandexPay'

Swift包管理器

使用Package.swift

要使用Package.swift将AcquiringSdk集成到您的项目中,请指定依赖项

dependencies: [
  .package(url: "https://github.com/tinkoff-mobile-tech/AcquiringSdk_IOS.git", .upToNextMajor(from: "3.0.0"))
]

通过Xcode

文件 -> 添加依赖项 -> https://github.com/tinkoff-mobile-tech/AcquiringSdk_IOS

选择所需的模块

spm-products

要求和限制

要使用Tinkoff Acquiring SDK,需要以下条件:

  • iOS 12.3及更高版本支持
  • Swift最低版本为5.7(Xcode 14.0)

准备工作

开始使用SDK所需的步骤如下:

  • TerminalKey - 卖家的终端标识符
  • PublicKey – 用于加密数据的公共密钥

这些数据可以从连接到互联网收单后在个人控制台中获取。

有关个人账户设置配置的更多详细信息,请参阅此处

确保使用SSL/TLC证书

如果撤销全局证书,SDK已提供切换到由“数字发展部”颁发证书的选项。

⚠️ 至关重要,请根据下面的说明适配您的项目。否则,如果证书突然被撤销,您的应用将无法接受支付

为了正确使用“数字发展部”的证书,需要在Info.plist中添加属性App Transport Security Settings,并将其标志设置为Allow Arbitrary Loads = true

您可以将source code复制并粘贴到Info.plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

如果您的应用使用Allow Arbitrary Loads接受特定域名,则应添加几个我们自己的域名(例如,optional rest-api-test.tinkoff.ru - 测试域名)并设置属性Allow Arbitrary Loads in Web Content = true

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>qr.nspk.ru</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>rest-api-test.tinkoff.ru</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
        <key>securepay.tinkoff.ru</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

初始化 SDK

为了初始化 SDK,首先需要创建配置,然后将其传递给 init。以下是一个具有最小必要参数的示例

import TinkoffASDKCore
import TinkoffASDKUI 

let credential = AcquiringSdkCredential(
    terminalKey: "TERMINAL_KEY",
    publicKey: "PUBLIC_KEY"
)

let coreSDKConfiguration = AcquiringSdkConfiguration(
    credential: credential,
    server: .prod // Используемое окружение
)

let uiSDKConfiguration = UISDKConfiguration()

do {
    let sdk = try AcquiringUISDK(
        coreSDKConfiguration: coreSDKConfiguration,
        uiSDKConfiguration: uiSDKConfiguration
    )
} catch {
    // Ошибка может возникнуть при некорректном параметре `publicKey`
    assertionFailure("\(error)")
}

AcquiringSdkConfiguration 中的额外参数

  • logger: ILogger? - 用于网络层工作的日志接口。您可以传递默认实现 - Logger,它将格式化并将数据输出到控制台
  • language - 服务器发送错误文本的语言。这些消息永远不会显示给用户,仅用于调试
  • requestsTimeoutInterval: TimeInterval - 网络请求的超时时间。默认值是 40 秒
  • tokenProvider: ITokenProvider? - 提供用于 API 收单请求签名的令牌的协议。仅当终端启用了令牌检查时需要。 了解更多
  • urlSessionAuthChallengeService: IURLSessionAuthChallengeService? - 用于请求数据和方式的接口,以及 URLSession 的认证。不建议盲目传递任何内容,因为默认实现将确保与服务器的正确交互,在切换到 Ministry of Investment and Development 的 SSL/TLC 证书时。 了解更多

UISDKConfiguration 中的额外参数

  • webViewAuthChallengeService: IWebViewAuthChallengeService? - 用于请求数据和方式的接口,以及 WKWebView 的认证。不建议盲目传递任何内容,因为默认实现将确保与服务器的正确交互,在切换到 Ministry of Investment and Development 的 SSL/TLC 证书时。 了解更多
  • paymentStatusRetriesCount: Int - 负责最大请求次数来更新支付状态。用于在用户完成支付后获得最终状态。可以设置为任何正数。默认使用10次尝试获取最终状态,每次间隔3秒。
  • addCardCheckType: PaymentCardCheckType - 绑定卡片时的检查类型。默认为 .no更多信息

使用令牌签名请求

如果您的终端支持发送到API收款requests的令牌验证,则必须实现协议 ITokenProvider 并将其传递到 AcquiringSdkConfiguration

func provideToken(
  forRequestParameters parameters: [String: String], // Параметры, участвующие в генерации токена
  completion: @escaping (Result<String, Error>) -> Void // Замыкание, которое необходимо вызвать, передав результат генерации токена
)

为了生成令牌,需要

  • 将终端密码添加到带有键 Password 的字典中
  • 根据键对键值对进行排序
  • 连接所有对的值
  • 对于得到的字符串,计算SHA-256哈希

关于请求签名的更多信息

示例

最简单的情况下,实现可能如下所示

import TinkoffASDKCore

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)
}

⚠️ 上述实现仅为示例。出于安全考虑,不应在移动应用代码中存储或与终端密码互动。最合适的场景是将获取的参数传递到服务器,在服务器端基于参数和密码生成令牌。

完成支付

所有与不同支付场景的交互都通过统一的门面 AcquiringUISDK 进行。其初始化的示例可以在 上面部分 中看到。

SDK中实现了每种支付场景的独立入口,以及包含多种支付方式的通用支付表单。

形成支付数据

要完成支付,需要创建一个`PaymentFlow`对象,并将其传递给`AcquiringUISDK`的相应函数。

`PaymentFlow`是一个`enum`,指示具体的支付方式。在SDK的所有支付场景中使用。

/// Тип проведения оплаты
public enum PaymentFlow: Equatable {
    /// Оплата совершится с помощью вызова `v2/Init` в API эквайринга, на основе которого будет сформирован `paymentId`
    case full(paymentOptions: PaymentOptions)
    /// Используется в ситуациях, когда вызов `v2/Init` и формирование `paymentId` происходит на бекенде продавца
    case finish(paymentOptions: FinishPaymentOptions)
}

这种划分允许SDK作为客户端实现支付数据生成逻辑的应用程序或服务器端工作的应用程序使用。

以下是每个案例的参数生成方法。

完整支付

在此处,客户端应用程序提供所有参与支付的数据。SDK将自行启动并完成支付。

创建类型为`.full`的`PaymentFlow`需要通过`PaymentOptions`传递支付参数

let receipt: Receipt
let shops: [Shop]
let receipts: [Receipt]

let orderOptions = OrderOptions(
    /// Идентификатор заказа в системе продавца
    orderId: "ORDER_ID",
    // Полная сумма заказа в копейках
    amount: 100000,
    // Краткое описание заказа
    description: "DESCRIPTION",
    // Данные чека
    receipt: receipt,
    // Данные маркетплейса. Используется для разбивки платежа по партнерам
    shops: shops,
    // Чеки для каждого объекта в `shops`.
    // В каждом чеке необходимо указывать `Receipt.shopCode` == `Shop.shopCode`
    receipts: receipts,
    // Сохранить платеж в качестве родительского
    savingAsParentPayment: false
)

let customerOptions = CustomerOptions(
    // Идентификатор покупателя в системе продавца. 
    // С помощью него можно привязать карту покупателя к терминалу после успешного платежа 
    customerKey: "CUSTOMER_KEY",
    // Email покупателя
    email: "EMAIL"
)

// Используется для редиректа в приложение после успешного или неуспешного совершения оплаты с помощью `TinkoffPay`
// В иных сценариях передавать эти данные нет необходимости
let paymentCallbackURL = PaymentCallbackURL(
    successURL: "SUCCESS_URL",
    failureURL: "FAIL_URL"
)

// Словарь, содержащий дополнительные параметры в виде `[Key: Value]`, которые можно передать по необходимости
let paymentData = ["someKey": "someValue"]

let paymentOptions = PaymentOptions(
    orderOptions: orderOptions,
    customerOptions: customerOptions,
    paymentCallbackURL: paymentCallbackURL,
    paymentData: paymentData
)

let paymentFlow: PaymentFlow = .full(paymentOptions: paymentOptions)

所有这些数据都可以用于通过`v2/Init`方法调用启动支付。有关详细信息,请参阅此处

完成支付

在此处,客户端应用程序提供最少的数据,以便在SDK外部已启动支付的情况下完成支付

// Идентификатор платежа, полученный при вызове `v2/Init`
let paymentId: String 

let finishOptions = FinishPaymentOptions(
    paymentId: paymentId,
    amount: 100000,
    orderId: "ORDER_ID",
    customerOptions: customerOptions
)

let paymentFlow: PaymentFlow = .finish(paymentOptions: finishOptions)

获取支付结果

在Acquiring SDK的所有支付场景中,支付结果的返回是通过在支付屏幕关闭后立即调用的闭包实现的。

/// Замыкание с результатом, вызываемое после закрытия экрана оплаты
public typealias PaymentResultCompletion = (PaymentResult) -> Void

在这里,PaymentResult是一个表示三种可能情况的枚举值。

/// Результат платежа
public enum PaymentResult {
    /// Успешное завершение оплаты
    case succeeded(PaymentInfo)
    /// Произошла ошибка на этапе оплаты
    case failed(Error)
    /// Оплата отменена пользователем
    case cancelled(PaymentInfo? = nil)
}

PaymentInfo包含关于已完成的支付的一些额外信息。

/// Информация о проведенном платеже
public struct PaymentInfo {
    /// Идентификатор платежа
    public let paymentId: String
    /// Идентификатор заказа в системе продавца
    public let orderId: String
    /// Сумма заказа в копейках
    public let amount: Int64
    // Последний детальный статус о платеже
    public let paymentStatus: AcquiringStatus
}

在SDK开始支付过程但用户关闭屏幕而不等待完成的情况下,PaymentInfo也可能位于cancelled中。

使用支付表单支付

SDK实现了通用支付表单。其中显示了几种可用于该终端的支付方式,用户可以选择任何一种。

  • 使用新信用卡支付
  • 使用已保存的信用卡支付
  • ТинькоффPay
  • 快速支付系统

⚠️ 要正确使用TinkoffPay和快速支付系统,需要额外配置您的项目,因此请参阅下面这些支付方式的描述。.

要显示支付表单,需要在AcquiringUISDK中调用相应的函数。

/// Отображает основную платежную форму с различными способами оплаты
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого отобразится платежная форма
///   - paymentFlow: Содержит тип платежа и параметры оплаты
///   - configuration: Конфигурация платежной формы
///   - cardScannerDelegate: Делегат, предоставляющий возможность отобразить карточный сканер поверх заданного экрана
///   - completion: Замыкание с результатом, вызываемое после закрытия экрана оплаты
public func presentMainForm(
    on presentingViewController: UIViewController,
    paymentFlow: PaymentFlow,
    configuration: MainFormUIConfiguration,
    cardScannerDelegate: ICardScannerDelegate? = nil,
    completion: PaymentResultCompletion? = nil
)

使用MainFormConfiguration对象可以设置支付表单的额外配置。

/// Конфигурация главной платежной формы
///
/// На основе этих данный будет формироваться отображение UI платежной формы с разными способами оплаты
public struct MainFormUIConfiguration {
  /// Очень краткое описание заказа, отображаемое пользователю
  public let orderDescription: String?
}

您可以传递一个指向实现ICardScannerDelegate的对象的引用,通过该实现用户可以扫描其银行信用卡。

支付表单将在支付完成后关闭,并返回一个包含PaymentResult对象的completion

使用TinkoffPay支付

要使TinkoffPay在您的应用程序中正常工作,首先需要在Info.plistLSApplicationQueriesSchemes键下的数组中添加tinkoffbank值。

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>tinkoffbank</string>
</array>

这样可以确保SDK能够正确地检测用户设备上是否安装了Тинькофф应用程序。

要显示TinkoffPay的支付屏幕,需要在AcquiringUISDK中调用相应的函数。

/// Отображает экран оплаты `TinkoffPay`
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран оплаты `TinkoffPay`
///   - paymentFlow: Содержит тип платежа и параметры оплаты
///   - completion: Замыкание с результатом оплаты, вызываемое после закрытия экрана `TinkoffPay`
public func presentTinkoffPay(
    on presentingViewController: UIViewController,
    paymentFlow: PaymentFlow,
    completion: PaymentResultCompletion? = nil
)

如果用户已安装Тинькофф应用程序,SDK将跳转进入该应用程序。

支付完成后将关闭屏幕,并在completion对象中返回PaymentResult

使用TinkoffPay进行支付同样可以通过支付表单进行。

使用快速支付系统进行支付

SDK提供了多种使用СБП进行支付的方式。在本节中,我们描述了向用户显示支持СБП的银行列表的情况。当用户从列表中选择特定银行时,将跳转至相应的银行应用程序。

SDK通过发送请求到НСПК,并接收包含银行应用程序URL方案的JSON列表来获取可用的银行列表。

{
  "version": "1.0",
  "dictionary": [
    {                
      "bankName": "Сбербанк",
      "logoURL": "https://qr.nspk.ru/proxyapp/logo/bank100000000111.png",
      "schema": "bank100000000111",
      "package_name": "ru.sberbankmobile"
    },
    {
      "bankName": "Тинькофф Банк",
      "logoURL": "https://qr.nspk.ru/proxyapp/logo/bank100000000004.png",
      "schema": "bank100000000004",
      "package_name": "com.idamob.tinkoff.android"
    },
    {                
      "bankName": "Банк ВТБ",
      "logoURL": "https://qr.nspk.ru/proxyapp/logo/bank100000000005.png",
      "schema": "bank110000000005",
      "package_name": "ru.vtb24.mobilebanking.android"                  
    }
  ]
}

由于列表包含超过一百家银行,SDK为了方便用户,首先显示那些确实安装在使用者设备上的银行。我们通过在schema值的基础上构建URL并调用系统函数canOpenURL(:)来实现这一点。

根据文档说明,该方法只在没有将方案添加到包含键LSApplicationQueriesSchemesInfo.plist数组时返回正确的响应。同时,说明中提到您可以添加不超过50个方案。

正因为如此,为了正确显示银行列表,您需要选择优先级的银行应用程序,它们将首先在快速支付系统的银行屏幕上显示,并将它们添加到Info.plist中。

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>bank100000000111</string>
  <string>bank100000000004</string>
  <string>bank110000000005</string>
  <string>bank100000000008</string>
</array>

⚠️ 由于AppStore上银行应用程序的阻止,URL可能会有所变化。您需要定期查看列表并更新您应用程序的Info.plist。

要显示包含银行列表的屏幕,请在AcquiringUISDK中调用相应的函数

/// Отображает экран со списком приложений банков, с помощью которых можно провести оплату через `Систему быстрых платежей`
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран со списком банков
///   - paymentFlow: Содержит тип платежа и параметры оплаты
///   - completion: Замыкание с результатом оплаты, вызываемое после закрытия экрана оплаты `СБП`
public func presentSBPBanksList(
    on presentingViewController: UIViewController,
    paymentFlow: PaymentFlow,
    completion: PaymentResultCompletion? = nil
)

支付完成后,屏幕将关闭,并在completion对象中返回PaymentResult对象。

此支付方式也可通过支付表单访问。

使用快速支付系统的QR码进行支付

SDK中提供了展示用于通过快速支付系统进行支付操作的二维码的功能。扫描用户设备上的二维码后,将在银行应用程序中打开支付表单。这里有两种类型的二维码需要特别指出

  • 静态QR - 用于多次支付商品或服务的快速支付系统生成的支付链接
  • 动态QR - 用于一次性支付商品或服务的快速支付系统生成的支付链接

使用静态QR支付

要启动静态QR支付,可以在AcquiringUISDK中使用以下功能

/// Отображает экран с многоразовым `QR-кодом`, отсканировав который, пользователь сможет провести оплату с помощью `Системы быстрых платежей`
///
/// При данном типе оплаты SDK никак не отслеживает статус платежа
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран с `QR-кодом`
///   - completion: Замыкание, вызываемое при закрытии экрана с `QR-кодом`
public func presentStaticSBPQR(
    on presentingViewController: UIViewController,
    completion: (() -> Void)? = nil
) 

关闭屏幕时将调用completion而没有任何数据

使用动态QR支付

要启动动态QR支付,可以在AcquiringUISDK中使用以下功能

/// Отображает экран с одноразовым `QR-кодом`, отсканировав который, пользователь сможет провести оплату  с помощью `Системы быстрых платежей`
///
/// При данном типе оплаты сумма и информация о платеже фиксируется, и SDK способен получить и обработать статус платежа
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран с `QR-кодом`
///   - paymentFlow: Содержит тип платежа и параметры оплаты
///   - completion: Замыкание с результатом оплаты, вызываемое после закрытия экрана с `QR-кодом`
public func presentDynamicSBPQR(
    on presentingViewController: UIViewController,
    paymentFlow: PaymentFlow,
    completion: @escaping PaymentResultCompletion
)

支付完成后将关闭屏幕,并在completion对象中返回PaymentResult

定期支付

⚠️定期支付不支持快速支付系统

如果存在定期支付的标识符rebillId,则也可以执行定期支付。这可以通过在AcquiringUISDK中使用函数来实现

/// Отображает экран, выполняющий рекуррентный платеж
  /// - Parameters:
  ///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран рекуррентного платежа
  ///   - paymentFlow: Содержит тип платежа и параметры оплаты
  ///   - rebillId: Идентификатор родительского платежа, на основе которого будет произведено списание средств
  ///   - failureDelegate: Делегат, обрабатывающий ошибку списания средств при вызове `v2/Charge`.
  ///   Используется только при оплате на основе уже существующего `paymentId (PaymentFlow.finish)`.
  ///   При `PaymentFlow.full` SDK способен самостоятельно обработать полученную ошибку.
  ///   - completion: Замыкание с результатом оплаты, вызываемое после закрытия экрана рекуррентного платежа
  public func presentRecurrentPayment(
      on presentingViewController: UIViewController,
      paymentFlow: PaymentFlow,
      rebillId: String,
      failureDelegate: IRecurrentPaymentFailiureDelegate? = nil,
      completion: PaymentResultCompletion? = nil
  )

支付完成后,屏幕将关闭,并在completion对象中返回PaymentResult对象。

使用PaymentFlow.finish时

这里需要强调一下failureDelegate参数。

在调用 PaymentFlow.finish 时,必须传递此委托的链接。这是因为当通过 API 请求 https://tinkoff.github.io/api_asdk/#tag/Metody-priema-platezhej/paths/~1Charge/post 的 v2/Charge 时,服务器可能会返回 错误 104。这意味着客户需要请求用户输入 CVC-码 并重新发起支付。

使用 PaymentFlow.full 时,SDK 已经具备了所有重新调用 v2/Init 所需的数据,因此客户端代码无需执行任何额外操作。

对于 PaymentFlow.finish,我们假设支付数据不会在移动应用程序中显示,因此您需要自行实现 IRecurrentPaymentFailiureDelegate 协议。

/// Делегат, обрабатывающий ошибку списания средств при вызове `v2/Charge`
///
/// Используется только при оплате на основе уже существующего `paymentId (PaymentFlow.finish)`
public protocol IRecurrentPaymentFailiureDelegate: AnyObject {
    /// В случае вызова этого метода делегата, необходимо совершить повторный запрос v2/Init, для получения обновленного paymentId
    /// для этого необходимо в запросе к полю DATA добавить additionalData (в PaymentOptions поле называется paymentFormData)
    /// - Parameters:
    ///   - additionalData: содержаться два доп. поля failMapiSessionId c failedPaymentId и recurringType
    ///   - completion: после успешного выполнения запроса, необходимо передать в completion новый paymentId
    func recurrentPaymentNeedRepeatInit(additionalData: [String: String], completion: @escaping (Result<PaymentId, Error>) -> Void)

预计在实现此协议时会调用卖家的服务器以通过调用 v2/Init 重新初始化支付。调用此方法时,必须在 DATA 字段中添加从 SDK 获得的 additionalData 字典中的所有值。然后,您需要通过调用 completion 将获得的 PaymentId 返回 SDK,SDK 将执行最终的支付处理。

使用 YandexPay 支付

您可以在专门的页面上阅读关于如何集成 YandexPay 按钮的详细说明,该按钮通过 Тинькофф Касса 的互联网收单接受支付:此处

管理银行卡

SDK 除此之外还提供了用于管理卡屏幕的入口点

已保存卡列表

要打开已保存卡列表屏幕,只需在 AcquiringUISDK 中调用函数即可

/// Отображает экран со списком карт
///
/// На этом экране пользователь может ознакомиться со списком привязанных карт, удалить или добавить новую карту
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран добавления карты
///   - customerKey: Идентификатор покупателя в системе Продавца, к которому будет привязана карта
///   - cardScannerDelegate: Делегат, предоставляющий возможность отобразить карточный сканер поверх заданного экрана
public func presentCardList(
    on presentingViewController: UIViewController,
    customerKey: String,
    cardScannerDelegate: ICardScannerDelegate? = nil
)

您可以传递一个指向实现ICardScannerDelegate的对象的引用,通过该实现用户可以扫描其银行信用卡。

绑定新卡

用户可以通过卡片列表页面绑定新卡,但您也可以根据需要将其集成到自己的应用中。为此,您需要在 AcquringUISDK 中调用以下函数:

/// Отображает экран привязки новой карты
/// - Parameters:
///   - presentingViewController: `UIViewController`, поверх которого будет отображен экран привязки карты
///   - customerKey: Идентификатор покупателя в системе Продавца, к которому будет привязана карта
///   - cardScannerDelegate: Делегат, предоставляющий возможность отобразить карточный сканер поверх заданного экрана
///   - completion: Замыкание с результатом привязки карты, которое будет вызвано на главном потоке после закрытия экрана
public func presentAddCard(
    on presentingViewController: UIViewController,
    customerKey: String,
    cardScannerDelegate: ICardScannerDelegate? = nil,
    completion: ((AddCardResult) -> Void)? = nil
)

您可以传递一个指向实现ICardScannerDelegate的对象的引用,通过该实现用户可以扫描其银行信用卡。

完成卡片绑定后,界面将关闭,并在 completion 返回 AddCardResult

/// Результат привязки карты
public enum AddCardResult {
    /// Привязка карты произошла успешно.
    /// В этом случае возвращается модель с подробной информацией о карте
    case succeded(PaymentCard)
    /// В процессе привязки карты произошла ошибка
    case failed(Error)
    /// Пользователь отменил привязку новой карты
    case cancelled
}

PaymentCard 对象将包含有关绑定的所有卡信息。

  • pan: String - 隐藏的卡片号码,例如 430000******0777
  • cardId: String - 卡在银行系统中的标识符
  • expDate: String? - 信用卡有效期,格式为 MMYY,例如 1212
  • status: PaymentCardStatus - 卡当前的状态。成功绑定后将显示为 active
  • parentPaymentId: Int64 - 最后注册为父付款的标识符

其他功能

使用UI ASDK进行无界面支付

创建一个新的 IPaymentController,通过它可以使用自己的 UI 进行付款,并完成 3DS 验证。

public func paymentController() -> IPaymentController {
  paymentControllerAssembly.paymentController()
}

使用UI ASDK操作无界面卡

创建一个新的 ICardsController,通过它可以获取活动卡片列表、删除卡以及用 3DS 验证绑定新卡,使用自己的 UI

/// - Parameter customerKey: Идентификатор покупателя в системе продавца
/// - Returns: ICardsController
public func cardsController(customerKey: String) -> ICardsController {
  cardsControllerAssembly.cardsController(customerKey: customerKey)
}

扫描卡片

当启动所有可能包含卡片数据输入字段的用户场景时,您有权传递指向实现协议 ICardScannerDelegate 的链接。

/// Замыкание, в которое необходимо передать карточные данные по завершении сканирования
public typealias CardScannerCompletion = (_ cardNumber: String?, _ expiration: String?, _ cvc: String?) -> Void

/// Делегат, предоставляющий возможность отобразить карточный сканер поверх заданного экрана
public protocol ICardScannerDelegate: AnyObject {
    /// Уведомляет о нажатии пользователем на кнопку сканера при вводе карточных данных
    ///
    /// Объект, реализующий данный протокол, должен отобразить экран со сканером.
    /// После завершения сканирования необходимо передать полученные карточные данные в `completion`
    /// - Parameters:
    ///   - viewController:`UIViewController`, поверх которого необходимо отобразить экран со сканером
    ///   - completion: Замыкание, в которое необходимо передать карточные данные по завершении сканирования
    func cardScanButtonDidPressed(on viewController: UIViewController, completion: @escaping CardScannerCompletion)
}

在这种情况下,用户将看到一个扫描器图标,点击它时您可以捕获 cardScanButtonDidPressed 事件并显示扫描器屏幕。

支持