VNSwitch can store a customer’s payment method so they do not have to enter it again, and so you can charge it later without them, for subscriptions or instalments. You only ever handle a reference to the stored method and masked details, never the full card number.

There are three patterns:

PatternCustomer present?What you send on the payment
Save a method for one-click checkoutYes, now and latersetup_future_usage: "on_session" and customer_acceptance
Pay with a saved methodYespayment_token from the customer’s saved methods
Recurring, merchant-initiated chargesNoFirst mandate_data with setup_future_usage: "off_session", then recurring_details with off_session: true

Every pattern needs a customer: pass the same customer_id on every payment.

How saving works

VNSwitch saves the payment method when a payment succeeds and the request contains:

  • a customer_id;
  • setup_future_usage: on_session if the customer will be present when you reuse the method, off_session if you will charge it without them;
  • the customer’s consent in customer_acceptance (or in mandate_data.customer_acceptance). Without consent, the method is not saved.

The payment response then carries a payment_method_id (for example pm_5d1c9a7e3b). Store it with your customer record.

customer_acceptance records how the customer agreed:

FieldRequiredDescription
acceptance_typeYesonline (agreed on your website or app) or offline.
accepted_atNoWhen they agreed, ISO 8601.
online.ip_address, online.user_agentWith onlineThe customer’s IP address and browser user agent at the time they agreed.

To know whether a method can be saved at all, check customer_acceptance_support in List available payment methods.

The examples below send card details from a server to keep them short. Only do this if your systems are certified to handle card data (PCI DSS). Otherwise collect the card in the browser and confirm the payment there with the publishable key and the payment’s client_secret (see Authentication). After the method is saved, your server never needs the card number again.

Save a card during a payment

Add setup_future_usage and customer_acceptance to a normal payment. When the payment succeeds, the card is saved to the customer and the response returns its payment_method_id. If the payment needs 3-D Secure, the card is saved once the customer completes it (see Redirects and customer actions).

Response (shortened)

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "payment_method": "card",
  "setup_future_usage": "on_session",
  "payment_method_id": "pm_5d1c9a7e3b",
  "payment_method_status": "active"
}

Pay with a saved method

Use this when the customer is at checkout and picks one of their saved methods.

  1. List the customer’s payment methods and show each one with its masked details (for example “Visa •••• 4242, 12/2030”).
  2. When the customer picks one, create the payment with that method’s payment_token and payment_method. No card data is sent.

Tokens are short-lived. Fetch the list at the start of each checkout and do not store tokens.

If the saved method has requires_cvv: true, the customer must enter their CVC again. Collect it in the browser and confirm the payment there with the publishable key and client_secret, sending payment_method_data: { "card_token": { "card_holder_name": "…", "card_cvc": "…" } } alongside the payment_token, so the CVC never reaches your server.

Response (shortened)

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "payment_method": "card",
  "payment_token": "1d6e8a2c-5b3f-4c71-9e0a-7f2b4c8d9e13",
  "payment_method_id": "pm_5d1c9a7e3b"
}

Set up a mandate for recurring payments

A mandate records the customer’s permission for you to charge them later. Create it on the customer’s first payment, while they are present, by adding setup_future_usage: "off_session" and mandate_data. The customer pays the first 150,000 VND now and may need to complete 3-D Secure. The response returns the mandate_id; store it with the subscription.

mandate_data fields:

FieldRequiredDescription
customer_acceptanceYesThe customer’s consent, as in How saving works.
mandate_type.single_useOne of the twoPermission for one later charge of at most amount.
mandate_type.multi_useOne of the twoPermission for repeated charges whose total is at most amount.
mandate_type.*.amountYesLimit in minor units. In the example, 1,800,000 VND covers twelve monthly charges of 150,000 VND.
mandate_type.*.currencyYesCurrency of the limit, for example VND.
mandate_type.*.start_date, end_dateNoPeriod in which the mandate can be used (ISO 8601). start_date must be before end_date.

Check that the mandate is active with Retrieve a mandate before scheduling charges (see Mandate statuses).

Response (shortened)

{
  "payment_id": "pay_8f2c1d9e0a",
  "status": "succeeded",
  "amount": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "payment_method": "card",
  "setup_future_usage": "off_session",
  "mandate_id": "man_7a4e2c9f1d",
  "payment_method_id": "pm_5d1c9a7e3b"
}

Charge a saved method without the customer

Run this from your billing job on each due date. The customer is not involved and no card data is sent. The request must have:

  • confirm: true and off_session: true;
  • the same customer_id that set up the mandate;
  • recurring_details, which names what to charge:
recurring_details.typerecurring_details.dataUse it when
mandate_idThe mandate_id, for example man_7a4e2c9f1dYou set up a mandate with mandate_data. VNSwitch checks the mandate is active and the amount is within its limit.
payment_method_idThe payment_method_id, for example pm_5d1c9a7e3bThe method was saved with setup_future_usage: "off_session" and you track the agreement yourself.

Do not send recurring_details together with mandate_data or payment_token on the same payment; the request is rejected.

Off-session charges can still fail, for example when the card has expired or the account has no funds. Treat failed like any failed payment (see Payment lifecycle), listen for webhooks, and ask the customer to update their method when needed.

Response (shortened)

{
  "payment_id": "pay_2c6b9e4f7a",
  "status": "succeeded",
  "amount": 150000,
  "currency": "VND",
  "customer_id": "cus_demo_001",
  "off_session": true,
  "mandate_id": "man_7a4e2c9f1d",
  "payment_method_id": "pm_5d1c9a7e3b"
}

Stop recurring payments

When a customer cancels a subscription or removes a saved method:

  1. Revoke the mandate so it can no longer be charged. VNSwitch cancels it with the payment provider too.
  2. If the customer also wants the method removed, delete the payment method.
  3. Stop your own billing schedule for that subscription.

To find the mandates to revoke, list the customer’s mandates. A customer with an active mandate cannot be deleted until the mandate is revoked.

Vietnamese bank accounts

Cards work as shown above. Linking a Vietnamese bank account or e-wallet as a saved method, and charging it on a schedule, depends on the bank or provider supporting stored credentials and on that provider being connected to VNSwitch.

Availability depends on the payment providers enabled for your account. Contact info@nivc.ai.

Before you build a bank-account subscription, call List available payment methods with recurring_enabled=true and check that the method you need is returned with customer_acceptance_support set to supported.