> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.qfapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Guide for Recurring Payments

> Developer guide for integrating recurring payment features, including setup flow, data model, and best practices.

This guide walks you through the complete integration flow for recurring payments using QFPay's Subscription API.

## Understanding the two-step process

When using recurring payments, the process involves two separate steps:

### 1. Token creation (after 3DS authentication)

After the customer completes 3DS via `qfpay.confirmPayment()` on the frontend, the system creates a payment token.

This step verifies the cardholder's identity and stores the payment method securely for future billing.

### 2. Subscription creation

The `token_id` generated in step 1 is then used to call the API `/subscription/v1/create`, which creates the subscription and schedules recurring billing.

### Why you see two transaction records

Because these two steps serve different purposes, you will normally see two transaction records:

* One for token creation / payment verification
* One for subscription billing

This is part of the normal recurring payment lifecycle. The system requires the tokenisation step before subscriptions can be created.

### Billing options

Depending on your business logic, you can implement the first charge in two different ways:

#### Option 1 — Verification charge + first subscription charge

**Example:** subscription HKD 100 / month starting January

**Token creation:** HKD 1 verification charge (Jan)

* Used only for identity verification and tokenisation.

**Subscription creation:**

* First billing HKD 100 in January
* Subsequent charges HKD 100 every month.

This approach is typically used when you want to separate verification from the actual billing.

#### Option 2 — First subscription charge during token creation

**Example:** subscription HKD 100 / month starting January

**Token creation:** HKD 100

* This charge serves both as identity verification and the first subscription payment.

**Subscription creation:**

* Billing starts from February onwards (HKD 100 monthly).

This approach avoids a small verification charge and uses the first payment as part of the subscription.

## Prerequisites

Before you begin, ensure you have:

* A QFPay merchant account with recurring payment features enabled
* API credentials (app\_code and API key)
* A web application with HTTPS enabled
* Basic understanding of REST APIs and webhooks

## Integration steps

### Step 1: Create customer

Create a customer record to associate with subscriptions.

```bash theme={null}
POST /subscription/v1/customer
```

**Request:**

```json theme={null}
{
  "customer_name": "John Doe",
  "customer_email": "john@example.com",
  "customer_phone": "+85212345678"
}
```

**Response:**

```json theme={null}
{
  "customer_id": "cus_abc123",
  "customer_name": "John Doe",
  "customer_email": "john@example.com"
}
```

### Step 2: Create product

Define the subscription product with pricing and billing cycle.

```bash theme={null}
POST /subscription/v1/product
```

**Request:**

```json theme={null}
{
  "product_name": "Premium Plan",
  "product_description": "Monthly premium subscription",
  "amount": 10000,
  "currency": "HKD",
  "billing_cycle": "monthly"
}
```

**Response:**

```json theme={null}
{
  "product_id": "prod_xyz789",
  "product_name": "Premium Plan",
  "amount": 10000,
  "currency": "HKD"
}
```

### Step 3: Render payment element (frontend)

Initialize the payment element on your checkout page.

```javascript theme={null}
const payment = qfpay.payment({
  customer_id: 'cus_abc123',
  amount: 10000,
  currency: 'HKD',
  save_card: true
});

payment.mount('#payment-element');
```

### Step 4: Confirm payment and create token

After customer enters card details, confirm the payment to trigger 3DS and create token.

```javascript theme={null}
const result = await qfpay.confirmPayment({
  payment,
  return_url: 'https://yoursite.com/payment/complete'
});

if (result.token_id) {
  // Send token_id to your backend
  await fetch('/api/create-subscription', {
    method: 'POST',
    body: JSON.stringify({
      token_id: result.token_id,
      customer_id: 'cus_abc123',
      product_id: 'prod_xyz789'
    })
  });
}
```

### Step 5: Create subscription (backend)

Use the token to create the subscription.

```bash theme={null}
POST /subscription/v1/create
```

**Request:**

```json theme={null}
{
  "customer_id": "cus_abc123",
  "product_id": "prod_xyz789",
  "token_id": "tok_def456",
  "start_date": "2024-01-01"
}
```

**Response:**

```json theme={null}
{
  "subscription_id": "sub_ghi789",
  "status": "active",
  "next_billing_date": "2024-02-01"
}
```

### Step 6: Handle webhooks

Set up webhook endpoints to receive subscription events.

```javascript theme={null}
app.post('/webhooks/subscription', (req, res) => {
  const event = req.body;
  
  switch(event.type) {
    case 'subscription.payment_succeeded':
      // Handle successful payment
      break;
    case 'subscription.payment_failed':
      // Handle failed payment
      break;
    case 'subscription.cancelled':
      // Handle cancellation
      break;
  }
  
  res.status(200).send('OK');
});
```

## Testing

Use test card numbers in sandbox environment:

* **Success:** 4111 1111 1111 1111
* **3DS Required:** 4000 0027 6000 3184
* **Declined:** 4000 0000 0000 0002

## Best practices

1. **Always validate webhooks** - Verify webhook signatures to ensure authenticity
2. **Handle failed payments gracefully** - Implement retry logic and notify customers
3. **Store subscription IDs** - Keep subscription\_id in your database for management
4. **Test thoroughly** - Test all scenarios including failures and cancellations
5. **Monitor subscription health** - Track payment success rates and churn

## Next steps

* [API Reference](/integration/online-shop/integration-by-use-case/recurring-payments/recurring-api-reference)
* [Webhook Events](/integration/online-shop/integration-by-use-case/recurring-payments/recurring-webhook)
* [Overview](/integration/online-shop/integration-by-use-case/recurring-payments/recurring-overview)
