#jesse677_checkout-webhooks-paymentmethod
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1272596022308376667
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
This is all of the code.
"use server";
import { isSignedIn } from "@/utils/auth";
import {
BillingMethod,
BillingPlan,
stripePricingTokens,
} from "@/utils/constants";
import { env } from "@/utils/env";
import { stripeInstance } from "@/utils/stripe";
import { GenericObject } from "@/utils/types";
import { cookies } from "next/headers";
export async function getCheckoutSession(sessionID: string) {
try {
const session = await stripeInstance.checkout.sessions.retrieve(sessionID);
const { email, plan } = session.metadata as GenericObject<string>;
return {
status: "Success",
plan,
customer_email: email,
subscription_id: session.subscription,
customer_id: session.customer as string,
} as const;
} catch {
return {
status: "Error",
} as const;
}
}
export async function getClientSecret(plan: BillingPlan, type: BillingMethod) {
const token = cookies().get("token")?.value || "";
const { user, signedIn } = await isSignedIn(token);
if (!signedIn) return "Unauthorized";
const session = await stripeInstance.checkout.sessions.create({
ui_mode: "embedded",
payment_method_types: ["card", "paypal"],
metadata: {
plan,
email: user.email,
},
line_items: [
{
price: stripePricingTokens[plan][type],
quantity: 1,
},
],
mode: "subscription",
return_url: `${env.BASE_URL}/purchase-plan/success?code={CHECKOUT_SESSION_ID}`,
});
return session.client_secret as string;
}
HI ๐
So you have the Checkout Session ID and you are retrieving the session. How do you know the session has been completed? Are you listening for a webhook event?
the getCheckoutSession is used in the /purchase-plan/success, which is the return_url of the embedded checkout
so it has to be finished in order for you to be at that page
Okay. i will point out that we recommend you listen to webhooks over the return URL, since it's possible your customers could close their browser or there could be bad internet weather that prevents them from landing on your page even though they completed the purchase
But, that being said, let's work with what you have
yh that's what I was thinking could be a problem if they closed it after putting in all their stuff
but I'll look into the webhooks
So you're using a recurring price that creates a Subscription.
yeah
so basically what I've got so far is when you complete the payment and land on the /success page, I run the function at the top (getCheckoutSession), and then through that I make some writes to the database giving the user authorization to the service
const redisPipeline = redis.pipeline();
redisPipeline.json.set(email, "$.plan", JSON.stringify(plan));
redisPipeline.json.set(email, "$.stripe_customer_id", customerID);
redisPipeline.json.set(email, "$.stripe_subscription_id", subscriptionID);
await redisPipeline.exec();
I'm hoping to be able to add .stripe_payment_method_id
but if not possible I'd just opt for making another call to the stripe API
which I'm hoping to avoid as it can be quite expensive and I'm trying to acheive the best UX possible
Yeah unfortunately the payment method isn't going to be available directly on the Checkout Session
The first place I would check is if you can retrieve the Subscription and the default_payment_method property
yh that's what I was thinking
ok that's fine
thanks for all your help
and telling me abt the webhooks
Sure thing, happy to shed what ๐ก I can ๐