Skip to content

Add multi-gateway support - #3631

Draft
dparker1005 wants to merge 1 commit into
strangerstudios:devfrom
dparker1005:multi-gateway-support
Draft

Add multi-gateway support#3631
dparker1005 wants to merge 1 commit into
strangerstudios:devfrom
dparker1005:multi-gateway-support

Conversation

@dparker1005

Copy link
Copy Markdown
Member

Summary

Adds the ability to enable multiple payment gateways simultaneously so members can choose their preferred payment method at checkout. This is a v4.0 breaking change — custom checkout templates will need to be updated.

Core Infrastructure

  • New pmpro_get_enabled_gateways() function with automatic migration from the legacy single pmpro_gateway option
  • New static methods on PMProGateway base class: get_checkout_label(), enqueue_checkout_scripts(), show_checkout_fields(), requires_billing_address(), get_required_billing_fields(), show_submit_button() — with legacy hook detection for gateways that haven't been updated
  • pmpro_getGateway() marked as deprecated

Admin UI

  • Payment Settings page redesigned with sortable Active Gateways table, collapsible Available Gateways panel, and activate/deactivate buttons
  • Gateway order determines checkout display order (first = default)

Checkout & Billing

  • Gateway selector radio buttons when multiple gateways enabled
  • Per-gateway payment field containers and submit buttons with JS toggling
  • Billing address visibility respects each gateway's requires_billing_address()
  • Free-level fallback submit button for discount-code-to-free scenarios
  • Billing page updated to use gateway static methods

Gateway Updates (Stripe, Check, PayPal Express)

  • Each overrides the new static methods for gateway-specific behavior
  • Stripe: SCA intent localization preserved, Stripe Checkout (offsite) handled
  • PayPal Express: offsite redirect button with free-level fallback

Backward Compatibility

  • Base class detects legacy filter callbacks via hooked filters AND method_exists() (covers secondary gateways whose init() didn't fire)
  • pmpro_gateway option kept in sync for legacy code
  • Pay by Check add-on UI deferred via pmpro_show_gateway_selector filter
  • Add PayPal Express add-on added to deprecated add-ons list (auto-deactivated)

Open TODOs

  • Live price updates at checkout — Could simplify the show/hide logic for payment fields when a discount code makes a level free/paid, replacing the current applydiscountcode.php JS approach
  • Per-level gateway configuration — The Pay by Check add-on currently allows enabling/disabling gateways per level. How should core support this? Per-level gateway overrides in the level editor?
  • Address for Free Levels Add On — How should this function with multi-gateway? Per-gateway toggle to force billing address? A sitewide checkbox? Currently requires_billing_address() is per-gateway but there's no admin-facing override
  • Duplicate DOM IDs — When two onsite gateways are enabled, each gateway's show_checkout_fields() renders elements with the same IDs. Gateway JS that binds by ID hits the wrong element. Needs a namespacing strategy
  • Deprecated gateways as secondary — Deprecated gateways (Braintree, etc.) render fields but not scripts when used as secondary gateways. Their init() only hooks checkout actions when they're the active gateway. They would need enqueue_checkout_scripts() overrides to work as secondary gateways
  • Discount code AJAX — Doesn't send the selected gateway parameter, so the server response can't be gateway-aware
  • Replace all @since TBD tags with actual version number before release

Test Plan

  • Fresh install: single gateway, no radio buttons, behavior identical to current
  • Enable Stripe + Check: radio buttons appear, fields toggle, both checkout flows complete
  • Enable Stripe + PayPal Express: on-site fields for Stripe, redirect button for PayPal
  • Stripe Checkout (offsite) + Check: no card fields for Stripe, check shows instructions
  • Stripe SCA/3D Secure: verify authentication flow completes after redirect
  • Discount code makes level free: gateway selector hides, free submit button shows
  • Discount code removed (level paid again): gateway selector restores, correct fields show
  • Update billing: uses original subscription gateway, correct fields render
  • Admin: activate/deactivate gateways, drag to reorder, verify save persists order
  • Admin: deactivate all gateways, verify testing mode notice
  • Pay by Check add-on active: core selector deferred, PBC radio buttons used instead
  • Add PayPal Express add-on: auto-deactivated with admin notice

🤖 Generated with Claude Code

Adds the ability to enable multiple payment gateways simultaneously so
members can choose their preferred payment method at checkout.

Core infrastructure:
- New pmpro_get_enabled_gateways() function with automatic migration
  from the legacy single pmpro_gateway option
- New static methods on PMProGateway base class: get_checkout_label(),
  enqueue_checkout_scripts(), show_checkout_fields(),
  requires_billing_address(), get_required_billing_fields(),
  show_submit_button() with legacy hook detection for gateways that
  have not been updated
- pmpro_getGateway() marked as deprecated

Admin UI:
- Payment Settings page redesigned with sortable Active Gateways table,
  collapsible Available Gateways panel, and activate/deactivate buttons
- Gateway order determines checkout display order

Checkout:
- Gateway selector radio buttons rendered when multiple gateways enabled
- Per-gateway payment field containers with JS-based toggling
- Per-gateway submit buttons (offsite gateways show branded buttons)
- Billing address visibility respects each gateway requirements
- Free-level fallback submit button for discount-code-to-free scenarios
- pmpro_show_gateway_selector filter for add-on compatibility

Billing page:
- Uses gateway static methods for field rendering and billing address

Gateway updates (Stripe, Check, PayPal Express):
- Override new static methods for gateway-specific behavior
- Stripe: SCA intent localization preserved, Stripe Checkout (offsite)
  handled, billing address setting respected
- Check: no payment fields, no billing address
- PayPal Express: offsite redirect button, free-level fallback

Backward compatibility:
- Base class detects legacy filter callbacks via hooked filters AND
  class method existence (covers secondary gateways whose init did not fire)
- pmpro_gateway option kept in sync for legacy code
- Pay by Check add-on UI deferred via pmpro_show_gateway_selector
- Add PayPal Express add-on added to deprecated add-ons list

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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