From e7c40cb5f1d5735ccb0e3021856d496cae3df6cf Mon Sep 17 00:00:00 2001 From: Amritanshu Date: Sun, 16 Feb 2025 04:34:07 +0000 Subject: [PATCH] Bug fixes where somehow payment_collection became an array and broke everything. Somehow the order is not being marked as captured. --- .../checkout/order-success/page.tsx | 17 ++++++ .../(storefront)/checkout/payment/page.tsx | 55 ++++++++++++++++--- .../checkout/payment/razorpay.tsx | 41 ++++---------- 3 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 src/app/(storefront)/checkout/order-success/page.tsx diff --git a/src/app/(storefront)/checkout/order-success/page.tsx b/src/app/(storefront)/checkout/order-success/page.tsx new file mode 100644 index 0000000..62560e6 --- /dev/null +++ b/src/app/(storefront)/checkout/order-success/page.tsx @@ -0,0 +1,17 @@ +// app/order-success/page.tsx + +'use client'; + +import Link from 'next/link'; + +export default function OrderSuccessPage() { + return ( +
+

Thank you for your order!

+

Your order has been placed successfully.

+ + Return to Homepage + +
+ ); +} diff --git a/src/app/(storefront)/checkout/payment/page.tsx b/src/app/(storefront)/checkout/payment/page.tsx index 45958d1..99c7208 100644 --- a/src/app/(storefront)/checkout/payment/page.tsx +++ b/src/app/(storefront)/checkout/payment/page.tsx @@ -1,6 +1,7 @@ 'use client'; // include with Next.js 13+ import { HttpTypes } from '@medusajs/types'; +import { useRouter } from 'next/navigation'; import { useCallback, useEffect, useState } from 'react'; import RazorpayPayment from './razorpay'; @@ -8,7 +9,8 @@ import RazorpayPayment from './razorpay'; import { useCart } from '@/providers/cart'; export default function CheckoutPaymentStep() { - const { cart, setCart } = useCart(); + const router = useRouter(); + const { cart, setCart, refreshCart } = useCart(); const [paymentProvider, setPaymentProvider] = useState(null); const [loading, setLoading] = useState(false); @@ -26,7 +28,6 @@ export default function CheckoutPaymentStep() { if (!cart) { return; } - console.log('useEffect cart', cart); fetch(`${process.env.NEXT_PUBLIC_STORE_URL}/store/payment-providers?region_id=${cart.region_id}`, { credentials: 'include', @@ -42,7 +43,8 @@ export default function CheckoutPaymentStep() { }); }, [cart]); - const fetchOrCreatePaymentCollection = async (cart: any) => { + const fetchOrCreatePaymentCollection = async (cartId: string) => { + const cart = await fetchUpdatedCart(cartId); const paymentCollectionId = cart.payment_collection?.id; if (paymentCollectionId) { return paymentCollectionId; @@ -59,7 +61,6 @@ export default function CheckoutPaymentStep() { cart_id: cart.id, }), }).then((res) => res.json()); - return payment_collection.id; }; const initializePaymentSession = async (paymentCollectionId: string, providerId: string) => { @@ -93,20 +94,19 @@ export default function CheckoutPaymentStep() { }; useEffect(() => { - console.log('useEffect paymentProvider', cart, paymentProvider); - if (!cart || !paymentProvider) { + if (!paymentProvider || !cart) { return; } const initializePayment = async () => { try { // Step 1: Fetch or create the Payment Collection - const paymentCollectionId = await fetchOrCreatePaymentCollection(cart); + const paymentCollectionId = await fetchOrCreatePaymentCollection(cart?.id); // Step 2: Initialize Payment Session for the provider const session = await initializePaymentSession(paymentCollectionId, paymentProvider.id); // Step 3: Fetch and update the cart to reflect the changes - const updatedCart = await fetchUpdatedCart(cart.id); + const updatedCart = await fetchUpdatedCart(cart?.id); if (JSON.stringify(cart) !== JSON.stringify(updatedCart)) { setCart(updatedCart); } @@ -120,10 +120,47 @@ export default function CheckoutPaymentStep() { initializePayment(); }, [paymentProvider]); + /** + * CAPTURE PAYMENT: + * - Called once Razorpay payment succeeds in the child component + * - Tries to "complete" the cart in Medusa which effectively captures the payment + */ + const capturePayment = useCallback( + async (cartId: string) => { + setLoading(true); + try { + // Complete the cart in Medusa + const result = await fetch(`${process.env.NEXT_PUBLIC_STORE_URL}/store/carts/${cartId}/complete`, { + credentials: 'include', + headers: { + 'x-publishable-api-key': process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || 'temp', + }, + method: 'POST', + }) + .then((res) => res.json()) + .then(({ type, cart, order, error }) => { + if (type === 'cart' && cart) { + // an error occured + console.error('Error completing cart:', error); + } else if (type === 'order' && order) { + console.log(order); + // Clears/reloads cart in your client state + refreshCart(); + router.push('/checkout/order-success'); + } + }); + } catch (err) { + console.error('Error completing cart:', err); + } finally { + setLoading(false); + } + }, + [cart], + ); const getPaymentUi = useCallback(() => { const activePaymentSession = cart?.payment_collection?.payment_sessions?.[0]; if (activePaymentSession) { - return ; + return ; } }, [cart]); diff --git a/src/app/(storefront)/checkout/payment/razorpay.tsx b/src/app/(storefront)/checkout/payment/razorpay.tsx index 19bb5f6..5aeccb3 100644 --- a/src/app/(storefront)/checkout/payment/razorpay.tsx +++ b/src/app/(storefront)/checkout/payment/razorpay.tsx @@ -5,11 +5,16 @@ import React, { useState } from 'react'; import { useCart } from '@/providers/cart'; +interface RazorpayPaymentProps { + cart: any; + capturePayment: (cartId: string) => Promise; +} + /** * This component injects the Razorpay checkout script * and displays the `RazorpayForm` after the script has loaded. */ -export default function RazorpayPayment() { +export default function RazorpayPayment({ cart, capturePayment }: RazorpayPaymentProps) { const [scriptLoaded, setScriptLoaded] = useState(false); return ( @@ -21,7 +26,7 @@ export default function RazorpayPayment() {