Setting the environment

  • Android
  • iOS

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)
        }
    }
  }
}

The linked-accounts endpoint

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

  • currency: string
    Optional, if provided filter list to banks that support given currency.
    Example : EUR

  • shopperEmail: string
    Either the shopperReference or shopperEmail fields are required
    Example: shopper1234@company.com

  • shopperReference: string
    Either the shopperReference or shopperEmail fields are required
    Example: shopper1234

If either 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": [
      "EUR"
    ],
    "country": {
      "id": "DE",
      "name": "Germany"
    },
    "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.

  • Android
  • iOS
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.

  • Android
  • iOS
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

  • currencyCode: string = 3 characters
    Required. Currency in which the payment should be made, in ISO 4217 format (3 uppercase letters)
    Example: EUR

  • amount: integer <= 2147483647
    Required. The amount of the transaction in 1/100 units (pence, cents, etc)
    Example: 1000

  • type: string. Enum: BILLGOODSPERSON_TO_PERSONSERVICESOTHER
    Required. The transaction type (please select the most appropriate for your transaction)
    Example: GOODS

  • uniqueReference: string <= 18 characters
    Unique reference for the payment from the merchant, must contain only alphanumeric characters. Unique reference has to be unique for given account identifications (i.e. IBAN) of the beneficiary.
    Required if merchantInternalReference is not provided.
    Example: fj9f4j498hWFH32u4t5

  • merchantInternalReference: string <= 100 characters
    A field that can be used to identify the transaction in the merchant’s system, which can be used as longer alternative to the uniqueReference field. If this field contains a value, but uniqueReference is not provided, then payment unique reference will be automatically generated by Volt.
    Required if uniqueReference is not provided.
    Example: skjghHTTHi4hs48t9sl
    Match pattern: ^[a-zA-Z0-9\!\@\#\$\%\^\&\*\(\)\_\+\=\{\[\]\}\;\:\?\|\-]*$

  • shopper: object Shopper
    Required. A shopper object that corresponds to this payment
    Example: { "firstName": "Johnny", "lastName": "Shopper", "reference": "reference123" }

    • reference: string >= 3 characters, <= 256 characters
      Required. Identifier of the payer, cannot be the same as uniqueReference used in the payment
      Example: reference123
      Match pattern: ^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@?[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$

    • firstName: string
      Payer’s first name (required when lastName also provided)
      Example: Johnny

    • lastName: string
      Payer’s last name (required when firstName also provided)
      Example: Shopper

    • organisationName: string
      Payer’s organization name (required when firstName and lastName are not provided)
      Example: Company

Headers

  • X-Volt-Api-Version: string
    Value: 4
  • X-Volt-Initiation-Channelstring
    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": "EUR",
  "amount": 100,
  "type": "GOODS",
  "uniqueReference": "payment123",
  "shopper": {
    "firstName": "Johnny",
    "reference": "reference123",
    "lastName": "Shopper"
  }
}'

Responses

  • 201 Created. The payment request was validated, accepted and payment was created
    • id: string uuid
      ID of the created payment request 
    • checkoutUrl: string uri
      Redirect URL to the checkout 
    • token: string JWT token
      JWT token containing data about the created payment request 
  • 400 Bad request. We cannot accept the payload from the request, because the data is invalid or malformed. The response will contain description of the actual problem
  • 401 Access denied. 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
  • 403 Not authorized. 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:

  • Android
  • iOS
Kotlin
Volt.payWithSelectedBank(
	 fragmentManager: FragmentManager,
	 token: String,
)
Swift
VStack(spacing: 44) {
  //View content
}
.voltPaymentSheet(token: $viewModel.token)