Skip to content

Commit 8f1318b

Browse files
committed
add handlePaddleSubscriptionCanceled
1 parent 5ccc22b commit 8f1318b

2 files changed

Lines changed: 34 additions & 3 deletions

File tree

backendApi.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
import { Plan, PlanName } from './Plan'
2828
import {
2929
handlePaddleSubscriptionActivated,
30+
handlePaddleSubscriptionCanceled,
3031
handleStripeCheckoutSessionCompleted,
3132
handleStripeCustomerSubscriptionDeleted,
3233
handleStripeInvoicePaymentFailed,
@@ -238,6 +239,9 @@ app.post('/paddle_webhook', async function (req, res) {
238239
case PaddleEventName.SubscriptionActivated:
239240
await handlePaddleSubscriptionActivated(eventData)
240241
break
242+
case PaddleEventName.SubscriptionCanceled:
243+
await handlePaddleSubscriptionCanceled(eventData)
244+
break
241245
default:
242246
log.warn(
243247
`Unhandled Paddle event type ${eventData.eventType}: %j`,

subscription.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import {
99
Environment,
1010
Paddle,
1111
SubscriptionActivatedEvent,
12+
SubscriptionCanceledEvent,
1213
} from '@paddle/paddle-node-sdk'
14+
import { ok } from 'node:assert/strict'
1315

1416
const stripe = new Stripe(process.env.STRIPE_API_KEY, {
1517
apiVersion: '2023-08-16',
@@ -91,11 +93,27 @@ export async function handlePaddleSubscriptionActivated(
9193
})
9294
}
9395

96+
export async function handlePaddleSubscriptionCanceled(
97+
event: SubscriptionCanceledEvent
98+
) {
99+
const userId = (event.data.customData as { userId: string }).userId
100+
101+
ok(userId, 'userId is missing in customData')
102+
103+
const hasSubscription = await hasActivePaddleSubscription(
104+
event.data.customerId
105+
)
106+
107+
if (!hasSubscription) {
108+
await switchToPlan(userId, PlanName.FREE)
109+
}
110+
}
111+
94112
export async function handleStripeCustomerSubscriptionDeleted({
95113
metadata,
96114
customer: stripeCustomerId,
97115
}: Stripe.Subscription) {
98-
const hasSubscription = await hasActiveSubscription(
116+
const hasSubscription = await hasActiveStripeSubscription(
99117
stripeCustomerId as string
100118
)
101119

@@ -135,7 +153,7 @@ export async function handleStripeInvoicePaymentFailed({
135153
return
136154
}
137155

138-
const hasSubscription = await hasActiveSubscription(
156+
const hasSubscription = await hasActiveStripeSubscription(
139157
stripeCustomerId as string
140158
)
141159

@@ -144,7 +162,7 @@ export async function handleStripeInvoicePaymentFailed({
144162
}
145163
}
146164

147-
async function hasActiveSubscription(stripeCustomerId: string) {
165+
async function hasActiveStripeSubscription(stripeCustomerId: string) {
148166
const { subscriptions } = (await stripe.customers.retrieve(stripeCustomerId, {
149167
expand: ['subscriptions'],
150168
})) as Stripe.Customer & {
@@ -153,3 +171,12 @@ async function hasActiveSubscription(stripeCustomerId: string) {
153171

154172
return subscriptions.data.some((sub) => sub.status === 'active')
155173
}
174+
175+
async function hasActivePaddleSubscription(paddleCustomerId: string) {
176+
const subscriptions = await paddle.subscriptions.list({
177+
customerId: [paddleCustomerId],
178+
status: ['active'],
179+
})
180+
181+
return subscriptions.hasMore
182+
}

0 commit comments

Comments
 (0)