@@ -5,6 +5,40 @@ import logger from '../config/logger.js';
55
66const router = express . Router ( ) ;
77
8+ const processPaidCheckout = async ( session ) => {
9+ let email = session . customer_details ?. email ;
10+ let name = session . metadata ?. name ;
11+ let productId = session . metadata ?. productId ;
12+ let plan = session . metadata ?. plan ;
13+
14+ if ( ! email || ! name ) {
15+ const customer = await retrieveCustomer ( session . customer ) ;
16+ email = email || customer . email ;
17+ name = name || customer . name ;
18+ }
19+
20+ if ( ! session . subscription ) {
21+ logger . warn ( 'No subscription found in session. This is not a subscription checkout.' , { sessionId : session . id } ) ;
22+ return ;
23+ }
24+
25+ const subscription = await retrieveSubscription ( session . subscription ) ;
26+
27+ // CRITICAL CHECK: Ensure the plan has a price greater than zero
28+ if ( subscription . items . data . length > 0 && subscription . items . data [ 0 ] . price . unit_amount > 0 ) {
29+ await createGhostMember ( {
30+ email,
31+ name,
32+ stripeCustomerId : session . customer ,
33+ stripeSubscriptionId : subscription . id ,
34+ productId,
35+ plan
36+ } ) ;
37+ } else {
38+ logger . info ( 'Skipping paid member creation for a zero-amount subscription.' ) ;
39+ }
40+ } ;
41+
842router . post (
943 '/custom-membership-stripe-webhook' ,
1044 express . raw ( { type : 'application/json' } ) ,
@@ -22,65 +56,32 @@ router.post(
2256 return res . status ( 400 ) . send ( `Webhook Error: ${ err . message } ` ) ;
2357 }
2458
25- if ( event . type === 'checkout.session.completed' ) {
26- try {
27- const session = event . data . object ;
28- logger . info ( 'Processing checkout.session.completed event' , {
29- sessionId : session . id ,
30- customer : session . customer
31- } ) ;
32-
33- // Extract info from metadata & customer if available
34- let email = session . customer_details ?. email ;
35- let name = session . metadata ?. name ;
36- let productId = session . metadata ?. productId ;
37- let plan = session . metadata ?. plan ;
38-
39- logger . debug ( 'Extracted session metadata' , {
40- emailPresent : ! ! email ,
41- namePresent : ! ! name ,
42- productId,
43- plan
44- } ) ;
45-
46- // If missing, fetch from Stripe (fallback)
47- if ( ! email || ! name ) {
48- logger . debug ( 'Missing email or name, fetching customer from Stripe' ) ;
49- const customer = await retrieveCustomer ( session . customer ) ;
50- email = email || customer . email ;
51- name = name || customer . name ;
59+ switch ( event . type ) {
60+ case 'checkout.session.completed' :
61+ try {
62+ const session = event . data . object ;
63+ if ( session . payment_status === 'paid' ) {
64+ await processPaidCheckout ( session ) ;
65+ } else {
66+ logger . info ( `Checkout session completed, but payment is not yet paid. Waiting for async_payment_succeeded. Session ID: ${ session . id } ` ) ;
67+ }
68+ } catch ( err ) {
69+ logger . error ( 'Error processing checkout.session.completed' , { error : err . message , stack : err . stack } ) ;
5270 }
71+ break ;
5372
54- // Always fetch subscription details
55- logger . debug ( 'Fetching subscription details' ) ;
56- const subscription = await retrieveSubscription ( session . subscription ) ;
57-
58- logger . info ( 'Creating Ghost member' , {
59- email : email ?. substring ( 0 , 3 ) + '...@...' + email ?. split ( '@' ) [ 1 ] ?. substring ( 0 , 3 ) ,
60- name : name ?. substring ( 0 , 2 ) + '...' ,
61- productId,
62- plan
63- } ) ;
64-
65- await createGhostMember ( {
66- email,
67- name,
68- stripeCustomerId : session . customer ,
69- stripeSubscriptionId : subscription . id ,
70- productId,
71- plan
72- } ) ;
73+ case 'checkout.session.async_payment_succeeded' :
74+ try {
75+ const session = event . data . object ;
76+ logger . info ( `Async payment succeeded for session: ${ session . id } . Proceeding with member creation.` ) ;
77+ await processPaidCheckout ( session ) ;
78+ } catch ( err ) {
79+ logger . error ( 'Error processing checkout.session.async_payment_succeeded' , { error : err . message , stack : err . stack } ) ;
80+ }
81+ break ;
7382
74- logger . info ( `Ghost member created: ${ email ?. substring ( 0 , 3 ) } ... (${ plan } plan)` ) ;
75- } catch ( err ) {
76- logger . error ( 'Error syncing with Ghost' , {
77- error : err . message ,
78- stack : err . stack ,
79- eventType : event . type
80- } ) ;
81- }
82- } else {
83- logger . debug ( 'Unhandled Stripe event type' , { eventType : event . type } ) ;
83+ default :
84+ logger . debug ( 'Unhandled Stripe event type' , { eventType : event . type } ) ;
8485 }
8586
8687 res . status ( 200 ) . end ( ) ;
0 commit comments