Android SDK
#
InstallationAdd the following repository to the project settings.gradle
file inside dependencyResolutionManagement
repositories:
maven { url "https://nexus.i.unit.co/repository/maven/"}
Add the un-components dependency to your project:
dependencies { implementation 'co.unit:un-components:0.8.0'}
#
Usage#
Initialize Unit SDKCall UnitSdk.init
with your requested environment and your theme.
It is recommended to call it in onCreate
method of your main activity.
You may use the data class UNEnviorment
:
enum UNEnvironment { sandbox, production}
#
function inputs:Name | Type | Required | Description |
---|---|---|---|
env | UNEnvironment | YES | Unit environment. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
fonts | UNFonts | NO | UNFonts object that specifies your custom fonts. |
webVersioningStrategy | UNWebVersioningStrategy | NO | Web SDK version management strategy. |
#
Example:import androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport co.unit.un_components.common.models.UNEnvironmentimport co.unit.un_components.api.UnitSdk
const val THEME = "<your json styles url>"const val LANGUAGE = "<your json language settings url>"
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) UnitSdk.init(UNEnvironment.Sandbox, THEME, LANGUAGE) }}
#
Fonts#
Add the Font File to Your Project- Locate the
.ttf
or.otf
font file you wish to add. - Add them to your
res/font
folder in your Android Studio project. Create the font folder if it doesn't exist. - Add them to your
assets/fonts
folder.
arial_regular.ttf
.#
Note: Android supports only alphanumeric characters and underscores in file names. Therefore, your custom font file name should adhere to this convention and may look like typealias UNFonts
as shown below:#
Now, You can configure custom fonts in your application by utilizing the typealias UNFonts = Map<UNFontFamilyName, Array<UNFontData>>typealias UNFontFamilyName = String
In this map, 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.
UNFontData
Properties#
Name | Type | Description |
---|---|---|
fontResId | Int | The resource id of the font |
fontWeight | FontWeight | Enum that defines the weight of the font. |
sources | [UNFontSource] | An array of UNFontSource objects. An array is used to provide fallback options. |
#
Note:It is imperative to recognize that the fontResId
should be designated as the primary font to be utilized by our SDK. The array of font sources primarily serves to offer fallback options in scenarios involving WebView usage.
UNFontSource
Properties#
Name | Type | Description |
---|---|---|
fileRelativePath | String | The custom font file relative path from the project assets directory. |
format | String? | (Optional) Font file format. Useful for specifying fallback behavior. |
#
Kotlin Code Exampleprivate val fonts: UNFonts = mapOf( "Lugrasimo" to arrayOf( UNFontData( fontResId = R.font.lugrasimo_regular, sources = listOf(UNFontSource(fileRelativePath = "fonts/lugrasimo/lugrasimo_regular.ttf")), fontWeight = FontWeight.Regular, ), UNFontData( fontResId = R.font.lugrasimo_bold, sources = listOf(UNFontSource(fileRelativePath = "fonts/lugrasimo/lugrasimo_bold.ttf")), fontWeight = FontWeight.Bold, ), ), "Arial" to arrayOf( UNFontData( fontResId = R.font.arial_regular, sources = listOf(UNFontSource(fileRelativePath = "fonts/arial/arial_regular.ttf")), fontWeight = FontWeight.Regular, ) ))
#
Web SDK Versioning Strategy GuideIt'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 sealed class UNWebVersioningStrategy
. Below are the options you can select from:
Exact Versioning -
data class Exact(val major: Int, val minor: Int, val patch: Int)
- This method allows you to lock onto a specific version that suits your needs.
Up to Next Minor -
data class UpToNextMinor(val major: Int, val minor: Int)
- 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.
Up to Next Major -
data class UpToNextMajor(val major: Int)
- 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.
val myWebVersioningStrategy = UNWebVersioningStrategy.UpToNextMinor(1, 2)
For the latest SDK, the latest webVersioningStrategy is upToNextMinor(major: 1, minor: 3)
.
#
ComponentsTo use a component you may call it constructor with your current context: SomeUNComponent(context)
.
Then, configure the component parameters.
#
Card View#
Component name: UNCardView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
cardId | String | YES | Unit card id. |
customerToken | String | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
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. |
onLoad | (onLoadResult: Result<UNCardData>) => Void | NO | Callback Occurs after a component is loaded. |
onStatusChanged | (card: UNCardData) => Void | NO | Callback for card status changes. |
onCardActivated | (card: UNCardData) => Void | NO | Callback for card activated. |
enablePushProvisioning | Boolean | NO | Enables Push Provisioning in case value is true. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.LinearLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.components.UNCardViewimport co.unit.un_components.common.models.UNCardData
class CardFragment : Fragment(){ override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unCardComponent = this.context?.let { UNCardView(it) } unCardComponent?.configure( YOUR_CARD_ID, YOUR_CUSTOMER_TOKEN, THEME, onStatusChanged = ::onStatusChanged, onLoad = ::cardUnitOnLoad, onCardActivated = ::onCardActivated )
yourView.addView(unCardComponent)
// ... }
private fun onStatusChanged(card: UNCardData) { println("Card Status is changed. New card data: $card") }
private fun cardUnitOnLoad(onLoadResult: Result<UNCardData>) { if(onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }
private fun onCardActivated(card: UNCardData) { println("Card is activated. Card-data: $card") }}
#
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()
#
Adding a card to Google Wallet (Optional)Start by following the Add card to wallet instructions to use this capability.
After that, Pass the enablePushProvisioning
parameter To the Card Component with the value of true
.
Then, you can add a card to Google Wallet using the "Manage Google Wallet" tab in the Card Components's native menu or using an UNCardMenuAction.AddToWallet
Incoming event.
#
Book Payment View#
Component name: UNBookPaymentView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | YES | Unit account id. The account from which money is being sent. |
customerToken | String | YES | A Unit Customer token. |
counterPartyAccountId | String | YES | Unit account id. The account which will receive money. |
counterPartyName | String | YES | Name of the counterparty. This is the name that will be displayed in the Book Payment UI during the transfer. |
isSameCustomer | Boolean | NO | Stating whether both accounts belong to the same customer. Allows fetching additional information about the counterparty account. Default false |
isAutoFocus | Boolean | NO | Auto-focus the money input field once the component is mounted. Default false |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
onPaymentCreated | (data: UNBookPaymentData) => Void | NO | Callback for the created bookPayment. |
onLoad | (onLoadResult: Result<UNAccountData>) => Void | NO | Callback Occurs after a component is loaded. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.components.UNBookPaymentView
class BookPaymentFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unBookPaymentView = this.context?.let { UNBookPaymentView(it) } unBookPaymentView?.configure( ACCOUNT_ID, CUSTOMER_TOKEN, COUNTER_PARTY_ACCOUNT_ID, COUNTER_PARTY_NAME, IS_SAME_CUSTOMER, THEME, onPaymentCreated = ::onPaymentCreated, onLoad = ::bookPaymentUnitOnLoad
)
yourView.addView(unBookPaymentView)
// ... } private fun onPaymentCreated(data: UNBookPaymentData) { println("[Book Payment Component] paymentCreatedResponse: $data") }
private fun bookPaymentUnitOnLoad(onLoadResult: Result<UNAccountData>) { if(onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }
#
Activity View#
Component name: UNActivityView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | NO | Unit account id. The account from which money is being sent. |
customerToken | String | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
paginationType | UNActivityComponentPaginationType | NO | Defines the method by which additional content is loaded. Possible values: .InfiniteScroll (default), .Pagination |
transactionsPerPage | Int | NO | Number of transactions to fetch on each page or scroll to bottom. Also acts as initial number of transactions to fetch. The default is 8 for pagination and 15 for infinite scroll |
hideFilterButton | Boolean | NO | Hide filter button in case value is true. |
onLoad | (onLoadResult: Result<UNActivityOnLoadResponse>) => Void | NO | Callback Occurs after a component is loaded. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.components.UNActivityView
class ActivityFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unActivityView = this.context?.let { UNActivityView(it) } unActivityView?.configure( ACCOUNT_ID, CUSTOMER_TOKEN, THEME, onLoad = ::activityUnitOnLoad )
yourView.addView(unActivityView)
// ... }
private fun activityUnitOnLoad(onLoadResult: Result<UNActivityOnLoadResponse>) { if (onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }
#
Account View#
Component name: UNAccountView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | NO | Unit account id. The account to show, when not provided, one of the customer's accounts will be shown. |
customerToken | String | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
onLoad | (onLoadResult: Result<List<UNAccountData>>) => Void | NO | Callback Occurs after a component is loaded. |
onAccountChanged | (account: UNAccountData) => Void | No | Callback for account changes. |
hideActionsMenuButton | Boolean | NO | Hide actions menu button in case value is true. |
hideSelectionMenuButton | Boolean | NO | Hide selection menu button in case value is true. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.components.UNAccountViewimport co.unit.un_components.common.models.UNAccountData
class AccountFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unAccountView = this.context?.let { UNAccountView(it) } unAccountView?.configure( ACCOUNT_ID, CUSTOMER_TOKEN, THEME, onLoad = ::accountUnitOnLoad, onAccountChanged =:: handleAccountChange
)
yourView.addView(unAccountView)
// ... }
private fun accountUnitOnLoad(onLoadResult: Result<List<UNAccountData>>) { if(onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }
private fun handleAccountChange(account: UNAccountData) { print("Account Change: $account") }}
#
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 menu bottom-sheet from a custom button.
Important Note: one can use the openActionsMenu()
only after UNAccountComponent
is loaded.
#
Example:unAccountComponent.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:import co.unit.un_components.common.models.Account.UNAccountMenuAction
// .......
unAccountComponent.openAction(UNAccountMenuAction.OpenAccountDetails)
#
Check Deposit View#
Component name: UNCheckDepositView#
Prerequirements:To enable check scanning with our SDK, please request the camera permissions in your application manifest.
<uses-permission android:name="android.permission.CAMERA" />
#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | YES | Unit account id. The account from which money is being sent. |
fee | Double | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
onDepositCreated | (depositCheckData: UNCheckDeposit) => Void | NO | Occurs when a check deposit is successfully created |
onRestartRequest | (depositCheckData: UNCheckDeposit) => Void | NO | Occurs when "Deposit another check" is clicked |
onLoad | (onLoadResult: Result<UNAccountData>) => Void | NO | Callback Occurs after a component is loaded. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.components.UNCheckDepositView
class CheckDepositFragment : Fragment() {
private var unCheckDepositView: UNCheckDepositView? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
unCheckDepositView = this.context?.let { UNCheckDepositView(it) } unCheckDepositView?.configure( accountId = "424242", fee = 1.5, customerToken = "<Your customer token>", onDepositCreated = { checkData: UNCheckDepositData -> println("Check Deposit Created. Check ID: ${checkData.id}") }, onRestartRequest = { checkData: UNCheckDepositData -> println("Check Deposit Restart Request. Check ID: ${checkData.id}") }, onLoad = { onLoadResult: Result<UNAccountData> -> handleUnitOnLoad(onLoadResult) } )
val fragmentLayout = inflater.inflate(R.layout.fragment_check_deposit, container, false) fragmentLayout.findViewById<FrameLayout>(R.id.check_deposit_container).addView(unCheckDepositView)
return fragmentLayout }}
#
ACH Debit Payment View#
PrerequirementsThis 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
#
Register your app id in Plaid's dashboardBy doing this Plaid will be able to redirect the user back to your app.
- Sign in to the Plaid Dashboard and go to the Team Settings -> API page.
- Next to Allowed Android Package Names click Configure then Add New Android Package Name.
- Enter your package name, for example com.plaid.example.
- Click Save Changes.
#
Using plaid in your app- declare a variable to act as your activity result launcher.
private var linkAccountToPlaid: ActivityResultLauncher<LinkTokenConfiguration>? = null
- Implement the configure parameter
openPlaid
, which is required. When you attempt to add a new account, it will be triggered, opening the Plaid Link Activity.
private fun openPlaid(linkTokenConfiguration: LinkTokenConfiguration) { linkAccountToPlaid?.launch(linkTokenConfiguration)}
- You need to sign up for the
OpenPlaidLink()
contract in youronCreate
method. Once you have a result, you should submit it to theonPlaidLink(result: LinkResult)
method located inside theUNACHDebitView
.
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) linkAccountToPlaid = registerForActivityResult(OpenPlaidLink()) { unACHDebitView?.onPlaidLink(it) }}
#
Component name: UNACHDebitView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | YES | Unit account id. The account from which money is being sent. |
customerToken | String | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
fee | Double | NO | Bill your counterparty for his activity. |
isAutoFocus | Boolean | NO | Auto-focus the 'add new recipient' button once the component is mounted. Default "false" |
sameDay | Boolean | NO | Enables Same Day ACH |
onPaymentCreated | (data: UNACHData) => Void | NO | Callback for the created ACH payment. |
openPlaid | (linkTokenConfiguration: LinkTokenConfiguration) => Void | YES | Callback Occurs when the Plaid Activity should open |
onLoad | (onLoadResult: Result<UNACHDebitOnLoadResponse>) => Void | NO | Callback Occurs after a component is loaded. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.common.models.UNACHDataimport co.unit.un_components.components.UNACHDebitViewimport constants.*import com.plaid.link.OpenPlaidLinkimport com.plaid.link.configuration.LinkTokenConfiguration
class ACHDebitFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unACHDebitView = this.context?.let { UNACHDebitView(it) } private var linkAccountToPlaid: ActivityResultLauncher<LinkTokenConfiguration>? = null
unACHDebitView?.configure( ACCOUNT_ID, CUSTOMER_TOKEN, FEE, IS_AUTO_FOCUS, onPaymentCreated = ::onPaymentCreated, openPlaid = ::openPlaid, onLoad = ::achDebitUnitOnLoad )
yourView.addView(unACHDebitView)
// ... }
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) linkAccountToPlaid = registerForActivityResult(OpenPlaidLink()) { unACHDebitView?.onPlaidLink(it) } }
private fun openPlaid(linkTokenConfiguration: LinkTokenConfiguration) { linkAccountToPlaid?.launch(linkTokenConfiguration) }
private fun onPaymentCreated(data: UNACHData) { println("[ACH Debit Component] paymentCreatedResponse: $data") }
private fun achDebitUnitOnLoad(onLoadResult: Result<UNACHDebitOnLoadResponse>) { if(onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }}
#
ACH Credit Payment View#
Prerequirements:If you wish to use plaid in this component, please follow the pre-requisites of [ACHDebitComponent]{https://guides.unit.co/android-sdk#ach-debit-component}.
#
Component name: UNACHCreditView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
accountId | String | YES | Unit account id. The account from which money is being sent. |
customerToken | String | YES | A Unit Customer token. |
theme | String | NO | A URL that specifies the UI configuration. |
language | String | NO | A URL that specifies the language configuration. |
fee | Double | NO | Bill your counterparty for his activity. |
isAutoFocus | Boolean | NO | Auto-focus the 'add new recipient' button once the component is mounted. Default "false" |
sameDay | Boolean | NO | Enables Same Day ACH |
onPaymentCreated | (data: UNACHData) => Void | NO | Callback for the created ACH payment. |
openPlaid | (linkTokenConfiguration: LinkTokenConfiguration) => Void | NO | Callback Occurs when the Plaid Activity should open |
onLoad | (onLoadResult: Result<UNACHCreditOnLoadResponse>) => Void | NO | Callback Occurs after a component is loaded. |
#
Example:import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.common.models.UNACHDataimport co.unit.un_components.components.UNACHCreditViewimport constants.*
class ACHCreditFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val unACHCreditView = this.context?.let { UNACHCreditView(it) } unACHCreditView?.configure( ACCOUNT_ID, CUSTOMER_TOKEN, FEE, IS_AUTO_FOCUS, onPaymentCreated = ::onPaymentCreated, onLoad = ::achCreditUnitOnLoad
)
yourView.addView(unACHCreditView)
// ... }
private fun onPaymentCreated(data: UNACHData) { println("[ACH Credit Component] paymentCreatedResponse: $data") }
private fun achCreditUnitOnLoad(onLoadResult: Result<UNACHCreditOnLoadResponse>) { if(onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }}
#
Multiple Cards View#
Component name: UNMultipleCardsView#
configure parameters:Name | Type | Required | Description |
---|---|---|---|
customerToken | String | YES | A Unit Customer token. |
language | String | NO | A URL that specifies the language configuration. |
theme | String | NO | A URL that specifies the UI configuration. |
paginationType | UNMultipleCardsComponentPaginationType | NO | Defines how more content is loaded. Possible values: .InfiniteScroll (default), .Pagination |
cardsPerPage | Int | NO | Number of cards to fetch on each page or scroll to bottom. Also acts as initial number of cards to fetch. The default is 8 for pagination and 15 for infinite scroll |
disableCardClick | Boolean | NO | When true, will not publish a unitMultipleCardsCardClicked event when a row is clicked. Possible values: true / false (default) |
queryFilter | String | NO | Query for filtering cards: Cards |
hideTitle | Boolean | NO | Hide the component title in case value is 'true'. Possible values: true / false (default) |
onLoad | (onLoadResult: Result<List<UNCardData>>) => Void | NO | Callback Occurs after a component is loaded. |
onCardClicked | (card: UNCardData) => Void | NO | Callback Occurs when a card row is clicked |
#
Example:
import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.FrameLayoutimport androidx.fragment.app.Fragmentimport co.unit.un_components.common.models.UNErrorimport co.unit.un_components.common.models.multipleCards.UNMultipleCardsComponentPaginationTypeimport co.unit.un_components.components.UNMultipleCardsView
class MultipleCardsFragment : Fragment() { private var unMultipleCardsView: UNMultipleCardsView? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View? { unMultipleCardsView = this.context?.let { UNMultipleCardsView(it) } unMultipleCardsView?.configure( customerToken = CUSTOMER_TOKEN, onLoad = ::multipleCardsUnitOnLoad, paginationType = UNMultipleCardsComponentPaginationType.Pagination, )
yourView.addView(unMultipleCardsView)
// ... }
private fun multipleCardsUnitOnLoad(onLoadResult: Result<List<UNCardData>>) { if (onLoadResult.isSuccess) { println(onLoadResult.getOrNull()) } else { when (val exception = onLoadResult.exceptionOrNull()) { is UNError.OnLoad -> { println(exception) } } } }}
#
Flows#
Add card to wallet flowStart by following the Add card to wallet instructions to use this flow.
After that, you can add a card to Google Wallet by calling the Unit SDK's startPushProvisioningFlow(context: Context, cardId: String, customerToken: String)
method.
#
Example:...import co.unit.un_components.api.UnitSdk...
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... UnitSdk.ui.flows.startPushProvisioning(context, YOUR_CARD_ID, YOUR_CUSTOMER_TOKEN) ... }}
#
Additional Capabilities#
Add card to walletThis capability can be used with the Card Component or without it, as a separate flow.
#
PrerequirementsComplete 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 SDKComplete the following steps at integration steps:
- Prerequirements.
- Add VDE (Visa Digital Enablement) SDK to your project (steps 1,2 and 3).
#
Add to Wallet flowYou 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.Contextimport androidx.lifecycle.ProcessLifecycleOwnerimport co.unit.un_components.common.interfaces.UNVisaProvidingimport co.unit.un_components.common.models.card.addToWallet.*import com.visa.mobileEnablement.inAppCore.VisaInAppConfigimport com.visa.mobileEnablement.inAppCore.VisaInAppCoreimport com.visa.mobileEnablement.inAppCore.VisaInAppCoreApplicationObserverimport com.visa.mobileEnablement.inAppCore.VisaInAppEnvironmentimport 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 }}
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 UNVisaProviderCall UnitSdk.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 UnitSdk
with UNEnvironment.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.VisaInAppEnvironmentimport co.unit.un_components.api.UnitSdkimport co.unit.un_components.common.models.UNEnvironmentimport androidx.appcompat.app.AppCompatActivityimport android.os.Bundle
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... UnitSdk.setVisaProvider(UNVisaProvider(YOUR_APP_ID, VisaInAppEnvironment.Production, this)) ... }}
#
After app development remaining stepsWhen you are done with the integration, complete the following steps.
#
Error HandlingBy using unitOnLoad callback you can get a result of type Kotlin.Result for the requested component. On error - you will get a sealed class UNError that consist of several cases.
#
UNError:Case | fields | Description |
---|---|---|
OnLoad | errors: ArrayList<UNErrorResponseObject> | Report UNErrorResponse on errors that happen during loading time |
#
UNErrorResponseObject:Name | Type | Description |
---|---|---|
status | String | A Unit-specific code, uniquely identifying the error type. |
title | String | The title of the error type. |
detail | String? | Additional information about the error. |
details | String? | Additional information about the error. |
meta | Any? | Identifier to be used for further investigation. |
Note: An UNErrorResponseObject
MUST contain a title and the HTTP status code members.