Subscription billing

Integration guide

A. Process flow

 

B. API configuration

The header will be built according to the Integration Rules for the APIs listed below.

 

1. Plan

1.1. Create Plan

POST /sub/plans

 

Request parameters

Attribute Type Required Description

plan_name

string (1-100 characters), no special characters allowed

yes

Plan name

plan_description

string (1-255 characters), no special characters allowed

yes

Detailed plan description

plan_status

string  

no

Plan Initialization Status (CREATED/ACTIVE/INACTIVE)  

- If this parameter is not provided, the default status is ACTIVE.  

- CREATED: The plan has been created. You cannot create a subscription when the plan is in this status.  

- ACTIVE: The plan is active. You can create a subscription only when the plan is in this status.  

- INACTIVE: The plan is inactive. You cannot create a subscription when the plan is in this status.  

billing_cycles

array of objects

 

An array of billing cycles for trial billing and regular billing. A plan can have at most two trial cycles and only one regular cycle.

Array ([ 1 .. 12 ] items)

     

tenure_type

string

yes

The tenure type of the billing cycle. In case of a plan having trial cycle, only 2 trial cycles are allowed per plan.

TRIAL: A trial billing cycle.

REGULAR: A regular billing cycle.

sequence

integer

yes

The order in which this cycle is to run among other billing cycles. For example, a trial billing cycle has a sequence of 1 while a regular billing cycle has a sequence of 2, so that trial cycle runs before the regular cycle.

total_cycles

integer

no

The number of times this billing cycle gets executed. Trial billing cycles can only be executed a finite number of times (value between 1 and 999 for total_cycles). Regular billing cycles can be executed infinite times (value of 0 for total_cycles) or a finite number of times (value between 1 and 999 for total_cycles)

frequency

integer

yes

The frequency details for this billing cycle. Unit: D (day)

pricing_scheme

object

yes

 

pricing_scheme.fixed_price

object

yes

 

pricing_scheme.fixed_price.amount

string

yes

Amount to be Paid (min 10,000 VND, max 200,000,000 VND)

For tenure_type = TRIAL, the amount can be set to 0.

pricing_scheme.fixed_price.currency

string

yes

Currency unit. Only VND is supported.

 

Example request

    "plan_name": "Fresh Clean Tees Plan",

    "plan_description": "Each shirt they send out to subscribers is designed with lots of attention to detail",

    "plan_status": "ACTIVE",

    "billing_cycles": [

        {

            "frequency": 7,

            "tenure_type": "TRIAL",

            "sequence": 1,

            "total_cycles": 1,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "0",

                    "currency": "VND"

                }

            }

        },

       {

            "frequency": 14,

            "tenure_type": "TRIAL",

            "sequence": 2,

            "total_cycles": 2,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "10000",

                    "currency": "VND"

                }

            }

        },

        {

            "frequency": 7,

            "tenure_type": "REGULAR",

            "sequence": 3,

            "total_cycles": 1,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "200000",

                    "currency": "VND"

                }

            }

        }

   ]

}

 

Response parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

 

failure_reason

String

Detailed error code description. Refer to List error codes

plan_id

String

Plan code generated by 9Pay

plan_name

string (1-100 characters), no special characters allowed

Same as the original request

plan_description

string (1-255 characters), no special characters allowed

Same as the original request

plan_status

string  

CREATE / ACTIVE / INACTIVE

create_time

datetime

Plan creation time.Format YYYY-MM-DD(UTC+0)

billing_cycles

array of objects

 

Array ([ 1 .. 12 ] items)

   

tenure_type

string

Same as the original request

sequence

integer

Same as the original request

total_cycles

integer

Same as the original request

frequency

integer

Same as the original request

pricing_scheme

object

 

pricing_scheme.fixed_price

object

 

pricing_scheme.fixed_price.amount

string

Same as the original request

pricing_scheme.fixed_price.currency

