Skip to content

fix(onboarding): preserve BCDC state during branded-only mode upgrades (5897)#4104

Open
Narek13 wants to merge 3 commits intodev/developfrom
dev/PCP-5897-branded-only-acdc-visible-on-block-chekout
Open

fix(onboarding): preserve BCDC state during branded-only mode upgrades (5897)#4104
Narek13 wants to merge 3 commits intodev/developfrom
dev/PCP-5897-branded-only-acdc-visible-on-block-chekout

Conversation

@Narek13
Copy link
Collaborator

@Narek13 Narek13 commented Feb 20, 2026

Issue Description

When upgrading from v3.4.0 with branded-only mode enabled, BCDC (PayPal-branded card button) was being disabled even though merchants had it enabled. This violated the acceptance criteria that merchants' BCDC state should be preserved during upgrades.

Root Causes

For new merchants:
During onboarding, toggle_payment_gateways() enables ACDC, Apple Pay, and Google Pay for business sellers without checking if branded-only mode is active. These white-label methods should never be enabled in branded-only mode.

For existing merchants:
Previous versions had ACDC enabled in settings but hidden from the UI in branded-only mode. When disabling ACDC during the upgrade:

  1. Calling is_method_enabled(CreditCardGateway::ID) triggers WC()->payment_gateways()->payment_gateways()
  2. This initializes ALL WooCommerce gateways, including both ACDC and BCDC
  3. Gateway initialization has side effects that modify BCDC state (likely due to interdependencies or filters that run during init)
  4. BCDC's original enabled state is lost before we can preserve it

PR Description

Changes Made

1. Prevent white-label methods during onboarding (new merchants)

Added action hook on woocommerce_paypal_payments_toggle_payment_gateways_apms that runs during the onboarding flow to immediately disable ACDC, Apple Pay, and Google Pay in branded-only mode. This prevents them from being enabled even temporarily.

add_action(
    'woocommerce_paypal_payments_toggle_payment_gateways_apms',
    static function ( PaymentSettings $payment_settings ): void {
        $payment_settings->toggle_method_state( CreditCardGateway::ID, false );
        $payment_settings->toggle_method_state( ApplePayGateway::ID, false );
        $payment_settings->toggle_method_state( GooglePayGateway::ID, false );
    }
);

2. Preserve BCDC state during upgrades (existing merchants)

Read BCDC's enabled state directly from WordPress options (woocommerce_ppcp-card-button-gateway_settings) BEFORE any PaymentSettings method calls that would trigger gateway initialization.

This is critical because:

  • is_method_enabled() and toggle_method_state() call WC()->payment_gateways()->payment_gateways()
  • This initializes all gateways and has side effects that modify BCDC state
  • Must capture BCDC state from raw DB before this initialization occurs
// Read BCDC state before any PaymentSettings calls
$gateway_name     = CardButtonGateway::ID;
$gateway_settings = get_option( "woocommerce_{$gateway_name}_settings", array() );
$gateway_enabled  = $gateway_settings['enabled'] ?? false;

if ( $payment_settings->is_method_enabled( CreditCardGateway::ID ) ) {
    $payment_settings->toggle_method_state( CreditCardGateway::ID, false );
    // Re-enable BCDC if it was previously enabled
    if ( $gateway_enabled === 'yes' ) {
        $payment_settings->toggle_method_state( CardButtonGateway::ID, true );
    }
    $payment_settings->save();
}

Technical Details

Gateway Initialization Side Effects

The PaymentSettings::get_gateway() method calls WC()->payment_gateways()->payment_gateways() which initializes all WooCommerce payment gateways, not just the requested one. This initialization:

  • Runs gateway constructors and init() methods
  • Triggers WordPress filters/actions registered by gateways
  • Applies business logic that checks relationships between gateways (e.g., BCDC might defer to ACDC)
  • Can modify gateway settings based on current configuration

This is why we must read BCDC state from raw WordPress options before making any PaymentSettings calls - to capture its true state before the initialization cycle corrupts it.

Testing

Acceptance Criteria:

  • In branded-only mode, only BCDC is available in admin settings and visible on frontend checkout (ACDC, Google Pay, and Apple Pay are disabled and hidden)
  • When upgrading the plugin to the PR's version:
    • If merchant had BCDC enabled → it remains enabled after the upgrade
    • If merchant had BCDC disabled → it remains disabled after the upgrade
  • Verify BCDC card button is only displayed on checkout and block checkout pages when in branded-only mode
  • Verify all payment methods work correctly in non-branded-only mode to ensure the fix didn't introduce regressions

When upgrading from v3.4.0 with branded-only mode enabled, BCDC was
being disabled even though merchants had it enabled. This occurred
because:

1. Existing merchants had ACDC enabled in settings (but hidden from UI)
2. Calling PaymentSettings methods to disable ACDC triggered WooCommerce
   gateway initialization for all gateways
3. This initialization had side effects that modified BCDC state
4. BCDC's enabled state was lost before we could preserve it

Solution:
- Add action hook on 'woocommerce_paypal_payments_toggle_payment_gateways_apms'
  to prevent white-label methods from being enabled during new merchant
  onboarding in branded-only mode
- For existing merchants: read BCDC state directly from WordPress options
  BEFORE any PaymentSettings calls that would trigger gateway initialization
- Disable ACDC, then re-enable BCDC if it was previously enabled
- This preserves BCDC state across upgrades
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant