Perform merchant-initiated or card-on-file transactions.
Card components support two types of recurring payments:
- Merchant-initiated transactions (MITs): For subscription-based payments where the customer signs up and pays initially, and you then automatically charge them at a specified interval. This means there's no customer action needed for renewals.
- Card-on-file transactions with shopper consent: For storing payment methods with customer consent for future use. This allows you to provide a faster checkout experience for returning customers.
To set up a recurring payment, you need to include the recurring object in your transaction data of your sdkConfig. You'll need to specify the frequency of this recurring payment (in days), but the expiration data is optional.
// Configure subscription transaction data
const transactionData = {
amount: 9.99,
currency: 'USD',
entryType: 'Ecom',
intent: {
card: 'Authorisation'
},
merchantTransactionId: 'sub-setup-123',
merchantTransactionDate: () => new Date().toISOString(),
recurring: {
frequencyInDays: 30,
frequencyExpiration: '2025-12-31'
}
};
// Create complete SDK configuration
const sdkConfig = {
transactionData, // ← This connects Step 1 to Step 2
apiKey: 'your-api-key',
environment: 'sandbox',
// ... other SDK settings
};Next, you're going to use your sdkConfig to create the relevant components. When the customer clicks submit, the recurring payments will start.
const cardNumberComponent = new CardNumberComponent(sdkConfig);
const cardExpiryComponent = new CardExpiryDateComponent(sdkConfig);
const cardCvcComponent = new CardCvcComponent(sdkConfig);
const cardSubmitComponent = new CardSubmitComponent(sdkConfig, {
cardNumberComponent,
cardExpiryDateComponent: cardExpiryComponent,
cardCvcComponent,
useCardOnFile: false,
submitText: 'Start subscription',
onPostAuthorisation: async (data) => {
console.log('Subscription setup completed');
// Get full result from backend
const result = await getAuthorisationResultFromGateway(data.merchantTransactionId, data.systemTransactionId);
if (result.state === 'Authorised' || result.state === 'Captured') {
console.log('Subscription started!');
// The recurring data from step 1 was automatically used
// Store the subscription details in your system
}
}
});
// Mount components
cardNumberComponent.mount('card-number');
cardExpiryComponent.mount('card-expiry');
cardCvcComponent.mount('card-cvc');
cardSubmitComponent.mount('submit-button');To save a card, you'll first need to ask for the customer's consent during the initial transaction. If the customer ticks the checkbox, their card details will be saved as a token for future reuse.
const transactionData = {
amount: 99.99,
currency: 'USD',
entryType: 'Ecom',
intent: {
card: 'Authorisation'
},
merchantTransactionId: 'order-12345',
merchantTransactionDate: () => new Date().toISOString()
};
const sdkConfig = {
transactionData,
// ... other SDK configuration
};
// Create the card consent component
const cardConsentComponent = new CardConsentComponent(sdkConfig, {
label: 'Save this card for faster checkout in the future',
class: 'consent-checkbox'
});
// Create the card input components
const cardNumberComponent = new CardNumberComponent(sdkConfig);
const cardExpiryComponent = new CardExpiryDateComponent(sdkConfig);
const cardCvcComponent = new CardCvcComponent(sdkConfig);
// Create the card submit component
const cardSubmitComponent = new CardSubmitComponent(sdkConfig, {
cardNumberComponent,
cardExpiryDateComponent: cardExpiryComponent,
cardCvcComponent,
cardConsentComponent, // Include consent component
useCardOnFile: false, // Use a new card, not a saved card
submitText: 'Pay & save card',
onPostTokenisation: async (data) => {
console.log('Card tokenised. Gateway Token ID:', data.gatewayTokenId);
// Get full token details from backend if needed for validation
const tokenDetails = await getTokenDetailsFromBackend(data.gatewayTokenId);
console.log('Card saved for future use');
// Store the token reference in your system
},
onPostAuthorisation: async (data) => {
console.log('Payment completed');
// Get full result from backend
const result = await getAuthorisationResultFromGateway(data.merchantTransactionId, data.systemTransactionId);
if (result.state === 'Authorised' || result.state === 'Captured') {
console.log('Payment successful, card saved for future use');
}
}
});
// Mount components
cardNumberComponent.mount('card-number');
cardExpiryComponent.mount('card-expiry');
cardCvcComponent.mount('card-cvc');
cardConsentComponent.mount('card-consent');
cardSubmitComponent.mount('submit-button');For subsequent transactions, you can use choose from:
- A traditional card selection: This is best for customers with multiple saved cards and provides full card management (edit, delete, update) but requires more interaction from the customer. It uses the card-on-file component.
- A streamlined click-once checkout: This is ideal for customers with one primary payment method and offers a faster checkout experience, but less flexibility. It uses the standalone click-once component.
- A hybrid approach: This combines the two components. It defaults to displaying a primary card, but allows customers to choose a different one if they want to.
const cardOnFileComponent = new CardOnFileComponent(sdkConfig, {
limitTokens: 10,
orderBy: {
lastUsageDate: { direction: 'desc', priority: 1 }
},
deleteCardButtonAriaLabel: 'Delete this card',
editCardInformationAriaLabel: 'Edit card details'
});