string

Same as the original request

 

Example response

{

     "status": 2,

    "error_code": "000",

    "failure_reason": "Success",

    "plan_id":"12344556",

    "plan_name": "Fresh Clean Tees Plan",

    "plan_description": "Each shirt they send out to subscribers is designed with lots of attention to detail",

    "plan_status": "ACTIVE",

    "create_time": "2024-04-24",

    "billing_cycles": [

        {

            "frequency": 7,

            "tenure_type": "TRIAL",

            "sequence": 1,

            "total_cycles": 1,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "0",

                    "currency": "VND"

                }

            }

        },

       {

            "frequency": 14,

            "tenure_type": "TRIAL",

            "sequence": 2,

            "total_cycles": 2,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "10000",

                    "currency": "VND"

                }

            }

        },

        {

            "frequency": 7,

            "tenure_type": "REGULAR",

            "sequence": 3,

            "total_cycles": 1,

            "pricing_scheme": {

                "fixed_price": {

                    "amount": "200000",

                    "currency": "VND"

                }

            }

        }

   ]

}

 

1.2. Update Plan

POST /sub/plans/{plan_id}

 

Request parameters

Attribute Type Required Description

plan_name

string (1-100 characters), no special characters allowed

yes

Plan name

plan_description

string (1-255 characters), no special characters allowed

yes

Detailed plan description

plan_status

string  

no

Plan status (ACTIVE/INACTIVE)

 

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

plan_id

String

Plan code generated by 9Pay

plan_name

string (1-100 characters), no special characters allowed

Same as the original request

plan_description

string (1-255 characters), no special characters allowed

Same as the original request

plan_status

string  

CREATE / ACTIVE / INACTIVE

update_time

datetime

Plan update time.Format YYYY-MM-DD(UTC+0)

billing_cycles

array of objects

 

Array ([ 1 .. 12 ] items)

   

tenure_type

string

Same as the original request

sequence

integer

Same as the original request

total_cycles

integer

Same as the original request

frequency

integer

Same as the original request

pricing_scheme

object

 

pricing_scheme.fixed_price

object

 

pricing_scheme.fixed_price.amount

string

Same as the original request

pricing_scheme.fixed_price.currency

string

Same as the original request

 

1.3. Show plan details

GET /sub/plans/{plan_id}

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

plan_id

String

Plan code generated by 9Pay

plan_name

string (1-100 characters), no special characters allowed

Plan name

plan_description

string (1-255 characters), no special characters allowed

Detailed plan description

plan_status

string  

CREATE / ACTIVE / INACTIVE

create_time

datetime

Plan creation time.Format YYYY-MM-DD(UTC+0)

update_time

datetime

Plan update time.Format YYYY-MM-DD(UTC+0)

billing_cycles

array of objects

 

Array ([ 1 .. 12 ] items)

   

tenure_type

string

The tenure type of the billing cycle. In case of a plan having trial cycle, only 2 trial cycles are allowed per plan.

TRIAL: A trial billing cycle.

REGULAR: A regular billing cycle.

sequence

integer

The order in which this cycle is to run among other billing cycles. For example, a trial billing cycle has a sequence of 1 while a regular billing cycle has a sequence of 2, so that trial cycle runs before the regular cycle.

total_cycles

integer

The number of times this billing cycle gets executed. Trial billing cycles can only be executed a finite number of times (value between 1 and 999 for total_cycles). Regular billing cycles can be executed infinite times (value of 0 for total_cycles) or a finite number of times (value between 1 and 999 for total_cycles)

frequency

integer

The frequency details for this billing cycle. Unit: D (day)

pricing_scheme

object

 

pricing_scheme.fixed_price

object

 

pricing_scheme.fixed_price.amount

string

Amount to be Paid (min 10,000 VND, max 200,000,000 VND)

For tenure_type = TRIAL, the amount can be set to 0.

pricing_scheme.fixed_price.currency

string

Currency unit. Only VND is supported.

 

1.4. List plans

GET /sub/plans

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

plans

array of objects

 

Array […] items

 

 

plan_id

string

Plan code generated by 9Pay

plan_name

string (1-100 characters), no special characters allowed

Plan name

plan_description

string (1-255 characters), no special characters allowed

Detailed plan description

plan_status

string

CREATE / ACTIVE / INACTIVE

create_time

datetime

Plan creation time.Format YYYY-MM-DD(UTC+0)

 

Example response

{

    "status": 2,

    "error_code": "000",

    "failure_reason": "Success",

    "plans":[

       {

       "plan_id":"12344556",

       "plan_name": "Fresh Clean Tees Plan",

       "plan_description": "Each shirt they send out to subscribers is designed with lots of attention to detail",

       "plan_status": "ACTIVE",

       "create_time": "2024-04-24"

       },

       {

       "plan_id":"12344556",

       "plan_name": "Fresh Clean Tees Plan",

       "plan_description": "Each shirt they send out to subscribers is designed with lots of attention to detail",

       "status": "ACTIVE",

       "create_time": "2024-04-24"

       }       

    ]

    }

 

}

 

2. Subscription

2.1. Create subscription

POST /sub/subscriptions

 

Request parameters

Attribute Type Required Description

request_id

string (40)
([a-zA-Z0-9])

yes

The partner's request ID is unique and identifies the transaction when sent to 9Pay to request payment.

plan_id

string

yes

The plan_id created by 9Pay. (Only successful subscription creation with plan status = ACTIVE; otherwise, it will return invalid.)

subscription_name

string (1-100 characters), no special characters allowed

yes

The name of the subscription package. No special characters allowed, accepts Vietnamese characters with diacritics.

subscription_start_time

datetime

yes

The time to start billing for the subscription package. Past time is not accepted. Format: YYYY-MM-DD (UTC+0).

description

string(255)

yes

Order information description..

return_url

string

yes

A URL from the partner. This URL is used to redirect from 9Pay back to the partner's purchase page after the customer has completed payment.

lang

string

no

The language displayed on the transaction screens for customers (vi and en). Default is en.

 

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

request_id

string

Same as the initial request ID.

plan_id

string

Same as the initial request.

subscription_status

string

Status of the subscription. 

PENDING: Awaiting processing. The first transaction has not yet been successfully completed.
ACTIVE: is active

subscription_id

string

Subscription code created by 9Pay.

subscription_name

string

Same as the initial request.

subscription_start_time

datetime

Same as the initial request.

payment_url

string

The URL to navigate to the payment page of 9Pay.

order_code

number

Transaction code from 9Pay.

amount

number

The amount to be paid. 

The amount depends on the Plan details and the subscription start time. Below are two cases to note:

 

1. For subscriptions with a TRIAL period and a subscription_start_time of the current or future date, the default amount is 10,000 VND.

   

2. For subscriptions with either a TRIAL or REGULAR period (ranging from 10,000 VND to 200 million VND) and a subscription_start_time in the future, the default amount is also 10,000 VND.

 

9Pay will deduct the default amount of 10,000 VND to verify the card's validity, and this amount will be refunded to the customer within 15 days.

currency

string

VND

submitted_at

datetime

Payment request creation time (UTC+0).

 

 

2.2. Processing payment result

After a successful payment, the Partner will receive the transaction result through:

 

Return

After the payment flow is completed, the customer is redirected to the return_url provided by the Partner when generating the payment URL.

