A client session is the starting point for integrating payments at Primer.
You can attach all the metadata associated with the order to the client session, and generate a clientToken, 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 v2.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.
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:
orderId
currencyCode
amount
order.countryCode
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.
Prepare the UniversalCheckout.EventListener that will handle the events that happen during the lifecycle:
12345678910111213141516171819202122232425262728
class CheckoutActivity :AppCompatActivity(){privateval listener =object: CheckoutEventListener {overridefunonCheckoutEvent(e: CheckoutEvent){when(e){is CheckoutEvent.TokenizationSuccess ->{/* TODO */}is CheckoutEvent.ResumeSuccess ->{/* TODO */}else->// handle other events}}}overridefunonCreate(savedInstanceState: Bundle?){super.onCreate(savedInstanceState)configureCheckout()}privatefunconfigureCheckout(){// with default settings Primer.instance.configure(listener = listener)}}
kotlin
copy
Step 3. Prepare the 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:
12345678910111213141516171819202122232425262728
class CheckoutActivity :AppCompatActivity(){// other code goes hereprivatelateinitvar viewModel: CheckoutViewModeloverridefunonCreate(savedInstanceState: Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)setupViewModel()setupObservers()fetchClientToken()}privatefunsetupViewModel(){ viewModel =ViewModelProvider(this).get(CheckoutViewModel::class.java)}// prepare the client (docs here)privatefunfetchClientToken()= viewModel.fetchClientToken()privatefunsetupObservers(){ viewModel.clientToken.observe(this){ clientToken ->// show checkout}}}
kotlin
copy
12345678910
class CheckoutViewModel :ViewModel(){privateval _clientToken= MutableLiveData<String>()val clientToken: LiveData<String>= _clientTokenfunfetchClientToken(){// fetch your token here (ask your backend to provide token) add our docs to exlain _clientToken.postValue("retrieved_token")}}
kotlin
copy
Step 4. Show Universal Checkout
When the client token is retrieved, show Universal Checkout.
1234567891011121314
class CheckoutActivity :AppCompatActivity(){// other code goes hereprivatefunsetupObservers(){ viewModel.clientToken.observe(this){ clientToken ->showUniversalCheckout(clientToken)}}privatefunshowUniversalCheckout(clientToken: String){ Primer.instance.showUniversalCheckout(this, clientToken)}}
kotlin
copy
Step 5. Handle callbacks for creating and resuming payments
Once the payment method data has been securely captured, Primer will return a uniform paymentMethodToken via CheckoutEvent.TokenizationSuccess that can be safely passed to your server to create a payment with the Payments API.
class CheckoutViewModel :ViewModel(){//..funsendPaymentMethodToken(token: PaymentMethodToken, handler: ResumeHandler){// Send the payment method token to your server to create a payment// (https://primer.io/docs/payments/#one-create-a-payment-request) with `paymentMethod.token`val paymentResponse =//...if(paymentResponse.isSuccessful()){// If the payment is successful, call resumeHandler.handleSuccess(). handler.handleSuccess()}elseif(paymentResponse.isPending()){// Payments API may return a new `clientToken` for additional steps. In this case, call `resumeHandler.handleNewClientToken(clientToken)` handler.handleNewClientToken(paymentResponse.requiredAction.clientToken)}else{// If the payment is unsuccessful, call `resumeHandler.handleError(error: Error)` to show an error / failed message. handler.handleError(Error())}}}
kotlin
copy
Handle CheckoutEvent.ResumeSuccess event
Once the required actions are completed, Primer will return resumeToken via CheckoutEvent.ResumeSuccess that can be safely passed to your server to resume a payment with the Payments API.
class CheckoutViewModel :ViewModel(){//...funsendResumeToken(token: String, handler: ResumeHandler){// Send a resume payment request with resumeToken (https://primer.io/docs/payments/#two-handle-resuming-payment-flows)val paymentResponse =//..if(paymentResponse.isSuccessful()){// If the payment is successful, call resumeHandler.handleSuccess(). handler.handleSuccess()}elseif(paymentResponse.isPending()){// Payments API may return a new `clientToken` for additional steps. In this case, call `resumeHandler.handleNewClientToken(clientToken)` handler.handleNewClientToken(paymentResponse.requiredAction.clientToken)}else{// If the payment is unsuccessful, call `resumeHandler.handleError(error: Error)` to show an error / failed message. handler.handleError(Error())}}}
kotlin
copy
Create a Payment
Once you've received a paymentMethodToken from Universal Checkout, use it to create a payment.
The payment request is synchronous. It will trigger a Workflow and return a payment object containing, among other things, the payment status. In circumstances where the payment flow is asynchronous, you may receive a status of PENDING.
12345678910111213
// 2XX response{"id":"slklmjh4","status":"AUTHORIZED","orderId":"<YOUR_ORDER_ID>","currencyCode":"GBP","amount":800,"paymentMethodToken":"<PAYMENT_METHOD_TOKEN>"// ... additional attributes for the Payment object// ... see API ref}
json
copy
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.
To receive updates about the status of your payments you’ll need to listen to webhooks. Head to the Developers area to setup a webhook for PAYMENT.STATUS event.
If you are not yet ready to receive webhooks, you can use https://webhook.site to test your implementation.