ok - #311
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
Visit the preview URL for this PR (updated for commit 93f619d): https://hacklytics2027--pr-311-c59kpeud.web.app (expires Wed, 12 Aug 2026 05:01:33 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c48ba34db61581e25fe2978355160b5eefe0e83f |
|
| Filename | Overview |
|---|---|
| packages/api/src/routers/stripe.ts | Adds Stripe key-mode validation and authenticated, idempotent reconciliation of succeeded membership PaymentIntents. |
| sites/mainweb/app/(portal)/api/webhooks/stripe/route.ts | Completes the prior async-payment fix by processing Stripe's asynchronous-success event and activating memberships for linked pending payments. |
| sites/mainweb/components/portal/LinkStripeAccount.tsx | Runs payment reconciliation on portal load and after client confirmation exhausts its retries. |
| sites/mainweb/components/portal/StripePaymentModal.tsx | Retries server-side payment recording and provides a recovery message after a confirmed charge cannot immediately be recorded. |
| sites/mainweb/postcss.config.mjs | Replaces the cross-package PostCSS import with an equivalent self-contained Tailwind plugin configuration. |
Sequence Diagram
sequenceDiagram
participant U as User
participant C as Checkout
participant S as Stripe
participant W as Webhook
participant D as Database
C->>S: Create Checkout Session
S-->>W: checkout.session.completed (unpaid)
W->>D: Record pending payment linked to user
S-->>W: checkout.session.async_payment_succeeded (paid)
W->>D: Mark payment paid
W->>D: Create or update membership
U->>D: Load portal
D->>S: Search succeeded membership intents
S-->>D: Missing successful payments
D->>D: Idempotently record and activate
Reviews (2): Last reviewed commit: "lol" | Re-trigger Greptile
|
|
||
| try { | ||
| const session = await stripe.checkout.sessions.create({ |
There was a problem hiding this comment.
Async payments never activate membership
If asynchronous payment methods are enabled in the Stripe Dashboard, omitting payment_method_types allows Checkout to complete while payment is still unpaid. The webhook records that initial unpaid state, but neither handles the later asynchronous-success event nor accepts the Checkout-created PaymentIntent, so the customer can be charged without receiving membership.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6e5e4c1. Configure here.

Note
High Risk
Changes membership activation, payment recording, and webhook handling on money paths; misconfiguration or reconcile/search edge cases could grant or delay access incorrectly, though idempotency and user-scoped metadata limit blast radius.
Overview
Hardens membership payments so charges that clear in Stripe still become memberships when the browser confirm step fails, and checkout can use Dashboard-enabled payment methods without breaking settlement.
Stripe API (
stripe.ts) addsassertKeyModesMatchbefore checkout and PaymentIntent creation so live vs test secret/publishable keys fail fast with a clear error. Hosted Checkout no longer pinspayment_method_typesto card only, enabling dynamic payment methods. NewreconcileMyPaymentssearches Stripe for succeeded membership intents for the current user, inserts missingstripePaymentsrows (or links half-finished ones), and grants membership—idempotent via PaymentIntent / synthetic session ids.Webhook now handles
checkout.session.async_payment_succeededalongsidecheckout.session.completed, upgrading previously unpaid rows to paid and activating membership when async methods finally settle.Portal UI runs reconcile on
LinkStripeAccountload and when the modal reports payment succeeded but server confirm failed.StripePaymentModalretriesconfirmMembershipAfterPaymentthree times, then triggers reconcile and shows a “payment went through, membership will appear” message instead of “contact support.”Build replaces
postcss.config.js(cross-package re-export) with inlinedpostcss.config.mjsso Turbopack can load PostCSS/CSS without the__turbopack_context__.aerror.Reviewed by Cursor Bugbot for commit 93f619d. Bugbot is set up for automated code reviews on this repo. Configure here.