The Partner uses this result to display a success/failure transaction message to the customer (contained in the query string when returning to the Partner's link).

 

IPN - Instant Payment Notification

After a successful payment transaction, 9Pay will send a POST request (x-www-form-urlencoded) to the IPN_url registered by the Partner.

 

The IPN data includes

Attribute Type Required Description

result

string

yes

Transaction information

checksum

string

yes

The checksum generated using the result and the partner's checksum key

version

string

no

IPN version

 

The value in the result after decoding:

Attribute Type Description

request_id

string

The partner's request ID is unique and identifies the transaction when sent to 9Pay to request payment.

subscription_id

string

Subscription code created by 9Pay.

subscription_status

string

Subscription status

PENDING: Pending processing. The first transaction has not been successfully completed.

ACTIVE: Active.

CANCELLED: Cancelled, can be reactivated.

SUSPENDED: Suspended after multiple unsuccessful payment retries. Cannot be reactivated in this status.

DELINQUENT: Overdue due to failed payment at the due date.

COMPLETED: This is the end state when all scheduled payments have been successfully completed. This status applies to subscriptions set up with a fixed number of payments.

subscription_name

string

The name of the subscription package. No special characters allowed, accepts Vietnamese characters with diacritics.

subscription_start_time

datetime

The time to start billing for the subscription package. Past time is not accepted. Format: YYYY-MM-DD (UTC+0)

create_time

datetime

Request creation time. Format: YYYY-MM-DD (UTC+0).

card_info

array

Card information.

card_info.card_name

string

Cardholder's name.

card_info.card_brand

string

Card brand name.

card_info.card_number

string

Card number in the format 123233xxxx1341.

card_info.token

string

Payment token.

billing_info

object

Detailed payment cycle information of the subscription.

billing_info.cycle_executions

array of objects

Execute TRIAL and REGULAR cycles.

array ([ 0 .. 3 ] items

 

 

tenure_type

string

The tenure type of the billing cycle. In case of a plan having trial cycle, only 2 trial cycles are allowed per plan.

TRIAL: A trial billing cycle.

REGULAR: A regular billing cycle

sequence

integer [1..3]

The order in which this cycle is to run among other billing cycles. For example, a trial billing cycle has a sequence of 1 while a regular billing cycle has a sequence of 2, so that trial cycle runs before the regular cycle

cycles_completed

integer

Number of completed payment cycles.

cycles_remaining

integer

Number of remaining payment cycles. If the cycle is unlimited, the default value is 0.

total_cycles

integer

Total number of payment cycles to be executed.

billing_info.last_payment

object

Details about the last payment.

billing_info.last_payment.status

string

Transaction status code. Refer to List error codes

billing_info.last_payment.error_code

string

Error code Refer to List error codes

billing_info.last_payment.failure_reason

string

Detailed error description.Refer to List error codes

billing_info.last_payment.transaction_type

string

PAYMENT/REFUND. 

Refer to the notes below.

billing_info.last_payment.amount

string

Amount paid.

billing_info.last_payment.currency

string

VND

billing_info.last_payment.submitted_at

string

Transaction creation time.

billing_info.last_payment.next_failed_payment_retry_date

datetime

Time to attempt to recharge the failed transaction.

billing_info.next_billing_time

string

Next payment time for the subscription.

 

Lưu ý: Đối với các chu kỳ thanh toán có số tiền = 0 thì có những lưu ý sau

  • Nếu merchant tạo mới subscription gắn với plan có chu kỳ TRIAL số tiền = 0 thì 9Pay sẽ khấu trừ số tiền mặc định 10,000 VND của khách hàng để đảm bảo thẻ hợp lệ, số tiền này sẽ hoàn lại cho khách hàng trong vòng 15 ngày. 

IPN giao dịch gửi cho merchant sẽ có transaction_type = refund.

  • Nếu sau khi tạo mới subscription thành công, đến chu kì thanh toán tiếp theo số tiền = 0 thì 9Pay không tạo giao dịch và không gửi IPN thông báo. Merchant chủ động truy vấn theo API cung cấp để nắm bắt thông tin.

 

2.3. Show subscription details

GET /sub/subscriptions/{subscription_id}

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

plan_id

string

Plan code associated with the subscription

subscription_status

string

Status of the subscription.

PENDING, ACTIVE, CANCELLED, SUSPENDED, DELINQUENT, COMPLETED 

subscription_id

string

Subscription code created by 9Pay.

subscription_name

string

The name of the subscription package. No special characters allowed, accepts Vietnamese characters with diacritics.

subscription_start_time

datetime

The time to start billing for the subscription package. Past time is not accepted. Format: YYYY-MM-DD (UTC+0)

create_time

datetime

Request creation time. Format: YYYY-MM-DD (UTC+0).

card_token

array

Payment token information.

billing_info

object

Detailed payment cycle information of the subscription.

billing_info.cycle_executions

array of objects

Execute TRIAL and REGULAR cycles.

array ([ 0 .. 3 ] items

 

 

tenure_type

string

Plan cycle type. It includes two values:

  • TRIAL: Trial period
  • REGULAR: Regular payment cycle

sequence

integer [1..3]

Execution order of the cycles. For example: if the trial period has a sequence of 1 and the regular payment cycle has a sequence of 2, then the trial period runs before the regular payment cycle. The maximum sequence value is 3.

cycles_completed

integer

Number of completed payment cycles.

cycles_remaining

integer

Number of remaining payment cycles. If the cycle is unlimited, the default value is 0.

total_cycles

integer

Total number of payment cycles to be executed.

billing_info.last_payment

object

Details about the last payment.

billing_info.last_payment.status

string

Transaction status code.Refer to 6.1.

billing_info.last_payment.error_code

string

Error code.Refer to 6.2

billing_info.last_payment.failure_reason

string

Detailed error description.Refer to 6.2

billing_info.last_payment.transaction_type

string

PAYMENT/REFUND. 

Refer to the notes below.

billing_info.last_payment.amount

string

Amount paid.

billing_info.last_payment.currency

string

VND

billing_info.last_payment.submitted_at

string

Transaction creation time.

billing_info.last_payment.next_failed_payment_retry_date

datetime

Time to attempt to recharge the failed transaction.

billing_info.next_billing_time

string

Next payment time for the subscription.

     

2.4. Update subscription

POST /sub/subscriptions/{subscription_id}

 

Request parameters

Attribute Type Required Description

subscription_status

String

yes

ACTIVE, CANCELLED
Subscription status.

  • If the subscription is in Pending, Delinquent, Suspended, or Completed, you cannot update the status.
  • If the subscription is Active, you can update it to Cancelled.
  • If the subscription is Cancelled, you can update it to Active.

 

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

plan_id

string

Plan code associated with the subscription

subscription_status

string

Status of the subscription.

PENDING, ACTIVE, CANCELLED, SUSPENDED, DELINQUENT, COMPLETED 

subscription_id

string

Subscription code created by 9Pay.

subscription_name

string

The name of the subscription package. No special characters allowed, accepts Vietnamese characters with diacritics.

subscription_start_time

datetime

The time to start billing for the subscription package. Past time is not accepted. Format: YYYY-MM-DD (UTC+0)

create_time

datetime

Request creation time. Format: YYYY-MM-DD (UTC+0).

card_token

array

Payment token information.

billing_info

object

Detailed payment cycle information of the subscription.

billing_info.cycle_executions

array of objects

Execute TRIAL and REGULAR cycles.

array ([ 0 .. 3 ] items

 

 

tenure_type

string

Plan cycle type. It includes two values:

  • TRIAL: Trial period
  • REGULAR: Regular payment cycle

sequence

integer [1..3]

Execution order of the cycles. For example: if the trial period has a sequence of 1 and the regular payment cycle has a sequence of 2, then the trial period runs before the regular payment cycle. The maximum sequence value is 3.

cycles_completed

integer

Number of completed payment cycles.

cycles_remaining

integer

Number of remaining payment cycles. If the cycle is unlimited, the default value is 0.

total_cycles

integer

Total number of payment cycles to be executed.

billing_info.last_payment

object

Details about the last payment.

billing_info.last_payment.status

string

Transaction status code.Refer to 6.1.

billing_info.last_payment.error_code

string

Error code.Refer to 6.2

billing_info.last_payment.failure_reason

string

Detailed error description.Refer to 6.2

billing_info.last_payment.transaction_type

string

PAYMENT/REFUND. 

Refer to the notes below.

billing_info.last_payment.amount

string

Amount paid.

billing_info.last_payment.currency

string

VND

billing_info.last_payment.submitted_at

string

Transaction creation time.

billing_info.last_payment.next_failed_payment_retry_date

datetime

Time to attempt to recharge the failed transaction.

billing_info.next_billing_time

string

Next payment time for the subscription.

 

2.5. List transaction of subscription

GET /sub/subscriptions/{subscription_id}/transactions

 

Reponse parameters

Attribute Type Description

status

Number

API Call Status:

2: Completed

1: Failed

error_code

String

Error code corresponding to status. Refer to List error codes

failure_reason

String

Detailed error code description. Refer to List error codes

transactions

Array of objects

Transaction list.

Array ([ 0 .. 9999 ] items

 

 

order_code

String

9Pay transaction code.

status

Number

Transaction status code.

error_code

String

Error code

failure_reason

String

Detailed error description.

amount

String

Amount paid.

currency

String

VND

card_token

String

Payment token.

submitted_at

String

Transaction initiation time

 

 

2.6. Failed Recurring Payment Retry System

Processing steps:

  1. Automatic periodic payment fails.
  2. The subscription will apply the retry rule and will:
  • Set the next retry payment schedule (next_failed_payment_retry_date).
  • Update the subscription status from ACTIVE to DELINQUENT.
  • Send an IPN notification.

 

Subscriptions Default Retry Rules:

After successfully creating a subscription, if the system fails to process subsequent periodic payments, it will attempt to retry a maximum of 5 times within 7 days from the date of the failed periodic payment.

  1. Retry Attempt 1
  • Interval: The subscription waits 12 hours from the time of the failed transaction to the first retry attempt.
  • Subscription Status during Retry: DELINQUENT.
  • Retry Transaction Result:Failure: Proceed to Retry Attempt 2 and send an IPN notification.
  • Retry Transaction Result:Success: Update the subscription status to ACTIVE and send an IPN notification.

 

  1. Retry Attempt 2
  • Interval: The subscription waits 12 hours from the first retry attempt.
  • Subscription Status during Retry: DELINQUENT.
  • Retry Transaction Result:Failure: Proceed to Retry Attempt 3 and send an IPN notification.
  • Retry Transaction Result:Success: Update the subscription status to ACTIVE and send an IPN notification

 

  1. Retry Attempt 3
  • Interval: The subscription waits 24 hours from the second retry attempt.
  • Subscription Status during Retry: DELINQUENT.
  • Retry Transaction Result:Failure: Proceed to Retry Attempt 4 and send an IPN notification.
  • Retry Transaction Result:Success: Update the subscription status to ACTIVE and send an IPN notification

 

  1. Retry Attempt 4
  • Interval: The subscription waits 48 hours from the third retry attempt.
  • Subscription Status during Retry: DELINQUENT.
  • Retry Transaction Result:Failure: Proceed to Retry Attempt 5 and send an IPN notification.
  • Retry Transaction Result:Success: Update the subscription status to ACTIVE and send an IPN notification

 

  1. Retry Attempt 5
  • Interval: The subscription waits 72 hours from the fourth retry attempt.
  • Subscription Status during Retry: DELINQUENT.
  • Retry Transaction Result:Failure: Update the subscription status to SUSPENDED and send an IPN notification.
  • Retry Transaction Result:Success: Update the subscription status to ACTIVE and send an IPN notification

 

3. See also