Follow this guide to start accepting online payments on Android with Primer using Universal Checkout

Generate a Client Token

Get an API Key

You require an API Key to talk with our APIs. Head to the developers area to manage your API keys.

When your account is created, we will also create an API token automatically. You can use this API key to get started.

Only client_tokens:write is required as the scope of the key.

Never share your API Key, only your backend should have access to it.

Find out more about API Keys in our API Reference

Generate a Client Session

client token A client session is the starting point for integrating payments at Primer. You can attach all the additional data associated with the order to the client session, and generate a client token, a temporary key used to initialize Universal Checkout.

The information you include in the client session is used in the Dashboard to conditionally route payments with Workflows, and activate payment methods and other features in Universal Checkout, so pass as much information as you can.

The X-Api-Version specifies the API version information. Earlier, this was supposed to be a date. For example, 2021-10-19.

This has changed post API version v2 which was represented by 2021-09-27 date.

Starting API version v2.1, the X-Api-Version needs to provide the API version as 2.1.

Depending upon the API version specified in the client-session request, your client-session will be processed accordingly with requisite features and options that are available for that version.

See API Reference Changelog to see the differences between API versions.

Here is how the client session request to the Primer API should look like:

# Generate a client token with cURLcurl --location --request \  POST '' \  --header 'X-Api-Key: <YOUR_API_KEY>' \  --header 'X-Api-Version: 2.2' \  --header 'Content-Type: application/json'  --data '{    "orderId": "<YOUR_ORDER_ID>",    "currencyCode": "GBP",    "amount": 4999,    "customerId": "<YOUR_CUSTOMER_ID>"    "order": {      "lineItems":  [{        "itemId": "shoes-123",        "amount": 2500,        "quantity": 2      }],      "countryCode": "GB"    }  }'

Example Response

{  "clientToken": "<THE_CLIENT_TOKEN>",  "clientTokenExpirationDate": "2021-08-12T16:14:08.578695",  "orderId": "<YOUR_ORDER_ID>",  "currencyCode": "GBP",  "amount": 1200,  "customerId": "<YOUR_CUSTOMER_ID>",  "metadata": {},  "warnings": [],  "order": { "countryCode": "GB" }}
Make sure to pass all the information required by the payment methods and features activated on your Dashboard.

As a rule of thumb, pass as much information as you can when creating the client session. As a minimum, make sure to pass:

Your reference for the payment.

Make sure to keep track of orderId - you will later receive updates to the payment via Webhooks. The payment will contain the orderId specified in the client session.
The three-letter currency code in ISO 4217 format.
e.g. use USD for US dollars.
  1. order
The details of the line items of the order.

The clientToken is a key concept within Primer. You may receive a client token from various places but as long as you pass it to the SDK, Universal Checkout knows where to start/resume the flow.

Set up Universal Checkout

Step 1. Install

Add the following to your app/build.gradle file:

repositories {  mavenCentral()} dependencies {  implementation 'io.primer:android:latest.version'}

For more details about SDK versions, please see our changelog.

It is highly recommended to add following settings to your app/build.gradle file:

android {    kotlinOptions {        freeCompilerArgs += '-Xjvm-default=all'    }}

Step 2. Initialize the SDK

Prepare the PrimerCheckoutListener that will handle the callbacks that happen during the lifecycle. Import the Primer SDK and set its listener as shown in the following example:

class CheckoutActivity : AppCompatActivity() {     private val listener = object : PrimerCheckoutListener {         override fun onCheckoutCompleted(checkoutData: PrimerCheckoutData) {            // Primer checkout completed with checkoutData            // show an order confirmation screen, fulfil the order...        }    }     override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)         configureCheckout()    }     private fun configureCheckout() {        // Initialize the SDK with the default settings.        Primer.instance.configure(listener = listener)    }}

Check the SDK API here to customize your SDK settings.

Step 3. Generate a client token

Make an API call to your backend to fetch a client token. Here is a simple example of how it can be done from your activity:

class CheckoutActivity : AppCompatActivity() {   // other code goes here  private lateinit var viewModel: CheckoutViewModel   override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity_main)     setupViewModel()    setupObservers()    fetchClientToken()  }    private fun setupViewModel() {    viewModel = ViewModelProvider(this).get(  }   // prepare the client (docs here)  private fun fetchClientToken() = viewModel.fetchClientToken()   private fun setupObservers() {    viewModel.clientToken.observe(this) { clientToken ->      // show checkout    }  }}

Your view model code may look something like this:

class CheckoutViewModel : ViewModel() {     private val _clientToken = MutableLiveData<String>()    val clientToken: LiveData<String> = _clientToken     fun fetchClientToken() {        // fetch your client token here (ask your backend to provide token)        _clientToken.postValue("retrieved_client_token")    }}

Step 4. Show Universal Checkout

When the client token is retrieved, show Universal Checkout.

class CheckoutActivity : AppCompatActivity() {     // other code goes here     private fun setupObservers() {        viewModel.clientToken.observe(this) { clientToken ->            showUniversalCheckout(clientToken)        }    }     private fun showUniversalCheckout(clientToken: String) {        Primer.instance.showUniversalCheckout(this, clientToken)    }}

You should now be able to see Universal Checkout! The user can now interact with Universal Checkout, and the SDK will create the payment. The payment’s data will be returned on onCheckoutCompleted(checkoutData) configured in Step 2.

Step 5. Process the Payment Status Webhook

Create a PAYMENT.STATUS Webhook on your Dashboard

Use this event as a single source of truth to update your database and to fulfill the order.

12345678'/webhooks/payment-status', async (req, res) => {    const { eventType, payment } = req.body    const { id, orderId, status } = payment     if (status === 'AUTHORIZED' || status === 'SETTLED') {        // Fullfil the order for the Payment / Client Session labelled with `orderId`    }})

Step 6. Customize Universal Checkout

Head to our Customization guide to learn more about the styling options.

Take a look at our Advanced guides to adapt Universal Checkout to your needs.

Step 7. Prepare 3DS

3DS is supported out of the box by Universal Checkout

To improve 3DS success rates, it is recommended to pass the following elements in the Client Session:

  1. customer
The customer's email address
  1. customer
The customer's billing address

Learn more about how to configure 3DS!

Did It Work?

If everything went well, you should be able to see the payment you just created on your Dashboard under the Payments menu. Payment list