Payments
Integrate Volume SDK
React Native
Get Started

Quick Start

Let's get started with Volume in less than 5 minutes.

React Native component for Volume is a thin wrapper that allows you to display Volume Transparent checkout and start accepting payments from your customers in zero time into any React Native app.

Getting Started

Get started by installing the required dependencies:

💡

@react-native-async-storage/async-storage is a native dependency that we use to persist your customers last used payment method to device storage. This is to enhance the user experience by not requiring them to select the payment method again on subsequent payments.

npm install @getvolume/react-native @react-native-async-storage/async-storage

Volume Provider

The volume provider should be placed at the root level of your application, this provides key global configuration for using volume in your application.

export default function App() {
  return (
    <VolumeProvider
      applicationId="123456789"
      volumeEnvironment="sandbox"
      onEvent={handleEvent}
    >
      <App />
    </VolumeProvider>
  )
}

Props

Full reference documentation on the VolumeProvider props can be found here: VolumeProvider

Expand the section below for a quick glance at what you need to know.

VolumeProvider props

Required Props

keytypeexampledescription
applicationIdstring123456789Your Application Id as provided in your Merchant Portal. (For BETA merchants please contact us directly for your ID.)
volumeEnvironmentstringsandboxEnvironement to be used, this is either 'live' | 'sandbox' | A full URI if we have provided a specific environment for you.

Optional Props

keytypeexampledescription
onEventfunctionEventsEvent handler function, see Events for detailed instructions on how this works
showWebBanksbooleantrueIn addition to the banks installed on the device, with this flag set to true, modelo-sandbox and natwest-sandbox are available for selction. Paying with these banks will redirect to the in device browser.
featureFlagsFeatureFlags{flagName:true,flag2Name:false}Object of keys with boolean values.
minPaymentAmountnumber0.01 (default: 0.01)Minimum value the amount key in paymentMeta prop of the <Volume/> component, when supplying a value smaller than this, a PAYMENT_AMOUNT_TOO_SMALL event will be emitted and the payment will not reach the volume api.
maxPaymentAmountnumber15000 (default: 15000)Maximum value the amount key in paymentMeta prop of the <Volume/> component, when supplying a value larger than this, a PAYMENT_AMOUNT_TOO_LARGE event will be emitted and the payment will not reach the volume api.
buttonTextstringPlace depositOverride the payment button text (default: "Pay with")
buttonCustomisationstring{headingFontSizePx:20}Tweak the look and feel of the Volume button, properties to make changes to the colous, text, and border of the button. Each property has a typescript docstring comment to explain its output and the default value
💡

For more information on Events with onEvent. Check out Events.

The Volume Button

Once you have added the VolumeProvider, all you need to do is add the Volume component to your app!

Available countries

CountryCountry codeCurrency
United KingdomGBGBP
GermanyDEEUR
FranceFREUR
NetherlandsNLEUR
SpainESEUR
BelgiumBEEUR

The Volume button accepts following props:

paymentMeta provides the details for the current payment
keytypeconstraintsexampledescription
amountnumberMin 0.01, up to 2 decimal places1Amount to be paid, ie £1.00.
currencystringISO 4217GBPCurrency of payment
referencestringMax 18 chars, AlphanumericABC-123Pass a bank transfer reference, it will be visible by both a client and merchant in bank transfer history.
countrystringISO 3166-1 alpha-2GBCountry of origin of the payment.
merchantPaymentIdstring (Optional)Max 50 chars, unique per payment123456Pass a merchantPaymentId to associate a unique identifier for the payment, this will be returned to you in any webhook or api responses for the given payment
metadatajson object (Optional)Max 5000 chars length after serialization to string{ "mydata": "myvalue" }metadata is an optional JSON object which will be passed back in webhooks as paymentMetadata. Detailed description below.
onButtonEventfunctionEvent handler function, see Events for detailed instructions on how this works
buttonContainerStyles allows you to provide custom styling

Regular Style prop as passed to RN component ie

<View style={{
    ...
}}/>

isButtonEnabled allows you to disable Volume button based on your own validation rules

If not provided the default value is set true

onButtonEvent callback function to handle button events

This is useful if you have multiple Volume components in your app and you want to handle events differently for each of them.

The callback function is passed a single object argument of the following shape

