Link

JUSPAY integration

Pre requisites:

  • Set User and construction of SubscriptionParams refer api.md
  • Juspay dashboard needs to be set up with a redirect url
  • In the cases, where user closes the browser after making the payment or Internet goes down for the user. We recoincile the subscriptions by communicating with the payment gateways with the help of webhooks. Go to Webhooks section in Juspay settings, Update the Authentication section with webhook username and webhook password in your Accesstype dashboard under payment gateways, Juspay section. Update the version to 2018-10-25. Update the webhook url to webhook url present in Accesstype dashboard under payment gateways, Juspay section.

User Flow:

  • User goes to story page or wherever Juspay has to be triggered. Then user clicks a button for example “Pay with Juspay”.
  • Then a pop up will appear with iFrame of Juspay loaded.
  • Before the pop-up loads, Accesstype JS will create an event on the page where Pay with Juspay is present and will listen to the pop up.
  • Once the User completes the payment, The iFrame will redirect to an URL which is specified by you in the Juspay dashboard.

You need to make sure that the below code block is present in the redirect URL

  (function() {
    var queryParams = window.location.search
    if( queryParams.includes('signature') &&
        queryParams.includes('signature_algorithm') &&
        queryParams.includes('order_id') &&
        queryParams.includes('status')
      ) {
      window.opener.postMessage(queryParams, "*");
    }
  })();

In the page, where AccessType is loaded, when the user clicks Pay with Juspay.

You can pass optional parameters to juspay payment gateway depending on the payment gateways you want juspay to render.

