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:
- Capability was invisible — the merchant had no way to see, declare, or override which gateways supported subscription auto-renew.
- 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.
- 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>:
- If the site-level
force_manual_renewalsetting is on, fall through to manual. (Kill switch — see below.) - Look up
<gateway_id>in the merged capability map (defaults < stored overrides <woonoow_gateway_subscription_capabilitiesfilter). - If the lookup returns
subscription_auto_renew = true, attempt auto-debit via the gateway'sprocess_subscription_renewal_paymentmethod. On success, runhandle_renewal_success. On failure, fall through to manual and notify the customer. - If the lookup is missing or false, skip auto-debit entirely, create a
manual renewal order, and send the
renewal_payment_dueemail.
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:
- Configuration — the standard 12-field schema (button text,
pause/cancel permissions, retry policy, kill switch, etc.). Driven
by the existing
SubscriptionSettingsschema. - 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 viaPOST /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.