Pay & Subscribe Checkout
Comprehensive guide for setting up subscription payments and agreements using Pay & Subscribe checkout
Overview
The PayTo Pay & Subscribe checkout feature lets merchants set up subscription payments with customers through a three-step integration. First, merchants enable Checkout App with PayTo in their dashboard. Next, they create a payment request with initial and recurring payment details, then redirect customers to the Azupay checkout URL to authorize the immediate payment and ongoing agreement via PayTo. After completion, merchants receive a paymentAgreementId via API polling or webhook, representing the customer's payment mandate. Finally, merchants use this ID to initiate recurring payments at set intervals (weekly, monthly, or annually) without further customer action. Merchants should monitor the payment agreement status (ACTIVE, CANCELLED, or SUSPENDED) since customers can manage agreements anytime through their banking app.
Integration Guide
The PayTo Pay & Subscribe checkout feature lets merchants set up subscription payments with customers through a three-step integration. First, merchants enable Checkout App with PayTo in their dashboard. Next, they create a payment request with initial and recurring payment details, then redirect customers to the Azupay checkout URL to authorize the immediate payment and ongoing agreement via PayTo. After completion, merchants receive a paymentAgreementId via API polling or webhook, representing the customer's payment mandate. Finally, merchants use this ID to initiate recurring payments at set intervals (weekly, monthly, or annually) without further customer action. Merchants should monitor the payment agreement status (ACTIVE, CANCELLED, or SUSPENDED) since customers can manage agreements anytime through their banking app.
Part 1: Dashboard Configuration
Enable Checkout App v3 with PayTo
Before using the PayTo Subscribe feature, you must enable the checkout app v3 with PayTo functionality in your dashboard.
- Access Dashboard: Log into your Azupay merchant dashboard
- Navigate to Apps: Go to the Apps section
- Enable Checkout v3: Find and enable the "Checkout" App
- Configure PayTo: Ensure PayTo functionality is enabled in the app settings
- Optional Settings: Choose a default landing product for when your checkout does not require a recurring agreement.
Part 2: Create Payment Request and Redirect Customer
Creating a Payment Request with Subscription
To create a payment request that includes subscription setup, include the following fields in your payment request:
Required Fields:
clientId: Your client identifierclientTransactionId: Unique transaction identifierpaymentAmount: Initial payment amountpaymentDescription: Description of the paymentrecurringPaymentAmount: Amount for recurring paymentsrecurringPaymentFrequency: Payment frequencyrecurringPaymentEndDate: The date after which the agreement will expire inyyyy-mm-ddformat. The Agreement will not have an end date if not provided.recurringPaymentType: Determines the type of Agreement. Default isVARIABLEwhen not provided.FIXED: Future recurring payments must be of exactlyrecurringPaymentAmount.VARIABLE: Future recurring payments can be of equal or less thanrecurringPaymentAmount
When both the
recurringPaymentAmountandrecurringPaymentFrequencyare provided in the request, the Checkout UX will remove the PayID option and will only enable PayTo checkout. If neither is provided then it will present the UX depending what was configured in the Client Dashboard Apps Settings.
Supported Frequencies
DAILY- Daily recurring paymentsWEEKLY- Weekly recurring paymentsMONTHLY- Monthly recurring paymentsANNUAL- Annual recurring paymentsADHOC- Any time recurring payments.
Just be aware that choosing ADHOC Frequency might lead to agreements been denied by banks due to maximum amount restrictions.
API Endpoint: Create Payment Request
POST /paymentRequestHeaders:
Authorization: your-api-key
Content-Type: application/jsonRequest Body:
{
"PaymentRequest": {
"clientId": "your-client-id",
"clientTransactionId": "unique-transaction-id",
"paymentAmount": 100.00,
"recurringPaymentAmount": 50.00,
"recurringPaymentFrequency": "ANNUAL",
"recurringPaymentType": "VARIABLE",
"recurringPaymentEndDate": "2026-11-04",
"paymentDescription": "Annual subscription setup",
"paymentNotification": {
"paymentNotificationEndpointUrl": "https://my-webhook.merchantname.com",
"paymentNotificationAuthorizationHeaderValue": "webhook-secret"
}
}
}Response:
{
"PaymentRequest": {
"clientId": "your-client-id",
"clientTransactionId": "unique-transaction-id",
"paymentAmount": 100.00,
"recurringPaymentAmount": 50.00,
"recurringPaymentFrequency": "ANNUAL",
"recurringPaymentType": "VARIABLE",
"recurringPaymentEndDate": "2026-11-04",
"paymentDescription": "Annual subscription setup",
"checkoutUrl": "https://pay.azupay.com.au/xxxx/pay"
},
"PaymentRequestStatus": {
"paymentRequestId": "abc123",
"status": "WAITING",
"createdDateTime": "2024-01-15T10:30:00Z"
}
}Redirect Customer to Checkout
Once you receive the response, redirect your customer to the checkoutUrl from the response:
If you are not embedding this checkoutUrl inside an iframe on your checkout app then provide the following additional query parameters to the checkout url:
redirectURL: the url that a successful transaction should be redirected to.cancelRedirectURL: the url that an unsuccessful transaction should be redirected to.
const checkoutUrl = response.PaymentRequest.checkoutUrl;
// Create a URL object
const url = new URL(checkoutUrl);
// Add your redirect URLs
url.searchParams.set("redirectURL", "https://example.com/success");
url.searchParams.set("cancelRedirectURL", "https://example.com/cancel");
// Redirect
window.location.href = url.toString();Obtaining the Payment Agreement ID
After successful payment, you can obtain the paymentAgreementId in two ways:
Get Payment Request Status
GET /paymentRequest?id={paymentRequestId}Response:
{
"PaymentRequest": {
"clientId": "your-client-id",
"clientTransactionId": "unique-transaction-id",
"paymentAmount": 100.00,
"recurringPaymentAmount": 50.00,
"recurringPaymentFrequency": "ANNUAL",
"paymentDescription": "Annual subscription setup",
"checkoutUrl": "https://pay.azupay.com.au/xxxx/pay"
},
"PaymentRequestStatus": {
"paymentRequestId": "abc123",
"status": "COMPLETE",
"createdDateTime": "2024-01-15T10:30:00Z",
"completedDatetime": "2024-01-15T10:35:00Z",
"settledBy": "PayTo",
"paymentAgreementId": "agreement-456"
}
}Webhook Notification
If you defined paymentNotification details in the PaymentRequest or you have global webhook configuration setup, you'll receive a notification with the payment status including the paymentAgreementId:
Webhook Endpoint:
POST https://my-webhook.merchantname.com/Headers:
Authorization: webhook-secret
Content-Type: application/jsonWebhook Body:
{
"PaymentRequest": {
"clientId": "your-client-id",
"clientTransactionId": "unique-transaction-id",
"paymentAmount": 100.00,
"recurringPaymentAmount": 50.00,
"recurringPaymentFrequency": "ANNUAL",
"paymentDescription": "Annual subscription setup",
"checkoutUrl": "https://pay.azupay.com.au/xxxx/pay"
},
"PaymentRequestStatus": {
"paymentRequestId": "abc123",
"status": "COMPLETE",
"createdDateTime": "2024-01-15T10:30:00Z",
"completedDatetime": "2024-01-15T10:35:00Z",
"settledBy": "PayTo",
"paymentAgreementId": "agreement-456"
}
}Part 3: Payment Agreement Details and Recurring Payments
Payment Agreement Structure
When a subscription payment request is completed, a payment agreement is created with the following structure:
{
"PaymentAgreement": {
"payerDetails": {
"name": "John Doe",
"payIDDetails": {
"payID": "[email protected]",
"payIDType": "EMAIL"
}
},
"agreementDetails": {
... This depends on the parameters provided to the paymentRequest
}
},
"PaymentAgreementStatus": {
"status": "ACTIVE"
}
}If you provided recurringPaymentType of FIXED then the Agreement details will look like the following. The firstPaymentAmount will correspond to the amount of the Payment Request.
{
...
"agreementDetails": {
"fixedAgreementDetails": {
"firstPaymentAmount": "100.00",
"amount": "50.00",
"frequency": "ANNUAL",
"endDate": "2024-05-06"
}
}
}Otherwise, if the recurringPaymentType is VARIABLE then the Agreement details will look something like this.
{
...
"agreementDetails": {
"variableAgreementDetails": {
"maximumAmount": "200.00",
"frequency": "ANNUAL",
"endDate": "2024-05-06"
}
}
}Agreement Properties
firstPaymentAmount: The initial payment amount that was processed. Only forFIXEDtype.amount: The recurring payment amount for future payments. Only forFIXEDtypemaximumAmount: The maximum amount that can be withdraw. Only for theVARIABLEtypes.frequency: The payment frequency (WEEKLY, MONTHLY, ANNUAL)endDate: Null for open-endedstatus: Agreement status (ACTIVE, CANCELLED, EXPIRED)
Agreement Status
The payer might suspend or cancel the agreement at any time.
Checking for ACTIVE agreement status before initiating a payment is desired.
ACTIVE- Agreement is active and ready for recurring paymentsCANCELLED- Agreement has been cancelled by the payer on their banking app.SUSPENDED- Agreement has been suspended by the payer on their banking app.
Initiating Recurring Payments
To initiate a recurring payment using the payment agreement after the first period has elapsed, use the payment initiation endpoint:
POST /paymentInitiationHeaders:
Authorization: your-api-key
Content-Type: application/jsonRequest Body:
{
"PaymentInitiation": {
"paymentAgreementId": "agreement-456",
"paymentDescription": "Monthly subscription payment",
"clientTransactionId": "recurring-payment-789",
"paymentInitiationNotification": {
"endpointURL": "https://my-webhook.merchantname.com",
"authorizationHeader": "webhook-secret"
}
}
}Response:
{
"PaymentInitiation": {
"paymentAgreementId": "agreement-456",
"paymentDescription": "Monthly subscription payment",
"clientTransactionId": "recurring-payment-789"
},
"PaymentInitiationStatus": {
"paymentInitiationId": "initiation-123",
"status": "WAITING",
"createdDateTime": "2024-02-15T10:30:00Z"
}
}You can wait for a webhook notification with the status of SETTLED for the paymentInitiation on the endpointURL you provided when the paymentInitiation was created.
PaymentInitiation Statuses
- CREATED - Payment instruction created
- PENDING - Payment processing in progress
- SETTLED - Payment completed successfully
- FAILED - Payment failed
- RETURN_IN_PROGRESS - Refund in progress
- RETURN_COMPLETE - Refund completed successfully
- RETURN_FAILED - Refund failed
Additional PayTo Features
Agreement Management
Search Payment Agreements
Endpoint: POST /paymentAgreement/search
Search for payment agreements based on various criteria such as:
- Payment agreement ID
- Contract ID
- Date range (from/to dates)
Example Request:
{
"PaymentAgreementSearch": {
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA="
}
}Amend Agreement
Endpoint: POST /paymentAgreement/amendment
Create amendments to existing payment agreements to modify details like maximum amount or frequency.
Example Request:
{
"PaymentAgreementAmendment": {
"clientTransactionId": "TX-AMD-001-20241201-002",
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"agreementDetails": {
"variableAgreementDetails": {
"maximumAmount": "200.00",
"frequency": "FORTNIGHTLY"
}
}
}
}Payment Initiation Management
Search Payment Initiations
Endpoint: POST /paymentInitiation/search
Search for payment initiations based on various criteria like client transaction ID or date range.
Example Request:
{
"PaymentInitiationSearch": {
"clientTransactionId": "TX-PMT-001-20241201-001"
}
}Refund Payment Initiation
Endpoint: POST /paymentInitiation/refund
Initiate a refund for a completed payment initiation.
Test Data
Test PayID Values for successful transactions:
- Email PayID:
[email protected] - Phone PayID:
0400234567
Best Practices
Security
- Always validate with the backend that the transaction has been completed either with the webhook or the API.
- Provide a secret header for the webhook and validate it.
Other
- Do not append query parameters to the
checkoutUrluse a proper url parsing tool to prevent the code to break if the url changes. - Checking for ACTIVE agreement status before initiating a payment and notify the payer if required.
Additional Information
See the documentation on each of the APIs for more information on all statuses and features
Updated about 14 hours ago
