Skip to main content

iOS SDK

Installation#

Cocoapods#

  1. Set the dependency in your Podfile as follows: pod 'UnitComponents', '0.9.0'
  2. Execute pod install in Terminal.

Usage#

Unit SDK Manager class#

In order to interact with Unit's SDK, use the UnitSDK.manager class:

let manager = UnitSDK.manager

Setup SDK parameters#

Customer Token#

Set your customer token as follows:

manager.customerToken = "token"

Environment#

The UNEnvironment enum should be used:

public enum UNEnvironment {    case sandbox    case production}

Set the UNEnvironment as follows:

manager.environment = .sandbox

Setup UI parameters#

Setting Manager Properties During Initialization#

It is essential to note that the manager's setters should only be invoked during the initial phase of your application. This approach aims to eliminate the need for your application to wait for resource loading, thereby enhancing operational efficiency.

Parameters that have a global impact, such as the theme JSON or fonts, should be exclusively set during the initialization of our SDK. Failure to adhere to this guideline may result in inconsistent behavior throughout the application.

In certain cases, it may be permissible to define new themes or other parameters at a component level. Such alterations can be accomplished by providing the requisite parameters as arguments when initializing the specific component.

In particular, the best practice is to define it in the AppDelegate file, as follow:

@mainclass AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {        let manager: UNManagerProtocol = UnitSDK.manager        manager.environment = .sandbox        manager.customerToken = customerToken
        return true    }

Theme#

The theme is a URL that specifies the UI configuration. Set the theme as follows:

manager.ui.setTheme("https://url.com")

Language#

The language is a URL that specifies the language configuration. Set the language as follows:

manager.ui.setLanguage("https://url.com")

Web SDK Versioning Strategy Guide#

It's essential to understand that this SDK utilizes the web SDK views for certain components.

To give you optimal flexibility in managing the Web SDK versions, we've devised a strategy that allows you to either keep your SDK up-to-date or fixate on a particular version. To set your preferred versioning approach, utilize the enum UNWebVersioningStrategy. Below are the options you can select from:

  1. Exact Versioning - exact(major: 1, minor: 1, patch: 3)

    • This method allows you to lock onto a specific version that suits your needs.
  2. Up to Next Minor - upToNextMinor(major: 1, minor: 2)

    • This is the default and recommended approach. While it keeps your SDK updated with minor patches, a manual update is needed for minor version changes.
  3. Up to Next Major - upToNextMajor(major: 1)

    • With this strategy, your SDK will automatically update until there's a major version change.

For a comprehensive understanding, refer to our Web SDK - Versioning Guide.

manager.webVersioningStrategy = .exact(major: 1, minor: 2, patch: 2)

For the latest SDK, the latest webVersioningStrategy is upToNextMinor(major: 1, minor: 3).

Fonts#

Add the Font File to Your Project#
  1. Locate the .ttf or .otf font file you wish to add.
  2. Drag and drop the font file into your Xcode project. Make sure to check the "Copy items if needed" option and add it to your desired target.

Edit Info.plist#

You need to register the custom font by adding the "Fonts provided by application" key in the Info.plist file.

Now, You can configure custom fonts in your application by utilizing the typealias UNFonts as shown below:#
public typealias UNFonts = [UNFontFamilyName: [UNFontData]]public typealias UNFontFamilyName = String

In this dictionary, the keys typically represent the font family names. Corresponding to each font family name, there is an array containing various fonts from that particular family.

Note: Our current implementation supports font names formatted as <font-family>-<font-weight>.#

UNFontData Properties#

NameTypeDescription
fontWeightFontWeightEnum that defines the weight of the font.
sources[UNFontSource]An array of UNFontSource objects. An array is used to provide fallback options.

UNFontSource Properties#

NameTypeDescription
fileNameStringThe custom font file name, as specified in the info.plist of your target
formatString?(Optional) Font file format. Useful for specifying fallback behavior.

Swift Code Example#

manager.ui.setFonts([            "Poppins": [                UNFontData(fontWeight: FontWeight.regular, sources: [UNFontSource(fileName: "Poppins-Regular.ttf")]),                UNFontData(fontWeight: FontWeight.bold, sources: [UNFontSource(fileName: "Poppins-Bold.ttf")])            ],            "Arial": [                UNFontData(fontWeight: FontWeight.regular, sources: [UNFontSource(fileName: "Arial-Regular.ttf")]),            ]        ])

Components#

All the components extend from UIView. Each component receives the callbacks as an argument, the callbacks is a typealias of a method that receives a callback enum and returns nothing. The callback enum has all of the possible callbacks that you can receive from this component.

