Cards
The card component allows you to show your customers their different cards, and allows them to manage the cards lifecycle:
- Reveal card information
- Activate card
- Set / Change PIN
- Freeze / unfreeze
- Replace a damaged card
- Report card lost/stolen
- Add card to mobile wallet (on mobile platforms only)
Note: The preview is in Sandbox, meaning this is not a real card.
Implementation
Web Components
Add the card element to your app where you'd like the card to be presented.
<unit-elements-card
card-id="632197"
customer-token=""
theme=""
learn-more-url="www.google.com"
menu-items="freeze,addToWallet,managePin,replace,report,close"
></unit-elements-card>
<!-- Hide actions menu button & sensitive data button. -->
<unit-elements-card
card-id="632197"
customer-token=""
theme=""
hide-actions-menu-button="false"
hide-sensitive-data-button="false"
></unit-elements-card>
Inputs:
Name | Type | Required | Description |
---|---|---|---|
card-id | string | Yes | Unit card id. |
customer-token | string | Yes | A Unit Customer token. Required Scopes: customers cards cards-sensitive cards-sensitive-write cards-write |
theme | string | No | A URL that specifies the UI configuration. |
language | string | No | A URL that specifies the language configuration. |
hide-actions-menu-button | string | No | Hide menu button in case value is 'true'. |
hide-card-title | string | No | Hide card title in case value is 'true'. |
hide-sensitive-data-button | string | No | Hide sensitive data button in case value is 'true'. |
learn-more-url | string | No | A “Learn more” URL on the report lost/close card info note. |
menu-items | string | No | A list of actions, The menu dynamically adjusts based on the provided list freeze,addToWallet,managePin,replace,report,close . |
Events:
Event Name | Description | Detail |
---|---|---|
unitOnLoad | Occurs when a component is loaded | Card |
unitCardStatusChanged | Occurs when a Card status changes, excluding first time card activation | [Promise] Card |
unitCardActivated | Occurs when a Card is activated | [Promise] Card |
Incoming events:
In some cases, the default menu button won't fit into the design of an application. By using the unitRequestOpenActionsMenu
incoming event, it's possible to open the card actions bottom sheet from a custom button
<unit-elements-card
hide-actions-menu-button="false"
hide-card-title="false"
hide-sensitive-data-button="false"
card-id="632197"
>
</unit-elements-card>
<button id="#custom-button">Manage Card</button>
<script>
document.querySelector('#custom-button').addEventListener('click', () => {
document
.querySelector('unit-elements-card')
.dispatchEvent(new CustomEvent('unitRequestOpenActionsMenu'));
});
</script>
It's also possible to create your own menu and call card actions from it. Use unitRequestCardAction
event and send inside an action you want to perform.
Possible actions: Activate
, Freeze
, Unfreeze
, Report
(for report lost / stolen), Close
, Replace
, ManagePin
, ChangePin
, SetPin
, AddToWallet
Use API Docs in order to understand which actions could be applied for any particular card statuses.
<unit-elements-card
hide-actions-menu-button="false"
hide-card-title="false"
hide-sensitive-data-button="false"
card-id="632197"
>
</unit-elements-card>
<button id="#custom-button">Freeze card</button>
<script>
document.querySelector('#custom-button').addEventListener('click', () => {
document.querySelector('unit-elements-card').dispatchEvent(
new CustomEvent('unitRequestCardAction', {
detail: { action: 'Freeze' },
})
);
});
</script>
React Native SDK
UNCardComponent props:
Name | Type | Required | Description |
---|---|---|---|
customerToken | string | YES | A Unit Customer token. |
cardId | string | YES | Unit card id. |
theme | string | NO | A URL that specifies the UI configuration. |
language | string | NO | A URL that specifies the language configuration. |
menuItems | UNCardMenuItem[] | NO | A list of actions, The menu dynamically adjusts based on the provided list. The keys for UNCardMenuItem are: freeze , addToWallet , managePin , replace , report , and close . |
hideActionsMenuButton | boolean | NO | Hide menu button in case value is true |
hideCardTitle | boolean | NO | Hide card title in case value is true |
hideSensitiveDataButton | boolean | NO | Hide sensitive data button in case value is true |
learnMoreUrl | string | NO | A “Learn more” URL on the report lost/close card info note. |
onStatusChanged | (card: UNCardData) => void | NO | Callback for card status changes. |
onLoad | (response: UNOnLoadResponse<UNCardData>) => void | NO | Callback for a loaded component |
onCardActivated | (card: UNCardData) => void | NO | Callback for card activated. |
pushProvisioningModule | typeof NativeModules | NO | A Native Module that implements Visa's push provisioning |
Example:
import React from 'react';
import { UNCardComponent, UNCardData } from 'react-native-unit-components';
import { NativeModules } from 'react-native';
const { PushProvisioningModule } = NativeModules;
export default function YourComponent() {
return (
<UNCardComponent
cardId={'632197'}
customerToken={/*Customer token here*/}
onStatusChanged={(card: UNCardData) => { console.log(card) }}
onCardActivated={(card: UNCardData) => { console.log(card) }}
pushProvisioningModule={PushProvisioningModule}
onLoad={(response: UNOnLoadResponse<UNCardData>) => { console.log(response) }}
/>
);
}
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:
import { UNCardComponent, CardRef } from 'react-native-unit-components';
...
const cardRef = useRef<CardRef>(null);
...
const openActionsMenu = () => {
cardRef.current?.openActionsMenu();
};
...
<UNCardComponent
ref={cardRef}
cardId={"4242"}
customerToken={''}
/>
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 API Docs in order to understand which actions could be applied for any particular card statuses.Example:
import { UNCardMenuAction } from 'react-native-unit-components';
// .......
const openAction = (action: UNCardMenuAction) => {
cardRef.current?.openAction(action);
};
// .......
- 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:
// .......
const showSensitiveData = () => {
cardRef.current?.showSensitiveData();
};
const hideSensitiveData = () => {
cardRef.current?.hideSensitiveData();
};
// .......
Add card to wallet
This capability can be used with the Card Component, or without it, as a separate flow. Complete the add to wallet guide for React Native, skipping the last module access from javascript, to use this capability.
Adding a card to Wallet with the Card Component
After completing the instructions to use this capability, pass the PushProvisioningModule
as a prop to Unit's Card Component. This will let the SDK get wallets and start card provisioning for you once the native Add to Wallet button was pressed.
Then, you can add a card to the wallet using the "Manage Apple Wallet" or "Manage Google Wallet" tab in the Card Components's native menu or using an AddToWallet
as the Incoming event action.
Add card to wallet as a separate flow
After completing the instructions to use this flow, call UnitSDK.setPushProvisioningModule(PushProvisioningModule)
with your PushProvisioningModule
Native Module.
After that, you can add a card to Apple or Google Wallet by calling the Unit SDK's startPushProvisioning(cardId: string, customerToken: string)
.
Example:
UnitSDK.ui.flows.startPushProvisioning(YOUR_CARD_ID, YOUR_CUSTOMER_TOKEN);
Android SDK
Component name: UNCardComponent
getCardComponent parameters:
Name | Type | Required | Description |
---|---|---|---|
cardId | String | YES | Unit card id. |
additionalSettings | UNCardViewSettingsInterface | NO | Additional settings unique for this component |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
callbacks | UNCardComponentCallbacks | NO | Component's Callbacks sealed class |
UNCardComponentCallbacks
The callbacks parameter for UNCardComponent is of the following type:
typealias UNCardComponentCallbacks = (callback: UNCardComponentCallback) -> Unit
The UNCardComponentCallback is sealed class that has the following callbacks that you can receive from a Card component:
sealed class UNCardComponentCallback {
data class OnLoad(val onLoadResponse: Result<UNCardData>): UNCardComponentCallback()
data class CardStatusChanged(val card: UNCardData): UNCardComponentCallback()
data class CardActivated(val card: UNCardData): UNCardComponentCallback()
}
To get the Card Component fragment, call the getCardComponent
method of UnitComponentsSdk.manager.ui.views
.
Example:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import co.unit.un_components.api.UnitComponentsSdk
import co.unit.un_components.common.builders.UNCardViewSettingsBuilder
import co.unit.un_components.common.enums.UNCardComponentCallback
import co.unit.un_components.components.UNCardView
import co.unit.un_components.common.models.UNCardData
import co.unit.un_components.common.models.UNCardMenuAction
class CardFragment : Fragment(){
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
private var unCardComponent: UNCardComponent? = null
unCardComponent = UnitComponentsSdk.manager.ui.views.getCardComponent(
cardId = YOUR_CARD_ID,
theme = YOUR_THEME_URL,
language = YOUR_LANGUAGE_URL
) { callback ->
when(callback) {
is UNCardComponentCallback.CardActivated -> handleCardActivated(callback.card)
is UNCardComponentCallback.CardStatusChanged -> handleCardStatusChanged(callback.card)
is UNCardComponentCallback.OnLoad -> handleOnLoad(callback.onLoadResponse)
}
}
val fragmentLayout = inflater.inflate(R.layout.FILE_NAME, container, false)
childFragmentManager.beginTransaction()
.replace(R.id.CONTAINER_NAME, unCardComponent as Fragment)
.commitNow()
return fragmentLayout
}
// ...
// Event handlers
// ...
}
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:
unCardComponent.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 API Docs in order to understand which actions could be applied for any particular card statuses.
Example:
import co.unit.un_components.common.models.UNCardMenuAction
// .......
unCardComponent.openAction(UNCardMenuAction.Freeze)
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:
```kotlin
unCardComponent.showSensitiveData()
unCardComponent.hideSensitiveData()
The additionalSettings
parameter for UNCardComponent
has this attribute:
UNCardViewSettingsInterface
Name | Type | Default Value | Description | |
---|---|---|---|---|
hideActionsMenuButton | Boolean | false | Hide menu button in case value is true. | |
hideCardTitle | Boolean | false | Hide card title in case value is true. | |
hideSensitiveDataButton | Boolean | false | Hide sensitive data button in case value is true. | |
enablePushProvisioning | Boolean | false | Enables Push Provisioning in case value is true. | |
learnMoreUrl | String | "" | A “Learn more” URL on the report lost/close card info note. | |
menuItems | List<UNCardMenuItem> | null | 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 interface and define your additional settings.
val additionalSettings = UNCardViewSettingsBuilder()
.learnMoreUrl(...)
.hideCardTitle(...)
.hideActionsMenuButton(...)
.hideSensitiveDataButton(...)
.enablePushProvisioning(...)
.menuItems(...)
unCardComponent = UnitComponentsSdk.manager.ui.views.getCardComponent(
cardId = YOUR_CARD_ID,
additionalSettings = additionalSettings,
theme = YOUR_THEME_URL,
language = YOUR_LANGUAGE_URL
)
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 Steps to support Google Pay - Google Pay Prerequirements:
- Step 1 (UX/branding review) with screenshots that you can get from Unit.
- Step 2 (Push Provisioning API access).
Steps to integrate with the Visa SDK
Complete the following steps at integration steps:
- Prerequirements.
- Add VDE (Visa Digital Enablement) SDK to your project (steps 1,2 and 3).
Add to Wallet flow
You can find an overview of the add to wallet flow in this link.
Create a Kotlin
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 android.content.Context
import androidx.lifecycle.ProcessLifecycleOwner
import co.unit.un_components.common.interfaces.UNVisaProviding
import co.unit.un_components.common.models.card.addToWallet.*
import com.visa.mobileEnablement.inAppCore.VisaInAppConfig
import com.visa.mobileEnablement.inAppCore.VisaInAppCore
import com.visa.mobileEnablement.inAppCore.VisaInAppCoreApplicationObserver
import com.visa.mobileEnablement.inAppCore.VisaInAppEnvironment
import com.visa.mobileEnablement.pushProvisioning.*
class UNVisaProvider(appId: String, env: VisaInAppEnvironment, context: Context):
UNVisaProviding, VisaPushProvisioningListener {
private var applicationContext: Context
private var pushProvisioningInterface: VisaPushProvisioningInterface? = null
private var launchInitializeCallback: ((signedNonce: UNVPResult<String>) -> Unit)? = null
private var launchGetWalletsCallback: ((wallets: UNVPResult<List<UNVisaWallet>>) -> Unit)? = null
private var launchStartCardProvisioningCallback: ((result: UNVPResult<UNVisaProvisionStatus>) -> Unit)? = null
init {
/* Configure Visa's SDK */
applicationContext = context.applicationContext
val visaInAppConfig = VisaInAppConfig(env, appId)
VisaInAppCore.configure(applicationContext, visaInAppConfig)
ProcessLifecycleOwner.get().lifecycle.addObserver(VisaInAppCoreApplicationObserver())
}
override fun launchInitialize(
launchInitializeCallback: (signedNonce: UNVPResult<String>) -> Unit,
) {
this.launchInitializeCallback = launchInitializeCallback
/* Initialize Visa's SDK */
pushProvisioningInterface = VisaPushProvisioningInterfaceFactory
.createPushProvisioningInterface(this)
pushProvisioningInterface?.initialize()
}
override fun launchGetWallets(
encPayload: String,
launchGetWalletsCallback: (wallets: UNVPResult<List<UNVisaWallet>>) -> Unit
) {
this.launchGetWalletsCallback = launchGetWalletsCallback
/* Get Wallets using Visa's SDK */
val supportedWalletsRequest = VPSupportedWalletRequest(encPayload)
pushProvisioningInterface?.getSupportedWallets(supportedWalletsRequest)
}
override fun launchStartCardProvisioning(
walletCode: String,
walletName: String,
launchStartCardProvisioningCallback: (result: UNVPResult<UNVisaProvisionStatus>) -> Unit
) {
this.launchStartCardProvisioningCallback = launchStartCardProvisioningCallback
/* Start Card Provisioning */
val vpCardProvisioningRequest = VPCardProvisioningRequest(enumValueOf(walletCode), walletName)
pushProvisioningInterface?.startCardProvisioning(applicationContext, vpCardProvisioningRequest)
}
/* VisaPushProvisioningListener callbacks */
override fun initializationFailure(
pushProvisioningInterface: VisaPushProvisioningInterface,
error: VPError
) {
launchInitializeCallback?.let {
it(UNVPResult.Error(UNVPError(error.code, error.description, error.type.toUNVPErrorType(), error.correlationId)))
}
}
override fun initializationSuccess(
pushProvisioningInterface: VisaPushProvisioningInterface,
response: VPInitResponse
) {
launchInitializeCallback?.let {
it(UNVPResult.Success(response.signedNonce))
}
}
override fun supportedWalletFailure(
pushProvisioningInterface: VisaPushProvisioningInterface,
error: VPError
) {
launchGetWalletsCallback?.let {
it(UNVPResult.Error(UNVPError(error.code, error.description, error.type.toUNVPErrorType(), error.correlationId)))
}
}
override fun supportedWalletSuccess(
pushProvisioningInterface: VisaPushProvisioningInterface,
response: VPSupportedWalletResponse
) {
launchGetWalletsCallback?.let {
it(UNVPResult.Success(response.wallets.map { it.toUNVPSupportedWallet() }))
}
}
override fun cardProvisioningFailure(
pushProvisioningInterface: VisaPushProvisioningInterface,
error: VPError
) {
launchStartCardProvisioningCallback?.let {
it(UNVPResult.Error(UNVPError(error.code, error.description, error.type.toUNVPErrorType(), error.correlationId)))
}
}
override fun cardProvisioningSuccess(
pushProvisioningInterface: VisaPushProvisioningInterface,
response: VPCardProvisioningResponse
) {
launchStartCardProvisioningCallback?.let {
it(UNVPResult.Success(response.walletStatus.toUNVPProvisionStatus()))
}
}
}
fun VPErrorType.toUNVPErrorType(): UNVPErrorType {
return when(this) {
VPErrorType.EmptyAppId -> UNVPErrorType.EmptyAppId
VPErrorType.DeviceAuthenticationFailed -> UNVPErrorType.DeviceAuthenticationFailed
VPErrorType.DeviceRootDetection -> UNVPErrorType.DeviceRootDetection
VPErrorType.HookDetection -> UNVPErrorType.HookDetection
VPErrorType.PlayIntegrityCheckFailed -> UNVPErrorType.PlayIntegrityCheckFailed
VPErrorType.EmptyEncryptedPayload -> UNVPErrorType.EmptyEncryptedPayload
VPErrorType.NoWallets -> UNVPErrorType.NoWallets
VPErrorType.InvalidCardId -> UNVPErrorType.InvalidCardId
VPErrorType.ProvisioningNotAllowed -> UNVPErrorType.ProvisioningNotAllowed
VPErrorType.CancelledByUser -> UNVPErrorType.CancelledByUser
VPErrorType.GoogleWalletCreationFailed -> UNVPErrorType.GoogleWalletCreationFailed
VPErrorType.UnknownErrorOccured -> UNVPErrorType.UnknownErrorOccured
VPErrorType.WalletProvisioningInconclusive -> UNVPErrorType.WalletProvisioningInconclusive
VPErrorType.WalletProvisioningError -> UNVPErrorType.WalletProvisioningError
VPErrorType.NetworkFailure -> UNVPErrorType.NetworkFailure
VPErrorType.SessionExpired -> UNVPErrorType.SessionExpired
VPErrorType.InvalidInfo -> UNVPErrorType.InvalidInfo
VPErrorType.PayloadDecryptionFailed -> UNVPErrorType.PayloadDecryptionFailed
VPErrorType.ApiError -> UNVPErrorType.ApiError
VPErrorType.InvalidNonce -> UNVPErrorType.InvalidNonce
VPErrorType.SDKLockout -> UNVPErrorType.SDKLockout
VPErrorType.NoBrowserFound -> UNVPErrorType.NoBrowserFound
VPErrorType.TLCMFeatureNotSupported -> UNVPErrorType.TLCMFeatureNotSupported
VPErrorType.TLCMUnsupportedWallet -> UNVPErrorType.TLCMUnsupportedWallet
VPErrorType.TLCMDetailsNotFoundInPaySdk -> UNVPErrorType.TLCMDetailsNotFoundInPaySdk
VPErrorType.TLCMTokenStatusExists -> UNVPErrorType.TLCMTokenStatusExists
VPErrorType.TLCMInvalidOperationInput -> UNVPErrorType.TLCMInvalidOperationInput
VPErrorType.TLCMInvalidRequest -> UNVPErrorType.TLCMInvalidRequest
VPErrorType.TLCMUpdateStatusNotAllowed -> UNVPErrorType.TLCMUpdateStatusNotAllowed
VPErrorType.TLCMTokenNotFound -> UNVPErrorType.TLCMTokenNotFound
VPErrorType.VerificationNotAllowed -> UNVPErrorType.VerificationNotAllowed
VPErrorType.PaymentMethodRemoved -> UNVPErrorType.PaymentMethodRemoved
VPErrorType.SdkInternalError -> UNVPErrorType.SdkInternalError
}
}
fun VPSupportedWallet.toUNVPSupportedWallet(): UNVisaWallet {
return UNVisaWallet(
code = this.code.toUNVisaSupportedWalletCode(),
name = this.name,
reason = this.reason?.reason,
status = this.status.toUNVPProvisionStatus()
)
}
fun VPSupportedWalletCode.toUNVisaSupportedWalletCode(): UNVisaSupportedWalletCode {
return when(this) {
VPSupportedWalletCode.GooglePayPushProvision -> UNVisaSupportedWalletCode.GooglePayPushProvision
VPSupportedWalletCode.SamsungPayPushProvision -> UNVisaSupportedWalletCode.SamsungPayPushProvision
VPSupportedWalletCode.VCEHPushProvision -> UNVisaSupportedWalletCode.VCEHPushProvision
}
}
fun VPProvisionStatus.toUNVPProvisionStatus(): UNVisaProvisionStatus {
return when(this) {
VPProvisionStatus.ReadyToProvision -> UNVisaProvisionStatus.ReadyToProvision
VPProvisionStatus.AlreadyProvisioned -> UNVisaProvisionStatus.AlreadyProvisioned
VPProvisionStatus.NotInstalled -> UNVisaProvisionStatus.NotInstalled
VPProvisionStatus.NotAvailable -> UNVisaProvisionStatus.NotAvailable
VPProvisionStatus.WalletSetupNotCompleted -> UNVisaProvisionStatus.WalletSetupNotCompleted
VPProvisionStatus.WalletAppUpdateAvailable -> UNVisaProvisionStatus.WalletAppUpdateAvailable
VPProvisionStatus.AlreadyProvisionedAndSetAsDefault -> UNVisaProvisionStatus.AlreadyProvisionedAndSetAsDefault
}
}
Set Unit SDK with the UNVisaProvider
Call UnitComponentsSdk.manager.services.setVisaProvider
with a UNVisaProvider
instance. It is recommended to call it in the onCreate
method of your main activity. You will need to make sure you're initializing the UnitComponentsSdk
with UNComponentsEnvironment.Production
environment prior to this step. Make sure you pass the UNVisaProvider
your Visa's App ID, VisaInAppEnvironment.Production
and your app's context
.
Example:
import com.visa.mobileEnablement.inAppCore.VisaInAppEnvironment
import co.unit.un_components.api.UnitComponentsSdk
import co.unit.un_components.common.models.UNComponentsEnvironment
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
UnitComponentsSdk.manager.services.setVisaProvider(UNVisaProvider(YOUR_APP_ID, VisaInAppEnvironment.Production, this))
...
}
}
After app development remaining steps
When you are done with the integration, complete the following steps.
Adding a card to Wallet with the Card Component
After completing the instructions to use this capability, 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.
val additionalSettings = UNCardViewSettingsBuilder()
...
.enablePushProvisioning(true)
...
Add card to wallet as a separate flow
After completing the instructions to use this flow, you can add a card to Google Wallet by calling the Unit SDK's startPushProvisioningFlow(context: Context, cardId: String)
method.
Example:
UnitComponentsSdk.manager.ui.flows.startPushProvisioning(context, YOUR_CARD_ID)
IOS SDK
Component name: UNCardComponent
Configuration parameters:
Name | Type | Required | Description |
---|---|---|---|
id | String | YES | A Unit card id. |
additionalSettings | UNCardViewSettingsProtocol | NO | Advanced optional settings. |
callbacks | UNCardComponentCallbacks | NO | Callbacks to interact with the Card component. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A 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:
Name | Type | Default Value | Description |
---|---|---|---|
hideActionsMenuButton | Bool | false | Hide the actions menu buttons. |
hideCardTitle | Bool | false | Hide the Card title |
hideSensitiveDataButton | Bool | false | Hide the Sensitive data ("Show details") button |
enablePushProvisioning | Bool | false | Enables Push Provisioning in case value is set to true. |
learnMoreUrl | String | "" | 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)
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:
- Request Apple Pay In-app provisioning entitlement.
- 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:
- Wallet Capability.
- In-App Provisioning entitlement.
- 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
}
...
}
Adding a card to Apple Wallet with the Card Component
After completing the instructions to use this capability, 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.
Add card to Apple Wallet as a separate flow
After completing the instructions to use this flow, 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)