#deme-checkout-metadata

1 messages · Page 1 of 1 (latest)

split thistleBOT
candid canopy
#

Here's the tRPC router for reference

  createCheckoutSession: publicProcedure
    .input(
      z.object({
        priceId: z.string(),
        // metadata: z.object({}),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const { stripe, userId, prisma, req } = ctx;

      if (!userId) {
        throw new Error("No user id");
      }

      const customerId = await getOrCreateStripeCustomerIdForUser({
        prisma,
        stripe,
        userId,
      });

      console.log(customerId, "customerId");
      if (!customerId) {
        throw new Error("Could not create customer");
      }

      // the base url is different depending on if we are in development or production
      const baseUrl =
        env.NODE_ENV === "development"
          ? `http://${req.headers.host ?? "localhost:3000"}`
          : `https://${req.headers.host ?? env.NEXTAUTH_URL}`;

      // Stripe Checkout Session
      const checkoutSession = await stripe.checkout.sessions.create({
        customer: customerId as string,
        client_reference_id: userId!,
        payment_method_types: ["card"],
        mode: "payment",
        // if using subscriptions
        // mode: "subscription",
        line_items: [
          {
            // price: env.STRIPE_PRICE_ID,
            price: input.priceId,
            quantity: 1,
          },
        ],
        // metadata: input.metadata,
        success_url: `${baseUrl}/store/orderSuccessful`,
        // redirect the user back to the item page if they cancel the purchase
        cancel_url: `${baseUrl}/store`,
        // if using subscriptions
        // subscription_data: {
        //   metadata: {
        //     userId: userId,
        //   },
        // },
      });

      if (!checkoutSession) {
        throw new Error("Could not create checkout session");
      }
      return { checkoutUrl: checkoutSession.url };
    }),
safe mango
#

deme-checkout-metadata

candid canopy
#
<button
        className="btn-primary btn bg-primary"
        onClick={async () => {
          if (!user.isSignedIn) {
            handleBuyNow();
          } else if (user.isSignedIn) {
            // create a checkout session
            const { checkoutUrl } = await createCheckoutSession({
              priceId: product.default_price,
              // metadata: {
              //   downloadUrl: product.metadata,
              // },
            });
            if (checkoutUrl) {
              void push(checkoutUrl);
            }
          }
        }}
      >
#

That's the button that initiates it all

safe mango
#

On the redirect page, you're supposed to know who the customer is since you sent them to Checkout. So when they came back you know who they are, find their Checkout Session you created for them, fetch it from the API and look at its metadata

candid canopy
#

Is there a way to access the session using the api in on the page component?

safe mango
#

I don't know what "on the page component" could mean

candid canopy
#
//pages/store/orderSuccessful.tsx

import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons";
import { useRouter } from "next/router";
import { GetStaticProps } from "next";
import { generateSSGHelper } from "~/server/helpers/ssgHelper";
import { api } from "~/utils/api";
import { usePathname } from "next/navigation";
import { stripe } from "~/server/helpers/stripe/client";

const OrderSuccessful = () => {
  const pathname = usePathname();
  // I want everything after the /`${baseUrl}/store/orderSuccessful
  const path = pathname.split("/").pop();
  console.log(path, "path");

  // get the stripe session metadata

  const { data: downloadUrls } = api.store.getS3DownloadUrl.useQuery();

  console.log(downloadUrls, "s3BucketDownloadLink");
  // const postPurchaseDownloadLink = downloadUrls;

  const router = useRouter();

  return (
    <div className="flex min-h-screen flex-col justify-center bg-gray-100 py-6 sm:py-12">
      <div className="relative mx-auto py-3 text-center sm:max-w-xl">
        <span className="text-6xl text-green-500">
          <FontAwesomeIcon icon={faCheckCircle} />
        </span>
        <h1 className="text-2xl font-semibold text-gray-900">
          Purchase Successful!
        </h1>
        <p className="text-gray-500">
          Thank you for your order. We hope you enjoy your purchase!
        </p>
        <p>Here's your download link: {url}</p>
        <div className="mt-6">
          <button
            onClick={() => {
              router.push("/");
            }}
            className="btn-primary btn mx-2"
          >
            Back to Home
          </button>
          <button
            onClick={() => {
              router.push("/store");
            }}
            className="btn-secondary btn mx-2"
          >
            Continue Shopping
          </button>
        </div>
      </div>

      <div className="mt-12">
        <h2 className="mb-4 text-center text-xl font-semibold text-gray-900">
          Other users also bought:
        </h2>
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {mappedProducts.map((product) => (
            <div key={product.id} className="rounded-lg bg-white p-4 shadow-md">
              <img
                className="mb-4 h-48 w-full rounded object-cover"
                src={product.images}
                alt={product.title}
              />
              <h3 className="text-lg font-semibold text-gray-900">
                {product.name}
              </h3>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default OrderSuccessful;

export const getStaticProps: GetStaticProps = async ({ req, res }: any) => {
  // use SSG to get the data from the server
  const ssg = generateSSGHelper(req, res);

  // get recent store activities for the carousel's top news
  await ssg.homePage.getRecentStoreActivities.prefetch();

  // return the props
  return {
    props: {
      trpcState: ssg.dehydrate(),
    },
  };
};
candid canopy
safe mango
#

in theory you have a Customer with an account on your app/website. They signed up or you have a cookie or something, so server-side you identify who they are when they come back from Checkout to your success URL and then you can retrieve the Checkout Session (or really have the S3 link in your own database and such)

candid canopy
#

Ah okay, I remember now. I have the stripe customer id on the user in the db.

I thought the id would change constantly so I wasn't sure if that was a reliable way to track the user forever.

So I can use that customer id to retrieve their session, then I can see what they bought, then I can present the metadata link?

safe mango
#

yes