Payment Setup
The payment module is the core of the Headless SDK. It lets you discover which payment methods are configured for a store, tokenize cards, and process payments with automatic 3DS, redirect, and polling handling.
Discover Available Payment Methods
Every store has a payment setup config — a map of payment methods (card, Apple Pay, Google Pay, Klarna, etc.) with their enabled/disabled state, processor IDs, and flow IDs.
const setup = await tagada.payment.getPaymentSetup(checkoutSessionId);
// Example response:
// {
// "card": { enabled: true, method: "card", paymentFlowId: "pf_xxx" },
// "apple_pay:stripe": { enabled: true, method: "apple_pay", express: true, processorId: "proc_xxx" },
// "google_pay:stripe": { enabled: true, method: "google_pay", express: true },
// "klarna:stripe": { enabled: true, method: "klarna", processorId: "proc_stripe" },
// }
Just the enabled method keys
const methods = await tagada.payment.getEnabledMethods(checkoutSessionId);
// ["card", "apple_pay:stripe", "google_pay:stripe"]
Express methods with browser availability
const express = await tagada.payment.getExpressMethods(checkoutSessionId);
// {
// applePay: { available: true, processorId: "proc_xxx" },
// googlePay: { available: true },
// klarna: { available: true, processorId: "proc_stripe" },
// }
The SDK automatically checks ApplePaySession.canMakePayments() in the browser to determine Apple Pay availability.
Card Payment Flow
Recommended: processPayment()
processPayment() is the high-level orchestrator that handles the entire payment lifecycle automatically:
- Submits payment to the processor
- If 3DS / bank auth is required → redirects the user and resumes on return
- If the payment is async → polls until a terminal status
- Returns a typed
ProcessPaymentResult
// 1. Tokenize
const { tagadaToken } = await tagada.payment.tokenizeCard({
cardNumber: '4242424242424242',
expiryDate: '12/28',
cvc: '123',
cardholderName: 'Jane Doe',
});
// 2. Process payment (3DS, redirects, polling all handled)
const result = await tagada.payment.processPayment({
checkoutSessionId: session.id,
tagadaToken,
});
// 3. Handle result
switch (result.status) {
case 'succeeded':
console.log('Payment confirmed!', result.order);
break;
case 'requires_redirect':
// In React, usePayment() handles this automatically.
// In vanilla JS, redirect manually:
window.location.href = result.redirectUrl;
break;
case 'failed':
console.error('Payment failed:', result.error);
break;
case 'pending':
console.log('Still processing...', result.paymentId);
break;
}
tokenizeCard() requires @tagadapay/core-js as an optional peer dependency. Install it: npm install @tagadapay/core-js.
Return type: ProcessPaymentResult
The return value is a discriminated union — check result.status for exhaustive handling:
| Status | Fields | Meaning |
|---|
succeeded | payment, order | Payment confirmed. Show success screen. |
requires_redirect | redirectUrl, method?, postData?, paymentId | User must visit a URL (3DS, bank auth, APM). |
failed | error, payment? | Payment declined or errored. |
pending | paymentId | Still processing (rare — polling timed out). |
3DS Return URL
After a 3DS redirect, the bank sends the user back to your page with query parameters. The SDK auto-detects these and resumes the payment:
- React (
usePayment): Handled automatically on mount — detects ?paymentAction=... params, polls for result, fires callbacks.
- Vanilla JS: Call
tagada.payment.resumeAfterRedirect(paymentId) manually after detecting the return.
// Vanilla JS — on page load, check for return from 3DS
const params = new URLSearchParams(window.location.search);
const paymentId = params.get('paymentId');
if (params.get('paymentAction') === 'requireAction' && paymentId) {
const result = await tagada.payment.resumeAfterRedirect(paymentId);
// result is a ProcessPaymentResult
}
Express Checkout
Apple Pay
const result = await tagada.payment.processApplePay({
checkoutSessionId: session.id,
applePayToken: applePayEvent.payment.token,
});
Google Pay
const result = await tagada.payment.processGooglePay({
checkoutSessionId: session.id,
googlePayToken: paymentData.paymentMethodData.tokenizationData.token,
});
Redirect APMs (Klarna, iDEAL, etc.)
const result = await tagada.payment.processApm({
checkoutSessionId: session.id,
paymentMethod: 'klarna',
processorId: 'proc_stripe',
});
if (result.payment.requireAction === 'redirect') {
window.location.href = result.payment.requireActionData.redirectUrl;
}
React Hook
import { usePayment } from '@tagadapay/headless-sdk/react';
function PaymentForm({ sessionId }) {
const {
processPayment,
tokenizeCard,
isProcessing,
paymentSetup,
loadPaymentSetup,
} = usePayment({
onPaymentSuccess: (result) => {
router.push(`/thank-you?orderId=${result.order?.id}`);
},
onPaymentFailed: (result) => {
setError(result.error);
},
});
const handleSubmit = async () => {
const { tagadaToken } = await tokenizeCard({ cardNumber, expiryDate, cvc });
await processPayment({ checkoutSessionId: sessionId, tagadaToken });
// 3DS redirects + return detection + polling all handled automatically
};
return (
<button onClick={handleSubmit} disabled={isProcessing}>
{isProcessing ? 'Processing...' : 'Pay Now'}
</button>
);
}
Full Hook API
| Property / Method | Description |
|---|
processPayment(opts) | High-level: tokenize → pay → 3DS → poll → callbacks. Recommended. |
pay(opts) | Low-level: submit payment, returns raw PayResult. No auto-redirect. |
tokenizeCard(card) | Tokenize card via @tagadapay/core-js |
isProcessing | True during payment processing |
paymentSetup | Cached payment method config |
loadPaymentSetup(sessionId) | Fetch available payment methods |
getExpressMethods(sessionId) | Check Apple Pay / Google Pay availability |
onPaymentSuccess | Callback when payment succeeds (including after 3DS return) |
onPaymentFailed | Callback when payment fails or is declined |
Low-Level API
For advanced use cases, you can create instruments and process payments separately:
// Create a reusable payment instrument
const { paymentInstrument } = await tagada.payment.createInstrument({
tagadaToken,
storeId: 'store_xxx',
customerData: { email: 'jane@example.com' },
});
// Create 3DS session
const threeds = await tagada.payment.create3dsSession({
paymentInstrumentId: paymentInstrument.id,
sessionData: { sessionId: 'bt_session_xyz' },
});
// Process with instrument directly
const result = await tagada.payment.payDirect({
checkoutSessionId: session.id,
paymentInstrumentId: paymentInstrument.id,
threedsSessionId: threeds.id,
});
Need even more control? For instrument-level management, MIT (merchant-initiated) charges, auth+capture flows, or mobile app integrations, see the Low-Level Payments guide which uses @tagadapay/core-js + REST directly.