Payment Gateways
How WooNuxt's plugin-based payment gateway system works and how to add your own
WooNuxt uses a plugin-based architecture for payment gateways. Each gateway implements the PaymentGatewayPlugin interface and registers itself at boot. The checkout page only coordinates which gateway is active — all gateway-specific UI, validation, readiness checks, and payment processing live inside the plugin itself.
Built-in Gateways
| Plugin file | Gateway | Notes |
|---|---|---|
stripe.ts | Stripe | Payment Element, saved card support, order metadata |
paypal.ts | PayPal / PPCP | Redirect-based; redirect handling stays in useCheckout() |
cod.ts | Cash on Delivery | No client-side processing required |
cheque.ts | Cheque | No client-side processing required |
Enabling / Disabling Gateways
Add or remove plugin entries in woonuxt_base/nuxt.config.ts:
plugins: [
resolve('./app/plugins/init.ts'),
resolve('./app/plugins/payment-gateways/stripe.ts'),
resolve('./app/plugins/payment-gateways/paypal.ts'),
resolve('./app/plugins/payment-gateways/cod.ts'),
resolve('./app/plugins/payment-gateways/cheque.ts'),
],
Remove any line to disable that gateway entirely — no other code changes needed.
The PaymentGatewayPlugin Interface
type PaymentGatewayPlugin = {
id: string; // Must match the WooCommerce gateway ID (e.g. 'stripe')
name?: string; // Display name
icon?: string | ((gateway: PaymentGateway) => string | null); // Image URL or resolver
iconName?: string; // Iconify icon name fallback (e.g. 'ion:card-outline')
component?: Component; // Vue component rendered below the payment option list
// Payment option list — override to return multiple rows (e.g. saved cards + new card)
getPaymentOptions?: (gateway: PaymentGateway) => PaymentGatewayOption[];
// Lifecycle
onSelect?: (gateway?: PaymentGateway | string | null) => void | Promise<void>;
onDeselect?: () => void | Promise<void>;
reset?: () => void; // Called before each checkout attempt
// Readiness
isReady?: () => boolean; // Checkout button is disabled when false
getDisabledMessage?: () => string;
// Component wiring (used with `component`)
getComponentProps?: () => Record<string, unknown>;
getComponentEvents?: () => Record<string, (...args: unknown[]) => void>;
// Payment processing
processPayment?: () => Promise<{ success: boolean; isPaid: boolean; error?: string }>;
};
Adding a Custom Gateway
Create woonuxt_base/app/plugins/payment-gateways/your-gateway.ts:
import type { PaymentGatewayPlugin } from '#types/payment-gateway-plugin';
const myGatewayPlugin: PaymentGatewayPlugin = {
id: 'my-gateway', // Must match the WooCommerce gateway ID
name: 'My Gateway',
iconName: 'ion:wallet-outline',
isReady: () => true,
processPayment: async () => {
// Run any client-side payment logic here.
// Return isPaid: true if the payment was already captured
// (e.g. Stripe PaymentIntent succeeded).
// Return isPaid: false to let WooCommerce handle capture server-side.
return { success: true, isPaid: false };
},
};
export default defineNuxtPlugin(() => {
const { registerGateway } = usePaymentGateways();
registerGateway(myGatewayPlugin);
});
Then register it in woonuxt_base/nuxt.config.ts:
resolve('./app/plugins/payment-gateways/your-gateway.ts'),
Custom UI Component
If your gateway needs UI rendered at checkout (like a card form), set the component field:
import MyGatewayForm from '../../components/payments/MyGatewayForm.vue';
const myGatewayPlugin: PaymentGatewayPlugin = {
id: 'my-gateway',
component: MyGatewayForm,
getComponentProps: () => ({ apiKey: useRuntimeConfig().public.MY_API_KEY }),
getComponentEvents: () => ({
ready: () => { /* mark gateway ready */ },
}),
// ...
};
<PaymentGatewayComponent> in checkout.vue automatically mounts your component when the gateway is selected and passes through props and events.
Multiple Payment Options Per Gateway
getPaymentOptions() lets a single WooCommerce gateway appear as multiple selectable rows — the Stripe plugin uses this to list saved cards alongside the "Credit / Debit Card" option:
getPaymentOptions: (gateway) => [
{
id: 'my-gateway-bank',
gateway,
title: 'Bank Transfer',
iconName: 'ion:business-outline',
onSelect: () => selectBankTransfer(),
},
{
id: 'my-gateway-wallet',
gateway,
title: 'Digital Wallet',
iconName: 'ion:wallet-outline',
onSelect: () => selectWallet(),
},
],
usePaymentGateways Composable
const {
registerGateway, // (plugin: PaymentGatewayPlugin) => void
getGateway, // (id: string) => PaymentGatewayPlugin | undefined
setActiveGateway, // (gateway) => Promise<void> — triggers onSelect/onDeselect
isActiveGatewayReady, // ComputedRef<boolean>
getActiveGatewayDisabledMessage, // () => string
resetActiveGateway, // () => void — calls plugin.reset()
processActiveGatewayPayment, // () => Promise<{ success, isPaid, error? }>
} = usePaymentGateways()