Implementation
Implementation guide for Volt Mobile SDK
Setting the environment
In the Application class, you should set the environment you're running the app in – this will either be Sandbox for testing or Production to enable real bank payments to be made.
Example - sandbox
import io.volt.sdk.Volt
class App : Application() {
override fun onCreate() {
super.onCreate()
Volt.init(
environment = VoltEnvironment.Sandbox,
)
}
}Use VoltSDK.shared.setEnvironment(environment: VoltEnvironment) to set the environment you're running the SDK in – this will either be .sandbox for testing or .production to enable real bank payments to be made.
When using .sandbox no money exchange hands, so it can be safely used for testing. You can switch between .sandbox and .production in runtime, however keep in mind that payments are not shared between these modes. To check which environment SDK is using at the moment use VoltSDK.shared.getEnvironment().isSandbox flag.
For other requests that your app will have to send to Volt API use VoltSDK.shared.getEnvironment().host to obtain host part of the API URL. This way requests that you make will always use the same host as the SDK.
Example - sandbox
import SwiftUI
import VoltSDK
@main
struct VoltApp: App {
var body: some Scene {
WindowGroup {
ExampleApp()
.onAppear {
VoltSDK.shared.setEnvironment(environment: .sandbox)
}
}
}
}Checking for returning shopper
Endpoint that is responsible for checking if a shopper is a returning one or paying for the first time. The response will include saved banks if there are any, that a shopper has completed a transaction with before.
Location
Sandbox server, for making test payments:
GET https://api.sandbox.volt.io/linked-accounts
Production server:
GET https://api.volt.io/linked-accounts
Parameters
Prop
Type
If neither of required parameters is provided, then the endpoint will return 404 error.
Headers
X-Volt-Api-Version: string
Value:4
Example request
GET http://api.localhost/linked-accounts
curl "https://api.volt.io/linked-accounts?shopperReference=reference123" \
-H 'Accept: application/json' \
-H 'X-Volt-Api-Version: 4' \
-H 'Authorization: Bearer **token**' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{}'Example response
GET http://api.localhost/linked-accounts
[
{
"id": "2a80bcad-737b-42a8-91d7-0cfbce6d5351",
"name": "revolut",
"supportedCurrencies": [
"GBP"
],
"country": {
"id": "GB",
"name": "England"
},
"officialName": "Revolut",
"active": true,
"logo": "https://cdn.rc.volt.io/banks/logos/gb_revolut.png",
"icon": "https://cdn.rc.volt.io/banks/icons/default.png",
"agreements": {
"supports": false,
"hasActive": false
}
}
]Selecting a bank
If there is a bank returned from the /linked-accounts endpoint, bank selection can be skipped. If there is no bank
returned or the shopper doesn't want to use the previously-used bank, then a new bank selection will be required.
Request bank selection through the SDK, and wait for the selected bank.
Kotlin
import io.volt.sdk.Volt
val launcher = registerForActivityResult(
StartActivityForResult(),
::onBankSelected,
)
Volt.selectBank(
context: Context,
launcher: ActivityResultLauncher<Intent>,
customerId: String,
)
fun onBankSelected(activityResult: ActivityResult?) {
val bankData = Volt.getBankData(activityResult)
}Swift
import VoltSDK
private var voltSdk = VoltSDK.shared
voltSdk.selectBank(customerId: String) { bankModel in
print("Bank selection view ended")
print(bankModel)
}Changing the selected bank
For changing a bank, you should use the changeBank method. The only difference is that welcome screen will be omitted.
Request the change of bank process through the SDK, and wait for the selected bank.
Kotlin
import io.volt.sdk.Volt
val launcher = registerForActivityResult(
StartActivityForResult(),
::onBankSelected,
)
Volt.changeBank(
context: Context,
launcher: ActivityResultLauncher<Intent>,
customerId: String,
)
fun onBankSelected(activityResult: ActivityResult?) {
val bankData = Volt.getBankData(activityResult)
}Swift
import VoltSDK
private var voltSdk = VoltSDK.shared
voltSdk.changeBank(customerId: String) { bankModel in
print("Bank selection view ended")
print(bankModel)
}Creating a payment
After the shopper has selected a bank to proceed with their payment, you'll need to create a payment using the Volt API. For that create a request using following endpoint providing all the details needed to make a payment.
Location
Sandbox server, for making test payments:
POST https://api.sandbox.volt.io/payments
Production server:
POST https://api.volt.io/payments
Body
Prop
Type
Headers
X-Volt-Api-Version: string
Value:4X-Volt-Initiation-Channel: string
Value:mobileSdk
Example request
POST https://api.sandbox.volt.io/payments
curl -X "POST" "https://api.volt.io/payments" \
-H 'X-Volt-Api-Version: 4' \
-H 'Authorization: Bearer **token**' \
-H 'X-Volt-Initiation-Channel: mobileSdk' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"currencyCode": "GBP",
"amount": 1000,
"type": "GOODS",
"uniqueReference": "payment123",
"shopper": {
"firstName": "Johnny",
"reference": "reference123",
"lastName": "Shopper"
}
}'Responses
The payment request was validated, accepted and payment was created.
Prop
Type
We cannot accept the payload from the request, because the data is invalid or malformed. The response will contain description of the actual problem.
Your credentials were invalid. It may be that the token you've used has expired. Try authenticating with valid or updated credentials and retry the payment request.
Although your credentials are correct, your access to this section of the API has been disabled or limited. Subsequent requests to this endpoint (even with valid data) will not be processed.
Example response
POST https://api.sandbox.volt.io/payments
{
"id": "ec3a7819-6055-44b4-bc99-84411358c01f",
"checkoutUrl": "https://checkout.volt.io/ec3a7819-6055-44b4-bc99-84411358c01f?auth=**token**",
"token": "**JWTtoken**"
}Starting a payment request
Request the payment process with the updated token:
Kotlin
Volt.payWithSelectedBank(
fragmentManager: FragmentManager,
token: String,
)Swift
VStack(spacing: 44) {
//View content
}
.voltPaymentSheet(token: $viewModel.token)Agreements Clause
If the SDK's welcome screen is skipped (e.g., in a returning shopper flow), you must present the Agreements Clause to the shopper before initiating payment. To ensure accuracy and up-to-date content, you can retrieve the Agreements Clause text directly from the SDK, guaranteeing it always links to the correct documents.
Compose based project
import io.volt.sdk.Volt
Text(
text = Volt.getAgreementClauseAnnotated(urlColor = Color.Blue),
color = Color.Black,
textAlign = TextAlign.Center,
)View based project
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />import io.volt.sdk.Volt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
val textView: TextView = findViewById(R.id.textView)
textView.text = Volt.getAgreementClauseSpannable(this)
textView.movementMethod = LinkMovementMethod.getInstance();
}
}Swift
Text(VoltSDK.agreementClause)
.multilineTextAlignment(.center)Getting raw banks list
If you want to customize bank selection, and want to implement this view on your own, then you can fetch banks list directly from our API. For that use the following endpoint:
Location
Sandbox server, for making test payments:
GET https://api.sandbox.volt.io/checkout/banks/{customerId}/{countryCode}/{currencyCode}
Production server:
GET https://api.volt.io/payments/checkout/banks/{customerId}/{countryCode}/{currencyCode}
Parameters
Prop
Type
Headers
X-Volt-Api-Version: string
Value:4
Example request
GET http://api.localhost/checkout/banks/{customerId}/{countryCode}/{currencyCode}
curl --request GET \
--url http://api.localhost/checkout/banks/{customerId}/{countryCode}/{currencyCode} \
--header 'Accept: application/json'Responses
List of banks available for the provided conditions.
Prop
Type
A general response for not found resources.
Prop
Type
Example response
GET http://api.localhost/checkout/banks/{customerId}/{countryCode}/{currencyCode}
[
{
"id": "c7d6f1b0-5e78-4d45-921f-332859b13b63",
"name": "Chase",
"searchAdditional": "Chase",
"images": {
"logo": "https://cdn.volt.io/banks/icons/xx_chase_simplified.svg",
"icon": "https://cdn.volt.io/banks/icons/xx_chase_web.png"
},
"types": [
"PERSONAL",
"BUSINESS"
],
"active": false,
"deactivationReason": 1
}
]How is this guide?
Last updated on