UNComponents SDK includes the following UI components:

ComponentProtocolCallbacks Type
CardUNCardViewUNCardComponentCallbacks
ACH CreditUNACHCreditViewUNACHCreditComponentCallbacks
ACH DebitUNACHDebitViewUNACHDebitComponentCallbacks
AccountUNAccountViewUNAccountComponentCallbacks
ActivityUNActivityViewUNActivityComponentCallbacks
BookPaymentUNBookPaymentViewUNBookPaymentComponentCallbacks
Check DepositUNCheckDepositViewUNCheckDepositComponentCallbacks
Multiple CardsUNMultipleCardsViewUNMultipleCardsComponentCallbacks

In order to access the UI components, use manager.ui.views:

let manager = UnitSDK.managerlet unViews = manager.ui.views

Card Component#

Component name: UNCardComponent#

Configuration parameters:#

NameTypeRequiredDescription
idStringYESA Unit card id.
additionalSettingsUNCardViewSettingsProtocolNOAdvanced optional settings.
callbacksUNCardComponentCallbacksNOCallbacks to interact with the Card component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNCardComponent is of the following type:

public typealias UNCardComponentCallbacks = (_ callback: UNCardComponentCallback) -> Void

The UNCardComponentCallback is an enum that has the following callbacks that you can receive from a Card component:

public enum UNCardComponentCallback {    case cardStatusChanged(card: UNCardData)    case cardActivated(card: UNCardData)    case unitOnLoad(result: Result<UNCardData, UNError>)}

