mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-03-29 11:12:19 +01:00
fix requested changes
This commit is contained in:
parent
d3e67b4eba
commit
a986348a7e
@ -35,10 +35,14 @@ interface CreateStripeCheckoutSessionParams {
|
||||
mode: StripeMode;
|
||||
}
|
||||
|
||||
export async function createStripeCheckoutSession({ priceId, customerId, mode }: CreateStripeCheckoutSessionParams) {
|
||||
export async function createStripeCheckoutSession({
|
||||
priceId,
|
||||
customerId,
|
||||
mode,
|
||||
}: CreateStripeCheckoutSessionParams) {
|
||||
try {
|
||||
const metadata = returnMetadataByMode({ mode, priceId });
|
||||
|
||||
const paymentIntentData = getPaymentIntentData({ mode, priceId });
|
||||
|
||||
return await stripe.checkout.sessions.create({
|
||||
line_items: [
|
||||
{
|
||||
@ -58,7 +62,7 @@ export async function createStripeCheckoutSession({ priceId, customerId, mode }:
|
||||
// We do this so that we can capture priceId in the payment_intent.succeeded webhook
|
||||
// and easily confirm the user's payment based on the price id. For subscriptions, we can get the price id
|
||||
// in the customer.subscription.updated webhook via the line_items field.
|
||||
...metadata
|
||||
payment_intent_data: paymentIntentData,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -66,21 +70,16 @@ export async function createStripeCheckoutSession({ priceId, customerId, mode }:
|
||||
}
|
||||
}
|
||||
|
||||
interface ReturnMetadataByModeParams {
|
||||
mode: StripeMode;
|
||||
priceId: string;
|
||||
}
|
||||
|
||||
interface ReturnMetadataByModeResult {
|
||||
payment_intent_data: Stripe.Checkout.SessionCreateParams.PaymentIntentData;
|
||||
}
|
||||
|
||||
function returnMetadataByMode({ mode, priceId }: ReturnMetadataByModeParams): ReturnMetadataByModeResult | undefined {
|
||||
function getPaymentIntentData({ mode, priceId }: { mode: StripeMode; priceId: string }):
|
||||
| {
|
||||
metadata: { priceId: string };
|
||||
}
|
||||
| undefined {
|
||||
switch (mode) {
|
||||
case 'subscription':
|
||||
return undefined;
|
||||
case 'payment':
|
||||
return { payment_intent_data: { metadata: { priceId } } };
|
||||
return { metadata: { priceId } };
|
||||
default:
|
||||
assertUnreachable(mode);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { type PrismaClient } from '@prisma/client';
|
||||
import express from 'express';
|
||||
import { Stripe } from 'stripe';
|
||||
import { stripe } from './stripeClient';
|
||||
import { paymentPlans, PaymentPlanId, SubscriptionStatus } from '../plans';
|
||||
import { paymentPlans, PaymentPlanId, SubscriptionStatus, PaymentPlanEffect, PaymentPlan } from '../plans';
|
||||
import { updateUserStripePaymentDetails } from './paymentDetails';
|
||||
import { emailSender } from 'wasp/server/email';
|
||||
import { assertUnreachable } from '../../shared/utils';
|
||||
@ -35,7 +35,6 @@ export const stripeWebhook: PaymentsWebhook = async (request, response, context)
|
||||
break;
|
||||
case 'payment_intent.succeeded':
|
||||
const paymentIntent = event.data.object as Stripe.PaymentIntent;
|
||||
if (paymentIntent.invoice) return; // We handle invoices in the invoice.paid webhook.
|
||||
await handlePaymentIntentSucceeded(paymentIntent, prismaUserDelegate);
|
||||
break;
|
||||
case 'customer.subscription.updated':
|
||||
@ -77,7 +76,11 @@ export async function handleCheckoutSessionCompleted(
|
||||
});
|
||||
const lineItemPriceId = extractPriceId(line_items);
|
||||
const planId = getPlanIdByPriceId(lineItemPriceId);
|
||||
const { subscriptionPlan } = getPlanEffectDetailsById(planId);
|
||||
const plan = paymentPlans[planId];
|
||||
if (plan.effect.kind === 'credits') {
|
||||
return;
|
||||
}
|
||||
const { subscriptionPlan } = getPlanEffectPaymentDetails({ planId, planEffect: plan.effect });
|
||||
|
||||
return updateUserStripePaymentDetails(
|
||||
{ userStripeId, subscriptionPlan },
|
||||
@ -97,6 +100,12 @@ export async function handlePaymentIntentSucceeded(
|
||||
paymentIntent: Stripe.PaymentIntent,
|
||||
prismaUserDelegate: PrismaClient['user']
|
||||
) {
|
||||
// We handle invoices in the invoice.paid webhook. Invoices exist for subscription payments,
|
||||
// but not for one-time payment/credits products which use the Stripe `payment` mode on checkout sessions.
|
||||
if (paymentIntent.invoice) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userStripeId = validateUserStripeIdOrThrow(paymentIntent.customer);
|
||||
const datePaid = new Date(paymentIntent.created * 1000);
|
||||
|
||||
@ -109,10 +118,15 @@ export async function handlePaymentIntentSucceeded(
|
||||
}
|
||||
|
||||
const planId = getPlanIdByPriceId(metadata.priceId);
|
||||
const { subscriptionPlan, numOfCreditsPurchased } = getPlanEffectDetailsById(planId);
|
||||
const plan = paymentPlans[planId];
|
||||
if (plan.effect.kind === 'subscription') {
|
||||
return;
|
||||
}
|
||||
|
||||
const { numOfCreditsPurchased } = getPlanEffectPaymentDetails({ planId, planEffect: plan.effect });
|
||||
|
||||
return updateUserStripePaymentDetails(
|
||||
{ userStripeId, subscriptionPlan, numOfCreditsPurchased, datePaid },
|
||||
{ userStripeId, numOfCreditsPurchased, datePaid },
|
||||
prismaUserDelegate
|
||||
);
|
||||
}
|
||||
@ -195,21 +209,16 @@ function getPlanIdByPriceId(priceId: string): PaymentPlanId {
|
||||
return planId;
|
||||
}
|
||||
|
||||
function getPlanEffectDetailsById(planId: PaymentPlanId) {
|
||||
const plan = paymentPlans[planId];
|
||||
let subscriptionPlan: PaymentPlanId | undefined;
|
||||
let numOfCreditsPurchased: number | undefined;
|
||||
|
||||
switch (plan.effect.kind) {
|
||||
function getPlanEffectPaymentDetails({ planId, planEffect }: { planId: PaymentPlanId, planEffect: PaymentPlanEffect}): {
|
||||
subscriptionPlan: PaymentPlanId | undefined;
|
||||
numOfCreditsPurchased: number | undefined;
|
||||
} {
|
||||
switch (planEffect.kind) {
|
||||
case 'subscription':
|
||||
subscriptionPlan = planId;
|
||||
break;
|
||||
return { subscriptionPlan: planId, numOfCreditsPurchased: undefined };
|
||||
case 'credits':
|
||||
numOfCreditsPurchased = plan.effect.amount;
|
||||
break;
|
||||
return { subscriptionPlan: undefined, numOfCreditsPurchased: planEffect.amount };
|
||||
default:
|
||||
assertUnreachable(plan.effect);
|
||||
assertUnreachable(planEffect);
|
||||
}
|
||||
|
||||
return { subscriptionPlan, numOfCreditsPurchased };
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user