Payment Instruments
Introduction
The Payment Instrument service streamlines the management of payment instruments by offering key functions such as adding, verifying, retrieving, and removing them. This service facilitates the development of secure and efficient payment workflows, giving users the tools to manage their financial operations smoothly and safely, while adapting to different financial needs.
Key Features
- Adding payment instruments to a user’s account, enabling them to deposit or withdraw funds.
- Verifying card instruments, enabling them to deposit funds.
- Simultaneously add and verify payment instruments, such as bank accounts, through third-party verification services.
- The Payment Instrument service ensures that all sensitive data related to payment instruments is stored securely in compliance with industry standards and regulations.
Prerequisites
Before integrating the Payment Instrument Service, ensure you have:
- A valid Paysafe account with appropriate permissions.
- Set up instructions for Paysafe SDK Android or iOS.
To get started, initialize the PaymentInstrumentService
in your app as shown below:
- Kotlin
- Swift
import com.paysafe.wallet.android.core.wallet.Wallet
val instrumentsService = Wallet.getInstance().getPaymentInstrumentService()
import PaysafeWallet
let instrumentsService = Wallet.instance.paymentInstrumentService
Adding Payment Instruments
The section explains how to add and manage different types of payment instruments, highlighting specific methods and how they apply to various instruments.
Card instruments
Cards are added to the system when a deposit is made using the Deposit Service. If your application doesn't meet PCI DSS level 1 compliance requirements, you can use the Card Deposit Service. This service offers a fully integrated PCI DSS compliant user interface that also simplifies the card addition process.
US Bank Accounts
US bank accounts are added and verified through the startVerification
method which ensures that the account is both securely verified and
seamlessly integrated into your application, enhancing the overall user experience.
This method creates a new verification session and returns an InstrumentVerification
object. It accepts two parameters: InstrumentType
and a returnUrl
,
which should deep link back to your application after the flow is completed.
Visual Overview: Payment Instrument Addition & Verification Process
Thе diagram illustrates the steps for adding and verifying US bank accounts, providing a clear overview of the process from start to finish.
- Kotlin
- Swift
Details about the InstrumentVerification
object are available here
.
val instrumentVerificationRequest = InstrumentVerificationRequest(
returnUrl = "myapp://verification-completed",
instrumentType = InstrumentType.US_BANK_ACCOUNT
)
try {
val instrumentVerification = instrumentsService.startVerification(instrumentVerificationRequest)
instrumentsService.openExternalVerificationFlow(requireActivity(), instrumentVerification)
} catch (exception: Exception) {
// Handle exception
}
Details about the InstrumentVerification
object are available here
.
let request = Wallet.InstrumentVerificationRequest(
returnUrl: "myapp://verification-completed",
instrumentType: .usBankAccount
)
instrumentsService.startVerification(request: request) { result in
switch result {
case .success(let instrumentVerification):
instrumentsService.openExternalVerificationFlow(instrumentVerification: instrumentVerification, completion: ...)
case .failure(let error):
// Handle error
}
}
In order to use startVerification
method you need to implement deep link handling, either with custom scheme or universal links.
After obtaining the session with startVerification
, you should call openExternalVerificationFlow
method to open the
instrument verification flow in the system browser. Upon flow completion, the browser will redirect the customer
to the provided deep link returnUrl
.
After the customer has been redirected back to the application via the provided deep link, use completeExternalVerificationFlow
method with
the return URL as parameter to verify the status and retrieve an instrument verification session.
- Kotlin
- Swift
val deepLinkUri: Uri = intent.data
try {
val instrumentVerification = instrumentService.completeExternalVerificationFlow(deepLinkUri)
} catch (exception: Exception) {
// Handle exception
}
guard let deepLinkUrl = URLContexts.first?.url else { return }
instrumentsService.completeExternalVerificationFlow(returnUrl: deepLinkUrl) { result in
switch result {
case .success(let status):
// Display instrument verification status
case .failure(let error):
// Handle error
}
}
Peruvian Bank Accounts (CCI)
To add a Peruvian bank account (CCI) for seamless withdrawals via Pago Efectivo, the add
method should be used.
- Kotlin
- Swift
val cciBankAccount = CciBankAccount(
accountNumber = "00232616269435820577",
accountType = AccountType.CHECKING
)
try {
val instrument = instrumentsService.add(paymentInstrument: cciBankAccount)
} catch (exception: Exception) {
// Handle exception
}
let cciBankAccount = Wallet.CciBankAccount(
accountNumber: "10239485761029384756",
accountType: .checking
)
instrumentsService.add(paymentInstrument: cciBankAccount) { result in
switch result {
case .success(let instrument):
// Handle the created CCI instrument
case .failure(let error):
// Handle error
}
}
Verifying an Instrument
Cards
Throughout the use of a card instrument, at certain points you will be required to verify it. The most common cases are when:
- Nearing the card's deposit limit.
- Reaching the card's deposit limit.
The way to detect that a card instrument requires verification is when the PaymentInstrument
has a status of VERIFICATION_REQUIRED
and we provide the following ways to verify it.
For a card verification to take place at least one successful deposit must be made and the VERIFICATION_REQUIRED
status must be present on the card instrument.
Verifying a Card Instrument
The PaymentInstrumentService
provides a verifyCard
method for card instrument verification which expects a CardVerificationRequest
object.
If a deposit above the limit threshold is made, an error indicating that the limit is exceeded will be returned. In that case you have to make at least one succesful deposit below the limit threshold.
- Kotlin
- Swift
try {
val verifyCardRequest = CardVerificationRequest(
verificationCode = "1234",
instrumentId = "123456",
verificationType = CardVerificationType.VERIFICATION_CODE
)
val instrumentVerifications = instrumentsService.verifyCard(verifyCardRequest)
} catch (exception: Exception) {
// Handle exception
}
let verifyCardRequest = Wallet.CardVerificationRequest(
verificationCode: "1234",
instrumentID: "123456",
verificationType: .verificationCode
)
instrumentsService.verifyCard(request: verifyCardRequest) { result in
switch result {
case .success(let instrumentVerification):
// Display instrument verification
case .failure(let error):
// Handle error
}
}
Verifying a Card Instrument Using Native Flow
- Android
- iOS
The PaymentInstrumentService
also provides a startCardVerificaion
convenience method that starts a native flow screen which handles verifying the card instrument and returns a CardVerificationViewControllerResult
object holding the result of the verification process.
Keep in mind that the native flow is designed to work with card instruments that have a VERIFICATION_REQUIRED
status.
- Android
- iOS
// Use screen for result with launcher to start the card verification flow
private val launcher = registerForActivityResult(OpenStartCardVerification()) {
when (it) {
is CardVerificationActivityResult.Completed -> handleCompleted()
is CardVerificationActivityResult.Failure -> handleFailure()
is CardVerificationActivityResult.Cancelled -> handleCanceleled()
}
}
val cardVerificationParameters = CardVerificationParameters("1234")
launcher.launch(cardVerificationParameters)
Alternatively you can use startActivityForResult
method:
// Start the card verification screen for result
paymentInstrumentService.startCardVerification(this , 100, cardVerificationParameters)
// Then, obtain the verification result in onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100 && data != null) {
val result = IntentCompat.getParcelableExtra(data, "EXTRA_CARD_VERIFICATION_RESULT", CardVerificationActivityResult::class.java)
when (result) {
is CardVerificationActivityResult.Completed -> handleCompleted()
is CardVerificationActivityResult.Failure -> handleFailure()
is CardVerificationActivityResult.Cancelled -> handleCanceleled()
else -> handleOtherError()
}
}
}
// A 'UIViewController' instance should be provided as the starting point for presenting the card verification flow.
let cardVerificationparameters = Wallet.CardVerificationParameters(insturmentID: "1234")
Wallet.instance.startCardVerificaion(
parameters: cardVerificationparameters,
viewController: someViewController,
completion: { cardVerificationViewControllerResult in
// Handle cardVerificationViewControllerResult
})
Helper methods
The PaymentInstrumentService
also provides a handful of methods to either inspect a card instrument's verification information or query the verification attempts made on the instrument.
- To inspect a card instrument's verification information you have to call the
getCardVerificationInformation
method on thePaymentInstrumentService
by passing the id of the card instrument.
- Kotlin
- Swift
try {
val instrumentVerificationInformation = instrumentsService.getCardVerificationInformation(instrumentID: "123456")
} catch (exception: Exception) {
// Handle exception
}
instrumentsService.getCardVerificationInformation(instrumentID: "123456") { result in
switch result {
case .success(let instrumentVerificationInformation):
// Display instrument verification information
case .failure(let error):
// Handle error
}
}
- To get all the verification attempts on a card instrument, you have to call the
getCardVerifications
on thePaymentInstrumentService
passing an optionalCardVerificationsParameters
object.
- Kotlin
- Swift
try {
val cardVerificationsParameters = Wallet.CardVerificationsParameters(
limit: 10,
offset: 10,
status: .completed,
instrumentID: "123456"
)
val cardVerificationList = instrumentsService.getCardVerifications(parameters: cardVerificationsParameters)
} catch (exception: Exception) {
// Handle exception
}
let cardVerificationsParameters = Wallet.CardVerificationsParameters(
limit: 10,
offset: 10,
status: .completed,
instrumentID: "123456"
)
instrumentsService.getCardVerifications(parameters: cardVerificationsParameters) { result in
switch result {
case .success(let cardVerificationList):
// Display card verification list
case .failure(let error):
// Handle error
}
}
- You could also get a single verification attempt on a card instrument by calling the
getSingleCardVerification
method on thePaymentInstrumentService
and passing averificationID
string parameter.
- Kotlin
- Swift
try {
val singleCardVerification = instrumentsService.getSingleCardVerification(verificationID: "123456")
} catch (exception: Exception) {
// Handle exception
}
instrumentsService.getSingleCardVerification(verificationID: "123456") { result in
switch result {
case .success(let singleCardVerification):
// Display single card verification
case .failure(let error):
// Handle error
}
}
Managing Instrument Verification Sessions
For instruments that require verification, like US bank accounts, additional methods are available to manage the process.
Get Instrument Verification Session
The startVerification
method
used to add US bank accounts returns an InstrumentVerification
object, which is required for the following method. The getVerification
method retrieves a previously created verification session using the session ID from the InstrumentVerification
object.
- Kotlin
- Swift
try {
val instrumentVerifications = instrumentsService.getVerification(instrumentVerification.id)
} catch (exception: Exception) {
// Handle exception
}
instrumentsService.getVerification(sessionId: instrumentVerification.id) { result in
switch result {
case .success(let instrumentVerification):
// Display instrument verification
case .failure(let error):
// Handle error
}
}
Get Instrument Verification Sessions
To retrieve a list of instrument verification sessions use getAllVerifications
method. null/nil
can be passed
instead of InstrumentVerificationParameters
object.
You can achieve pagination by combining the limit
and offset
filters. For instance, implementing
pagination with a page size of 10 results per page would involve configuring:
- Page 1: limit=10, offset=0
- Page 2: limit=10, offset=10
- Page 3: limit=10, offset=20
- Kotlin
- Swift
Details about the InstrumentVerificationParameters
object are available here
.
val instrumentVerificationParameters = InstrumentVerificationParameters(
limit = 10,
offset = 10,
sessionStatus = InstrumentVerificationStatus.ACTIVE
)
try {
val instrumentVerifications = instrumentsService.getAllVerifications(instrumentVerificationParameters)
} catch (exception: Exception) {
// Handle exception
}
Details about the InstrumentVerificationParameters
object are available here
.
let parameters = Wallet.InstrumentVerificationParameters(
limit: 10,
offset: 10,
sessionStatus: .active
)
instrumentsService.getAllVerifications(parameters: parameters) { result in
switch result {
case .success(let instrumentVerifications):
// Display instrument verifications
case .failure(let error):
// Handle error
}
}
Managing Payment Instruments
Regardless of how a payment instrument is added — whether through the add
method (e.g., Peruvian bank accounts), the Deposit Service (e.g., cards),
or the startVerification
method (e.g., US bank accounts) — the following methods are available for managing all payment instruments:
Get Payment Instrument
To fetch details about a specific payment instrument by its identifier and type, use the get
method:
- Kotlin
- Swift
val paymentInstrumentParameters = PaymentInstrumentParameters(
instrumentId = "123456",
instrumentType = InstrumentType.SEPA_BANK_ACCOUNT
)
try {
val instrument = instrumentsService.get(paymentInstrumentParameters)
} catch (exception: Exception) {
// Handle exception
}
let parameters = Wallet.PaymentInstrumentParameters(
instrumentId: "123456",
instrumentType: .sepaBankAccount
)
instrumentsService.get(parameters: parameters) { result in
switch result {
case .success(let instrument):
// Display instrument
case .failure(let error):
// Handle error
}
}
Get Payment Instruments
To retrieve a list of payment instruments use the getAll
method. PaymentInstrumentsParameters
is used to filter the response by instrument type using instrumentType
and by payment option using paymentOption
.
If there are no filters applied null/nil
can be passed instead of PaymentInstrumentsParameters
.
- Kotlin
- Swift
Details about the PaymentInstrumentsParameters
object are available here
.
val paymentInstrumentParameters = PaymentInstrumentsParameters(
instrumentType = InstrumentType.SEPA_BANK_ACCOUNT,
paymentOption = PaymentOption.BANK_TRANSFER
)
try {
val instruments = instrumentsService.getAll(paymentInstrumentParameters)
} catch (exception: Exception) {
// Handle exception
}
Details about the PaymentInstrumentsParameters
object are available here
.
let parameters = Wallet.PaymentInstrumentsParameters(
instrumentType: .usBankAccount,
paymentOption: .bankTransfer
)
instrumentsService.getAll(parameters: parameters) { result in
switch result {
case .success(let instruments):
// Display instruments
case .failure(let error):
// Handle error
}
}
Delete Single Payment Instrument
To remove a specific payment instrument, use the delete
method by providing its identifier and type:
- Kotlin
- Swift
val paymentInstrumentParameters = PaymentInstrumentParameters(
instrumentId = "123456",
instrumentType = InstrumentType.SEPA_BANK_ACCOUNT
)
try {
val instrument = instrumentsService.delete(paymentInstrumentParameters)
} catch (exception: Exception) {
// Handle exception
}
let parameters = Wallet.PaymentInstrumentParameters(
instrumentId: "123456",
instrumentType: .sepaBankAccount
)
instrumentsService.delete(parameters: parameters) { result in
switch result {
case .success(let instrument):
// Display deleted instrument
case .failure(let error):
// Handle error
}
}