Files
WooNooW/docs/SUBSCRIPTION_GATEWAY_CAPABILITIES.md

6.9 KiB

Subscription Gateway Capabilities

How WooNooW decides which payment gateways can auto-debit subscription renewals, and how merchants can override that decision.

Why this exists

Before this system, a subscription renewal would attempt to call $gateway->process_subscription_renewal_payment($order, $subscription) if the gateway happened to implement that method. That had three problems:

  1. Capability was invisible — the merchant had no way to see, declare, or override which gateways supported subscription auto-renew.
  2. The default was unsafe — a gateway without the method silently fell through to manual payment. The system "worked," but the merchant believed auto-debit was happening and customers were surprised when they had to log in and pay manually.
  3. No override was possible — a merchant running a custom Stripe wrapper that does support auto-debit could not declare it, and a merchant using stock Stripe could not opt out.

What it is now

A per-gateway capability table that the merchant (or a WooNooW defaults policy) controls explicitly. The system consults the table at renewal time and decides whether to attempt auto-debit or fall through to manual. PHP method existence alone is no longer authoritative.

Storage

wp_option('woonoow_gateway_subscription_capabilities', [
    '<gateway_id>' => [ 'subscription_auto_renew' => bool ],
    ...
])

Decision flow

For a renewal where the subscription's stored payment_method is <gateway_id>:

  1. If the site-level force_manual_renewal setting is on, fall through to manual. (Kill switch — see below.)
  2. Look up <gateway_id> in the merged capability map (defaults < stored overrides < woonoow_gateway_subscription_capabilities filter).
  3. If the lookup returns subscription_auto_renew = true, attempt auto-debit via the gateway's process_subscription_renewal_payment method. On success, run handle_renewal_success. On failure, fall through to manual and notify the customer.
  4. If the lookup is missing or false, skip auto-debit entirely, create a manual renewal order, and send the renewal_payment_due email.

The decision is made by WooNooW\Modules\Subscription\GatewayCapabilities::should_attempt_auto_renew($gateway_id).

Built-in defaults

Gateway ID Default auto-renew Why
paypal true PayPal Reference Transactions supports recurring
stripe true With a WooNooW Stripe adapter implementing the contract
stripe_cc true Alias for stripe credit card
stripe_sepa true SEPA Direct Debit supports recurring
dodo true Dodo Payments supports recurring subscriptions
tripay false VA/QRIS/e-wallet — no recurring
midtrans false VA/QRIS/e-wallet — no recurring
xendit false Indonesian credit card requires customer re-auth (BI/PCI-DSS)
doku false Indonesian manual-only
duitku false Indonesian manual-only
cheque, bacs, cod false Offline / no auto-debit
any unknown false Safe default

The default for any unknown gateway is false. A merchant who has a custom adapter for an unknown gateway can flip the toggle in the admin UI (Settings → Modules → Subscription → Gateway Auto-Renew Capabilities).

Why per-gateway, not site-level "billing mode"

A site-level "manual vs auto" toggle asks the merchant to understand a concept that does not exist in their head. The merchant thinks in payment gateways. A checkbox next to each gateway in the admin is data the merchant already knows.

Additionally:

  • Different merchants use different gateways. A site-level toggle forces a single behavior even when the merchant runs two gateways (one auto-capable, one not) for different products.
  • The capability is a property of the integration, not of the store. The merchant did not choose "manual mode" — they chose Tripay, and Tripay is a manual gateway.
  • The capability can change as WooNooW ships new adapters. A per-gateway table updates as adapters ship.

Site-level kill switch

There is one site-level override:

  • force_manual_renewal (default off) — when on, all renewals are manual regardless of the per-gateway capability table. Useful as a kill switch during an incident or regulatory change.

This lives in the standard module settings form (Settings → Modules → Subscription) and is not on the gateway capability matrix screen.

Admin UI

Settings → Modules → Subscription now has two sections:

  1. Configuration — the standard 12-field schema (button text, pause/cancel permissions, retry policy, kill switch, etc.). Driven by the existing SubscriptionSettings schema.
  2. Gateway Auto-Renew Capabilities — one row per WooCommerce payment gateway with a per-gateway toggle. Built dynamically from WC()->payment_gateways(). The merchant can flip a gateway on or off, and the change is persisted via POST /woonoow/v1/subscriptions/gateway-capabilities.

When the kill switch is on, every row shows a "Forced manual" badge and the per-gateway toggles are disabled.

Customer messaging

The order-pay response (/checkout/order/{id}) and the subscription detail response both include gateway_supports_auto_renew. The customer-spa OrderPay page renders a different callout for manual gateways (amber) versus auto-renew gateways (blue):

  • Auto-renew: "Your subscription will renew automatically on the date shown below."
  • Manual: "Your saved payment method cannot be charged automatically for this gateway, so please complete the payment to continue your subscription."

This ensures the customer is never promised auto-debit that the system will not deliver.

Extending the table (for gateway adapter authors)

A gateway adapter or third-party plugin can extend the capability table at boot time via the woonoow_gateway_subscription_capabilities filter:

add_filter('woonoow_gateway_subscription_capabilities', function ($caps) {
    $caps['my_custom_stripe'] = ['subscription_auto_renew' => true];
    return $caps;
});

The adapter is then responsible for implementing process_subscription_renewal_payment(WC_Order $order, $subscription) on its gateway class. If the method does not exist, the capability declaration is meaningless — the renewal will fall through to manual.

Migration / no migration

This is a behavioral improvement, not a schema change. Existing subscriptions keep their payment_method value. The capability table is consulted at renewal time, not retroactively.

If a merchant upgrades WooNooW and previously relied on PHP method existence alone, the renewal will continue to work — but the merchant will now see the capability matrix and can confirm or override each gateway.