Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
55 changes: 55 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Domain
# This would be set to the production domain with an env var on deployment
# used by Traefik to transmit traffic and acquire TLS certificates
DOMAIN=localhost
# To test the local Traefik config
# DOMAIN=localhost.tiangolo.com

# Used by the backend to generate links in emails to the frontend
FRONTEND_HOST=http://localhost:5173
# In staging and production, set this env var to the frontend host, e.g.
# FRONTEND_HOST=https://dashboard.example.com

# Environment: local, staging, production
ENVIRONMENT=local

PROJECT_NAME="Full Stack FastAPI Project"
STACK_NAME=full-stack-fastapi-project

# Backend
BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,https://localhost:5173,http://localhost.tiangolo.com"
SECRET_KEY=changethis
[email protected]
FIRST_SUPERUSER_PASSWORD=changethis

# Emails
SMTP_HOST=
SMTP_USER=
SMTP_PASSWORD=
[email protected]
SMTP_TLS=True
SMTP_SSL=False
SMTP_PORT=587

# Postgres
POSTGRES_SERVER=localhost
POSTGRES_PORT=5432
POSTGRES_DB=app
POSTGRES_USER=postgres
POSTGRES_PASSWORD=changethis

SENTRY_DSN=

# Configure these with your own Docker registry images
DOCKER_IMAGE_BACKEND=backend
DOCKER_IMAGE_FRONTEND=frontend

# Razorpay Payment Gateway Configuration
# Get your API keys from: https://dashboard.razorpay.com/app/keys
# Test keys are available immediately (no KYC required)
# Live keys require KYC verification (1-2 working days)
RAZORPAY_KEY_ID=rzp_test_xxxxxxxxxxxxx
RAZORPAY_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxx
# Optional: For production webhook verification
# Get webhook secret from: Settings → Webhooks in Razorpay Dashboard
RAZORPAY_WEBHOOK_SECRET=your_webhook_secret_here
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules/
/playwright-report/
/blob-report/
/playwright/.cache/
.env
66 changes: 60 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<a href="https://github.com/fastapi/full-stack-fastapi-template/actions?query=workflow%3ATest" target="_blank"><img src="https://github.com/fastapi/full-stack-fastapi-template/workflows/Test/badge.svg" alt="Test"></a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/full-stack-fastapi-template" target="_blank"><img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/full-stack-fastapi-template.svg" alt="Coverage"></a>

A modern, full-stack FastAPI template with React frontend, authentication, and payment gateway integration.

## Technology Stack and Features

- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API.
Expand All @@ -23,30 +25,35 @@
- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer.
- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates.
- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions.
- 💳 **Payment Gateway Integration** with Razorpay for one-time payments, webhook handling, and payment analytics.

### Dashboard Login

