https://github.com/ashtishad/xpay
xPay is a digital wallet backend built with Go. It provides a secure foundation for digital financial transactions, including user-auth service, wallet service, card service and multiple payment gateway integrations.
https://github.com/ashtishad/xpay
aws docker domain-driven-design go golang postgresql
Last synced: 3 months ago
JSON representation
xPay is a digital wallet backend built with Go. It provides a secure foundation for digital financial transactions, including user-auth service, wallet service, card service and multiple payment gateway integrations.
- Host: GitHub
- URL: https://github.com/ashtishad/xpay
- Owner: ashtishad
- Created: 2024-10-06T20:30:39.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-01T17:22:41.000Z (over 1 year ago)
- Last Synced: 2025-03-22T04:31:42.518Z (over 1 year ago)
- Topics: aws, docker, domain-driven-design, go, golang, postgresql
- Language: Go
- Homepage:
- Size: 217 KB
- Stars: 4
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Table of Contents
- [Quick Start](#quick-start)
- [Tech Stack](#tech-stack)
- [Progress](#progress)
- [Architecture and Request Flow](#architecture-and-request-flow)
- [Directory Structure](#directory-structure)
- [API Documentation](#api-documentation)
## Quick Start
This project supports two environments: Production and Development. Docker Desktop is required to run the application.
Clone the repository:
```bash
git clone git@github.com:ashtishad/xpay.git && cd xpay
```
### Production
For users who want to run the project and interact with the API (no code changes):
```bash
make setup-prod-env # Set up the environment
make up # Run the application
### More Commands
make down # Stop the application
make down-data # Stop and remove postgres data
```
### Development
For developers who intend to modify the code and contribute to the project:
```bash
make setup-dev-env # Set up the environment
make up # Required for starting the postgres docker service
make watch # Run with live reload
### More Commands
make run # Run normally
make down # Stop the application
make down-data # Stop and remove postgres data
make test # Run tests
make lint # Run linter
make swagger # Generate Swagger docs
make migrate-create name=your_migration_name # Create a new migration
```
> **Note:** `setup-prod-env` and `setup-dev-env` copy appropriate configurations and set up necessary tools for each environment.
> **For all available commands, see the `Makefile` in the project root.**
> **For detailed guide on various aspects of the project, refer to the [wiki](https://github.com/ashtishad/xpay/wiki)**
## Tech Stack
**Core Libraries:** [Gin](https://github.com/gin-gonic/gin), [pgx](https://github.com/jackc/pgx), [golang-migrate](https://github.com/golang-migrate/migrate), [golang-jwt](https://github.com/golang-jwt/jwt/), [viper](https://github.com/spf13/viper), [swaggo/swag](https://github.com/swaggo/swag), [golangci-lint](https://golangci-lint.run/), and [testify](https://github.com/stretchr/testify).
## Progress
β
Implemented | π In Progress/Planned
| Area | Features and Best Practices | Status |
|------|------------------------------|--------|
| API Design & Architecture | β’ Domain Driven Design, Clean Architecure
β’ RESTful API
β’ Event streaming with Apache Kafka
β’ OpenAPI 2.0 specifications | β
β
π
β
|
| Security | β’ JWT-ES256 with ECDSA asymmetric key pairs
β’ AES-256-GCM for card data encryption
β’ SQL injection prevention with parameterized sql queries
β’ Role based access control (RBAC)
β’ DTO for controlled data to the client
β’ User input and query param validation
β’ IP-Based Rate limiting with Token Bucket algorithm | β
β
β
β
β
β
β
|
| Database | β’ ACID transactions with appropriate isolation levels
β’ Raw SQL for performance
β’ Connection pooling with pgx, exposing standard *sql.DB
β’ Optimized indexing and unique constraints
β’ Version-controlled schema changes with migrations | β
β
β
β
β
|
| Core Operations & Observability | β’ Custom AppError interface for error handling
β’ Centralized configuration management with Viper
β’ Structured logging with slog
β’ Context with timeout for each request
β’ Comprehensive test coverage
β’ Code quality with golangci-lint | β
β
β
β
β
β
|
| Payment Gateways | β’ Idempotent payment processing
β’ Stripe integration
β’ PayPal integration
β’ Webhook handling for asynchronous events | π
π
π
π |
| Deployment & Monitoring | β’ Multi-stage Docker builds for minimal image size
β’ GitHub Actions CI pipeline
β’ AWS RDS with PostgreSQL
β’ ECS Fargate for serverless container deployment
β’ Prometheus metrics and Grafana dashboards | β
β
π
π
π |
## Architecture and Request Flow:
The project follows domain-driven design, loosely coupled clean architecture, suited for large codebase.
```
βββββββββββ JSON βββββββββββββββββ Domain βββββββββββββββ
β Client βββββββββββββΊβ Handlers βββββββββββββΊβ Repositoriesβ
βββββββββββ (DTO) βββββββββββββββββ Models βββββββββββββββ
β β
β β
β Domain β
β Models β
β β
βββββββββββ JSON βββββββββββββββββ Domain βββββββββββββββ
β Client βββββββββββββ€ Handlers βββββββββββββ€Repositories β
βββββββββββ (DTO) βββββββββββββββββ Models βββββββββββββββ
```
Example: Create a wallet
wallet.go (model) -> wallet_repository.go -> wallet_handlers.go (using DTOs)
1. Domain Models: `internal/domain/*.go`
2. Repositories: `internal/domain/*_repository.go`
3. HTTP Handlers: `internal/server/handlers/*.go`
4. DTOs: `internal/server/dto/*.go`
5. Routes: `internal/server/routes/*.go`
## Directory Structure
command: `tree -a -I '.git|.DS_Store|.gitignore|.idea|.vscode|docs'`
```bash
βββ .github
β βββ workflows
β βββ test.yaml # CI/CD pipeline for running tests
βββ internal
β βββ domain
β β βββ card.go # Card domain model
β β βββ card_repository.go # Card repository interface, database interactions
β β βββ helpers.go # Domain-specific helper functions
β β βββ user.go # User domain model
β β βββ user_repository.go # User repository interface, database interactions
β β βββ wallet.go # Wallet domain model
β β βββ wallet_repository.go # Wallet repository interface, database interactions
β βββ secure
β β βββ card_aes.go # Card AES-256 with GCM mode, Validate, Encrypt and Decrypt
β β βββ jwt.go # JWT token handling, generate and validate tokens
β β βββ password.go # Password hashing and verification with bcrypt
β β βββ password_test.go # Password utility tests
β β βββ rbac
β β β βββ policy.json # RBAC policies for the API
β β β βββ policy.go # Loading policy from policy.json
β β β βββ rbac.go # Core logic of RBAC
β β β βββ rbac_test.go # Unit tests
β βββ server
β β βββ handlers
β β β βββ auth.go # Login, Register handlers
β β β βββ card.go # Card http handlers
β β β βββ helpers.go # Handlers helper functions
β β β βββ user.go # User HTTP handlers
β β β βββ wallet.go # Wallet HTTP handlers
β β βββ middlewares
β β β βββ auth.go # Auth middleware (Validate token, Set Authorized user in req context)
β β β βββ cors.go # CORS middleware
β β β βββ gin_logger.go # Custom Logging middleware for gin
β β β βββ middlewares.go # Core Middleware setup
β β β βββ rate_limiter.go # IP-Based rate limiter with token bucket algorithm
β β β βββ request_id.go # Request ID middleware, sets X-Request-ID header
β β βββ routes
β β β βββ auth.go # Authentication routes
β β β βββ card.go # Card routes
β β β βββ routes.go # Core routes setup
β β β βββ user.go # User routes
β β β βββ wallet.go # Wallet routes
β β βββ dto
β β β βββ auth.go # Authentication-related DTOs/REST API Request Response Structurers
β β β βββ card.go # Card dto
β β β βββ shared.go # Shared dto
β β β βββ user.go # User dto
β β β βββ wallet.go # Wallet routes
β β βββ server.go # HTTP server setup with gin
β βββ infra
β β βββ postgres
β β β βββ postgres_connection.go # Postgres connection setup with pgx, returns *sql.DB
β β β βββ postgres_migrations.go # Database migration handling with golang-migrate/v4
β β βββ kafka
β β β βββ sample.md # Placeholder for Kafka integration
β βββ common
β β βββ app_errs.go # Custom error types
β β βββ config.go # Configuration management
β β βββ constants.go # Global constants
β β βββ context_keys.go # Context key definitions
β β βββ custom_err_messages.go # Error message definitions
β β βββ slog_config.go # Structured logging configuration
β β βββ timeouts.go # Context timeout constants
βββ migrations
β βββ 000001_create_users_table.down.sql # User table rollback
β βββ 000001_create_users_table.up.sql # User table creation
β βββ 000002_create_wallets_table.down.sql # Wallet table rollback
β βββ 000002_create_wallets_table.up.sql # Wallet table creation
β βββ 000003_create_cards_table.down.sql # Cards table rollback
β βββ 000003_create_cards_table.up.sql # Cards table creation
βββ scripts/
β βββ pre-push # Git pre-push hook (runs tests and lint before every push)
β βββ setup-dev-env.sh # Script to set up development environment
β βββ setup-prod-env.sh # Script to set up production environment
βββ env-configs/
β βββ dev.Makefile # Makefile for development environment
β βββ prod.Makefile # Makefile for production environment
β βββ compose.dev.yaml # Docker Compose file for development
β βββ compose.prod.yaml # Docker Compose file for production
β βββ config.example.yaml # Example configuration file
βββ config.yaml # Application configuration
βββ main.go # Application entry point
βββ Makefile # Development commands and shortcuts
βββ Dockerfile # Docker file with multi stage builds
βββ .dockerignore # Directories to ignore in the Docker builds
βββ README.md # Project documentation
βββ compose.yaml # Docker Compose configuration
βββ go.mod # Go module definition
βββ go.sum # Go module checksums
βββ .air.toml # Live reload configuration with air
```
## API Documentation
### Authentication Endpoints
#### Register User
- **URL**: `/api/v1/register`
- **Method**: `POST`
- **Description**: Registers a new user with hashed password, generates JWT tokens, sets an HTTP-only cookie and X-Request-Id header.
- **Access**: Public
- **Request Body**:
```json
{
"fullName": "John Doe",
"email": "someone@example.com",
"password": "samplepass"
}
```
- **Success Response**: `201 Created`
- **Error Responses**: `400 Bad Request`, `409 Conflict`, `500 Internal Server Error`
#### Login
- **URL**: `/api/v1/login`
- **Method**: `POST`
- **Description**: Authenticate a user, verifies password, generates JWT token, sets an HTTP-only cookie and X-Request-Id header.
- **Access**: Public
- **Request Body**:
```json
{
"email": "someone@example.com",
"password": "samplepass"
}
```
- **Success Response**: `200 OK`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `404 Not Found`, `500 Internal Server Error`
### User Management Endpoints
#### Create User with Specific Role
- **URL**: `/api/v1/users`
- **Method**: `POST`
- **Description**: Creates a new user with a specific role.
- **Access**: Admin (can create any role), Agent (can create user or merchant roles)
- **Authentication**: Required (Bearer Token)
- **Request Body**:
```json
{
"fullName": "Keanu Reeves",
"email": "keanu@example.com",
"password": "keanupass",
"role": "admin"
}
```
- **Success Response**: `201 Created`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `409 Conflict`, `500 Internal Server Error`
### Wallet Endpoints
#### Create a New Wallet
- **URL**: `/api/v1/users/{user_uuid}/wallets`
- **Method**: `POST`
- **Access**: Admin, Merchant, User
- **Authentication**: Required (Bearer Token)
- **Request Body**:
```json
{
"currency": "USD"
}
```
- **Success Response**: `201 Created`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `409 Conflict`, `500 Internal Server Error`
#### Get Wallet Balance
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/balance`
- **Method**: `GET`
- **Access**: Admin, Agent, Merchant, User (own wallet only)
- **Authentication**: Required (Bearer Token)
- **Success Response**: `200 OK`
- **Error Responses**: `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`
#### Update Wallet Status
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/status`
- **Method**: `PATCH`
- **Access**: Admin, Agent, Merchant, User (own wallet only)
- **Authentication**: Required (Bearer Token)
- **Request Body**:
```json
{
"status": "inactive"
}
```
- **Success Response**: `200 OK`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`
### Card Endpoints
#### Add a New Card to Wallet
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/cards`
- **Method**: `POST`
- **Access**: Admin, Merchant, User (own wallet only)
- **Authentication**: Required (Bearer Token)
- **Request Body**:
```json
{
"cardNumber": "4111111111111111",
"provider": "visa",
"type": "credit",
"expiryDate": "12/25",
"cvv": "123"
}
```
- **Success Response**: `201 Created`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `409 Conflict`, `500 Internal Server Error`
#### Get Card Details
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/cards/{card_uuid}`
- **Method**: `GET`
- **Access**: Admin, Agent (read-only), Merchant, User (own cards only)
- **Authentication**: Required (Bearer Token)
- **Success Response**: `200 OK`
- **Error Responses**: `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`
#### Update Card Details
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/cards/{card_uuid}`
- **Method**: `PATCH`
- **Access**: Admin, Merchant, User (own cards only)
- **Authentication**: Required (Bearer Token)
- **Request Body**:
```json
{
"expiryDate": "12/26",
"status": "inactive"
}
```
- **Success Response**: `200 OK`
- **Error Responses**: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`
#### Delete Card
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/cards/{card_uuid}`
- **Method**: `DELETE`
- **Access**: Admin, Merchant, User (own cards only)
- **Authentication**: Required (Bearer Token)
- **Success Response**: `200 OK`
- **Error Responses**: `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `500 Internal Server Error`
#### List Cards
- **URL**: `/api/v1/users/{user_uuid}/wallets/{wallet_uuid}/cards`
- **Method**: `GET`
- **Access**: Admin, Agent (read-only), Merchant, User (own wallet only)
- **Authentication**: Required (Bearer Token)
- **Query Parameters**:
- `provider` (optional): Filter by card provider
- `status` (optional): Filter by card status
- **Success Response**: `200 OK`
- **Error Responses**: `401 Unauthorized`, `403 Forbidden`, `500 Internal Server Error`
[Back to Top](#top)