Getting tRPCClient error while integrating Razorpay in NextJS 14.1 app

15 views Asked by At

I get following error when I click checkout button

TRPCClientError at TRPCClientError.from (TRPCClientError-38f9a32a.mjs:33:20) at eval (httpBatchLink-d0f9eac9.mjs:204:105)

I am trying to integrate Razorpay in NextJS 14 website. I'm using MongoDB as database.

I have implemented a paymentRouter in tRPC. All code related to DB & order creation of Razorpay is in this file.

# payment-router.ts

import { z } from "zod";
import { privateProcedure, router } from "./trpc";
import { TRPCError } from "@trpc/server";
import { getPayloadClient } from "../lib/get-payload";
import shortid from "shortid";
import { NextResponse } from "next/server";
import { Orders } from "razorpay/dist/types/orders";
import Razorpay from "razorpay";

export const paymentRouter = router({
  createSession: privateProcedure
    .input(z.object({ productIds: z.array(z.string()) }))
    .mutation(async ({ ctx, input }) => {
      const { user } = ctx;
      let { productIds } = input;

      if (productIds.length === 0) {
        throw new TRPCError({ code: "BAD_REQUEST" });
      }

      const payload = await getPayloadClient();
      const razorpay = new Razorpay({
        key_id: `${process.env.RAZORPAY_ID}`,
        key_secret: `${process.env.RAZORPAY_KEY}`,
      });

      const { docs: products } = await payload.find({
        collection: "products",
        where: {
          id: {
            in: productIds,
          },
        },
      });

      const filteredProducts = products.filter((prod) => Boolean(prod.priceId));

      const amount = filteredProducts.reduce(
        (total, { price }) => total + price,
        0
      );

      const options = {
        amount: Math.round(amount * 100),
        currency: "INR",
        customer_id: user.id,
        payment_capture: true,
        receipt: shortid.generate(),
        notes: {
          // These notes will be added to your transaction. So you can search it within their dashboard.
          // Also, it's included in webhooks as well. So you can automate it.
          userId: `${user.id}`,
        },
      };

      const razorpayOrder = razorpay.orders.create(options);

      try {
        const order: Orders.RazorpayOrder = await razorpayOrder;

        return { order };
      } catch (err) {
        console.log(err);
        const dummyOrder = {
          amount: (await razorpayOrder).amount,
          // id: (await razorpayOrder).id,
          entity: (await razorpayOrder).entity,
          amount_paid: (await razorpayOrder).amount_paid,
          amount_due: (await razorpayOrder).amount_due,
          status: (await razorpayOrder).status,
          attempts: (await razorpayOrder).attempts,
          created_at: (await razorpayOrder).created_at,
          description: (await razorpayOrder).description,
          token: (await razorpayOrder).token,
          currency: (await razorpayOrder).currency,
          receipt: (await razorpayOrder).receipt,
          notes: (await razorpayOrder).notes,
        };
        return { order: dummyOrder };
      }
    }),
});

I'm returning the created order from this file to front-end & recieving it in page.tsx of Cart

# page.tsx (Cart)

const Page = () => {

    const { items, removeItem } = useCart()
    const productIds = items.map(({ product }) => product.id)

    const { mutate: createCheckoutSession, isLoading, } = trpc.payment.createSession.useMutation({
        onSuccess: async ({ order }) => {

            // const key = process.env.RAZORPAY_KEY
            console.log("amount:", order.amount)
            const orderOptions = {
                // key: key,
                amount: order.amount,
                currency: order.currency,
                // orderId: order.id,
                name: "test",
                // payment_capture: order.payment_capture,
                receipt: order.receipt,
                notes: order.notes,
                description: order.description,
            }
            const paymentObject = new (window as any).Razorpay(orderOptions);
            paymentObject.open();
        },
        onError(error, variables, context) {
            console.log(error, variables, context)
        },
    })

return (
<div className='mt-6'>
                            <Button
                                disabled={isLoading || items.length === 0}
                                className='w-full'
                                size='lg'
                                onClick={() => createCheckoutSession({ productIds })}
                            >
                                Checkout
                                {isLoading
                                    ? (<Loader2 className='h-4 w-4 animate-spin ml-1.5' />)
                                    : null}
                            </Button>
                        </div>
)

What should I do?

0

There are 0 answers