-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Stripe and payment processing improvements #493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
import type { SubscriptionStatus } from '../plans'; | ||
import { PaymentPlanId } from '../plans'; | ||
|
||
export async function updateUserStripePaymentDetails( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just old updateUserStripePaymentDetails
from stripe/paymentDetails
, but I've split it up into two separate functions which correspond to two different actions it does.
@@ -1,7 +1,7 @@ | |||
import Stripe from 'stripe'; | |||
import { requireNodeEnvVar } from '../../server/utils'; | |||
|
|||
export const stripe = new Stripe(requireNodeEnvVar('STRIPE_API_KEY'), { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having it named stripe
makes it easy to confuse with the Stripe
namespace often imported everywhere.
And it is a client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Looks great. Just a couple comments + we need to update docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What env vars were changed here? I want to make sure we're still using the old Product IDs and vars from Stripe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any idea why this changed? I assume you didn't actually deploy anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
- Align with changes coming in wasp-lang#493
Fixes #487
The idea of this PR is to improve the current Stripe payment processing system.
However some of the changes touch a wider concepts so it also changes files outside of
payments/stripe
.Main behavioral change is that we now generate
Stripe.Invoice
for one-time payments.We didn't do that before (in older Stripe API versions it wasn't possible), so we had to handle one-time payments separately from subscriptions. Now this is unified under
invoice.paid
event.Another side-effect of above is that users who only use one-time payments also have invoices.
So it felt wrong that accessing the Stripe billing portal was only possible to users with active subscriptions.
The billing portal allows you to:
So it should be accessible to everyone.
Changes to
AccountPage.tsx
are related to that change.I've also made it so we have create customer specific billing portals.
This can be seen in
stripe/paymentProcessor.ts
'sfetchCustomerPortalUrl
.The change here is that users are automatically logged in into their Stripe customer account when they open the link:
Screen.Recording.2025-08-11.at.13.38.02.mov
One bigger change is that I removed all parsing inside of
stripe/webhookPayload.ts
. This is because Stripe already verifies the event data itself. This is enforced by its SDK. No need to parse twice. We also lost type information by using custom parsing interfaces.The rest is not really behavioral changes.
Just improvements to old code.
There is also some noise because we updated
diffs
for some old files nobody updated the diff for.Changes:
fetchStripeCustomer
email
is not a unique field forStripe.Customer
Stripe.Customer
per 1User.email
but that is enforced by our own application logicStripe.Customer.id
underUser.paymentProcessorUserId
Stripe.Customer
by itsid
, which is unique, rather by itsemail
ensureStripeCustomer
stripePaymentProcessor.createCheckoutSession
Stripe.Customer
Stripe.Checkout.Session
User
toStripe.Customer
Stripe.Customer
(rather than fetching), and we error on creating aStripe.Checkout.Session
, we won’t connectUser
to the newly createdStripe.Customer
Stripe.Customer
since we fetch it byemail
Stripe.Customer
toUser
before we create aStripe.Checkout.Session
paymentDetails.ts
User
entity, let's mention the user in the namepaymentDetails.ts
->userPaymentDetails.ts
stripePaymentProcessor.fetchCustomerPortalUrl
STRIPE_CUSTOMER_PORTAL_URL
and then we fetch it though server on the client.stripeClient.billingPortal.sessions.create
, which creates a billing portal URL for that specific customerstripeClient
now, rather than using predefined URLSTRIPE_CUSTOMER_PORTAL_URL
stripe/webhookPayload.ts
zod
schemas.stripeClient.webhooks.constructEvent
.zod
schemas.I deleted the Stripe
webhookPayload.ts
.Payment details auditing problems
webhook.ts
invoice.paid
eventcheckout.session.completed
eventsCheckoutPage.tsx
CheckoutPage.tsx
->CheckoutResultPage.tsx
AccountPage.tsx
User.paymentProcessorId
should beOther than mentioned changes I've also clean up the types and general logic to be clearer.