Files
WooNooW/includes/Modules/Subscription/GatewayCapabilities.php

124 lines
4.3 KiB
PHP

<?php
/**
* Gateway Capabilities — Subscription auto-renew declaration
*
* Single source of truth for "can this payment gateway auto-debit a
* subscription renewal, or does it fall through to manual?"
*
* Storage:
* wp_option('woonoow_gateway_subscription_capabilities')
* shape: [ '<gateway_id>' => [ 'subscription_auto_renew' => bool, ... ], ... ]
*
* Defaults are explicit per gateway ID so the merchant sees a meaningful
* matrix out of the box. The defaults reflect the regulatory reality
* discussed in SUBSCRIPTION_MODULE_AUDIT.md §9.5:
* - Indonesian VA/QRIS/e-wallet gateways: false (no recurring)
* - Indonesian credit-card gateways: false (BI/PCI-DSS re-auth)
* - PayPal/Stripe/Dodo: true ONLY when the merchant has a working
* adapter that implements process_subscription_renewal_payment;
* we still default to true because the integration is the common
* case in WooNooW's target market.
*
* The default for any *unknown* gateway is `false` — the safe side.
*
* @package WooNooW\Modules\Subscription
*/
namespace WooNooW\Modules\Subscription;
if (!defined('ABSPATH')) exit;
class GatewayCapabilities
{
const OPTION_KEY = 'woonoow_gateway_subscription_capabilities';
/**
* Built-in safe defaults. Keyed by WooCommerce payment-gateway ID.
*
* Filter 'woonoow_gateway_subscription_capabilities' lets adapters
* and third-party code extend this list at boot time.
*/
public static function default_capabilities(): array
{
return [
// Global auto-debit-capable gateways
'paypal' => ['subscription_auto_renew' => true],
'stripe' => ['subscription_auto_renew' => true],
'stripe_cc' => ['subscription_auto_renew' => true],
'stripe_sepa' => ['subscription_auto_renew' => true],
'dodo' => ['subscription_auto_renew' => true],
// Indonesian manual-only gateways (VA/QRIS/e-wallet/CC re-auth)
'tripay' => ['subscription_auto_renew' => false],
'midtrans' => ['subscription_auto_renew' => false],
'xendit' => ['subscription_auto_renew' => false],
'doku' => ['subscription_auto_renew' => false],
'duitku' => ['subscription_auto_renew' => false],
// Cheques / offline / no auto-debit
'cheque' => ['subscription_auto_renew' => false],
'bacs' => ['subscription_auto_renew' => false],
'cod' => ['subscription_auto_renew' => false],
];
}
/**
* Read the merged capability map: defaults < stored < filter.
* Always returns a fully-populated array (missing keys default to false).
*/
public static function all(): array
{
$stored = get_option(self::OPTION_KEY, []);
if (!is_array($stored)) {
$stored = [];
}
$merged = array_merge(self::default_capabilities(), $stored);
$merged = (array) apply_filters('woonoow_gateway_subscription_capabilities', $merged);
return $merged;
}
/**
* Single-gateway capability lookup.
* Returns true ONLY if explicitly declared true. Anything else is false.
*/
public static function supports_auto_renew(string $gateway_id): bool
{
$gateway_id = sanitize_key($gateway_id);
if ($gateway_id === '') {
return false;
}
$caps = self::all();
if (!isset($caps[$gateway_id])) {
return false; // unknown gateway: safe default
}
return !empty($caps[$gateway_id]['subscription_auto_renew']);
}
/**
* Site-level kill switch. When true, EVERY gateway is treated as
* manual regardless of per-gateway capability.
*/
public static function force_manual(): bool
{
$settings = \WooNooW\Core\ModuleRegistry::get_settings('subscription');
return !empty($settings['force_manual_renewal']);
}
/**
* The single decision function the renewal flow should call.
* Combines: kill switch > gateway capability.
*/
public static function should_attempt_auto_renew(string $gateway_id): bool
{
if (self::force_manual()) {
return false;
}
return self::supports_auto_renew($gateway_id);
}
}