How to Build a Custom Payments Integration on the Platform

In order to integrate any payment provider into your website, you can use this framework.

How to Create a Marketplace App for Payment Provider

To create a marketplace App, login to marketplace dashboard. Once logged in, create a new marketplace app with the following config.

Required scopes


payments/orders.readonly

payments/orders.write

payments/subscriptions.readonly

payments/transactions.readonly

payments/custom-provider.readonly

payments/custom-provider.write

products.readonly

products/prices.readonly

Redirect URL       

This URL is used to complete the Oauth flow when your app is installed at any location. Once your app is installed at any location, the user is redirects to this given URL with a code  in query parameter. This code can be used to exchange it for a Oauth Access token which would be used for any API call.

Client Keys

Store these client keys on your backend server in a secure manner. These keys will be required while making calls for Oauth flow.

Webhook URL

This URL will receive webhook events whenever an App is installed or uninstalled from a location.

SSO Key

This SSO key should be securely stored. This will be used to decrypt the auth token received for Custom Page.

Payment Provider

Once the settings page config is done, let's move to creating a Payment provider. The payment provider basically ensures that the app is seen as a payments app. The config for payment provider is used to show payment provider details in App details page on marketplace. Below are the inputs required for payment provider.

Payment Provider type

  • One Time: This options indicates that one time payments are supported by payment provider where only single time fixed payment is collected without any kind of future payments possibility.

  • Recurring: This options indicates that the payment provider supports recurring payment where a fixed recurring charge can be created and started on payment provider. This type would mean you can support recurring products in payments, create and manage subscriptions on your end, as well as provide updates about all subscriptions to webhooks (more on this later). For ex. if subscription has a new payment, is canceled or unpaid etc.

  • Off Session: This option indicates that the payment provider supports off session payments. Which means a given customer can be charged any amount using an API not requiring any customer input/authorization. This typically works where you have the customer cards authorized on their profiles and can use those cards to charge the customer later in time

Profile

Once all the above settings are done. We can move to Profile section. Where the important bit is to set the category to Third Party Provider . This will ensure your app shows up correctly in App Marketplace, as well as it's visible on the Payments > Integrations page for improved discoverability.

Custom Pages

In order to collect payment related credentials from the user after the app is installed in a location, we recommend using a custom page. A Custom page is a public website that is loaded in an iFrame inside App details page once the app is installed on this location. For any payments app, after installation this custom page will be opened directly, so it's easier to discover for users. Also when you go to Payments > Integrations, if your app is already installed, then from there we redirect users to this Custom page in App marketplace section if they click on Manage Integration  in Payments >  Integration > Details page.

App Installation

  •  Whenever your app is installed in a location, immediately a new tab will open with oauth code on the redirect url provided earlier in config.

  • Once the app is installed, the configured custom page is loaded.

  • In parallel, payments expects an API call with some basic config for payment integration. This creates a basic config in payments for your payments app, as well as starts showing the payment app as a payment option in Integrations page. So the users can manage the integration from there as well.

info icon
{ name: String, // Name of the integration shown everywhere description: String, // A short description/tagline for payments app. Shown in Payments > Integrations page imageUrl: String, // Public image url for payment provider logo to be shown in locationId: String, // Sub-account ID where the app is installed queryUrl: String, // A url which received different requests for all queries related to payments. Ex. Verify, Refund etc. paymentsUrl: String, // Public page url loaded in Iframe for making payments on frontend }

  • Once the app is installed, the obvious next step for users should be to add relevant payment config (public keys, merchant Id etc.) required for the configuration of this payment gateway. Two kind of configs are needed for any payment provider, a test mode and a live mode config.

    • test mode config is used for testing payments where no real money is charged

      live mode config is used by Customer for real payment where actual money is charged from valid cards/Banks.

  • Once any user is updating the live or test config in the App Custom Page, payments expects a test and live mode config update as well in following format. The two main parameters required for test and live mode config on payments side are:

    • apiKey: This key will be used for verification in backend calls made from server to your server.

    • publishableKey: Public api key used for frontend verification while initiating payment.

    • Connect config API

  • Once the LiveMode or TestMode keys are added, that particular mode of payments can be used on payments. The last step is to set your app as a default payment provider for that account. That can be done in Payments > Integrations > Your app > Set as Default

How the Payment Flow Works


Payment flow to collect any payment is mentioned in the above diagram. The iframe events are defined below.

  1. Once the paymentUrl is loaded in iframe, it expects a ready event, which should ideally be dispatched once the iframe is loaded completely and is ready to receive payment data and process payment. Once the ready event is dispatched by Iframe, it dispatches a data event sending all the data needed for the iframe to process the payment.

info icon
// Ready event dispatched by payment Iframe { type: 'custom_provider_ready', loaded: true } // Payment data event dispatched by Topline { type: 'payment_initiate_props', publishableKey: String, // Publishable key sent while connecting integration API amount: Number, // Amount in decimal currency with max 2 decimal places currency: String, // Standard 3 letter notation for currencies ex. USD, INR mode: String, // Payment mode: subscription/payment productDetails: {productId: string, priceId: string}, // productId and priceId for recurring products. More details can be fetched using the public api for Products/Prices contact?: { // Customer details for customer placing the order id: String, // Customer id in Topline name: String, // Full name of the customer email: String, contact: String, // Contact Number of customer with country code }, orderId: String, // internal orderId for given order transactionId: String, // Topline internal transactionId for the given transaction subscriptionId: String, // Topline internal subscriptionId passed in case of a recurring product locationId: String, // Sub-account id for which the given order is created. }

  1. Once the payment data event is dispatched, the Iframe should start the payment process. After the payment is done, it expects the following events for different outcomes from the payment.

Payment is Successful

info icon
{ type: 'custom_element_success_response', chargeId: String, // Payment gateway chargeId for given transaction (Will be shown in order/transaction/subscription details page }our callout text goes here...
}

Payment Failed

info icon
{ type: 'custom_element_error_response', error: { description: String, // Error message to be shown to the user } }

Payment Canceled: emitted if user cancels the payment while going through the payment process

info icon
curl --location '${queryUrl}' \ --header 'Content-Type: application/json' \ --data '{ "type": "verify", "transactionId": "transaction_id", "apiKey": "661d4d5a2a0167fb235f99ae", "chargeId": "demo_charge_id", "subscriptionId":"subscription_id" }'

Refund Event

info icon
{ type: 'refund', amount: Number, transactionId: String, // Internal transaction ID against which refund is issued. }

Refund transactions can be partial as well. And a single transaction can have multiple refund requests with sum of their amount less than or equal to the transaction amount.


Webhook events

Webhook events are supported, for updates to subscriptions, order, transactions, refunds and other actions. Currently some events are supported with more events coming in soon. This list of events and supported payloads would keep expanding.

Events supported by webhooks:

  • subscriptions

    • subscription.trialing

    • subscription.active

    • subscription.canceled

    • subscription.complete

Did this answer your question?
😞
😐
😁