{
  type: "PAYMENT_INITIATED" | "PAYMENT_AUTHORIZED_SDP" | "PAYMENT_ERROR" | "GENERIC_ERROR" | "PAYMENT_AMOUNT_TOO_SMALL" | "PAYMENT_AMOUNT_TOO_LARGE",
  time: number,
  meta?: {
    merchantPaymentId?: string,
    error?: string,
  }
}

Use your IDE to explore the typescript types for the onButtonEvent callback function.

There is a docstring comment with more detail and an example implementation, similar to the one below.

export default function Product() {
  return (
    <>
      ...
      <View style={{ marginLeft: '10%' }}>
        <Text style={{ fontSize: 35 }}>Mens Nike Trainers</Text>
        <Text style={{ fontSize: 20 }}>Price: £50</Text>
      </View>
      <Image source={require('./nike-1.png')} />
      <View style={{ marginTop: 'auto' }}>
        <Volume
          paymentMeta={{
            amount: 50,
            currency: 'GBP',
            country: 'GB',
            reference: 'Example Reference', // Generate new reference value each time PAYMENT_AUTHORIZED_SDP event is emitted
            merchantPaymentId: '123456', // Generate new value each time PAYMENT_AUTHORIZED_SDP event is emitted
            metadata: {
              type: 'shirt',
              color: 'black',
              owner: {
                position: 'CTO',
                description: 'Very handsome man',
                details: {
                  name: 'John',
                  surname: 'Doe',
                },
                relatedItems: [
                  { itemName: 'trousers', color: 'blue' },
                  { itemName: 'shoes', color: 'white' },
                ],
              },
            },
            merchantProvidedPayerDetails: {
              email: 'john.doe@example.com',
              name: 'John Doe',
              phone: '+44 20 7946 0958',
              account: {
                holderName: 'John Doe',
                accountNumber: '12345678',
                sortCode: '123456',
                iban: 'DE89370400440532013000'
              },
              address: {
                addressLine1: '123 Main Street',
                addressLine2: 'Apt 4B',
                countryCode: 'GB',
                town: 'London',
                postCode: 'SW1A 1AA'
              },
              useForUxFlowOptimisation: true
            }
          }}
          onButtonEvent={(event) => {
            switch (event.type) {
              case 'GENERIC_ERROR':
                console.log('GENERIC_ERROR: ')
                // Meta does not exist
                // console.log('GENERIC_ERROR: ', event.meta);
                break
              case 'PAYMENT_AMOUNT_TOO_LARGE':
              case 'PAYMENT_AMOUNT_TOO_SMALL':
              case 'PAYMENT_AUTHORIZED_SDP':
              case 'PAYMENT_INITIATED':
                console.log(`${event.type}: ${event.meta?.merchantPaymentId}`)
                break
              case 'PAYMENT_ERROR':
                console.log(
                  `PAYMENT_ERROR: ${event.meta?.merchantPaymentId} | ${event.meta?.error}`
                )
                break
              default:
                break
            }
          }}
          buttonContainerStyles={{ marginBottom: 50 }}
          isButtonEnabled={true}
        />
      </View>
    </>
  )
}

metadata

metadata is an optional JSON object which will be passed back in webhooks as paymentMetadata. metadata must be a valid JSON object, so these values are not allowed:

metadata: 1
metadata: 'test'
metadata: [1, 2, 3]

metadata can be nested. This object is a valid example:

    metadata: {
        "id": "0001",
        "type": "donut",
        "name": "Cake",
        "batters":
            {
                "batter":
                    [
                        { "id": "1001", "type": "Regular" }
                    ]
            },
    }

Regenerating Merchant Payment ID

Each time VolumeEvent.PAYMENT_AUTHORIZED_SDP is emitted Merchant Payment ID should be set to a new unique value.

Merchant Provided Payer Details

The merchantProvidedPayerDetails parameter allows merchants to pre-populate payer information to optimize the user experience during payment flow. This is also required to gain access to Volume's Confirmation of Payer feature, and to enable the search and filtering of payments by these details.

Key Benefits

  • Faster UX: Automatic bank detection based on provided IBAN for EURO payments
  • Improved Conversion: Pre-filled forms reduce user friction
  • Confirmation of Payer: Verify the identity of account holders against your KYC data

Usage

merchantProvidedPayerDetails: {
  email: 'john.doe@example.com',
  name: 'John Doe',
  phone: '+44 20 7946 0958',
  account: {
    holderName: 'John Doe',
    accountNumber: '12345678',
    sortCode: '123456',
    iban: 'DE89370400440532013000'
  },
  address: {
    addressLine1: '123 Main Street',
    addressLine2: 'Apt 4B',
    countryCode: 'GB',
    town: 'London',
    postCode: 'SW1A 1AA'
  },
  useForUxFlowOptimisation: true
}

