Fixed Amount Subscriptions Walkthrough

Video Streaming Service Example

For this example, we will pretend to be a video streaming service that want to collect subscription payments from their end users.

  • First, we will need to determine suitable payment methods for our users based on the average basket size. Since the basket size for our basic and premium service is in the 5 USD to 15 USD quantum, eWallets, Direct Debit and Credit Cards will be suitable. We will proceed to apply with Xendit for these channels specifying that autodebit/ merchant initiated transaction is required.
  • While waiting for payment channel activation, we can proceed with testing. To start testing, we will first go to Xendit Dashboard to create an API key (Settings > Developers > API keys) and provide a URL which is hosted on our streaming service servers to receive Subscriptions webhooks from Xendit (Settings > Developers > Callbacks > SUBSCRIPTIONS).
  • Now that the set up is done, we can look at our use case and match it to the features on Xendit APIs
    • Payments are made once a month on the date that user first signs up
    • User must make one payment upfront
    • To maximize payment success rate, we want to perform payment retries when end user has balance again
    • To maximize payment success rate, we want to notify end users via Whatsapp when payment fails
    • If user fails to make payment for a month, we will terminate their service
  • We can start our integration by linking the payment flows to Xendit's APIs. The first API is Create Customer where we will pass our customer contact information into the request. This helps to store the contact information with Xendit so that the Whatsapp notification can be delivered. We can either provide the information based on user input during registration or create a form for user to input the data.
POST https://api.xendit.co/customers 
{
    "reference_id": "test_reference_id",
    "mobile_number": "+6218181818181",
    "email": "honeybadgey@xendit.co",
    "type" : "INDIVIDUAL",
    "individual_detail": {
        "given_names": "Honey Badgey"
        }
}
  • To simplify our integration, we will use Xendit's UI for creation of payment methods. The next API that we need to hit will be Create Plan.
POST https://api.xendit.co/recurring 
{
  "reference_id": "test_reference_id",
  "customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
  "recurring_action": "PAYMENT",
  "currency": "IDR",
  "amount": 100000,
  "schedule": {
    "reference_id": "test_reference_id",
    "interval": "MONTH",
    "interval_count": 1,
    "anchor_date": "2022-02-15T16:23:52Z",
    "retry_interval": "DAY",
    "retry_interval_count": 3,
    "total_retry": 3,
    "failed_attempt_notifications": [1,3]
  },
  "immediate_action_type": "FULL_AMOUNT",
  "notification_config": {
    "recurring_created": ["WHATSAPP"],
    "recurring_succeeded": ["WHATSAPP"],
    "recurring_failed": ["WHATSAPP"]
  },
  "failed_cycle_action": "STOP", 
  "metadata": null,
  "success_return_url": "https://www.xendit.co/successisthesumoffailures",
  "failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
}

The following parameters solves for these requirements:

ParameterUse case requirements
interval, interval_count, anchor_datePayments are made once a month on the date that user first signs up
immediate_action_typeUser must make one payment upfront
retry_interval, retry_interval_count, total_retryTo maximize payment success rate, we want to perform payment retries when end user has balance again
notification_configTo maximize payment success rate, we want to notify end users via Whatsapp when payment fails
failed_cycle_actionIf user fails to make payment for a month, we will terminate their service
  • Once the request is sent, we will receive a HTTPS response with a Subscriptions plan object that has status "REQUIRES_ACTION"
{
  "id": "repl-239c16f4-866d-43e8-9341-7badafbc019f",
  "reference_id": "test_reference_id",
  "customer_id": "cust-239c16f4-866d-43e8-9341-7badafbc019f",
  "recurring_action": "PAYMENT",
  "recurring_cycle_count": 0,
  "currency": "IDR",
  "amount": 100000,
  "status": "REQUIRES_ACTION",
  "created": "2020-11-20T16:23:52Z",
  "updated": "2020-11-20T16:23:52Z",
  "schedule_id": "resc-239c16f4-866d-43e8-9341-7badafbc019f",
  "schedule": {
    "reference_id": "test_reference_id",
    "interval": "MONTH",
    "interval_count": 1,
    "created": "2022-02-15T16:23:52Z",
    "updated": "2022-02-15T16:23:52Z",
    "anchor_date": "2022-02-15T16:23:52Z",
    "retry_interval": "DAY",
    "retry_interval_count": 3,
    "total_retry": 3,
    "failed_attempt_notifications": [1,3]
  },
  "immediate_action_type": "FULL_AMOUNT",
  "notification_config": {
    "recurring_created": ["WHATSAPP"],
    "recurring_succeeded": ["WHATSAPP"],
    "recurring_failed": ["WHATSAPP",],
    "locale": "en"
  },
  "failed_cycle_action": "STOP",
  "metadata": null,
  "description": null,
  "items": null,
  "actions": [{
      "action": "AUTH",
      "url": "https://linking-dev.xendit.co/pali_e53e1ca6-3c09-4026-be2e-95ed3d4bb25b",
      "url_type": "WEB",
      "method": "GET"
    }],
  "success_return_url": "https://www.xendit.co/successisthesumoffailures",
  "failure_return_url": "https://www.xendit.co/failureisthemotherofsuccess"
}

The status "REQUIRES_ACTION" indicates that we will need to set our user to be redirected to actions.url for them to complete their payment method account linking. Once our user has been redirected, we will need to listen to webhooks from Xendit to proceed with the next step.

  • If a webhook event for recurring.plan.activated was received, we will match it to the reference_id or id stored in our database to ensure it is an event for the plan we just created. Once confirmed, we can start providing service to the end user. If recurring.plan.inactivated was received, we can ask the end user to retry the Subscriptions flow.
  • At the same time, a recurring.cycle.succeeded webhook event for the immediate payment would be received. This webhook contains details about the immediate payment that was executed.
  • Lastly, a recurring.cycle.created webhook event would also be received for the upcoming month's payment subscriptions action. In this use case, it is optional to handle this webhook.
  • For subsequent months, if payments are successful, a recurring.cycle.succeeded webhook event would be received. If a recurring.cycle.retrying webhook event was received, that means that payment failed but Xendit will still continue trying. If a recurring.cycle.failed webhook event was received, we will terminate the user's service as all payment attempts including retries have failed.

Last Updated on 2023-06-02