sg-delivery-customer/payment_integration_guide.md

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>;
};
```