Replace Stripe Customer Portal with in-app payment methods page (ZUP-6010)#2537
Open
max-zuplo wants to merge 6 commits into
Open
Replace Stripe Customer Portal with in-app payment methods page (ZUP-6010)#2537max-zuplo wants to merge 6 commits into
max-zuplo wants to merge 6 commits into
Conversation
…6010) The "Manage payment details" menu item used to redirect users to the Stripe- hosted Customer Portal, where they could remove their only/default card and break billing. Replace /manage-payment with a custom in-app page where users list cards, add a card via Stripe Elements, set a default, and remove a non-default card — but not their default or last card. - PaymentMethodsPage: lists methods (brand •••• last4, expiry, Default badge) with set-default and remove per row. Remove is disabled on the default/last card with an explanation; the OpenMeter 409 guard is surfaced inline too. - AddPaymentMethodDialog: lazy-loaded Stripe Elements (PaymentElement + confirmSetup with redirect "if_required"), keeping Stripe out of the base bundle. - All calls go through the gateway (/v3/zudoku-metering/:deployment/stripe/*) using the existing TanStack Query + signRequest pattern; the browser never talks to OpenMeter directly. - Adds @stripe/stripe-js and @stripe/react-stripe-js. https://claude.ai/code/session_01BUZGtV2rjrDwWU9pphd1YW
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Manage payment details profile menu item used to open the Stripe-hosted Customer Portal in a new tab — where a user could delete their only/default card and break billing (ZUP-6010). This replaces
/manage-paymentwith a custom in-app page that only manages payment methods (no subscription cancel / plan change), in@zuplo/zudoku-plugin-monetization.UX
{Brand} •••• {last4},Expires mm/yy, a Default badge on the default card.POST .../setup-intent→ modal with StripePaymentElement→confirmSetup({ redirect: "if_required" })→ refresh on success (the new card may briefly show as non-default until Stripe's webhook syncs the default — expected).zuplo/openmeter#122) still fires (e.g. stale list), its 409 message is surfaced inline.PaymentElementerrors are shown inline.Implementation
pages/PaymentMethodsPage.tsx+ lazypages/AddPaymentMethodDialog.tsx(Stripe Elements is code-split — confirmed it lands in its own chunk, not the plugin base bundle)./manage-paymentmoved into the default-layout route group and repointed to the new page; menu item no longer opens a new tab. OldManagePaymentPage.tsx(the redirect) removed./v3/zudoku-metering/:deployment/stripe/*) using the existing TanStack Query +signRequestpattern; the browser never talks to OpenMeter directly. Response types are hand-typed (no OpenAPI codegen against the gateway in this repo).@stripe/stripe-jsand@stripe/react-stripe-js.Verification
Automated (all ✓):
pnpm --filter @zuplo/zudoku-plugin-monetization typecheck,build(tsdown),vitest(26 files / 276 tests),biome lint,oxfmt.Manual E2E (run against a staging deployment with a Stripe-test app installed): this sandbox has no staging creds / Stripe test keys / running gateway, so end-to-end wasn't run here — script to validate:
/manage-payment). Empty state shows if no cards.4242 4242 4242 4242, any future expiry / CVC / ZIP → Save. Card appears (becomes default once the webhook syncs).5555 5555 5555 4444. Two cards listed; one Default.Screenshots to be attached from the staging run.
Depends on
zuplo/gateway-service#666(gateway endpoints) andzuplo/openmeter#120+#122(OpenMeter portal API + delete guard).https://claude.ai/code/session_01BUZGtV2rjrDwWU9pphd1YW
Generated by Claude Code