To get the Card Component view, call the getCardComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class CardScreen: UIViewController {
    fileprivate lazy var cardComponent: UNCardView = {        let unViews = UnitSDK.manager.ui.views        let cardComponent = unViews.getCardComponent(id: "609414"){ callback in            switch callback {            case .cardStatusChanged(let card):                print("Card status changed \(card)")            case .cardActivated(let card):                print("Card activated -> \(card)")            case .unitOnLoad(let result):                switch result {                case .success(let card):                    print("Successfully loaded card. Card data: \(card)")                case .failure(let error):                    print("Failed to load Card component. Error details: \(error)")                }            }        }        return cardComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white
        // add the card component as a subview - using SnapKit for example        view.addSubview(cardComponent)        cardComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.leading.trailing.equalToSuperview()        }    }}

Incoming Events:#

In some cases, the default menu button won't fit into the design of an application. By using the openActionsMenu() method, it's possible to open the card actions bottom sheet from a custom button.

Important Note: one can use the openActionsMenu() only after UNCardComponent is loaded. (can be verified by onLoad callback)

Example:#

cardComponent.openActionsMenu()

It's also possible to create your own menu and call card actions from it. Use openAction(action: UNCardMenuAction) method and send inside an action you want to perform. Use Unit's API Docs in order to understand which actions could be applied.

Example:#

cardComponent.open(action: UNCardMenuAction.addToWallet)

You can choose to implement your own show / hide card sensitive data button. In this case use 'showSensitiveData()' method to show sensitive data and 'hideSensitiveData()' method to hide it.

Example:#

cardComponent.showSensitiveData()cardComponent.hideSensitiveData()

The additionalSettings parameter for UNCardComponent is of the following type:

UNCardViewSettingsProtocol:#

NameTypeDefault ValueDescription
hideActionsMenuButtonBoolfalseHide the actions menu buttons.
hideCardTitleBoolfalseHide the Card title
hideSensitiveDataButtonBoolfalseHide the Sensitive data ("Show details") button
enablePushProvisioningBoolfalseEnables Push Provisioning in case value is set to true.
learnMoreUrlString""A “Learn more” URL on the report lost/close card info note.

You can use UNCardViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNCardViewSettingsBuilder()    .hideCardTitle(true)    .hideSensitiveDataButton(true)    .enablePushProvisioning(true)
let unViews = UnitSDK.manager.ui.viewslet cardComponent = unViews.getCardComponent(id: "609414", additionalSettings: additionalSettings)

Adding a card to Apple Wallet (Optional)#

Start by following the Add card to wallet instructions to use this capability. After that, set the enablePushProvisioning with the value of true in the Card component additionalSettings parameter. Then, you can add a card to Apple Wallet using the "Manage Apple Wallet" tab in the Card Components's native menu or using an UNCardMenuAction.AddToWallet Incoming event.

ACH Credit Component#

Component name: UNACHCreditComponent#

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account from which money is being sent.
additionalSettingsUNACHCreditViewSettingsProtocolNOAdvanced optional settings.
callbacksUNACHCreditComponentCallbacksNOCallbacks to interact with the ACH Credit component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNACHCreditComponent is of the following type:

public typealias UNACHCreditComponentCallbacks = (_ callback: UNACHCreditComponentCallback) -> Void

The UNACHCreditComponentCallback is an enum that has the following callbacks that you can receive from an ACH Credit component:

public enum UNACHCreditComponentCallback {    case onPaymentCreated(data: UNACHData)    case unitOnLoad(result: Result<UNACHCreditOnLoadResponse, UNError>)}

To get the ACH Credit Component call the getACHCreditComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class ACHCreditScreen: UIViewController {
    fileprivate lazy var achCreditComponent: UNACHCreditView = {        let unViews = UnitSDK.manager.ui.views
        let achCreditComponent = unViews.getACHCreditComponent(accountId: "424242"){ callback in            switch callback {            case .onPaymentCreated(let data):                print("ACH Credit - onPaymentCreated: \(data)")            case .unitOnLoad(let result):                switch result {                case .success(let ACHCreditResponse):                    print("Successfully loaded ACHCredit Component. Data: \(ACHCreditResponse)")                case .failure(let error):                    print("Failed to load ACHCredit component. Error details: \(error)")                }            }        }        return achCreditComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()
        // add the ach credit component as a subview - using SnapKit for example        view.addSubview(achCreditComponent)        achCreditComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.trailing.equalToSuperview()        }    }}

The additionalSettings parameter for UNACHCreditComponent is of the following type:

UNACHCreditViewSettingsProtocol:#
NameTypeDefault ValueDescription
feeDouble0Bill your counterparty for his activity
isAutoFocusBoolfalseAuto-focus the 'add new recipient' button once the component is mounted
withPlaidBoolfalseUsing the Plaid API to connect your users' financial accounts. Default false
sameDayBoolfalseEnables Same Day ACH
Plaid integration:#

If you wish to use the Plaid API to connect your users' financial accounts using the Plaid integration. In order to utilize this integration, you must have a Plaid account and provide your Plaid credentials in the [Unit Sandbox Dashboard] (https://app.s.unit.sh/org-settings#tab=Integrations) and [Unit Production Dashboard] (https://app.unit.co/org-settings#tab=Integrations).

Enable camera support (for apps using Identity Verification only)#

If your app uses Identity Verification please follow these instructions

You can use UNACHCreditViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNACHCreditViewSettingsBuilder()    .fee(1.5)    .isAutoFocus(true)    .withPlaid(true)    .sameDay(true)
let unViews = UnitSDK.manager.ui.viewslet achCreditComponent = unViews.getACHCreditComponent(accountId: "424242", additionalSettings: additionalSettings)

ACH Debit Component#

Prerequirements:#

This component is using the Plaid API to connect your users' financial accounts using the Plaid integration. You must have a Plaid account and provide your Plaid credentials in the [Unit Sandbox Dashboard] (https://app.s.unit.sh/org-settings#tab=Integrations) and [Unit Production Dashboard] (https://app.unit.co/org-settings#tab=Integrations).

Enable camera support (for apps using Identity Verification only)#

If your app uses Identity Verification please follow these instructions

Component name: UNACHDebitComponent#

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account from which money is being sent.
additionalSettingsUNACHDebitViewSettingsProtocolNOAdvanced optional settings.
callbacksUNACHDebitComponentCallbacksNOCallbacks to interact with the ACH Debit component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNACHDebitComponent is of the following type:

public typealias UNACHDebitComponentCallbacks = (_ callback: UNACHDebitComponentCallback) -> Void

The UNACHDebitComponentCallback is an enum that has the following callbacks that you can receive from an ACH Debit component:

public enum UNACHDebitComponentCallback {    case onPaymentCreated(data: UNACHData)    case unitOnLoad(result: Result<UNACHDebitOnLoadResponse, UNError>)}

To get the ACH Debit Component call the getACHDebitComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class ACHDebitScreen: UIViewController {
    fileprivate lazy var achDebitComponent: UNACHDebitView = {        let unViews = UnitSDK.manager.ui.views
        let achDebitComponent = unViews.getACHDebitComponent(accountId: "424242"){ callback in            switch callback {            case .onPaymentCreated(let data):                print("ACH Debit - onPaymentCreated: \(data)")            case .unitOnLoad(let result):                switch result {                case .success(let ACHDebitResponse):                    print("Successfully loaded ACHDebit Component. Data: \(ACHDebitResponse)")                case .failure(let error):                    print("Failed to load ACHDebit component. Error details: \(error)")                }            }        }        return achDebitComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()
        // add the ach Debit component as a subview - using SnapKit for example        view.addSubview(achDebitComponent)        achDebitComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.trailing.equalToSuperview()        }    }}

The additionalSettings parameter for UNACHDebitComponent is of the following type:

UNACHDebitViewSettingsProtocol:#
NameTypeDefault ValueDescription
feeDouble0Bill your counterparty for his activity
isAutoFocusBoolfalseAuto-focus the 'add new recipient' button once the component is mounted
sameDayBoolfalseEnables Same Day ACH

You can use UNACHDebitViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNACHDebitViewSettingsBuilder()    .fee(1.5)    .isAutoFocus(true)    .sameDay(true)
let unViews = UnitSDK.manager.ui.viewslet achDebitComponent = unViews.getACHDebitComponent(accountId: "424242", additionalSettings: additionalSettings)

Account Component#

Component name: UNAccountComponent#

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account for which the activity will be shown.
additionalSettingsUNAccountViewSettingsProtocolNOAdvanced optional settings.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.
callbacksUNAccountComponentCallbacksNOCallbacks to interact with the Account component.

The callbacks parameter for UNAccountComponent is of the following type:

public typealias UNAccountComponentCallbacks = (_ callback: UNAccountComponentCallback) -> Void

The UNAccountComponentCallback is an enum that has the following callbacks that you can receive from an Account component:

public enum UNAccountComponentCallback {    case unitOnLoad(result: Result<[UNAccountData], UNError>)    case onAccountChange(account: UNAccountData)}

To get the Account Component call the getAccountComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class AccountScreen: UIViewController {
    fileprivate lazy var accountComponent: UNAccountView = {        let unViews = UnitSDK.manager.ui.views        let accountComponent = unViews.getAccountComponent(accountId: "424242"){ callback in            switch callback {            case .unitOnLoad(let result):                switch result {                case .success(let accounts):                    print("Success. Accounts Data: \(accounts)")                case .failure(let error):                    print("Fail to load Account component. Error details: \(error)")                }            case .onAccountChange(let account):                print(("Account \(account.id) is changed"))            }        }        return accountComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white        view.addSubview(accountComponent)        accountComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.leading.trailing.equalToSuperview()        }    }
}

Incoming Events:#

In some cases, the default menu button won't fit into the design of an application. By using the openActionsMenu() method, it's possible to open the account actions bottom sheet from a custom button.

Important Note: one can use the openActionsMenu() only after UNAccountComponent is loaded. (can be verified by onLoad callback)

Example:#

accountComponent.openActionsMenu()

It's also possible to create your own menu and call account actions from it. Use openAction(action: UNAccountMenuAction) method and send inside an action you want to perform. Use Unit's API Docs in order to understand which actions could be applied.

Example:#

accountComponent.open(action: UNAccountMenuAction.details)

The additionalSettings parameter for UNAccountComponent is of the following type:

UNAccountViewSettingsProtocol:#

NameTypeDefault ValueDescription
hideActionsMenuButtonBoolfalseHide the actions menu buttons.
hideSelectionMenuButtonBoolfalseHide selection menu button.

You can use UNAccountViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNAccountViewSettingsBuilder()    .hideActionsMenuButton(true)    .hideSelectionMenuButton(true)
let unViews = UnitSDK.manager.ui.viewslet cardComponent = unViews.getAccountComponent(accountId: "424242", additionalSettings: additionalSettings)

Activity Component#

Component name: UNActivityComponent#

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account to show.
additionalSettingsUNActivityViewSettingsProtocolNOAdvanced optional settings.
callbacksUNActivityComponentCallbacksNOCallbacks to interact with the Activity component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNActivityComponent is of the following type:

public typealias UNActivityComponentCallbacks = (_ callback: UNActivityComponentCallback) -> Void

The UNActivityComponentCallback is an enum that has the following callbacks that you can receive from an Activity component:

public enum UNActivityComponentCallbacks {    case unitOnLoad(result: Result<Void, UNError>)}

To get the Activity Component view call the getActivityComponent method of UnitSDK.manager.ui.views.

Example:#


class ActivityScreen: UIViewController {    let unViews = UnitSDK.manager.ui.views
    fileprivate lazy var activityComponent: UNActivityView = {        let activityComponent = unViews.getActivityComponent(accountId: accountId){ callback in            switch callback {                case .unitOnLoad(let result):                    switch result {                    case .success():                        print("Successfully load Activity Component.")                    case .failure(let error):                        print("Failed to load ACHCredit component. Error details: \(error)")                    }                }        }    return activityComponent}()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white        view.addSubview(activityComponent)        activityComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.trailing.equalToSuperview()        }    }}

The additionalSettings parameter for UNActivityComponent is of the following type:

UNActivityViewSettingsProtocol:#

NameTypeDefault ValueDescription
hideFilterButtonBoolfalseHide the filter button.
paginationTypeUNActivityComponentPaginationType.infiniteScrollDefines how more content is loaded. Possible values: .infiniteScroll, .pagination
transactionsPerPageInt8 for pagination and 15 for infinite scrollNumber of transactions to fetch on each page or scroll to bottom. Also acts as initial number of transactions to fetch

You can use UNActivityViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNActivityViewSettingsBuilder()    .hideFilterButton(true)    .paginationType(.pagination)    .transactionsPerPage(4)
let unViews = UnitSDK.manager.ui.viewslet cardComponent = unViews.getActivityComponent(accountId: accountId, additionalSettings: additionalSettings)

Check Deposit Component#

Component name: UNCheckDepositComponent#

Prerequirements:#

Check Deposit Component requires camera access. In order to enable this functionality, you need to include the Privacy - Camera Usage Description key in your info.plist file. The value should be the text that will be displayed when the app prompts the user for camera access.

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account to deposit to.
feeDoubleYESFee changed for making the check deposit, will be presented to the user.
callbacksUNCheckDepositComponentCallbacksNOCallbacks to interact with the Activity component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNCheckDepositComponent is of the following type:

public typealias UNCheckDepositComponentCallbacks = (_ callback: UNCheckDepositComponentCallback) -> Void

The UNCheckDepositComponentCallback is an enum that has the following callbacks that you can receive from a Book Payment component:

KeyTypeDescription
unitCheckDepositCreated(depositCheckData: UNCheckDeposit) => VoidOccurs when a check deposit is successfully created
unitCheckDepositRestartRequest(depositCheckData: UNCheckDeposit) => VoidOccurs when "Deposit another check" is clicked
unitOnLoad(result: Result<UNAccountData, UNError>) => VoidCallback for a loaded component

To get the Check Deposit Component view call the getCheckDepositComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class CheckDepositScreen: UIViewController {
    fileprivate lazy var checkDepositComponent: UNCheckDepositView = {        let unViews = UnitSDK.manager.ui.views
        let checkDepositComponent = unViews.getCheckDepositComponent(accountId: "424242", fee: 1.5) { callback in            switch callback {            case .unitCheckDepositCreated(let checkData):                print("Check deposit created, data: \(checkData)")            case .unitCheckDepositRestartRequest(let checkData):                print("Check deposit restart request \(checkData)")            case .unitOnLoad(let accountData):                print("CheckDeposit Component is loaded. Account: \(accountData)")            }        }        return checkDepositComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white        view.addSubview(checkDepositComponent)        checkDepositComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.equalTo(view.safeAreaLayoutGuide.snp.leading)            make.trailing.equalTo(view.safeAreaLayoutGuide.snp.trailing)        }    }}

Book Payment Component#

Component name: UNBookPaymentComponent#

Configuration parameters:#

NameTypeRequiredDescription
accountIdStringYESUnit account id. The account from which money is being sent.
counterpartyAccountIdStringYESUnit account id. The account which will receive money.
counterpartyNameStringYESName of the counterparty. This is the name that will be displayed in the Book Payment UI during the transfer.
isSameCustomerBoolNoStating whether both accounts belong to the same customer. Allows fetching additional information about the counterparty account. Default false.
additionalSettingsUNBookPaymentViewSettingsProtocolNOAdvanced optional settings.
callbacksUNBookPaymentComponentCallbacksNOCallbacks to interact with the Book Payment component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNBookPaymentComponent is of the following type:

public typealias UNBookPaymentComponentCallbacks = (_ callback: UNBookPaymentComponentCallback) -> Void

The UNBookPaymentComponentCallback is an enum that has the following callbacks that you can receive from a Book Payment component:

public enum UNBookPaymentComponentCallback {    case onPaymentCreated(data: UNBookPaymentData)    case unitOnLoad(result: Result<UNAccountData, UNError>)}

To get the Book Payment Component view, call the getBookPaymentComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class BookPaymentScreen: UIViewController {
    fileprivate lazy var bookPaymentComponent: UNBookPaymentView = {        let unViews = UnitSDK.manager.ui.views        let bookPaymentComponent = unViews.getBookPaymentComponent(accountId: "1105561", counterpartyAccountId: "1105562", counterpartyName: "Peter Parker") { callback in            switch callback {            case .onPaymentCreated(let data):                print("[Book Payment Screen] onPaymentCreated: \(data)")            case .unitOnLoad(let result):                switch result {                case .success(let account):                    print("Success Loading Book Payment. account: \(account)")                case .failure(let error):                    switch error {                    case .onLoad(let onLoadErrors):                        print("Fail to load Book Payment component. Errors:")                        for loadError in onLoadErrors {                            print("Status: \(loadError.status); Title:\(loadError.title)")                        }                    default:                        print("Error: \(error.description)")                    }                }            }        }        return bookPaymentComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white
        // add the book payment component as a subview - using SnapKit for example        view.addSubview(bookPaymentComponent)        bookPaymentComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.trailing.equalToSuperview()        }    }}

The additionalSettings parameter for UNBookPaymentComponent is of the following type:

UNBookPaymentViewSettingsProtocol:#

NameTypeDefault ValueDescription
isAutoFocusBoolfalseAuto-focus the money input field once the component is mounted.

You can use UNBookPaymentViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNBookPaymentViewSettingsBuilder()    .isAutoFocus(true)
let unViews = UnitSDK.manager.ui.viewslet bookPaymentComponent = unViews.getBookPaymentComponent(accountId: "1105561", counterpartyAccountId: "1105562", counterpartyName: "Peter Parker", additionalSettings: additionalSettings)

Multiple Cards Component#

Component name: UNMultipleCardsComponent#

Configuration parameters:#

NameTypeRequiredDescription
additionalSettingsUNMultipleCardsViewSettingsProtocolNOAdvanced optional settings.
callbacksUNMultipleCardsComponentCallbacksNOCallbacks to interact with the Multiple Cards component.
themeStringNOA URL that specifies the UI configuration.
languageStringNOA URL that specifies the language configuration.

The callbacks parameter for UNMultipleCardsComponent is of the following type:

public typealias UNMultipleCardsComponentCallbacks = (_ callback: UNMultipleCardsComponentCallback) -> Void

The UNMultipleCardsComponentCallback is an enum that has the following callbacks that you can receive from a Multiple Cards component:

public enum UNMultipleCardsComponentCallback {    case cardClicked(card: UNCardData)    case unitOnLoad(result: Result<[UNCardData], UNError>)}

To get the Multiple Cards Component view, call the getMultipleCardsComponent method of UnitSDK.manager.ui.views.

Example:#

import UIKitimport UNComponentsimport SnapKit
class MultipleCardsScreen: UIViewController {
    fileprivate lazy var multipleCardsComponent: UNMultipleCardsView = {        let unViews = UnitSDK.manager.ui.views        let multipleCardsComponent = unViews.getMultipleCardsComponent() { callback in            switch callback {            case let .cardClicked(card):                print("Card clicked, ID: \(card.id)")            case .unitOnLoad(let result):                switch result {                case .success(let cards):                    print("Success Loading Multiple Cards")                case .failure(let error):                    print("Error Loading Multiple Cards")                }            }        }        return multipleCardsComponent    }()
    override func viewDidLoad() {        super.viewDidLoad()        view.backgroundColor = .white
        // add the multiple cards component as a subview - using SnapKit for example        view.addSubview(multipleCardsComponent)        multipleCardsComponent.snp.makeConstraints { make in            make.top.equalTo(view.safeAreaLayoutGuide.snp.top)            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)            make.leading.trailing.equalToSuperview()        }    }}

The additionalSettings parameter for UNMultipleCardsComponent is of the following type:

UNMultipleCardsViewSettingsProtocol:#

NameTypeDefault ValueDescription
disableCardClickBoolfalseWhen true, will not publish a unitMultipleCardsCardClicked event when a row is clicked
paginationTypeUNMultipleCardsComponentPaginationType.infiniteScrollDefines how more content is loaded. Possible values: .infiniteScroll, .pagination
cardsPerPageInt8 for pagination and 15 for infinite scrollNumber of cards to fetch on each page or scroll to bottom. Also acts as initial number of cards to fetch

You can use UNMultipleCardsViewSettingsBuilder to create an instance of the protocol and define your additional settings.

Example:#
let additionalSettings = UNMultipleCardsViewSettingsBuilder()    .disableCardClick(true)    .paginationType(.pagination)    .cardsPerPage(4)
let unViews = UnitSDK.manager.ui.viewslet multipleCardsComponent = unViews.getMultipleCardsComponent(additionalSettings: additionalSettings)

Flows#

Add card to wallet flow#

Start by following the Add card to wallet instructions to use this flow.

After that, you can add a card to Apple Wallet by calling the Unit SDK's func startPushProvisioning(for cardId: String, theme: UNTheme?, language: UNLanguage?) method.

Example:#

UnitSDK.manager.ui.flows.startPushProvisioning(for: YOUR_CARD_ID)

Additional Capabilities#

Add card to wallet#

This capability can be used with the Card Component or without it, as a separate flow.

Prerequirements#

Complete the following steps at the Steps to support Apple Pay- Apple Pay Prerequirements:

  1. Request Apple Pay In-app provisioning entitlement.
  2. Setup your App in Apple Developer Portal once entitlement is granted by Apple.
Steps to integrate with the Visa SDK#

Complete the following integration-steps:

  1. Wallet Capability.
  2. In-App Provisioning entitlement.
  3. Add Visa SDK to your Xcode project.
Add to Wallet flow#

You can find an overview of the add to wallet flow in this link.

Create a Swift class named UNVisaProvider. This class will be responsible to communicate and pass data from the Unit SDK and the VDE(Visa Digital Enablement) SDK through your app.

UNVisaProvider code
import Foundationimport VisaPushProvisioningimport UIKitimport UNComponentsimport VisaInAppModuleCore

internal final class UNVisaProvider: UNVisaProviding {    private var provisioningInterface: VisaPushProvisioningInterface? = nil
    private var initializationCallback: UNVisaInitializationCompletion? = nil    private var supportedWalletsCallback: UNVisaSupportedWalletsCompletion? = nil    private var cardProvisioningCallback: UNVisaCardProvisioningCompletion? = nil
    init(environment: VisaInAppEnvironment, appId: String) {        // Setup Visa SDK Config        let visaInAppConfig = VisaInAppConfig(environment: environment, appId: appId)        do {            try VisaInAppCore.configure(config: visaInAppConfig)        } catch {            print(error)        }    }
    func initialize(completion: @escaping UNVisaInitializationCompletion) {        self.initializationCallback = completion        provisioningInterface = VisaPushProvisioningInterfaceFactory.createPushProvisioningInterface( listener: self)        provisioningInterface?.initialize()    }
    func getSupportedWallets(for payload: String, completion: @escaping UNVisaSupportedWalletsCompletion) {        self.supportedWalletsCallback = completion        let request = VPSupportedWalletRequest(encPayload: payload)        self.provisioningInterface?.getSupportedWallets(request: request)    }
    func startCardProvisioning(for walletName: String, in vc: UIViewController, completion: @escaping UNVisaCardProvisioningCompletion) {        self.cardProvisioningCallback = completion        let request = VPCardProvisioningRequest(walletCode: VPSupportedWalletCode(rawValue: 0)!, walletName: walletName)        provisioningInterface?.startCardProvisioning(request: request, initialView: vc)    }}
extension UNVisaProvider: VisaPushProvisioningListener {    func initializationSuccess(pushProvisioningInterface: VisaPushProvisioningInterface, response: VPInitResponse) {        self.initializationCallback?(response.signedNonce, nil)        self.initializationCallback = nil    }
    func initializationFailure(pushProvisioningInterface: VisaPushProvisioningInterface, error: VPError) {        let unError = UNVPError(code: error.code, description: error.description, type: error.type.toUNVPErrorType(), correlationId: error.correlationId)        self.initializationCallback?(nil, unError)        self.initializationCallback = nil    }
    func supportedWalletSuccess(pushProvisioningInterface: VisaPushProvisioningInterface, response: VPSupportedWalletResponse) {        self.supportedWalletsCallback?(response.wallets.map({ $0.toUNVPSupportedWallet()}), nil)        self.supportedWalletsCallback = nil    }
    func supportedWalletFailure(pushProvisioningInterface: VisaPushProvisioningInterface, error: VPError) {        self.supportedWalletsCallback?(nil, error.toUNVPError())        self.supportedWalletsCallback = nil    }
    func cardProvisioningSuccess(pushProvisioningInterface: VisaPushProvisioningInterface, response: VPCardProvisioningResponse) {        self.cardProvisioningCallback?(response.toUNVPCardProvisioningResponse(), nil)        self.cardProvisioningCallback = nil    }
    func cardProvisioningFailure(pushProvisioningInterface: VisaPushProvisioningInterface, error: VPError) {        self.cardProvisioningCallback?(nil, error.toUNVPError())        self.cardProvisioningCallback = nil    }}
fileprivate extension VPSupportedWallet {    func toUNVPSupportedWallet() -> UNVPSupportedWallet {        return UNVPSupportedWallet(name: self.name, description: self.description, status: self.status.toUNVPProvisionStatus(), reason: self.reason.toUNVPReason())    }}
fileprivate extension VPReason {    func toUNVPReason() -> UNVPReason {        return UNVPReason(reason: self.reason, description: self.description)    }}
fileprivate extension VPProvisionStatus {    func toUNVPProvisionStatus() -> UNVPProvisionStatus {        switch self {        case .ReadyToProvision:            return .readyToProvision        case .AlreadyProvisioned:            return .alreadyProvisioned        case .ProvisionedInCurrentDevice:            return .provisionedInCurrentDevice        case .ProvisionedInPairedDevice:            return .provisionedInPairedDevice        case .NotAvailable:            return .notAvailable        @unknown default: return .notAvailable        }    }}
fileprivate extension VPCardProvisioningResponse {    func toUNVPCardProvisioningResponse() -> UNVPCardProvisioningResponse {        return UNVPCardProvisioningResponse(walletStatus: self.walletStatus.toUNVPProvisionStatus())    }}
fileprivate extension VPError {    func toUNVPError() -> UNVPError {        return UNVPError(code: self.code, description: self.description, type: self.type.toUNVPErrorType(), correlationId: self.correlationId)    }}
fileprivate extension VPErrorType {    func toUNVPErrorType() -> UNVPErrorType {        switch self {        case .EmptyAppId:            return .emptyAppId        case .DeviceAuthenticationFailed:            return .deviceAuthenticationFailed        case .DeviceRootDetection:            return .deviceRootDetection        case .EmptyEncryptedPayload:            return .emptyEncryptedPayload        case .NoWallets:            return .noWallets        case .InvalidCardId:            return .invalidCardInfo        case .InvalidCardLast4Digits:            return .invalidCardLast4Digits        case .ProvisioningNotAllowed:            return .provisioningNotAllowed        case .CancelledByUser:            return .cancelledByUser        case .AppleWalletProvisioningError:            return .walletProvisioningError        case .UnableToCreateApplePaymentPassView:            return .unableToCreatePaymentPassView        case .ValidAppleCertificatesNotFound:            return .validCertificatesNotFound        case .NetworkFailure:            return .networkFailure        case .SessionExpired:            return .sessionExpired        case .InvalidInfo:            return .invalidCardInfo        case .PayloadDecryptionFailed:            return .payloadDecryptionFailed        case .ApiError:            return .apiError        case .InvalidNonce:            return .invalidNonce        case .SDKLockout:            return .sdkLockout        case .WalletProvisioningInconclusive:            return .walletProvisioningInconclusive        case .WalletProvisioningError:            return .walletProvisioningError        @unknown default: return .networkFailure        }    }}

Set Unit SDK with the UNVisaProvider#

Call UnitSDK.manager.services.setVisaProvider with a UNVisaProvider instance. It is recommended to call it inside the application didFinishLaunchingWithOptions method in the AppDelegate.swift file. You will need to make sure you're initializing the manager.environment with UNEnvironment.Production environment as well. Pass the UNVisaProvider with your Visa's App ID and a VisaInAppEnvironment.Production environment.

Example:#

import UIKitimport UNComponentsimport VisaInAppModuleCore
@mainclass AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {        // Override point for customization after application launch.        let manager: UNManagerProtocol = UnitSDK.manager        manager.services.setVisaProvider(UNVisaProvider(environment: VisaInAppEnvironment.Production, appId: YOUR_APP_ID))
        return true    }    ...}

Error Handling#

By using unitOnLoad callback you can get a Swift.Result about the requested component. OnError - you will get an enum UNError that consists of several cases.

UNError:#

CasefieldsDescription
onLoaderrors: [UNErrorResponse]Report UNErrorResponse on errors that happen during loading time

UNErrorResponse:#

NameTypeDescription
statusStringA Unit-specific code, uniquely identifying the error type
titleString?The title of the error type
detailString?Additional information about the error.
detailsString?Additional information about the error.
metaMeta?: { supportId: String }meta.supportId unique error identifier to be used for further investigation

Note: An "error object" MUST contain a title and the HTTP status code members.

Example:#

fileprivate lazy var accountComponent: UNAccountView = {        let unViews = UnitSDK.manager.ui.views        let accountComponent = unViews.getAccountComponent(accountId: "424242"){ callback in            switch callback {            case .unitOnLoad(let result):                switch result {                case .success(let accounts):                    print("Success. Accounts Data: \(accounts)")                case .failure(let error):                    switch error {                        case .onLoad(let onLoadErrors):                            print("Fail to load Account component. Errors:")                            for loadError in onLoadErrors {                                print("Status: \(loadError.status); Title:\(loadError.title)")                            }                    }                }        }            return accountComponent}()