refactor: resolve payment issue in paypal mode

This commit is contained in:
2025-05-13 06:01:15 +05:30
parent 5bb3be0aa4
commit 4851f34357
2 changed files with 120 additions and 82 deletions

View File

@@ -20,6 +20,7 @@ const PaymentComponent = ({ amount, onSuccess }) => {
country_code: "", country_code: "",
postal_code: "", postal_code: "",
}); });
const [shippingInfoCollected, setShippingInfoCollected] = useState(false);
useEffect(() => { useEffect(() => {
const fetchExchangeRate = async () => { const fetchExchangeRate = async () => {
@@ -56,7 +57,6 @@ const PaymentComponent = ({ amount, onSuccess }) => {
throw new Error("Failed to fetch exchange rate"); throw new Error("Failed to fetch exchange rate");
} }
} catch (err) { } catch (err) {
// setError("Currency conversion failed. Please try again later.");
console.error("Exchange rate error:", err); console.error("Exchange rate error:", err);
} }
}; };
@@ -80,22 +80,14 @@ const PaymentComponent = ({ amount, onSuccess }) => {
const handlePaymentSuccess = (response) => { const handlePaymentSuccess = (response) => {
onSuccess?.({ onSuccess?.({
...response, ...response,
shippingData, // Include the shipping data in the success callback address: shippingData, // Include the shipping data in the success callback
}); });
}; };
const handleRazorpayPayment = async () => { const handleRazorpayPayment = async () => {
if (!shippingData.address_line_1 || !shippingData.city || !shippingData.postal_code) {
setError("Please fill in all required fields.");
return;
}
try { try {
const order = await createOrder(); const order = await createOrder();
console.log(shippingData)
// log env varaible NEXT_RAZORPAY_CLIENT_ID in next js
console.log("Razorpay Client ID:", process.env.NEXT_PUBLIC_RAZORPAY_CLIENT_ID);
const options = { const options = {
key: "rzp_test_Xf4wnkvQQeUnCq", key: "rzp_test_Xf4wnkvQQeUnCq",
amount: order.amount, amount: order.amount,
@@ -109,8 +101,8 @@ const PaymentComponent = ({ amount, onSuccess }) => {
contact: shippingData.city, contact: shippingData.city,
}, },
handler: (response) => { handler: (response) => {
response.address = shippingData response.address = shippingData;
handlePaymentSuccess(response); // Pass the response to the success handler handlePaymentSuccess(response);
}, },
}; };
@@ -123,13 +115,23 @@ const PaymentComponent = ({ amount, onSuccess }) => {
}; };
const handlePopupSubmit = () => { const handlePopupSubmit = () => {
if (!shippingData.address_line_1 || !shippingData.city || !shippingData.postal_code) {
setError("Please fill in all required fields.");
return;
}
setShowPopup(false); setShowPopup(false);
handleRazorpayPayment(); setShippingInfoCollected(true);
setError(null);
}; };
// if (!usdAmount) { const validateShippingInfo = () => {
// return <div className="text-center p-4">Loading exchange rates...</div>; if (!shippingInfoCollected) {
// } setShowPopup(true);
return false;
}
return true;
};
return ( return (
<div className="max-w-md mx-auto"> <div className="max-w-md mx-auto">
@@ -143,68 +145,96 @@ const PaymentComponent = ({ amount, onSuccess }) => {
Error loading Razorpay: {razorpayError} Error loading Razorpay: {razorpayError}
</div> </div>
)} )}
<PayPalScriptProvider
options={{ {/* Show shipping info status */}
"client-id": process.env.NEXT_PUBLIC_CLIENT_ID, {shippingInfoCollected && (
}} <div className="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
> Shipping information collected
<PayPalButtons <button
style={{ onClick={() => setShowPopup(true)}
layout: "horizontal", className="ml-2 text-sm underline"
label: "checkout", >
tagline: false, Edit
fundingicons: true, </button>
}} </div>
disabled={isProcessing} )}
className="w-full"
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: usdAmount,
currency_code: "USD",
},
},
],
application_context: {
shipping_preference: "GET_FROM_FILE",
},
});
}}
onApprove={async (data, actions) => {
try {
setIsProcessing(true);
const order = await actions.order.capture();
onSuccess?.(order);
} catch (err) {
setError("Payment failed. Please try again.");
console.error("Payment error:", err);
} finally {
setIsProcessing(false);
}
}}
onError={(err) => {
setError("Payment failed. Please try again.");
}}
/>
</PayPalScriptProvider>
<button {/* Collect shipping info button */}
onClick={() => setShowPopup(true)} {!shippingInfoCollected && (
disabled={isProcessing || isLoading} <button
className="mt-4 w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600" onClick={() => setShowPopup(true)}
> className="w-full bg-gray-200 text-gray-800 py-2 px-4 rounded hover:bg-gray-300 mb-4"
{isLoading ? "Loading Razorpay..." : "Pay with Razorpay"} >
</button> Enter Shipping Information
</button>
)}
{/* Payment options - only enabled after shipping info is collected */}
<div className={!shippingInfoCollected ? "opacity-50 pointer-events-none" : ""}>
<PayPalScriptProvider
options={{
"client-id": process.env.NEXT_PUBLIC_CLIENT_ID,
}}
>
<PayPalButtons
style={{
layout: "horizontal",
label: "checkout",
tagline: false,
fundingicons: true,
}}
disabled={isProcessing || !shippingInfoCollected}
className="w-full"
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
amount: {
value: usdAmount,
currency_code: "USD",
},
},
],
application_context: {
shipping_preference: "GET_FROM_FILE",
},
});
}}
onApprove={async (data, actions) => {
try {
setIsProcessing(true);
const order = await actions.order.capture();
order.address = shippingData; // Add shipping data to PayPal order
handlePaymentSuccess(order);
} catch (err) {
setError("Payment failed. Please try again.");
console.error("Payment error:", err);
} finally {
setIsProcessing(false);
}
}}
onError={(err) => {
setError("Payment failed. Please try again.");
}}
/>
</PayPalScriptProvider>
<button
onClick={handleRazorpayPayment}
disabled={isProcessing || isLoading || !shippingInfoCollected}
className="mt-4 w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600"
>
{isLoading ? "Loading Razorpay..." : "Pay with Razorpay"}
</button>
</div>
{showPopup && ( {showPopup && (
<div className=" fixed inset-0 flex items-center justify-center bg-black bg-opacity-50" style={{ zIndex: 1000 }}> <div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50" style={{ zIndex: 1000 }}>
<div className="bg-white p-6 rounded-lg shadow-lg w-96"> <div className="bg-white p-6 rounded-lg shadow-lg w-96">
<h3 className="text-lg font-medium mb-4">Enter Your Shipping Details</h3> <h3 className="text-lg font-medium mb-4">Enter Your Shipping Details</h3>
<input <input
type="text" type="text"
placeholder="Address Line 1" placeholder="Address Line 1 *"
value={shippingData.address_line_1} value={shippingData.address_line_1}
onChange={(e) => setShippingData({ ...shippingData, address_line_1: e.target.value })} onChange={(e) => setShippingData({ ...shippingData, address_line_1: e.target.value })}
className="w-full p-2 mb-4 border border-gray-300 rounded" className="w-full p-2 mb-4 border border-gray-300 rounded"
@@ -218,7 +248,7 @@ const PaymentComponent = ({ amount, onSuccess }) => {
/> />
<input <input
type="text" type="text"
placeholder="City" placeholder="City *"
value={shippingData.city} value={shippingData.city}
onChange={(e) => setShippingData({ ...shippingData, city: e.target.value })} onChange={(e) => setShippingData({ ...shippingData, city: e.target.value })}
className="w-full p-2 mb-4 border border-gray-300 rounded" className="w-full p-2 mb-4 border border-gray-300 rounded"
@@ -232,24 +262,32 @@ const PaymentComponent = ({ amount, onSuccess }) => {
/> />
<input <input
type="text" type="text"
placeholder="Country Code" placeholder="Country Code *"
value={shippingData.country_code} value={shippingData.country_code}
onChange={(e) => setShippingData({ ...shippingData, country_code: e.target.value })} onChange={(e) => setShippingData({ ...shippingData, country_code: e.target.value })}
className="w-full p-2 mb-4 border border-gray-300 rounded" className="w-full p-2 mb-4 border border-gray-300 rounded"
/> />
<input <input
type="text" type="text"
placeholder="Postal Code" placeholder="Postal Code *"
value={shippingData.postal_code} value={shippingData.postal_code}
onChange={(e) => setShippingData({ ...shippingData, postal_code: e.target.value })} onChange={(e) => setShippingData({ ...shippingData, postal_code: e.target.value })}
className="w-full p-2 mb-4 border border-gray-300 rounded" className="w-full p-2 mb-4 border border-gray-300 rounded"
/> />
<button <div className="flex gap-2">
onClick={handlePopupSubmit} <button
className="w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600" onClick={() => setShowPopup(false)}
> className="w-1/2 bg-gray-300 text-gray-800 py-2 px-4 rounded hover:bg-gray-400"
Submit >
</button> Cancel
</button>
<button
onClick={handlePopupSubmit}
className="w-1/2 bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600"
>
Save Address
</button>
</div>
</div> </div>
</div> </div>
)} )}

View File

@@ -112,7 +112,7 @@ const ShoppingCart = () => {
paymentId: order.id, paymentId: order.id,
payerEmail: order.payer.email_address, payerEmail: order.payer.email_address,
cartId: cartItems[0].id, cartId: cartItems[0].id,
address: shippingAddress, // Include the shipping address address: order.address,
}; };
const apiResponse = await authAxios.post("/orders/payment/", paymentData); const apiResponse = await authAxios.post("/orders/payment/", paymentData);