132 lines
4.2 KiB
Markdown
132 lines
4.2 KiB
Markdown
# Frontend Payment SDK & API Integration Guide
|
|
|
|
This guide details how to integrate your client-side application (Web/React/React Native) with the backend Payment & Wallet module using Stripe Elements and Razorpay Checkout SDKs.
|
|
|
|
---
|
|
|
|
## 2. Razorpay Integration (Web & Mobile)
|
|
|
|
Razorpay uses **Orders API** where the backend pre-creates a transaction order, and the frontend opens a secure Checkout Widget overlay.
|
|
|
|
### SDK Installation
|
|
|
|
```html
|
|
<!-- For Web: include checkout script in index.html -->
|
|
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
|
|
```
|
|
|
|
```bash
|
|
# For Mobile (React Native)
|
|
npm install react-native-razorpay
|
|
```
|
|
|
|
### Complete Razorpay Checkout Flow (Web)
|
|
|
|
```typescript
|
|
declare const Razorpay: any;
|
|
|
|
export const RazorpayCheckout = ({ orderId, totalAmount, userProfile }) => {
|
|
const handlePayment = async () => {
|
|
// Step 1: Initialize Payment Session on backend to get Razorpay Order ID
|
|
const sessionResponse = await fetch('/payments/create-session', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ orderId, paymentMethod: 'UPI' }), // OR 'CARD'
|
|
});
|
|
|
|
const { gatewayOrderId, provider } = await sessionResponse.json();
|
|
|
|
// Step 2: Set up checkout configuration options
|
|
const options = {
|
|
key: process.env.REACT_APP_RAZORPAY_KEY_ID, // Enter public key
|
|
amount: totalAmount * 100, // Amount in paise
|
|
currency: 'INR',
|
|
name: 'Delivery Platform',
|
|
description: `Payment for Order #${orderId}`,
|
|
order_id: gatewayOrderId, // The Order ID fetched from backend
|
|
prefill: {
|
|
name: userProfile.name,
|
|
email: userProfile.email,
|
|
contact: userProfile.phone,
|
|
},
|
|
theme: { color: '#3399cc' },
|
|
// Step 3: Signature validation callback handler
|
|
handler: async (response: {
|
|
razorpay_payment_id: string;
|
|
razorpay_order_id: string;
|
|
razorpay_signature: string;
|
|
}) => {
|
|
// Step 4: Verify signature cryptographically on the backend
|
|
const verifyResponse = await fetch('/payments/process', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
gatewayOrderId: response.razorpay_order_id,
|
|
gatewayPaymentId: response.razorpay_payment_id,
|
|
gatewaySignature: response.razorpay_signature,
|
|
}),
|
|
});
|
|
|
|
const confirmation = await verifyResponse.json();
|
|
if (confirmation.success) {
|
|
alert('Order Placed and Driver Dispatched successfully!');
|
|
}
|
|
},
|
|
modal: {
|
|
ondismiss: function () {
|
|
console.log('Payment checkout dialog closed by customer.');
|
|
},
|
|
},
|
|
};
|
|
|
|
const rzp = new Razorpay(options);
|
|
rzp.open();
|
|
};
|
|
|
|
return <button onClick={handlePayment}>Pay via Razorpay</button>;
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Wallet Top-Up Flow (Backend-Only Deduction)
|
|
|
|
Wallet checkouts and top-ups run completely inside backend transactions without client-side redirects.
|
|
|
|
```typescript
|
|
export const WalletPayment = ({ orderId, walletBalance, totalAmount }) => {
|
|
const handleWalletPay = async () => {
|
|
if (walletBalance < totalAmount) {
|
|
alert('Insufficient wallet balance. Please top up.');
|
|
return;
|
|
}
|
|
|
|
// Initialize session for WALLET (processed fully by backend transaction)
|
|
const response = await fetch('/payments/create-session', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ orderId, paymentMethod: 'WALLET' }),
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
// For wallet, session creation directly attempts to deduct balance
|
|
const verifyResponse = await fetch('/payments/process', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
gatewayOrderId: result.paymentReference, // Virtual reference for wallet
|
|
gatewayPaymentId: `wallet_txn_${Date.now()}`,
|
|
}),
|
|
});
|
|
|
|
const confirmation = await verifyResponse.json();
|
|
if (confirmation.success) {
|
|
alert('Balance deducted and order confirmed!');
|
|
}
|
|
};
|
|
|
|
return <button onClick={handleWalletPay}>Deduct Wallet Balance</button>;
|
|
};
|
|
```
|