Skip to main content

iOS SDK

Requirements

NameVersion
iOS>= 14.0

Installation

Swift Package Manager

  1. Add the package dependency to your project: Navigate to File > Swift Packages > Add Package Dependency.
  2. Enter the package repository URL: https://github.com/unit-finance/unit-ios-components-pod.git.
  3. Specify the version: 1.0.0
  4. Add the package to your target.

Cocoapods

  1. Set the dependency in your Podfile as follows: pod 'UnitComponents', '1.0.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

Initialize SDK

To begin using the SDK, you must first initialize it using the initialize function. You may utilize the UNSDKConfigurationBuilder. This builder allows you to set essential parameters such as the environment and webVersioningStrategy.

Usage Example:

let unitSdkManager = UnitSDK.manager
let configurationSettings = UNSDKConfigurationBuilder()
.environment(UNEnvironment.sandbox)

unitSdkManager.initialize(with: configurationSettings)

Important Note: To utilize the SDK, you must configure a customer token. It is essential to note that the customer token is not included in the initial SDK setup because it may need to be updated periodically. Please refer to the Setup SDK Parameters section for more details.

Environment

The UNEnvironment enum should be used:

public enum UNEnvironment {
case sandbox
case production
}

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.
  4. Latest - .latest

    • With this strategy, your SDK will use the latest web SDK.

You can configure the web versioning strategy through the initialize method using the UNSDKConfigurationBuilder described above.

let configurationSettings = UNSDKConfigurationBuilder()
.environment(UNEnvironment.sandbox)
.webVersioningStrategy(UNWebVersioningStrategy.latest)

Setup SDK parameters

Customer Token

Set your customer token as follows:

manager.customerToken = "token"

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:

@main
class 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")

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

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.manager
let 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 UIKit
import UNComponents
import 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.
menuItems[UNCardComponentMenuItems]A list of actions, The menu dynamically adjusts based on the provided list [.freeze, .addToWallet, .managePin, .replace, .report, .close].

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)
.menuItems([.freeze])

let unViews = UnitSDK.manager.ui.views
let 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
accountIdStringNOUnit 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>)
case onInitialStageBackButtonClicked
case onFinalStageDoneButtonClicked
}

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

Example:

import UIKit
import UNComponents
import 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 .onInitialStageBackButtonClicked:
print("Back button clicked on the initial stage")
case .onFinalStageDoneButtonClicked:
print("Done button clicked on the final stage")
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
initialStageBackButtonBoolfalseAn action button at the first stage of the payment flow.
finalStageDoneButtonBoolfalseAn action button at the final stage of the payment flow.
plaidLinkCustomizationNameStringThe name of the Link customization from the Plaid Dashboard to be applied to Link. If not specified, the default customization will be used. When using a Link customization, the language in the customization must match the language selected via the language parameter.
plaidAccountFilters[UNPlaidAccountFilter]Account subtypes to display in Link based on the provided list [.checking, .savings]. If not specified, only checking subtype will be shown.
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 and Unit Production Dashboard.
Finally, you need to add Plaid dependency to your application (Documentation for installation).

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)
.initialStageBackButton(true)
.finalStageDoneButton(true)

let unViews = UnitSDK.manager.ui.views
let 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 and Unit Production Dashboard. Finally, you need to add Plaid dependency to your application (Documentation for installation).

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
accountIdStringNOUnit 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>)
case onInitialStageBackButtonClicked
case onFinalStageDoneButtonClicked
}

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

Example:

import UIKit
import UNComponents
import 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 .onInitialStageBackButtonClicked:
print("Back button clicked on the initial stage")
case .onFinalStageDoneButtonClicked:
print("Done button clicked on the final stage")
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
initialStageBackButtonBoolfalseAn action button at the first stage of the payment flow.
finalStageDoneButtonBoolfalseAn action button at the final stage of the payment flow.
plaidLinkCustomizationNameStringThe name of the Link customization from the Plaid Dashboard to be applied to Link. If not specified, the default customization will be used. When using a Link customization, the language in the customization must match the language selected via the language parameter.
plaidAccountFilters[UNPlaidAccount]Account subtypes to display in Link based on the provided list [.Checking, .Savings]. If not specified, only checking subtype will be shown.

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)
.initialStageBackButton(true)
.finalStageDoneButton(true)

let unViews = UnitSDK.manager.ui.views
let 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)
case onRequestLeftToSpendDetails(account: UNAccountData)
}

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

Example:

