This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DATABASE_URL="postgresql://postgres:secret@localhost:54321/stripe" | |
POSTGRES_PASSWORD="secret" | |
STRIPE_SECRET_KEY="sk_test_************************************" | |
STRIPE_WEBHOOK_ENDPOINT_SECRET="whsec_********************************" | |
ORIGIN="http://localhost:3000" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const handleInvoicePaymentFailed = async (data: Stripe.Event.Data.Object) => { | |
const invoice = data as Stripe.Invoice; | |
const stripeSub = invoice.subscription; | |
const subId = typeof stripeSub === 'string' ? stripeSub : stripeSub?.id; | |
const subscription = await db.subscription.findFirst({ | |
where: { | |
stripe_subscription_id: subId, | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const handleCustomerSubscriptionUpdated = async ( | |
data: Stripe.Event.Data.Object | |
) => { | |
const stripeSub = data as Stripe.Subscription; | |
const subscription = await db.subscription.findFirst({ | |
where: { | |
stripe_subscription_id: stripeSub.id, | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const handleCheckoutSessionCompleted = async ( | |
session: Stripe.Event.Data.Object | |
) => { | |
const data = session as Stripe.Checkout.Session; | |
const user = await db.user.findFirst({ | |
where: { email: data.customer_email! }, | |
}); | |
const stripeSubscriptionId = data.subscription?.toString(); | |
const stripeSub = await stripe.subscriptions.retrieve(stripeSubscriptionId!); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { ActionFunction } from '@remix-run/node'; | |
import { json } from '@remix-run/node'; | |
import { stripe } from '~/stripe.server'; | |
import { handleStripeEvent } from '~/routes/webhook.server'; | |
//[credit @kiliman to get this webhook working](https://github.com/remix-run/remix/discussions/1978) | |
export const action: ActionFunction = async ({ request }) => { | |
const payload = await request.text(); | |
const sig = request.headers.get('stripe-signature')!; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { LoaderFunction } from '@remix-run/server-runtime'; | |
import { redirect } from '@remix-run/server-runtime'; | |
import { getLoggedInUser } from '~/user.server'; | |
export const loader: LoaderFunction = async () => { | |
const user = await getLoggedInUser(); | |
if (!user) { | |
return redirect('/'); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { ActionFunction } from '@remix-run/server-runtime'; | |
import { redirect } from '@remix-run/server-runtime'; | |
import { stripe } from '~/stripe.server'; | |
import { getLoggedInUser } from '~/user.server'; | |
export const action: ActionFunction = async () => { | |
const user = await getLoggedInUser(); | |
if (!user) { | |
return redirect('/'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { ActionFunction } from "@remix-run/server-runtime"; | |
import { redirect } from "@remix-run/server-runtime"; | |
import { stripeCheckout } from "~/stripe.server"; | |
import { getPriceId } from "~/types/subscription"; | |
import { getLoggedInUser } from "~/user.server"; | |
export const action: ActionFunction = async ({ request }) => { | |
const user = await getLoggedInUser(); | |
if (!user) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export enum USER_STATUS { | |
NO_ACTIVE_SUBSCRIPTION, | |
IS_IN_TRIAL, | |
IN_SUBSCRIPTION, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const plans = [ | |
{ | |
name: "Basic", | |
tier: "basic", | |
price: 5, | |
priceId: "price_1MNhAzFSrpGVHE9i8tGqm0R7", | |
}, | |
{ | |
name: "Pro", | |
tier: "pro", |