-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathroute.tsx
103 lines (88 loc) · 3.55 KB
/
route.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { ActionFunction, json } from "@remix-run/node"
import { PayPlanType } from "~/models/portal/sdk"
import { Stripe, stripe } from "~/models/stripe/stripe.server"
import { getErrorMessage } from "~/utils/catchError"
import { getRequiredServerEnvVar } from "~/utils/environment"
function arrayBufferToBufferCycle(ab: ArrayBuffer) {
var buffer = Buffer.alloc(ab.byteLength)
var view = new Uint8Array(ab)
for (var i = 0; i < buffer.length; i++) {
buffer[i] = view[i]
}
return buffer
}
export const action: ActionFunction = async ({ request }) => {
const url = new URL(request.url)
// This is your Stripe CLI webhook secret for testing your endpoint locally.
const endpointSecret = getRequiredServerEnvVar("STRIPE_WEBHOOK_SECRET")
if (request.method !== "POST") {
return json({ message: "Method not allowed" }, 405)
}
const body = await request.arrayBuffer()
const buf = arrayBufferToBufferCycle(body)
let event: Stripe.Event | null = null
// Only verify the event if you have an endpoint secret defined.
// Otherwise, use the basic event deserialized with JSON.parse
if (endpointSecret) {
// Get the signature sent by Stripe
try {
const signature = request.headers.get("stripe-signature")
if (!signature) throw new Error("no signature in header")
event = stripe.webhooks.constructEvent(buf, signature, endpointSecret)
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, getErrorMessage(err))
return json({ message: "Signature mismatch" }, 401)
}
}
// Handle the event
if (event) {
switch (event.type) {
case "checkout.session.completed":
const sessionCompleted = event.data.object as Stripe.Checkout.Session
if (
sessionCompleted.subscription &&
typeof sessionCompleted.subscription === "string"
) {
const subscription = await stripe.subscriptions.update(
sessionCompleted.subscription,
{
metadata: sessionCompleted.metadata,
},
)
// there is only ever 1 subscription item in our subscriptions so just grabbing it here
await stripe.subscriptionItems.update(subscription.items.data[0].id, {
metadata: sessionCompleted.metadata,
})
if (sessionCompleted.metadata?.account_id) {
const formData = new FormData()
formData.set("id", sessionCompleted.metadata.account_id)
formData.set("type", PayPlanType.PayAsYouGoV0)
formData.set("subscription", sessionCompleted.subscription)
// update account plan and store subscription id
await fetch(`${url.origin}/api/admin/update-plan`, {
method: "post",
body: formData,
})
}
}
break
case "customer.subscription.deleted":
const subscriptionDeleted = event.data.object as Stripe.Subscription
console.log(`Customer subscription deleted for ${subscriptionDeleted.id}!`)
const accountIdDeleted = subscriptionDeleted.metadata.account_id
const formData = new FormData()
formData.set("id", accountIdDeleted)
formData.set("type", PayPlanType.FreetierV0)
await fetch(`${url.origin}/api/admin/update-plan`, {
method: "post",
body: formData,
})
break
default:
// Unexpected event type
console.log(`Unhandled event type ${event.type}.`)
return json({ message: "Unhandled event type" }, 404)
}
}
return json({ success: true }, 200)
}