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 fileGatewayNotes
stripe.tsStripePayment Element, saved card support, order metadata
paypal.tsPayPal / PPCPRedirect-based; redirect handling stays in useCheckout()
cod.tsCash on DeliveryNo client-side processing required
cheque.tsChequeNo 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()
Designed and Built by Scottyzen | © 2026 WooNuxt | All rights reserved