[![API docs](img/login.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![Login](img/login.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Dashboard - Admin

[![API docs](img/dashboard.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![Dashboard](img/dashboard.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Dashboard - Create User

[![API docs](img/dashboard-create.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![Create User](img/dashboard-create.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Dashboard - Items

[![API docs](img/dashboard-items.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![Items](img/dashboard-items.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Dashboard - User Settings

[![API docs](img/dashboard-user-settings.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![User Settings](img/dashboard-user-settings.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Dashboard - Dark Mode

[![API docs](img/dashboard-dark.png)](https://github.com/fastapi/full-stack-fastapi-template)
[![Dark Mode](img/dashboard-dark.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Payment Checkout

[![Payment Checkout](img/checkout.png)](https://github.com/fastapi/full-stack-fastapi-template)

### Interactive API Documentation

Expand Down Expand Up @@ -140,6 +147,53 @@ You can (and should) pass these as environment variables from secrets.

Read the [deployment.md](./deployment.md) docs for more details.

## Payment Integration (Razorpay)

This template now includes Razorpay payment gateway integration for accepting one-time payments.

### Setup

1. **Create Razorpay Account**: Sign up at [https://dashboard.razorpay.com/signup](https://dashboard.razorpay.com/signup)
2. **Get API Keys**: Navigate to Settings → API Keys in Razorpay Dashboard
3. **Configure Environment Variables**: Add to `.env`:
```bash
RAZORPAY_KEY_ID=rzp_test_xxxxxxxxxxxxx
RAZORPAY_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxx
RAZORPAY_WEBHOOK_SECRET=your_webhook_secret_here # Optional for production
```

### Features

- **Order Creation**: Backend creates Razorpay orders and saves to database
- **Payment Verification**: Secure signature verification for payment confirmation
- **Webhook Handling**: Real-time payment status updates via webhooks
- **Frontend Integration**: React components for checkout, success, and failure pages
- **Payment Analytics**: Dashboard showing payment history and statistics
- **Database Models**: Order and Payment models with proper relationships

### API Endpoints

- `POST /api/v1/payments/create-order` - Create payment order (requires auth)
- `POST /api/v1/payments/verify` - Verify payment signature (requires auth)
- `POST /api/v1/payments/webhook` - Razorpay webhook handler (public, signature verified)
- `GET /api/v1/payments/orders` - List user orders (requires auth)
- `GET /api/v1/payments/orders/{order_id}` - Get order details (requires auth)

### Database Schema

New tables added:
- `order` - Stores payment orders with Razorpay order IDs
- `payment` - Stores payment records linked to orders

Migrations are handled automatically via Alembic. See [backend/README.md](./backend/README.md#database-migrations-with-alembic) for details.

### Documentation

For detailed setup and configuration:
- Payment API details: [backend/README.md](./backend/README.md#payment-api-endpoints)
- Database migrations: [backend/README.md](./backend/README.md#database-migrations-with-alembic)
- Development guide: [development.md](./development.md)

### Generate Secret Keys

Some environment variables in the `.env` file have a default value of `changethis`.
Expand Down
61 changes: 61 additions & 0 deletions backend/app/alembic/versions/7c4cf1d2308a_add_payment_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Add payment models

Revision ID: 7c4cf1d2308a
Revises: 1a31ce608336
Create Date: 2024-11-02 12:10:28.000000

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
import sqlmodel.sql.sqltypes

# revision identifiers, used by Alembic.
revision = '7c4cf1d2308a'
down_revision = '1a31ce608336'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('order',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('amount', sa.Numeric(precision=19, scale=2), nullable=False),
sa.Column('currency', sa.String(length=3), nullable=False),
sa.Column('receipt', sa.String(length=255), nullable=True),
sa.Column('notes', postgresql.JSON(astext_type=sa.Text()), nullable=True),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('razorpay_order_id', sa.String(length=255), nullable=False),
sa.Column('status', sa.String(length=50), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_order_razorpay_order_id'), 'order', ['razorpay_order_id'], unique=True)
op.create_table('payment',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('order_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('razorpay_payment_id', sa.String(length=255), nullable=False),
sa.Column('razorpay_signature', sa.String(length=500), nullable=True),
sa.Column('status', sa.String(length=50), nullable=False),
sa.Column('amount', sa.Numeric(precision=19, scale=2), nullable=False),
sa.Column('currency', sa.String(length=3), nullable=False),
sa.Column('method', sa.String(length=50), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['order_id'], ['order.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_payment_razorpay_payment_id'), 'payment', ['razorpay_payment_id'], unique=True)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_payment_razorpay_payment_id'), table_name='payment')
op.drop_table('payment')
op.drop_index(op.f('ix_order_razorpay_order_id'), table_name='order')
op.drop_table('order')
# ### end Alembic commands ###

3 changes: 2 additions & 1 deletion backend/app/api/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from fastapi import APIRouter

from app.api.routes import items, login, private, users, utils
from app.api.routes import items, login, payments, private, users, utils
from app.core.config import settings

api_router = APIRouter()
api_router.include_router(login.router)
api_router.include_router(users.router)
api_router.include_router(utils.router)
api_router.include_router(items.router)
api_router.include_router(payments.router)


if settings.ENVIRONMENT == "local":
Expand Down
2 changes: 2 additions & 0 deletions backend/app/api/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import payments

Loading
Loading