const subscriptionParams = {
  "type": "standard",
  "plan": {
    "id": "1",
    "price_cents": "29900",
    "price_currency": "INR",
    "title": "This is the stuff"
  },
  "payment": {
    "payment_type": "juspay",
    "amount_cents": "29900",
    "amount_currency": "INR"
  },
  "metadata": {
    "billing_address_first_name": "Juspay",
    "billing_address_last_name": "Technologies",
    "billing_address_line1": "Girija Building",
    "billing_address_line2": "Ganapathi Temple Road",
    "billing_address_line3": "8th Block, Koramangala",
    "billing_address_city": "Bengaluru",
    "billing_address_state": "Karnataka",
    "billing_address_country": "India",
    "billing_address_postal_code": "560095",
    "billing_address_phone": "9988775566",
    "billing_address_country_code_iso": "IND",
    "shipping_address_first_name": "Juspay",
    "shipping_address_last_name": "Technologies",
    "shipping_address_line1": "Girija Building",
    "shipping_address_line2": "Ganapathi Temple Road",
    "shipping_address_line3": "8th Block, Koramangala",
    "shipping_address_city": "Bengaluru",
    "shipping_address_state": "Karnataka",
    "shipping_address_postal_code": "560095",
    "shipping_address_phone": "9962881912",
    "shipping_address_country_code_iso": "IND",
    "shipping_address_country": "India"
  },
  "juspay": {
    "window_config": {
      // this value can be either "mobile" or "web", when not sent, web is considered to be default
      "type": "mobile"
    }
  }
}
AccessType.getPaymentOptions().then((paymentOptions) => paymentOptions.juspay.proceed(subscriptionParams
)).then((response) => {
  // add your additional functionality like call google analytics
  response.proceed(subscriptionParams).then((subscription) => {// returns a subscription }, (error) => {// handle error});
})

You can customize the juspay iframe popup by passing a few key value pairs object inside window_config under juspay key. The layout of the iframe content can be defined by passing type to the window_config object.

If the type is not passed to the window_config, by default, the type of iframe content will be web.

The whole juspay key is optional for the above subscriptionParams object.

Razorpay Recurring Integration

For a plan that is set as recurring in Accesstype, subscriptionParams.payment.payment_type needs to be razorpay_recurring.

Stripe Integration

Stripe has a redirect flow implemented for payment. By default user will be redirected back to where he was after the payment. If you want to redirect to any specific url after success or failure of payment, specify the urls in options as part of subscriptionParams object.

"options": {
  "urls": {
    "success_url": "https://your_website/success_url.com", //The URL to which customer will be directed when payment is complete
    "cancel_url": "https://your_website/cancel_url.com" //The URL the customer will be directed to if they decide to cancel payment
  }
}

Paypal Integration

Pre-requisites:

  • create one route for approval_success(e.g. https://your_website/return_url) and add the following code on that page:
    (function() {
    var queryParams = window.location.search
    if( queryParams.includes('token')) {
      window.opener.postMessage(queryParams, "*");
    }
    })();
    
  • create one route for approval_cancel(e.g. https://your_website/cancel_url) and add the following code on that page:
    (function() {
    window.close();
    })();
    
  • Send return_url and cancel_url in options as part of subscriptionParams object.
    "options": {
    "urls": {
      "return_url": "https://your_website/return_url",
      "cancel_url": "https://your_website/cancel_url"
    }
    }
    

User flow:

  • User clicks on pay button.
  • A new tab is opened with ‘loading…’ message and ATjs adds a listener for tab close. If the tab is closed by user, ATjs will throw an error which can be handled as part of catch.
  • ATjs makes a preview call and gets the approval link from Paypal. The user is then redirected to this url in the new tab and ATjs starts listening for message from this tab.
  • The user is redirected to return_url or cancel_url depending on whether the user approved the payment request or cancelled it by clicking on cancel in the paypal payment window.
  • If the request is cancelled, the tab is closed via the code snippet added on cancel_url; so, Atjs throws athe same error as when the user closes the tab.
  • If the request is approved, ATjs comes to know via the code snippet on return_url and hence will make the create_subscription call which will again return a success or failure depending on whether the subscripiton is created on AT or not.

Please note that if the create_subscription call fails for some reason even after the user has approved it, we will create the subscription for the user via webhook.

For testing/troubleshooting paypal:

  • You should use sandbox credentials in staging. To get that, toggle to sandbox under My Apps & Credentials in dashboard.
  • You can add/see accounts for making payments in Accounts under Sandbox. Use personal account for purchasing.
  • You can login to sandbox.paypal.com with the personal and business account to check status of plans bought and money debited/credited. Money is debited from personal account and credited to business account.
  • You can generate credit cards in Credit card generator under Mock section. Any 3 digit otp will be considered valid.
  • If you face problems while making payments in staging, you can try by using different card, a new user or trying again after some time. Usually, problem resolves on it’s own after a day or two. If problem persists, try contacting paypal’s customer service.

Paypal Recurring Integration

For a plan that is set as recurring in Accesstype, subscriptionParams.payment.payment_type needs to be paypal_recurring.

  • Auto debit for active recurring subscriptions occur at 10:00 am, GMT irrespective of country.

Googlepay Integration

ATJS does not provide first class integration for Googlepay. After calling previewSubscription, you need to initiate purchase flow at you end. You need to send attempt_token received in preview response as developer payload while making purchase on Googlepay as {attempt_token: <attempt-token-here>}. Accesstype listens to webhook notifications to create/renew subscriptions. Raad how to integrate Google inApp purcahses for more details.

const subscriptionParams =
{
    "plan": {
      "id": "1",
      "price_cents": "120000",
      "price_currency": "INR",
      "title": "This is the stuff"
    },
    "payment": {
        "payment_type": "googlepay_recurring",
        "amount_cents": "120000",
        "amount_currency": "INR",
        "payment_token": "nfccgldljhibhmnedaclcicd.AO-J1OyrW780EAy9g0GxaM65x9cuPSYE9fIxMU2wpHxURnB3Gk_6EDJK8J16spT11zKGt1EBJ48bjM3YOVI2lyKiQ9_DEbay6hHylX82xS_embMRIcW7y-c",
        "payment_attributes": {
          "orderId":"GPA.3316-7874-6202-40089",
          "packageName":"com.bacardi",
          "productId":"bacardi_sub_001",
          "purchaseTime":1590655929378,
          "purchaseState":0,"purchaseToken":"nfccgldljhibhmnedaclcicd.AO-J1OyrW780EAy9g0GxaM65x9cuPSYE9fIxMU2wpHxURnB3Gk_6EDJK8J16spT11zKGt1EBJ48bjM3YOVI2lyKiQ9_DEbay6hHylX82xS_embMRIcW7y-c",
          "autoRenewing":true,
          "acknowledged":false
        }
    }
  }

Omise Onetime Integration

For Omise one time payment integration, subscription params need to be sent to omise payment gateway method with subscriptionParams.payment.payment_type as omise.

For eg., following can be the subscription params

{
  "type": "standard",
  "plan": {
    "id": 89, //  Id of plan
    "price_cents": 2500,  // Price of plan in cents
    "price_currency": "USD",  // Currency
    "title": "Basic" // Plan title
  },
  "payment": {
    "payment_type": "omise",  //Payment gateway
    "amount_cents": 2500, // Price of plan in cents
    "amount_currency": "USD"  // Currency
  }
}
  • Charge limits should be followed for certain currencies

  • NOTE : For internet banking payment method, You must need to add webhook end point on omise dashboard otherwise subscription will never be create on Accesstype. Accesstype is dependent on omise webhook for internet banking payment method.

Following will be the webhook endpoint on omise dashboard

  • Production: https://accesstype.com/api/v1/callbacks/:account_key/omise.json

  • Staging: https://staging.accesstype.com/api/v1/callbacks/:account_key/omise.json

Omise Recurring Integration

For a plan that is set as recurring in Accesstype, subscriptionParams.payment.payment_type needs to be omise_recurring.

Some limitions/assumptions when using this payment gateway are listed below,

  • No recurring plans support natively, instead omise provides a schedule API, which can be used for recurring style payment
  • No trail period support for recurring flow
  • Charge limits should be followed for certain currencies
  • End date for creating a schedule is mandatory, so we have taken 50 years from now as the end date
  • Occurence of the plan in access type supports years, but this is not supported in omise, so we have taken a year to be 12 months
  • Omise requires us to specify when the billing schedule should happen, so we have taken the billing schedule to start as follows,
Period Billing is done
Day Every Day
Week On the day of the week, when the schedule started, for example, if the schedule starts on a monday, then every monday
Month On the day of the month, when the schedule started, for example, if the schedule starts on 1st, then 1st of every month
  • Omise needs a customer object to be created in their system before creating a schedule for them, we have taken only email logins for our subscribers, this means if a subscriber does not have an email subscriber identity, then they cannot use omise
  • Monthly schedules do not support the following days of the month (29th, 30th and 31st) for processing the charge schedule, we have taken 1st of the month for charge scheduling
  • Customer is always created as a new entity along with a card, even if the customer is already present, this means that there will be multiple customers in the omise dashboard with same email, other assumptions made for a omise customer
    1. We take only the email logins of a customer
    2. We take only the first card of the customer

Adyen Integration

  • For one time integration, subscription params need to be sent to the adyen payment gateway method with subscriptionParams.payment.payment_type as adyen. For recurring, subscriptionParams.payment.payment_type is adyen_recurring
  • Adyen doesn’t support trial periods
  • Adyen needs id of a html element to render payment methods and the element needs to be present in the DOM. Id of the html element can be passed in subscriptionParams.options.dropin_container_id
  • Adyen can render Drop-in (their payment methods UI) in multiple languages. You can pass the language that drop-in needs to be rendered in subscriptionParams.options.locale .The default locale is en-US. For all valid locale codes, please refer adyen docs
  • After a successful/failure transaction , the subscriber will be redirected to the url passed in subscriptionParams.additonal_data.publisher_return_url with the resultCode as query string. That means you need to have a separate landing page created for this and could render different content based on resultCode. The resultCode indicates the status of the transaction/payment.
    • Possible result codes are Authorised, Pending, Received,Refused, Error.
      • Authorised - Payment is successful and subscription has been created
      • Pending,Received - Awaiting status of payment. We will get to know the final status from adyen in a short while.
      • Refused - Payment has been refused. You can check the exact reason of payment refusal in adyen dashboard. Some of the reasons could be high risk score, incorrect cvv, expiry date.
      • Error - Some error occurred during the transaction. Can ask the customer to retry payment
    • So, after a successful transaction, you will be redirected to http://www.barandbench.com?resultCode=Authorised when subscriptionParams.additonal_data.publisher_return_url is http://www.barandbench.com
  • A sample adyen subscriptionParams object
    {
     "plan":{
        "id":"28",
        "price_cents":"4000",
        "price_currency":"EUR",
        "title":"display-title"
     },
     "type":"standard",
     "additional_data":{
        "publisher_return_url":"http://localhost:3000" // mandatory field
     },
     "payment":{
        "payment_type":"adyen",
        "amount_cents":"4000",
        "amount_currency":"EUR"
     },
     "options":{
        "dropin_container_id":"dropin-container", // mandatory field
        "locale": "fr-FR" /** optional default - "en-US" **/
     }
    }
    

For testing adyen

  • account_type should be sandbox in accounts table for staging/local Accesstype account (You can ask accesstype team to configure this)
  • Adyen Environment should be test for staging /local AT account. Environment can be configured in payment gateway page of AT dashboard

Apple IAP Integration

A purchase via Apple IAP can only be triggered natively from the app. After calling previewSubscription, you need to initiate native purchase flow at your end through the app. The response for the purchase flow will contain transactionId and originalTransactionIdentifierIOS. When the purchase is successful, the createSubscription call shall be made to AT including these details. For example, subscriptionParams.payment object may have the following details

  {
  "payment_type": "applepay_recurring",  //"applepay" for one time payments
  "amount_cents": 3000,
  "amount_currency": "USD",
  "payment_token": "1000000900265",  // transactionId received in the IAP purchase response
  "receipt_data": "<receipt-data>",
  "original_payment_token": "10000041498"  // originalTransactionIdentifierIOS received in the IAP purchase response
  }

Raad how to integrate Apple In App Purchases for more details.

Paytrail Integration

User Flow:

  • User clicks on pay button.
  • A new tab is opened and ATjs adds a listener for tab close. If the tab is closed by user, ATjs will throw an error which can be handled as part of catch.
  • ATjs makes a preview call and gets the payment link from Paytrail. The user is then redirected to this url in the new tab and ATjs starts listening for message from this tab.
  • The user is redirected to /paytrail-success.html or /paytrail-cancel.html depending on whether the user approved the payment request or cancelled it by clicking on cancel in the paytrail payment window.
  • If the request is cancelled, the tab is closed via the code snippet added on /paytrail-cancel.html; so, ATjs throws athe same error as when the user closes the tab.
  • If the request is approved, ATjs comes to know via the code snippet on /paytrail-success.html and hence will make the create_subscription call which will again return a success or failure depending on whether the subscripiton is created on AT or not.

Please note that if the create_subscription call fails for some reason even after the user has approved it, we will create the subscription for the user via webhook.

Integration Requirements:

  1. Paytrail expects a callback url for success and failure. These pages have to be created as follows.
  2. window.origin.location is used for getting the host.
  3. /paytrail-success.html and /paytrail-cancel.html pages will be the success and failure paths.
  4. /paytrail-success.html page has to contain the following snippet,
  <script>
        var queryParams = window.location.search
        if(queryParams.includes('signature')) {
          window.opener.postMessage(queryParams, "*");
        }
  </script>
  1. /paytrail-cancel.html has to contain the following snippet,
  <script>
    (function() {
      window.close();
    })();
  </script>