Loading...
ā ļø PRELIMINARY DOCUMENTATION - NEEDS REVIEW
Note: This documentation was created with assumptions about the project architecture and technology stack. It requires review and correction based on the actual implementation.
This document will be reworked once the project is closer to final release.
If you notice inaccuracies, please flag them so this can be updated with actual project details.
How Razorpay payments are integrated into Flash Turbo CMS.
graph TB
subgraph Customer["š¤ Customer"]
Browse["Browse Products"]
Cart["Add to Cart"]
Checkout["Checkout"]
end
subgraph Frontend["š„ļø Storefront"]
CartUI["Cart UI"]
CheckoutUI["Checkout Form"]
PaymentModal["Payment Modal"]
end
subgraph Backend["āļø Flash Turbo Backend"]
API["Payment API"]
Order["Order Service"]
Inventory["Inventory Service"]
end
subgraph Razorpay["š³ Razorpay"]
Gateway["Payment Gateway"]
Processing["Card Processing"]
Settlement["Settlement"]
end
subgraph Database["š¾ Data Storage"]
Orders["Orders Collection"]
Transactions["Transactions Collection"]
Logs["Payment Logs"]
end
Customer --> Browse
Browse --> CartUI
Cart --> CartUI
Checkout --> CheckoutUI
CheckoutUI --> PaymentModal
PaymentModal --> Gateway
API --> Order
Order --> Inventory
Gateway --> Processing
Processing --> Settlement
API --> Orders
API --> Transactions
API --> Logs
sequenceDiagram
Customer->>Frontend: Click "Proceed to Checkout"
Frontend->>API: POST /api/checkout/init
API->>Inventory: Check product stock
Inventory->>DB: Verify quantities
DB->>Inventory: Return availability
Inventory->>API: All in stock
API->>Razorpay: Create payment order
Note over Razorpay: Key: {key_id}, Amount: {total}
Razorpay->>API: Return orderId
API->>Frontend: Return payment config
Frontend->>Frontend: Initialize Razorpay
sequenceDiagram
Customer->>PaymentModal: See payment form
Customer->>PaymentModal: Enter card details
Customer->>PaymentModal: Click "Pay"
PaymentModal->>Razorpay: POST payment (encrypted)
Razorpay->>Bank: Token to card issuer
Bank->>Razorpay: OTP/Verification
Razorpay->>Bank: Charge card
Bank->>Razorpay: Amount debited
Razorpay->>PaymentModal: payment_success
PaymentModal->>Frontend: Success callback
sequenceDiagram
Frontend->>API: POST /api/verify-payment
Note over Frontend: Send paymentId from Razorpay
API->>Razorpay: GET payment details
Razorpay->>API: Return payment data
API->>API: Verify signature
API->>API: Confirm amount matches
alt Payment Valid
API->>DB: Create Order document
API->>DB: Create Transaction record
API->>Inventory: Decrease stock
API->>Cache: Clear inventory cache
API->>Email: Send confirmation
API->>Frontend: Return order ID
Frontend->>Customer: Show confirmation
else Payment Invalid
API->>Frontend: Return error
Frontend->>Customer: Show error message
end
Orders Collection
{
_id: ObjectId,
customerId: string,
tenantId: string, // ā Tenant isolation
items: [
{ productId, quantity, price }
],
totalAmount: number,
paymentStatus: "pending" | "paid" | "failed",
paymentMethod: "razorpay",
razorpayOrderId: string, // ā Razorpay reference
razorpayPaymentId: string, // ā After payment
shippingAddress: {...},
billingAddress: {...},
createdAt: Date
}
PaymentTransactions Collection
{
_id: ObjectId,
orderId: ObjectId,
tenantId: string,
transactionId: string, // ā Razorpay transaction ID
amount: number,
currency: string,
status: "success" | "failed" | "pending",
razorpayData: {...}, // ā Full Razorpay response
createdAt: Date
}
PaymentLogs Collection
{
_id: ObjectId,
tenantId: string,
orderId: ObjectId,
action: "order_created" | "payment_verified" | "webhook_received",
razorpayResponse: {...},
metadata: {...},
createdAt: Date
}
sequenceDiagram
Razorpay->>Backend: POST webhook
Note over Backend: Event: payment.authorized
Backend->>Backend: Verify signature
Backend->>DB: Find order by razorpayOrderId
DB->>Backend: Return order
alt Signature Valid
Backend->>DB: Update order (status=paid)
Backend->>DB: Create transaction log
Backend->>Cache: Invalidate order cache
Backend->>Email: Send confirmation
Backend->>Razorpay: Return 200 OK
else Invalid Signature
Backend->>Backend: Log security event
Backend->>Razorpay: Return 400 error
Note over Backend: Webhook not processed
end
graph TB
Customer["Customer"]
Error["Payment Failed"]
Status["Order Status"]
Retry["Retry Payment"]
Customer -->|Try Payment| Error
Error -->|Card Declined| Status
Error -->|Insufficient Funds| Status
Error -->|Network Timeout| Status
Error -->|3D Secure Failed| Status
Status -->|Mark as failed| DB["Database"]
DB -->|Preserve cart| Session["Session"]
Session -->|Customer notified| Email["Email"]
Email -->|Can retry| Retry
Retry -->|New payment| Customer
sequenceDiagram
Admin->>Manager: Click "Issue Refund"
Manager->>API: POST /api/refunds/create
API->>DB: Get payment details
DB->>API: Return transaction data
API->>Razorpay: Create refund
Note over Razorpay: Amount: {refund_amount}
Razorpay->>Bank: Send reversal
Bank->>Customer: Process refund
Razorpay->>API: Refund confirmed
API->>DB: Record refund transaction
API->>Email: Send refund confirmation
API->>Manager: Refund complete
Manager->>Admin: Show success
Email->>Customer: Refund notification
API Key Separation
Signature Verification
// Verify webhook from Razorpay
const generated_signature = hmac_sha256(
body + secret_key
);
assert(generated_signature === webhook_signature);
PCI Compliance
HTTPS Only
Amount Verification
// Always verify amount matches
if (payment.amount !== order.total) {
throw new Error("Amount mismatch");
}
graph TB
Tenant["Tenant Settings"]
RazorpayConfig["Razorpay Config"]
Keys["Razorpay Keys"]
Tenant --> RazorpayConfig
RazorpayConfig -->|Public Key| Keys
RazorpayConfig -->|Secret Key| Keys
RazorpayConfig -->|Webhook Secret| Keys
Keys -->|Stored Encrypted| DB["Database"]
DB -->|Retrieved at| Runtime["Runtime"]
Runtime -->|Used for| Payments["Payments"]
note["Each tenant has separate credentials"]
| Card Type | Number | Status |
|---|---|---|
| Visa Success | 4111 1111 1111 1111 | Success |
| Mastercard Success | 5555 5555 5555 4444 | Success |
| Failed | 4000 0000 0000 0002 | Failed |
| Auth Declined | 4000 0000 0000 0010 | Declined |
# Test webhook endpoint locally
curl -X POST http://localhost:3000/api/webhooks/razorpay \
-H "Content-Type: application/json" \
-H "X-Razorpay-Signature: test_signature" \
-d '{
"event": "payment.authorized",
"payload": {
"payment": {
"entity": {...}
}
}
}'
// Don't block on email
await Promise.all([
db.updateOrder(orderId), // Synchronous
]);
// Send email in background
sendConfirmationEmail(order).catch(err =>
logger.error('Email failed', err)
);
// Prevent fraud via repeated attempts
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 min
max: 5 // 5 attempts
});
app.post('/api/checkout/init', limiter);
Last Updated: October 27, 2025 Version: 1.0 Status: ā Production Ready