Properties

PropertyTypeRequiredDescription
emailStringNoCustomer's email address
nameStringNoCustomer's full name
phoneStringNoCustomer's phone number ideally in +XX 123456 format
accountPayerAccountNoCustomer's bank account details
addressPayerAddressNoCustomer's address details
useForUxFlowOptimisationBooleanNoEnable UX optimizations like bank detection

PayerAccount Properties

PropertyTypeRequiredDescription
holderNameStringNoAccount holder's name as it appears on the bank account
accountNumberStringNoBank account number (use with sortCode)
sortCodeStringNoBank sort code without dashes (use with accountNumber)
ibanStringNoInternational Bank Account Number

PayerAddress Properties

PropertyTypeRequiredDescription
addressLine1StringNoFirst line of the address
addressLine2StringNoSecond line of the address
countryCodeStringNoISO 3166-1 alpha-2 country code
townStringNoCity or town
postCodeStringNoPostal code or ZIP code

Account Identification Rules

⚠️

Important: You must use either IBAN (EUR) or the combination of account number and sort code (GBP), but not both:

  • IBAN Method: When iban is provided, accountNumber and sortCode should be null or not provided
  • Account Number Method: When accountNumber and sortCode are provided, iban should be null or not provided

Example with IBAN:

account: {
  holderName: 'John Doe',
  accountNumber: null,
  sortCode: null,
  iban: 'DE89370400440532013000',
}

Example with Account Number and Sort Code:

account: {
  holderName: 'John Doe',
  accountNumber: '12345678',
  sortCode: '123456',
  iban: null,
}

Important Notes

⚠️

When using merchantProvidedPayerDetails with IBAN, ensure the country parameter matches the country of the provided IBAN. Note that there are banks like Revolut or Wise that are available in many countries.

  • Bank detection works automatically for EURO payments when a valid IBAN is provided
  • The useForUxFlowOptimisation flag is set to true to enable all UX improvements
  • All fields are optional, allowing partial pre-population based on available data

Implementing the after payment screen (Callback) in mobile app

IMPORTANT: Handling properly Callback links is critical for the smooth User journey ending in Merchant app on payment status page.

Follow instructions for the Volume Callback handling: Callback

iOS Banks detection required setup

To make bank detection work Apple require we add some values in your Info.plist to indicate intent to work with app schemes, we use this to detect which banking apps the end user has installed on their phone so that we can show them only banks they have installed.

To complete the setup there are some <string> tags we need to add under the LSApplicationQueriesSchemes key in Info.plist file.

<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>BMBGB</string>
		<string>revolut</string>
		<string>natwestbank</string>
		<string>monzo</string>
		<string>santanderretail</string>
		<string>rbs</string>
		<string>lloyds-retail</string>
		<string>ukcomhsbcmobilebanking</string>
		<string>zappcfi437759</string>
		<string>hsbc-pwnwguti5z</string>
		<string>zapp</string>
		<string>launchAIB</string>
		<string>ie.aib.mobilebanking</string>
		<string>BOIOneAPP</string>
		<string>halifax-retail</string>
		<string>starlingbank</string>
		<string>tescobank</string>
		<string>tsbmobile</string>
		<string>sparda-app</string>
		<string>bankingappspardaproduktion</string>
		<string>secureappspardaproduktion</string>
		<string>sapp-pushtan</string>
		<string>sapp-invest</string>
		<string>de.sparda.securego</string>
		<string>bos-retail</string>
		<string>launchbca</string>
		<string>comfirstdirectbankingonthego</string>
		<string>cs-com.virginmoney.uk.mobile.ios</string>
		<string>transferwise</string>
		<string>ybssavings</string>
		<string>chase-international</string>
	</array>

Testing

After you have completed the steps above, then you can start testing.

We strongly recommend to use sandbox environment before switching to live environment.

Please note that sandbox testing will not open the Banking app due to lack of testing environment offered by the different banks in the UK. However, a successful test will open the bank environment via the browser. The user experience will differ bank by bank. Ask us more information at support@getvolume.com or use the chat in this page to get immediate assistance.

Please check Sandbox Banks Credentials to be able to test with Natwest Sandbox and other sandbox banks.