Skip to content

feat(paypal): guided setup wizard for manual credentials + OAuth flag gate#1120

Merged
superdav42 merged 2 commits intomainfrom
opencode/hidden-meadow
May 5, 2026
Merged

feat(paypal): guided setup wizard for manual credentials + OAuth flag gate#1120
superdav42 merged 2 commits intomainfrom
opencode/hidden-meadow

Conversation

@superdav42
Copy link
Copy Markdown
Collaborator

Summary

When the OAuth/partner integration is disabled (the default since WU_PAYPAL_OAUTH_ENABLED was added in #e9b9aede), merchants previously had to copy PayPal API credentials into a flat settings panel with no guidance and no way to verify them before saving.

This PR delivers two things:

  1. Constant gate (already shipped in commit e9b9aede) — Confines OAuth/partner code paths behind a WU_PAYPAL_OAUTH_ENABLED constant defaulting to false, so production installs make zero outbound /status probes when the partner integration is unavailable. Set the constant to true in wp-config.php to re-enable.
  2. Guided setup wizard for the manual credentials path — A five-step wizard, mirroring the host-integration wizard pattern, that walks merchants through creating PayPal REST app credentials, persists them, verifies them with PayPal, and auto-installs the webhook on success.

Wizard Flow

Step Description
Welcome Introduces the integration; sandbox vs live toggle (sandbox by default).
Get Credentials Four-step walkthrough of the PayPal Developer Dashboard with a deep link to the correct environment.
Configure Client ID + Secret form. Persists via wu_save_setting() and adds paypal-rest to active_gateways.
Test Connection Small Vue widget pings POST /v1/oauth2/token with the saved credentials. On success, auto-installs the webhook via POST /v1/notifications/webhooks. On failure, surfaces PayPal's own error message + troubleshooting list.
Done Green confirmation; both buttons land on the Payments settings tab so the merchant can run a test checkout immediately.

Settings Panel CTA

A new "Guided setup" card on the Payments settings panel links into the wizard when OAuth is disabled. The webhook URL row is no longer pinned to the legacy paypal_rest_show_manual_keys flag, so it stays visible alongside the manual credential fields in either mode.

New Files

  • inc/admin-pages/class-paypal-setup-wizard-admin-page.php
  • views/wizards/paypal-setup/{welcome,instructions,configure,test,done}.php
  • assets/js/paypal-setup-wizard.js (+ minified)
  • tests/WP_Ultimo/Admin_Pages/PayPal_Setup_Wizard_Admin_Page_Test.php

Modified Files

  • constants.php — defines WU_PAYPAL_OAUTH_ENABLED (default false).
  • inc/gateways/class-paypal-oauth-handler.php — gated on the constant.
  • inc/gateways/class-paypal-rest-gateway.php — renders the CTA and decouples the webhook URL row from the legacy manual-keys toggle.
  • inc/class-wp-ultimo.php — registers the wizard page and its AJAX handler.
  • tests/WP_Ultimo/Gateways/PayPal_OAuth_Handler{_Test,_Standalone_Test}.php — adds the constant assertion and skip helper for proxy-probe tests.

Test Plan

Automated

  • 33 new PHPUnit tests / 60 assertions (PayPal_Setup_Wizard_Admin_Page_Test) covering: page properties, sections list, sandbox/live mode detection, all section views, the configure handler (nonce, sandbox + live persistence, empty-credentials notice), AJAX handler registration, AJAX endpoint branches (bad nonce, missing credentials, PayPal rejection, transport error, success-with-webhook).
  • All existing OAuth tests still pass (skipped when the constant short-circuits, preserving coverage when undefined).
  • PHPStan clean on every changed file.
vendor/bin/phpunit --filter PayPal_Setup_Wizard_Admin_Page_Test
# 33/33 OK (60 assertions)

vendor/bin/phpstan analyse inc/admin-pages/class-paypal-setup-wizard-admin-page.php inc/gateways/class-paypal-rest-gateway.php inc/gateways/class-paypal-oauth-handler.php
# OK

Manual / Browser

End-to-end verification against a local WordPress multisite install:

  1. Welcome — renders intro, logos, sandbox checkbox.
  2. Get Credentials — 4-step PayPal Developer Dashboard walkthrough renders.
  3. Configure — submitting AQTESTclientid12345 / EBTESTsecret67890 persisted to paypal_rest_sandbox_client_id and paypal_rest_sandbox_client_secret; paypal-rest added to active_gateways (verified via wp eval).
  4. Test — Vue widget mounts, makes the AJAX call to PayPal, displays PayPal's real "Client Authentication failed" rejection with troubleshooting list.
  5. Done — green confirmation; clicking Finish! lands on ?page=wp-ultimo-settings&tab=payment-gateways.
  6. Settings CTA?page=wp-ultimo-settings&tab=payment-gateways shows the "Guided setup" card with the "Open setup wizard" button when the OAuth constant is false. No OAuth/Connect-with-PayPal button. Webhook URL row visible alongside manual credential fields.

Backwards Compatibility

  • OAuth code paths preserved verbatim; re-enable with define('WU_PAYPAL_OAUTH_ENABLED', true); in wp-config.php.
  • No database migrations.
  • No public API/hook signature changes.

superdav42 added 2 commits May 5, 2026 16:09
…flag

PayPal denied our Commerce Platform partnership, so the one-click
'Connect with PayPal' (Partner Referrals) flow is not available. Hide
the partner-only code paths behind a feature flag that defaults to
false, so non-partner installs:

- Never make outbound /status proxy probes during settings rendering
- Don't register the AJAX endpoints for the OAuth init/disconnect flow
- Don't render the OAuth connect button in the gateway settings
- Still preserve already-connected merchant data (read-only) for any
  install that was connected before the partnership ended

When Ultimate Multisite is approved as a PayPal partner again, define
WU_PAYPAL_OAUTH_ENABLED as true in wp-config.php to re-enable the
one-click flow. The handler class, AJAX endpoints, partner-token
proxy call, and PayPal-Auth-Assertion logic all remain in the
codebase ready to switch back on.

Tests: existing proxy-probe tests skip when the constant defines a
short-circuit value (the default shipped configuration). A new test
asserts the constant short-circuit returns the expected bool.
When the OAuth/partner integration is disabled (the default since
WU_PAYPAL_OAUTH_ENABLED was added), merchants previously had to copy
PayPal API credentials into a flat settings panel with no guidance and
no way to verify them before saving. This adds a five-step wizard that
walks them through the entire process and verifies the credentials with
PayPal before completing.

Wizard steps
- Welcome: introduces the integration and lets the merchant choose
  sandbox vs live (sandbox by default).
- Get Credentials: four-step walkthrough of the PayPal Developer
  Dashboard, with a deep link to the right environment.
- Configure: Sandbox/Live Client ID and Secret form, persisted via
  wu_save_setting() and adds paypal-rest to active_gateways.
- Test Connection: a small Vue widget pings POST /v1/oauth2/token with
  the saved credentials and, on success, auto-installs the webhook via
  POST /v1/notifications/webhooks. Failures surface PayPal's own error
  message plus a troubleshooting list.
- Done: green confirmation with two buttons that both land on the
  Payments tab so the merchant can run a test checkout immediately.

Settings panel CTA
- Adds a "Guided setup" card to the PayPal Payments settings that links
  into the wizard when OAuth is disabled.
- Webhook Listener URL row no longer requires the legacy
  paypal_rest_show_manual_keys flag, so it stays visible alongside the
  manual credential fields in either mode.

New files
- inc/admin-pages/class-paypal-setup-wizard-admin-page.php
- views/wizards/paypal-setup/{welcome,instructions,configure,test,done}.php
- assets/js/paypal-setup-wizard.js (+ minified)
- tests/WP_Ultimo/Admin_Pages/PayPal_Setup_Wizard_Admin_Page_Test.php

Modified
- inc/class-wp-ultimo.php registers the wizard page and its AJAX handler.
- inc/gateways/class-paypal-rest-gateway.php renders the CTA and decouples
  the webhook URL row from the legacy manual-keys toggle.

Tests
- 33 new PHPUnit tests / 60 assertions covering page properties, sections,
  sandbox/live mode detection, all section views, the configure handler
  (nonce, sandbox+live persistence, empty-credentials notice), AJAX
  handler registration, and AJAX endpoint branches (bad nonce, missing
  credentials, PayPal rejection, transport error, success-with-webhook).
- PHPStan clean on every changed file.
- Browser-verified end-to-end against the local WordPress dev install:
  welcome → instructions → configure (creds persisted) → test (real
  PayPal /v1/oauth2/token call, error UI rendered correctly) → done
  (Finish lands on Payments tab).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Warning

Rate limit exceeded

@superdav42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 32 minutes and 58 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42fc3c06-b09e-4f11-9f66-5c1cdfeadb20

📥 Commits

Reviewing files that changed from the base of the PR and between d6991bc and af59616.

⛔ Files ignored due to path filters (1)
  • assets/js/paypal-setup-wizard.min.js is excluded by !**/*.min.js
📒 Files selected for processing (14)
  • assets/js/paypal-setup-wizard.js
  • constants.php
  • inc/admin-pages/class-paypal-setup-wizard-admin-page.php
  • inc/class-wp-ultimo.php
  • inc/gateways/class-paypal-oauth-handler.php
  • inc/gateways/class-paypal-rest-gateway.php
  • tests/WP_Ultimo/Admin_Pages/PayPal_Setup_Wizard_Admin_Page_Test.php
  • tests/WP_Ultimo/Gateways/PayPal_OAuth_Handler_Standalone_Test.php
  • tests/WP_Ultimo/Gateways/PayPal_OAuth_Handler_Test.php
  • views/wizards/paypal-setup/configure.php
  • views/wizards/paypal-setup/done.php
  • views/wizards/paypal-setup/instructions.php
  • views/wizards/paypal-setup/test.php
  • views/wizards/paypal-setup/welcome.php
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch opencode/hidden-meadow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42 superdav42 merged commit 4050ba0 into main May 5, 2026
11 checks passed
@superdav42
Copy link
Copy Markdown
Collaborator Author

Summary

When the OAuth/partner integration is disabled (the default since WU_PAYPAL_OAUTH_ENABLED was added in #e9b9aede), merchants previously had to copy PayPal API credentials into a flat settings panel with no guidance and no way to verify them before saving.
This PR delivers two things:

  1. Constant gate (already shipped in commit e9b9aede) — Confines OAuth/partner code paths behind a WU_PAYPAL_OAUTH_ENABLED constant defaulting to false, so production installs make zero outbound /status probes when the partner integration is unavailable. Set the constant to true in wp-config.php to re-enable.
  2. Guided setup wizard for the manual credentials path — A five-step wizard, mirroring the host-integration wizard pattern, that walks merchants through creating PayPal REST app credentials, persists them, verifies them with PayPal, and auto-installs the webhook on success.

Wizard Flow

Step Description
Welcome Introduces the integration; sandbox vs live toggle (sandbox by default).
Get Credentials Four-step walkthrough of the PayPal Developer Dashboard with a deep link to the correct environment.
Configure Client ID + Secret form. Persists via wu_save_setting() and adds paypal-rest to active_gateways.
Test Connection Small Vue widget pings POST /v1/oauth2/token with the saved credentials. On success, auto-installs the webhook via POST /v1/notifications/webhooks. On failure, surfaces PayPal's own error message + troubleshooting list.
Done Green confirmation; both buttons land on the Payments settings tab so the merchant can run a test checkout immediately.

Settings Panel CTA

A new "Guided setup" card on the Payments settings panel links into the wizard when OAuth is disabled. The webhook URL row is no longer pinned to the legacy paypal_rest_show_manual_keys flag, so it stays visible alongside the manual credential fields in either mode.

New Files

  • inc/admin-pages/class-paypal-setup-wizard-admin-page.php
  • views/wizards/paypal-setup/{welcome,instructions,configure,test,done}.php
  • assets/js/paypal-setup-wizard.js (+ minified)
  • tests/WP_Ultimo/Admin_Pages/PayPal_Setup_Wizard_Admin_Page_Test.php

Modified Files

  • constants.php — defines WU_PAYPAL_OAUTH_ENABLED (default false).
  • inc/gateways/class-paypal-oauth-handler.php — gated on the constant.
  • inc/gateways/class-paypal-rest-gateway.php — renders the CTA and decouples the webhook URL row from the legacy manual-keys toggle.
  • inc/class-wp-ultimo.php — registers the wizard page and its AJAX handler.
  • tests/WP_Ultimo/Gateways/PayPal_OAuth_Handler{_Test,_Standalone_Test}.php — adds the constant assertion and skip helper for proxy-probe tests.

Test Plan

Automated

  • 33 new PHPUnit tests / 60 assertions (PayPal_Setup_Wizard_Admin_Page_Test) covering: page properties, sections list, sandbox/live mode detection, all section views, the configure handler (nonce, sandbox + live persistence, empty-credentials notice), AJAX handler registration, AJAX endpoint branches (bad nonce, missing credentials, PayPal rejection, transport error, success-with-webhook).
  • All existing OAuth tests still pass (skipped when the constant short-circuits, preserving coverage when undefined).
  • PHPStan clean on every changed file.
vendor/bin/phpunit --filter PayPal_Setup_Wizard_Admin_Page_Test
# 33/33 OK (60 assertions)
vendor/bin/phpstan analyse inc/admin-pages/class-paypal-setup-wizard-admin-page.php inc/gateways/class-paypal-rest-gateway.php inc/gateways/class-paypal-oauth-handler.php
# OK

Manual / Browser

End-to-end verification against a local WordPress multisite install:

  1. Welcome — renders intro, logos, sandbox checkbox.
  2. Get Credentials — 4-step PayPal Developer Dashboard walkthrough renders.
  3. Configure — submitting AQTESTclientid12345 / EBTESTsecret67890 persisted to paypal_rest_sandbox_client_id and paypal_rest_sandbox_client_secret; paypal-rest added to active_gateways (verified via wp eval).
  4. Test — Vue widget mounts, makes the AJAX call to PayPal, displays PayPal's real "Client Authentication failed" rejection with troubleshooting list.
  5. Done — green confirmation; clicking Finish! lands on ?page=wp-ultimo-settings&tab=payment-gateways.
  6. Settings CTA?page=wp-ultimo-settings&tab=payment-gateways shows the "Guided setup" card with the "Open setup wizard" button when the OAuth constant is false. No OAuth/Connect-with-PayPal button. Webhook URL row visible alongside manual credential fields.

Backwards Compatibility

  • OAuth code paths preserved verbatim; re-enable with define('WU_PAYPAL_OAUTH_ENABLED', true); in wp-config.php.
  • No database migrations.
  • No public API/hook signature changes.


Merged via PR #1120 to main.
Merged by deterministic merge pass (pulse-wrapper.sh).


aidevops.sh v3.14.72 spent 31s on this as a headless bash routine.

@superdav42
Copy link
Copy Markdown
Collaborator Author

Summary

When the OAuth/partner integration is disabled (the default since WU_PAYPAL_OAUTH_ENABLED was added in #e9b9aede), merchants previously had to copy PayPal API credentials into a flat settings panel with no guidance and no way to verify them before saving.
This PR delivers two things:

  1. Constant gate (already shipped in commit e9b9aede) — Confines OAuth/partner code paths behind a WU_PAYPAL_OAUTH_ENABLED constant defaulting to false, so production installs make zero outbound /status probes when the partner integration is unavailable. Set the constant to true in wp-config.php to re-enable.
  2. Guided setup wizard for the manual credentials path — A five-step wizard, mirroring the host-integration wizard pattern, that walks merchants through creating PayPal REST app credentials, persists them, verifies them with PayPal, and auto-installs the webhook on success.

Wizard Flow

Step Description
Welcome Introduces the integration; sandbox vs live toggle (sandbox by default).
Get Credentials Four-step walkthrough of the PayPal Developer Dashboard with a deep link to the correct environment.
Configure Client ID + Secret form. Persists via wu_save_setting() and adds paypal-rest to active_gateways.
Test Connection Small Vue widget pings POST /v1/oauth2/token with the saved credentials. On success, auto-installs the webhook via POST /v1/notifications/webhooks. On failure, surfaces PayPal's own error message + troubleshooting list.
Done Green confirmation; both buttons land on the Payments settings tab so the merchant can run a test checkout immediately.

Settings Panel CTA

A new "Guided setup" card on the Payments settings panel links into the wizard when OAuth is disabled. The webhook URL row is no longer pinned to the legacy paypal_rest_show_manual_keys flag, so it stays visible alongside the manual credential fields in either mode.

New Files

  • inc/admin-pages/class-paypal-setup-wizard-admin-page.php
  • views/wizards/paypal-setup/{welcome,instructions,configure,test,done}.php
  • assets/js/paypal-setup-wizard.js (+ minified)
  • tests/WP_Ultimo/Admin_Pages/PayPal_Setup_Wizard_Admin_Page_Test.php

Modified Files

  • constants.php — defines WU_PAYPAL_OAUTH_ENABLED (default false).
  • inc/gateways/class-paypal-oauth-handler.php — gated on the constant.
  • inc/gateways/class-paypal-rest-gateway.php — renders the CTA and decouples the webhook URL row from the legacy manual-keys toggle.
  • inc/class-wp-ultimo.php — registers the wizard page and its AJAX handler.
  • tests/WP_Ultimo/Gateways/PayPal_OAuth_Handler{_Test,_Standalone_Test}.php — adds the constant assertion and skip helper for proxy-probe tests.

Test Plan

Automated

  • 33 new PHPUnit tests / 60 assertions (PayPal_Setup_Wizard_Admin_Page_Test) covering: page properties, sections list, sandbox/live mode detection, all section views, the configure handler (nonce, sandbox + live persistence, empty-credentials notice), AJAX handler registration, AJAX endpoint branches (bad nonce, missing credentials, PayPal rejection, transport error, success-with-webhook).
  • All existing OAuth tests still pass (skipped when the constant short-circuits, preserving coverage when undefined).
  • PHPStan clean on every changed file.
vendor/bin/phpunit --filter PayPal_Setup_Wizard_Admin_Page_Test
# 33/33 OK (60 assertions)
vendor/bin/phpstan analyse inc/admin-pages/class-paypal-setup-wizard-admin-page.php inc/gateways/class-paypal-rest-gateway.php inc/gateways/class-paypal-oauth-handler.php
# OK

Manual / Browser

End-to-end verification against a local WordPress multisite install:

  1. Welcome — renders intro, logos, sandbox checkbox.
  2. Get Credentials — 4-step PayPal Developer Dashboard walkthrough renders.
  3. Configure — submitting AQTESTclientid12345 / EBTESTsecret67890 persisted to paypal_rest_sandbox_client_id and paypal_rest_sandbox_client_secret; paypal-rest added to active_gateways (verified via wp eval).
  4. Test — Vue widget mounts, makes the AJAX call to PayPal, displays PayPal's real "Client Authentication failed" rejection with troubleshooting list.
  5. Done — green confirmation; clicking Finish! lands on ?page=wp-ultimo-settings&tab=payment-gateways.
  6. Settings CTA?page=wp-ultimo-settings&tab=payment-gateways shows the "Guided setup" card with the "Open setup wizard" button when the OAuth constant is false. No OAuth/Connect-with-PayPal button. Webhook URL row visible alongside manual credential fields.

Backwards Compatibility

  • OAuth code paths preserved verbatim; re-enable with define('WU_PAYPAL_OAUTH_ENABLED', true); in wp-config.php.
  • No database migrations.
  • No public API/hook signature changes.


Merged via PR #1120 to main.
Merged by deterministic merge pass (pulse-wrapper.sh).


aidevops.sh v3.14.72 spent 27s on this as a headless bash routine.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Performance Test Results

Performance test results for 72f1e75 are in 🛎️!

Note: the numbers in parentheses show the difference to the previous (baseline) test run. Differences below 2% or 0.5 in absolute values are not shown.

URL: /

Run DB Queries Memory Before Template Template WP Total LCP TTFB LCP - TTFB
0 41 37.79 MB 787.50 ms 149.50 ms (-8.50 ms / -6% ) 973.00 ms (-65.50 ms / -7% ) 1906.00 ms (-62.00 ms / -3% ) 1815.00 ms (-53.45 ms / -3% ) 89.00 ms
1 56 49.11 MB 951.00 ms 143.50 ms 1091.50 ms 2104.00 ms 2021.70 ms 81.05 ms

@superdav42 superdav42 deleted the opencode/hidden-meadow branch May 6, 2026 12:01
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