import UIKit
import UNComponents
import 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"))
case .onRequestLeftToSpendDetails(let account):
print(("Request left to spend details for account \(account.id)"))
}
}
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)

By using the refresh() method, it's possible to to refresh the component data from a custom button. Important Note: one can use the refresh() only after UNAccountComponent is loaded.

Example:

accountComponent.refresh()

The additionalSettings parameter for UNAccountComponent is of the following type:

UNAccountViewSettingsProtocol:

NameTypeDefault ValueDescription
hideActionsMenuButtonBoolfalseHide the actions menu buttons.
hideSelectionMenuButtonBoolfalseHide selection menu button.
menuItems[UNAccountComponentMenuItems]A list of actions, The menu dynamically adjusts based on the provided list [.details, .statements, .bankVerification].
showLeftToSpendBoolfalseShow amount left to spend in case value is true, only relevant for credit accounts.

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

Example:
let additionalSettings = UNAccountViewSettingsBuilder()
.hideActionsMenuButton(true)
.hideSelectionMenuButton(true)
.menuItems([.details])
let unViews = UnitSDK.manager.ui.views
let 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()
}
}
}

Incoming Events:

By using the refresh() method, it's possible to to refresh the component data from a custom button. Important Note: one can use the refresh() only after activityComponent is loaded.

Example:

activityComponent.refresh()

The additionalSettings parameter for UNActivityComponent is of the following type:

UNActivityViewSettingsProtocol:

NameTypeDefault ValueDescription
hideFilterButtonBoolfalseHide the filter button.
hideTitleBoolfalseHide the component title in case value is true.
hideBackToTopBoolfalseHide back to top button in case value is true.
queryFilterStringQuery for filtering transactions and authorizations: Transactions, Authorizations.
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.views
let 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.
feeDoubleNOFee changed for making the check deposit, will be presented to the user.
additionalSettingsUNCheckDepositViewSettingsProtocolNOAdvanced optional settings.
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
onInitialStageBackButtonClicked() => VoidOccurs when the back button is clicked on the initial stage
onFinalStageDoneButtonClicked() => VoidOccurs when the done button is clicked on the final stage

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

Example:

import UIKit
import UNComponents
import 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 .onInitialStageBackButtonClicked
print("Back button clicked on the initial stage")
case .onFinalStageDoneButtonClicked
print("Done button clicked on the final stage")
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)
}
}
}

The additionalSettings parameter for UNCheckDepositComponent is of the following type:

UNCheckDepositViewSettingsProtocol:

NameTypeDefault ValueDescription
initialStageBackButtonBoolfalseAn action button at the first stage of the payment flow.
finalStageDoneButtonBoolfalseAn action button at the final stage of the payment flow.

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

Example:
let additionalSettings = UNCheckDepositViewSettingsBuilder()
.initialStageBackButton(true)
.finalStageDoneButton(true)

let unViews = UnitSDK.manager.ui.views
let checkDepositComponent = unViews.unViews.getCheckDepositComponent(accountId: "424242", fee: 1.5, additionalSettings: additionalSettings)

Book Payment Component

Component name: UNBookPaymentComponent

Configuration parameters:

NameTypeRequiredDescription
accountIdStringNOUnit account id. The account from which money is being sent.
counterpartyAccountIdStringNOUnit account id. The account which will receive money.
counterpartyNameStringNOName 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>)
case onInitialStageBackButtonClicked
case onFinalStageDoneButtonClicked
}

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

Example:

import UIKit
import UNComponents
import 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 .onInitialStageBackButtonClicked:
print("Back button clicked on the initial stage")
case .onFinalStageDoneButtonClicked:
print("Done button clicked on the final stage")
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.
initialStageBackButtonBoolfalseAn action button at the first stage of the payment flow.
finalStageDoneButtonBoolfalseAn action button at the final stage of the payment flow.

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

Example:
let additionalSettings = UNBookPaymentViewSettingsBuilder()
.isAutoFocus(true)
.initialStageBackButton(true)
.finalStageDoneButton(true)

let unViews = UnitSDK.manager.ui.views
let 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 UIKit
import UNComponents
import 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
hideTitleBoolfalseHide the component title in case value is true.
hideBackToTopBoolfalseHide back to top button in case value is true.
queryFilterStringQuery for filtering cards: Cards.
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.views
let 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 Foundation
import VisaPushProvisioning
import UIKit
import UNComponents
import 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 UIKit
import UNComponents
import VisaInAppModuleCore

@main
class 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
}()