Recurring payments
Charge a stored card for subscriptions and other repeated payments, without your customer being present.
Use recurring payments for subscriptions, instalments and other repeated charges. They cover two kinds of series:
schedule_type | Use it for | Example |
|---|---|---|
scheduled | Charges at fixed intervals | A monthly subscription |
unscheduled | Charges at moments that vary | Automatic top-ups when a balance runs low |
Recurring payments work in two stages:
- First transaction. Your customer pays, or verifies their card, and authenticates. Ginger Payments stores the card in the vault and returns a
vault_token. - Subsequent transactions. You charge the stored card whenever a payment is due. Your customer isn't present and doesn't need to do anything.
Keep these rules in mind:
- A recurring series is valid for at most one year. After that, start a new series with a new first transaction.
- The amount of the first transaction can differ from the subsequent ones.
- For a payment that your customer starts themselves, such as a faster checkout, use one-click payments instead.
Apple Pay and Google Pay support recurring payments as well, with a few differences. See Recurring payments with Apple Pay and Recurring payments with Google Pay.
Step 1: Create the first transaction
Create an order with a credit-card transaction and set these fields in payment_method_details:
| Field | Value |
|---|---|
recurring_type | first |
schedule_type | scheduled or unscheduled |
How your customer completes the payment depends on your integration.
Create the order and redirect your customer to the payment_url of the transaction in the response. Your customer enters their card details and authenticates on the hosted payment page.
curl https://api.dev.gingerpayments.com/v1/orders/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"merchant_order_id": "SUB-001",
"amount": 1000,
"currency": "EUR",
"description": "Subscription setup",
"return_url": "https://www.example.com/return",
"transactions": [
{
"payment_method": "credit-card",
"payment_method_details": {
"recurring_type": "first",
"schedule_type": "scheduled"
}
}
],
"customer": {
"merchant_customer_id": "CUST-ABCDE",
"email_address": "jane.doe@example.com",
"first_name": "Jane",
"last_name": "Doe",
"address_type": "billing",
"address": "123 Abbey Road",
"postal_code": "NW8 9AY",
"country": "GB",
"city": "London",
"ip_address": "203.0.113.10"
}
}'Verify a card without charging it
To only store and verify the card, set amount to 0 in the first transaction. Your customer still authenticates, but isn't charged.
Step 2: Store the vault token
When the order is completed, retrieve it to get the vault_token:
curl https://api.dev.gingerpayments.com/v1/orders/5d2a9c84-1f6b-4e37-9a0d-7c3e8b1f2a96/ \
--user "$API_KEY:"The token is in the payment_method_details of the transaction. The response is shortened:
{
"id": "5d2a9c84-1f6b-4e37-9a0d-7c3e8b1f2a96",
"status": "completed",
"transactions": [
{
"id": "a41f7e2c-8b3d-4c95-9e60-1d7b2f8c3a04",
"payment_method": "credit-card",
"payment_method_details": {
"card_expiry": "122029",
"cardholder_name": "Jane Doe",
"recurring_type": "first",
"schedule_type": "scheduled",
"truncated_pan": "************4444",
"vault_token": "0c8fd8ab-25ec-4109-ac8f-495804aa5026"
},
"status": "completed"
}
]
}Store the vault_token and the transaction id securely, and link them to your customer's subscription. You need one of them for every subsequent charge.
Step 3: Charge subsequent payments
When a payment is due, create an order with recurring_type set to recurring. Reference the series with the first_transaction_id, the id of the transaction from step 1:
curl https://api.dev.gingerpayments.com/v1/orders/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"merchant_order_id": "SUB-001-CYCLE-02",
"amount": 4000,
"currency": "EUR",
"description": "Monthly subscription",
"webhook_url": "https://www.example.com/webhook",
"transactions": [
{
"payment_method": "credit-card",
"payment_method_details": {
"recurring_type": "recurring",
"first_transaction_id": "a41f7e2c-8b3d-4c95-9e60-1d7b2f8c3a04"
}
}
],
"customer": {
"merchant_customer_id": "CUST-ABCDE",
"ip_address": "203.0.113.10"
}
}'Instead of the first_transaction_id, you can send the vault_token from step 2.
The payment is processed without your customer. There's no payment_url to redirect to. Follow the result with a webhook and a status request.
Continue a series from another platform
Did the first transaction of a series run on another payment platform? You can continue the series with Ginger Payments, without asking your customer to authenticate again. This is only possible with a server-to-server integration.
You need the first_network_transaction_id: the identifier the card network assigned to the first authorization of the series. Ask your previous payment provider for it.
Create the order
Create an order with recurring_type set to recurring and the first_network_transaction_id:
curl https://api.dev.gingerpayments.com/v1/orders/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"merchant_order_id": "MIGRATED-SUB-001",
"amount": 4000,
"currency": "EUR",
"description": "Monthly subscription",
"transactions": [
{
"payment_method": "credit-card",
"payment_method_details": {
"recurring_type": "recurring",
"first_network_transaction_id": "MDSIZQ7RH0128"
}
}
]
}'The transaction in the response contains a setup_token in its payment_method_details. Save it, together with the order id and transaction id.
Store the card in the vault
Send the card details and the setup_token to the vault. The setup token can be used once, within 300 seconds:
curl https://tokens.dev.gingerpayments.com/v1/cards/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"name": "John Doe",
"pan": "4111111111111111",
"expiry": "012030",
"setup_token": "5d04ff5e-eb9d-42c8-8bcd-8a29f49ccf58"
}'The response contains a vault_token that refers to the stored card.
Start the payment
Assign the vault_token to the transaction to process the payment:
curl https://api.dev.gingerpayments.com/v1/orders/0a73c8e3-7a2f-40ee-8f6c-fa41a37c140a/transactions/7e5d1b90-2c4a-4f83-b6d1-9a0e3c5f8b27/initiate/ \
--user "$API_KEY:" \
--header "Content-Type: application/json" \
--data '{
"vault_token": "ab39817c-7e19-497a-ac7b-23526473b3c1"
}'The response contains the order and its transaction. It's shortened here:
{
"id": "0a73c8e3-7a2f-40ee-8f6c-fa41a37c140a",
"amount": 4000,
"currency": "EUR",
"merchant_order_id": "MIGRATED-SUB-001",
"status": "processing",
"transactions": [
{
"id": "7e5d1b90-2c4a-4f83-b6d1-9a0e3c5f8b27",
"amount": 4000,
"payment_method": "credit-card",
"payment_method_brand": "visa",
"payment_method_details": {
"approval_code": "08C405",
"authorization_iso_response_code": "00",
"first_network_transaction_id": "MDSIZQ7RH0128",
"network_transaction_id": "MDSIRCRRH0128",
"recurring_type": "recurring",
"schedule_type": "unscheduled",
"vault_token": "ab39817c-7e19-497a-ac7b-23526473b3c1"
},
"status": "accepted"
}
]
}Store the vault_token. For the next charges in the series, skip the vault step: create the order and start the payment with the stored vault_token.
Visa Account Name Inquiry
Visa Account Name Inquiry (ANI) checks whether the cardholder name your customer enters matches the name the issuer has on file. It runs automatically when all of these apply to the first transaction:
- The
amountis0. - Your customer pays with a Visa card.
- Your customer enters the cardholder name.
The result is in the payment_method_details of the transaction:
{
"ani_results": {
"status": "00",
"status_description": "ANI successfully performed",
"match": "01",
"match_description": "full match"
}
}status | Meaning |
|---|---|
00 | ANI was performed. |
01 | ANI was requested but not performed. |
02 | ANI was requested but the issuer doesn't support it. |
match | Meaning |
|---|---|
01 | Full match |
50 | Partial match |
99 | No match |