@@ -2,13 +2,12 @@ import { type MiddlewareConfigFn, HttpError } from 'wasp/server';
22import { type PaymentsWebhook } from 'wasp/server/api' ;
33import { type PrismaClient } from '@prisma/client' ;
44import express from 'express' ;
5- import { paymentPlans , PaymentPlanId } from '../plans' ;
5+ import { paymentPlans , PaymentPlanId , SubscriptionStatus } from '../plans' ;
66import { updateUserLemonSqueezyPaymentDetails } from './paymentDetails' ;
77import { type Order , type Subscription , getCustomer } from '@lemonsqueezy/lemonsqueezy.js' ;
88import crypto from 'crypto' ;
99import { requireNodeEnvVar } from '../../server/utils' ;
1010
11-
1211export const lemonSqueezyWebhook : PaymentsWebhook = async ( request , response , context ) => {
1312 try {
1413 const rawBody = request . body . toString ( 'utf8' ) ;
@@ -94,7 +93,11 @@ async function handleOrderCreated(data: Order, userId: string, prismaUserDelegat
9493 console . log ( `Order ${ order_number } created for user ${ lemonSqueezyId } ` ) ;
9594}
9695
97- async function handleSubscriptionCreated ( data : Subscription , userId : string , prismaUserDelegate : PrismaClient [ 'user' ] ) {
96+ async function handleSubscriptionCreated (
97+ data : Subscription ,
98+ userId : string ,
99+ prismaUserDelegate : PrismaClient [ 'user' ]
100+ ) {
98101 const { customer_id, status, variant_id } = data . data . attributes ;
99102 const lemonSqueezyId = customer_id . toString ( ) ;
100103
@@ -106,7 +109,7 @@ async function handleSubscriptionCreated(data: Subscription, userId: string, pri
106109 lemonSqueezyId,
107110 userId,
108111 subscriptionPlan : planId ,
109- subscriptionStatus : status ,
112+ subscriptionStatus : status as SubscriptionStatus ,
110113 datePaid : new Date ( ) ,
111114 } ,
112115 prismaUserDelegate
@@ -118,26 +121,29 @@ async function handleSubscriptionCreated(data: Subscription, userId: string, pri
118121 console . log ( `Subscription created for user ${ lemonSqueezyId } ` ) ;
119122}
120123
121-
122124// NOTE: LemonSqueezy's 'subscription_updated' event is sent as a catch-all and fires even after 'subscription_created' & 'order_created'.
123- async function handleSubscriptionUpdated ( data : Subscription , userId : string , prismaUserDelegate : PrismaClient [ 'user' ] ) {
125+ async function handleSubscriptionUpdated (
126+ data : Subscription ,
127+ userId : string ,
128+ prismaUserDelegate : PrismaClient [ 'user' ]
129+ ) {
124130 const { customer_id, status, variant_id } = data . data . attributes ;
125131 const lemonSqueezyId = customer_id . toString ( ) ;
126132
127133 const planId = getPlanIdByVariantId ( variant_id . toString ( ) ) ;
128134
129135 // We ignore other statuses like 'paused' and 'unpaid' for now, because we block user usage if their status is NOT active.
130136 // Note that a status changes to 'past_due' on a failed payment retry, then after 4 unsuccesful payment retries status
131- // becomes 'unpaid' and finally 'expired' (i.e. 'deleted').
132- // NOTE: ability to pause or trial a subscription is something that has to be additionally configured in the lemon squeezy dashboard.
137+ // becomes 'unpaid' and finally 'expired' (i.e. 'deleted').
138+ // NOTE: ability to pause or trial a subscription is something that has to be additionally configured in the lemon squeezy dashboard.
133139 // If you do enable these features, make sure to handle these statuses here.
134140 if ( status === 'past_due' || status === 'active' ) {
135141 await updateUserLemonSqueezyPaymentDetails (
136142 {
137143 lemonSqueezyId,
138144 userId,
139145 subscriptionPlan : planId ,
140- subscriptionStatus : status ,
146+ subscriptionStatus : status as SubscriptionStatus ,
141147 ...( status === 'active' && { datePaid : new Date ( ) } ) ,
142148 } ,
143149 prismaUserDelegate
@@ -146,31 +152,41 @@ async function handleSubscriptionUpdated(data: Subscription, userId: string, pri
146152 }
147153}
148154
149- async function handleSubscriptionCancelled ( data : Subscription , userId : string , prismaUserDelegate : PrismaClient [ 'user' ] ) {
155+ async function handleSubscriptionCancelled (
156+ data : Subscription ,
157+ userId : string ,
158+ prismaUserDelegate : PrismaClient [ 'user' ]
159+ ) {
150160 const { customer_id } = data . data . attributes ;
151161 const lemonSqueezyId = customer_id . toString ( ) ;
152162
153163 await updateUserLemonSqueezyPaymentDetails (
154164 {
155165 lemonSqueezyId,
156166 userId,
157- subscriptionStatus : 'cancel_at_period_end' , // cancel_at_period_end is the Stripe equivalent of LemonSqueezy's cancelled
167+ // cancel_at_period_end is the Stripe equivalent of LemonSqueezy's cancelled
168+ subscriptionStatus : 'cancel_at_period_end' as SubscriptionStatus ,
158169 } ,
159170 prismaUserDelegate
160171 ) ;
161172
162173 console . log ( `Subscription cancelled for user ${ lemonSqueezyId } ` ) ;
163174}
164175
165- async function handleSubscriptionExpired ( data : Subscription , userId : string , prismaUserDelegate : PrismaClient [ 'user' ] ) {
176+ async function handleSubscriptionExpired (
177+ data : Subscription ,
178+ userId : string ,
179+ prismaUserDelegate : PrismaClient [ 'user' ]
180+ ) {
166181 const { customer_id } = data . data . attributes ;
167182 const lemonSqueezyId = customer_id . toString ( ) ;
168183
169184 await updateUserLemonSqueezyPaymentDetails (
170185 {
171186 lemonSqueezyId,
172187 userId,
173- subscriptionStatus : 'deleted' , // deleted is the Stripe equivalent of LemonSqueezy's expired
188+ // deleted is the Stripe equivalent of LemonSqueezy's expired
189+ subscriptionStatus : SubscriptionStatus . Deleted ,
174190 } ,
175191 prismaUserDelegate
176192 ) ;
@@ -181,7 +197,9 @@ async function handleSubscriptionExpired(data: Subscription, userId: string, pri
181197async function fetchUserCustomerPortalUrl ( { lemonSqueezyId } : { lemonSqueezyId : string } ) : Promise < string > {
182198 const { data : lemonSqueezyCustomer , error } = await getCustomer ( lemonSqueezyId ) ;
183199 if ( error ) {
184- throw new Error ( `Error fetching customer portal URL for user lemonsqueezy id ${ lemonSqueezyId } : ${ error } ` ) ;
200+ throw new Error (
201+ `Error fetching customer portal URL for user lemonsqueezy id ${ lemonSqueezyId } : ${ error } `
202+ ) ;
185203 }
186204 const customerPortalUrl = lemonSqueezyCustomer . data . attributes . urls . customer_portal ;
187205 if ( ! customerPortalUrl ) {
@@ -198,4 +216,5 @@ function getPlanIdByVariantId(variantId: string): PaymentPlanId {
198216 throw new Error ( `No plan with LemonSqueezy variant id ${ variantId } ` ) ;
199217 }
200218 return planId ;
201- }
219+ }
220+
0 commit comments