Paytm is a comprehensive digital payment platform designed to provide secure and seamless financial transactions for both users and merchants. The application supports features like user authentication, bank transactions, QR code payments, and merchant-specific operations, making it a versatile tool for financial management.
Although this project lacks advanced features like a robust QR code system and cutting-edge authentication mechanisms, it serves as an excellent starting point for learning on-ramping, webhooks, and various other concepts. Future updates will focus on enhancing authentication methods, improving the UI/UX, and adding more functionality.
This project is structured as a Turborepo, leveraging a monorepo architecture to manage multiple interconnected packages efficiently.
- Secure Authentication: Users can sign in via email or phone number.
- Google Login for Merchants: Facilitates easy access for merchants.
- Postgres: Relational database to store structured data.
- Prisma ORM: Simplifies interactions with the database.
- Next.js: Full-stack framework handling server-side rendering and backend logic.
- Express.js: Auxiliary backend used for specific tasks and additional APIs.
- Next.js: Seamlessly integrates frontend and backend for better performance.
- Tailwind CSS: A utility-first CSS framework used for building responsive and customizable UIs.
- Common: Shared utilities and services across the app.
- UI: Frontend components and design system elements.
- Backend: Core server logic and API functionalities.
- Hosted on a scalable cloud provider for optimal performance and availability.
A comprehensive schema designed to handle user accounts, merchant transactions, and financial data flow.
RESTful APIs with structured routes ensure smooth communication between frontend and backend.
A well-organized set of components providing an intuitive and interactive user experience.
- Login: Supports sign-in via email/phone.
- On-Ramp and Off-Ramp: Bank transfers to/from user accounts.
- P2P Transfers: Peer-to-peer transfers via phone number or name.
- QR Code Payments: Users can make payments by scanning merchant-generated QR codes.
- Google Login: Enables quick merchant authentication.
- QR Code Generation: Merchants can generate their own QR codes for receiving payments.
- Notifications & Alerts: Merchants receive alerts for new payments and transaction updates.
- Automated Bank Transfers: Every 2 days, merchant balances are transferred to their bank accounts.
- Frontend & Backend: Next.js
- Auxiliary Backend: Express.js
- Monorepo Management: Turborepo
- Database: Postgres
- ORM: Prisma
- Styling: Tailwind CSS
- Sending Money: Streamlined peer-to-peer (P2P) transaction flow.
- Merchant Withdrawals: Ensures timely transfer of merchant funds to their bank accounts.
- User Withdrawals: Facilitates user withdrawals back to their bank accounts.
- Bank Webhooks: Handles money transfers from banks via webhooks for real-time updates.
- Definition: Webhooks are HTTP callbacks triggered by specific events (like bank transfers). They allow for real-time updates within the application, ensuring smooth data synchronization.
- When a user clicks the "Send Money" button, a new entry is created in the
onRampTransactions
table. - Bank webhook events process and update the transaction status accordingly.
- Once the transaction is complete, users can transfer money to other wallets or bank accounts.
import express from "express";
import db from "@repo/db/client";
const app = express();
app.use(express.json());
app.post("/hdfcWebhook", async (req, res) => {
// TODO: Add zod validation here?
// TODO: HDFC bank should ideally send us a secret so we know this is sent by them
const paymentInformation = {
token: req.body.token,
userId: req.body.user_identifier,
amount: req.body.amount
};
try {
await db.$transaction([
db.balance.updateMany({
where: {
userId: Number(paymentInformation.userId)
},
data: {
amount: {
increment: Number(paymentInformation.amount)
}
}
}),
db.onRampTransaction.updateMany({
where: {
token: paymentInformation.token
},
data: {
status: "Success",
}
})
]);
res.json({
message: "Captured"
});
} catch (e) {
console.error(e);
res.status(411).json({
message: "Error while processing webhook"
});
}
});
app.listen(3003);
const initiateTransaction = async (userId, amount, targetAccount) => {
try {
// Create a new transaction entry
const transaction = await prisma.onRampTransactions.create({
data: {
userId,
amount,
targetAccount,
status: 'PENDING',
},
});
// Simulate webhook callback for transaction completion
setTimeout(async () => {
await prisma.onRampTransactions.update({
where: { id: transaction.id },
data: { status: 'COMPLETED' },
});
console.log('Transaction completed successfully');
}, 5000);
return transaction;
} catch (error) {
console.error('Transaction initiation failed:', error);
throw new Error('Failed to initiate transaction');
}
};
module.exports = { initiateTransaction };
git clone <repository-url>
npm install
- Local:
docker run -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 postgres
- Cloud: Use services like neon.tech to host your database.
- Copy all
.env.example
files to.env
in their respective directories. - Update
.env
files with the correct database URL.
cd packages/db
npx prisma migrate dev
npx prisma db seed
- Navigate to the user app directory:
cd apps/user-app
npm run dev
- Login using the following credentials:
- Phone:
1111111111
- Password:
alice
(seeseed.ts
for details)
- Phone:
- Optional: Useful for visualizing database relationships.
- Features are driven by product requirements.
- Balances simplicity and efficiency to avoid technical debt.
- Designed to grow with user needs and business demands, supporting high availability and performance.
- Improve authentication mechanisms.
- Enhance UI/UX for better usability.
- Add advanced features to streamline operations further.