Fix: Add a new button for Stripe integration to "Fetch Products” in t…#417
Fix: Add a new button for Stripe integration to "Fetch Products” in t…#417reygcalantaol wants to merge 8 commits intodevelopfrom
Conversation
…he WPUM Stripe settings to refresh the transient cache - Add product.created, product.updated, and product.deleted stripe event hook handler @polevaultweb Resolves #416
…hooks - Fix `use` statement: `Controllers\products` → `Controllers\Products` - Replace undefined `$subscription` with `$payload` in handleProductCreated, handleProductDeleted, and handleProductUpdated webhook handlers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…not-showing-in-registration-form
- Merge develop into PR branch to resolve conflicts - Add stripe-fetch-products.spec.ts with 3 tests: - Fetch Products button visible on Stripe settings page - Button click refreshes products and redirects back - Non-admin users cannot access the fetch endpoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…l transient delete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds admin UX + backend hooks to refresh Stripe product caching in WPUM Stripe integration, including a manual “Fetch Stripe Products” action and webhook-driven cache refresh when products change in Stripe.
Changes:
- Adds a “Fetch Stripe Products” button on the Stripe settings tab that flushes and re-fetches products from Stripe.
- Adds webhook handlers for
product.created,product.updated, andproduct.deletedto refresh the cached products list. - Adds WPUnit + Playwright E2E coverage around the fetch handler behavior and webhook method wiring.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
includes/integrations/stripe/Settings.php |
Adds fetch-products button URL + admin_init handler to flush and refetch Stripe products. |
includes/integrations/stripe/StripeWebhookController.php |
Adds product webhook handlers and stores gateway mode/secret key for refreshing products cache. |
tests/wpunit/Stripe/StripeFetchProductsTest.php |
Introduces WPUnit coverage for handler guards and webhook handler method existence/visibility. |
tests/e2e/stripe-fetch-products.spec.ts |
Adds Playwright E2E coverage for button presence, redirect behavior, and permissions guard. |
tests/e2e/helpers/stripe.ts |
Adjusts Stripe settings helper to tolerate transient deletion failures in some environments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public function test_init_registers_admin_init_hook_for_fetch_products() { | ||
| // Remove any existing hooks from previous calls, then re-init. | ||
| remove_all_actions( 'admin_init' ); | ||
|
|
||
| $this->settings->init(); |
There was a problem hiding this comment.
remove_all_actions('admin_init') wipes all admin_init handlers globally and can leak into other wpunit tests, causing unrelated failures depending on execution order. Prefer asserting the hook registration without clearing global hooks, or remove only the specific callbacks you add within this test.
| public function test_init_registers_admin_init_hook_for_disconnect() { | ||
| remove_all_actions( 'admin_init' ); | ||
|
|
||
| $this->settings->init(); | ||
|
|
There was a problem hiding this comment.
remove_all_actions('admin_init') wipes all admin_init handlers globally and can leak into other wpunit tests, causing unrelated failures depending on execution order. Prefer asserting the hook registration without clearing global hooks, or remove only the specific callbacks you add within this test.
| /** | ||
| * Tests for the Stripe fetch-products handler and webhook controller methods | ||
| * introduced in PR #417. | ||
| * | ||
| * Verifies security guards (nonce, capability, query parameter) on | ||
| * Settings::handle_fetch_stripe_products() and confirms the new webhook | ||
| * handler methods exist on StripeWebhookController. |
There was a problem hiding this comment.
| protected function handleProductCreated( $payload ) { | ||
| $products = new Products( $this->secret_key, $this->gateway_mode ); | ||
| $products->all( true ); | ||
|
|
||
| do_action( 'wpum_stripe_webhook_product_updated', $payload ); | ||
|
|
||
| return new \WP_REST_Response( 'Webhook handled', 200 ); | ||
| } |
There was a problem hiding this comment.
These three product webhook handlers duplicate the same cache-refresh logic and action dispatch. Consider extracting the shared "refresh products cache" behavior into a single protected/private helper to reduce maintenance risk if this flow changes later.
| 'id' => 'test_stripe_products', | ||
| 'name' => __( 'Eligible Products', 'wp-user-manager' ), | ||
| 'desc' => sprintf( 'Select the product prices users can subscribe to on the account page. This should be the same as the products defined in the <a target="_blank" href="%s">Stripe Customer Portal Subscription settings</a>.', 'https://wpusermanager.com/article/337-recurring-subscriptions/#configure-eligible-products' ), | ||
| 'desc' => sprintf( 'Select the product prices users can subscribe to on the account page. This should be the same as the products defined in the <a target="_blank" href="%s">Stripe Customer Portal Subscription settings</a>. %s', 'https://wpusermanager.com/article/337-recurring-subscriptions/#configure-eligible-products ', $fetch_product_btn ), | ||
| 'type' => 'multiselect', |
There was a problem hiding this comment.
The documentation URL in this description has a trailing space at the end of the href string, which will be URL-encoded and can break the link target. Remove the trailing space so the anchor points to the intended section.
| // Clear product cache | ||
| $this->flush_product_cache(); | ||
|
|
||
| $products = new Products( $this->connect->get_stripe_secret(), $this->connect->get_gateway_mode() ); | ||
| $products->all( true ); | ||
|
|
There was a problem hiding this comment.
This handler triggers a Stripe API fetch via Products::all(true). Products::getProducts() does not catch exceptions from the per-product Price::all() call, so an API error here can throw and break the settings page load. Consider wrapping the fetch in a try/catch and redirecting back (optionally with an admin_notice / query flag) when the refresh fails.
| '_wpnonce', | ||
| 'fetch-products', | ||
| ) | ||
| ); |
There was a problem hiding this comment.
After removing the query args, the redirect URL no longer includes the "#/stripe" fragment, so users may be redirected away from the Stripe tab (fragments are not sent to the server). Consider appending "#/stripe" to the redirect target so the UI reliably returns to the Stripe settings tab after fetching.
| ); | |
| ); | |
| $redirect .= '#/stripe'; |
| ) | ||
| ); | ||
|
|
||
| return wp_safe_redirect( esc_url_raw( $redirect ) ); |
There was a problem hiding this comment.
wp_safe_redirect() does not terminate execution. To avoid any additional processing after sending the Location header (and to match common WP redirect patterns), call exit immediately after the redirect.
| return wp_safe_redirect( esc_url_raw( $redirect ) ); | |
| wp_safe_redirect( esc_url_raw( $redirect ) ); | |
| exit; |
Resolves #416
Summary
Adds a Fetch Stripe Products button to the Stripe settings page and webhook handlers to keep the local product cache in sync when products change in Stripe.
Changes:
product.created,product.updated, andproduct.deletedevents — automatically refreshes the product cache when Stripe products changeManual Test Plan
Prerequisites
1. Verify Fetch Products button appears
2. Test manual product fetch
3. Test with no new products
4. Test security (nonce/permissions)
_wpnoncevalue in the URL to something invalidmanage_optionscapability5. Test webhook sync (if webhook endpoint configured)
6. Test both gateway modes
WPUnit Test Coverage
21 tests in
tests/wpunit/Stripe/StripeFetchProductsTest.php:handle_fetch_stripe_productsmethod exists and is hooked toadmin_initmanage_optionscapability check, query param validationhandleProductCreated,handleProductDeleted,handleProductUpdated)protected(only accessible via dispatch)product.*events to correct handler methods🤖 Generated with Claude Code