Bug fixes where somehow payment_collection became an array and broke everything.
Somehow the order is not being marked as captured.
This commit is contained in:
parent
12d7d21d28
commit
e7c40cb5f1
17
src/app/(storefront)/checkout/order-success/page.tsx
Normal file
17
src/app/(storefront)/checkout/order-success/page.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
// app/order-success/page.tsx
|
||||
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function OrderSuccessPage() {
|
||||
return (
|
||||
<div className='mx-auto max-w-lg py-10 text-center'>
|
||||
<h1 className='text-2xl font-bold mb-4'>Thank you for your order!</h1>
|
||||
<p className='mb-6'>Your order has been placed successfully.</p>
|
||||
<Link href='/' className='text-blue-600 underline'>
|
||||
Return to Homepage
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -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<HttpTypes.StorePaymentProvider | null>(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 <RazorpayPayment />;
|
||||
return <RazorpayPayment cart={cart} capturePayment={capturePayment} />;
|
||||
}
|
||||
}, [cart]);
|
||||
|
||||
|
@ -5,11 +5,16 @@ import React, { useState } from 'react';
|
||||
|
||||
import { useCart } from '@/providers/cart';
|
||||
|
||||
interface RazorpayPaymentProps {
|
||||
cart: any;
|
||||
capturePayment: (cartId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
<Script src='https://checkout.razorpay.com/v1/checkout.js' onLoad={() => setScriptLoaded(true)} />
|
||||
|
||||
{/* Only render the payment form if the script has loaded */}
|
||||
{scriptLoaded && <RazorpayForm />}
|
||||
{scriptLoaded && <RazorpayForm cart={cart} capturePayment={capturePayment} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -30,8 +35,8 @@ export default function RazorpayPayment() {
|
||||
* A simple form that triggers the Razorpay checkout
|
||||
* using data from the cart.
|
||||
*/
|
||||
function RazorpayForm() {
|
||||
const { cart, refreshCart } = useCart();
|
||||
function RazorpayForm({ cart, capturePayment }: RazorpayPaymentProps) {
|
||||
const { refreshCart } = useCart();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// Typically the order_id is generated on your server (Medusa backend)
|
||||
@ -67,33 +72,7 @@ function RazorpayForm() {
|
||||
// `response.razorpay_order_id` will have the Order ID
|
||||
// `response.razorpay_signature` will have the signature
|
||||
|
||||
try {
|
||||
// Complete the cart in Medusa
|
||||
const result = await fetch(`${process.env.NEXT_PUBLIC_STORE_URL}/store/carts/${cart.id}/complete`, {
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'x-publishable-api-key': process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || 'temp',
|
||||
},
|
||||
method: 'POST',
|
||||
});
|
||||
const data = await result.json();
|
||||
// Example response shape:
|
||||
// { type: "order" | "cart", order?: any, cart?: any, error?: any }
|
||||
|
||||
if (data.type === 'cart' && data.cart) {
|
||||
// Some error or failure state
|
||||
console.error('Error completing cart:', data.error);
|
||||
} else if (data.type === 'order' && data.order) {
|
||||
// Payment and order creation successful
|
||||
alert('Order placed.');
|
||||
// Clears/reloads cart in your client state
|
||||
refreshCart();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error completing cart:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
await capturePayment(cart.id);
|
||||
},
|
||||
prefill: {
|
||||
// Prefill customer data in the Razorpay form
|
||||
|
Loading…
x
Reference in New Issue
Block a user