init
This commit is contained in:
428
README.md
Normal file
428
README.md
Normal file
@@ -0,0 +1,428 @@
|
||||
# Charging Station Mock API (json-server)
|
||||
|
||||
Mock server cho feature Charging Station theo tài liệu:
|
||||
- `docs/charging_station_final_spec.md`
|
||||
|
||||
## 1. Cài dependency
|
||||
|
||||
```bash
|
||||
cd mock/charging-station
|
||||
bun install
|
||||
```
|
||||
|
||||
## 2. Chạy server
|
||||
|
||||
```bash
|
||||
bun run start
|
||||
```
|
||||
|
||||
Mặc định chạy ở `http://localhost:3100`.
|
||||
|
||||
Có thể đổi port:
|
||||
|
||||
```bash
|
||||
PORT=3200 bun run start
|
||||
```
|
||||
|
||||
## 3. Static Files (Images)
|
||||
|
||||
Server serve static files từ folder `public/`. Cấu trúc:
|
||||
|
||||
```
|
||||
mock/charging-station/
|
||||
├── public/
|
||||
│ └── images/
|
||||
│ ├── banners/ # Ảnh banner (800x400 recommended)
|
||||
│ │ ├── banner_summer_sale.png
|
||||
│ │ ├── banner_cashback.png
|
||||
│ │ └── banner_new_year.png
|
||||
│ └── vouchers/ # Ảnh voucher (300x200 recommended)
|
||||
│ ├── starbucks.png
|
||||
│ ├── kfc.png
|
||||
│ ├── grab.png
|
||||
│ └── ...
|
||||
├── db.json
|
||||
└── server.js
|
||||
```
|
||||
|
||||
**Cách thêm ảnh mới:**
|
||||
1. Đặt file ảnh vào `public/images/banners/` hoặc `public/images/vouchers/`
|
||||
2. Cập nhật `imageUrl` trong `db.json` với path tương đối: `/images/banners/ten_file.png`
|
||||
3. Server sẽ tự động build full URL: `http://localhost:3100/images/banners/ten_file.png`
|
||||
|
||||
**Access trực tiếp:**
|
||||
```bash
|
||||
# Xem ảnh trong browser
|
||||
open http://localhost:3100/images/banners/banner_summer_sale.png
|
||||
```
|
||||
|
||||
## 4. Endpoints
|
||||
|
||||
Tất cả endpoint dùng `POST`:
|
||||
|
||||
| Endpoint | Mô tả |
|
||||
|----------|-------|
|
||||
| `POST /charging-station/execute` | Thực thi giao dịch nạp tiền |
|
||||
| `POST /charging-station/getHomeData` | Lấy dữ liệu trang Home |
|
||||
| `POST /charging-station/search` | Tìm kiếm với AI gợi ý |
|
||||
| `POST /charging-station/reward/getList` | Danh sách ưu đãi/voucher |
|
||||
|
||||
## 5. Validation Rules
|
||||
|
||||
### `POST /charging-station/execute`
|
||||
|
||||
**Input validation:**
|
||||
|
||||
| Field | Rule | Regex |
|
||||
|-------|------|-------|
|
||||
| `accountNumber` | Bắt buộc, đúng **9 ký tự**, chỉ chứa số | `^[0-9]{9}$` |
|
||||
| `amount` | Bắt buộc, > 0, tối đa **1,000,000,000** | — |
|
||||
| `accountName` | Không bắt buộc, chỉ chữ cái và khoảng trắng | `^[a-zA-ZÀ-ỹ\s]*$` |
|
||||
|
||||
**Error codes:**
|
||||
|
||||
| Code | Điều kiện | Message |
|
||||
|------|-----------|---------|
|
||||
| `01` | Dữ liệu không hợp lệ / TK không tồn tại | Tùy context |
|
||||
| `02` | Số dư không đủ | "Số dư không đủ" |
|
||||
| `03` | Vượt hạn mức (> 1 tỷ) | "Số tiền tối đa là 1,000,000,000 VND" |
|
||||
|
||||
**Simulate scenarios:**
|
||||
|
||||
| Scenario | Cách test |
|
||||
|----------|-----------|
|
||||
| TK không tồn tại | `accountNumber` bắt đầu bằng `999` |
|
||||
| Số dư không đủ | `accountNumber` bắt đầu bằng `111` + `amount > 500000000` |
|
||||
| Vượt hạn mức | `amount > 1000000000` |
|
||||
|
||||
### `POST /charging-station/search`
|
||||
|
||||
- `query` rỗng: trả full default data (recent + suggested + chips).
|
||||
- `query` có giá trị: filter `suggestions` theo `title/description`.
|
||||
|
||||
### `POST /charging-station/reward/getList`
|
||||
|
||||
- Hỗ trợ `category` để filter voucher/brand.
|
||||
- Hỗ trợ `page` + `pageSize` để phân trang `vouchers`.
|
||||
- Trả thêm `paging` để client dễ test load more.
|
||||
|
||||
## 6. Curl samples
|
||||
|
||||
### Execute success
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sessionId": "abc123",
|
||||
"deviceId": "device-001",
|
||||
"accountNumber": "012345678",
|
||||
"amount": "1000000",
|
||||
"accountName": "NGUYEN VAN A",
|
||||
"isDefaultAccount": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Execute - TK không tồn tại
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"accountNumber": "999123456",
|
||||
"amount": "1000000"
|
||||
}'
|
||||
```
|
||||
|
||||
### Execute - Số dư không đủ
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"accountNumber": "111234567",
|
||||
"amount": "600000000"
|
||||
}'
|
||||
```
|
||||
|
||||
### Execute - Vượt hạn mức
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"accountNumber": "012345678",
|
||||
"amount": "1500000000"
|
||||
}'
|
||||
```
|
||||
|
||||
### Execute - accountNumber sai format
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"accountNumber": "12345",
|
||||
"amount": "1000000"
|
||||
}'
|
||||
```
|
||||
|
||||
### Execute - accountName có ký tự đặc biệt
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/execute \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"accountNumber": "012345678",
|
||||
"amount": "1000000",
|
||||
"accountName": "Nguyen Van A@123"
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Home Data
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/getHomeData \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"sessionId":"abc123","deviceId":"device-001"}'
|
||||
```
|
||||
|
||||
**Response structure:**
|
||||
- `accounts[]` - Danh sách tài khoản cá nhân (DEFAULT, APPLE_PAY, OVERDRAFT, SALARY)
|
||||
- `businessAccounts[]` - Danh sách tài khoản hộ kinh doanh
|
||||
- `loyaltyPoints`, `cashbackAmount`, `memberLevel` - Thông tin loyalty
|
||||
- `recentTransactions[]` - Giao dịch gần đây
|
||||
|
||||
### Search default
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"sessionId":"abc123","query":"","page":1,"pageSize":20}'
|
||||
```
|
||||
|
||||
### Search with query
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"sessionId":"abc123","query":"chuyển tiền","page":1,"pageSize":20}'
|
||||
```
|
||||
|
||||
### Reward - page 1 (có banners)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/reward/getList \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"sessionId":"abc123","page":1,"pageSize":5}'
|
||||
```
|
||||
|
||||
**Response structure:**
|
||||
- `banners[]` - Danh sách banner (chỉ trả về ở page 1)
|
||||
- `vouchers[]` - Danh sách voucher (phân trang)
|
||||
- `paging` - Thông tin phân trang
|
||||
|
||||
### Reward - load more (page 2+, không có banners)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/charging-station/reward/getList \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"sessionId":"abc123","page":2,"pageSize":5}'
|
||||
```
|
||||
|
||||
**Voucher fields:**
|
||||
- `imageUrl` - URL ảnh voucher
|
||||
- `content` - Nội dung/mô tả ưu đãi
|
||||
- `expiry` - Thời hạn (rỗng = không giới hạn)
|
||||
- `requireCardSpending` - `true` = yêu cầu chi tiêu thẻ
|
||||
|
||||
---
|
||||
|
||||
## 7. BASE_URL Configuration
|
||||
|
||||
| Environment | BASE_URL |
|
||||
|-------------|----------|
|
||||
| Local | `http://localhost:3100` |
|
||||
| VPS Production | `https://api-mock.example.com` |
|
||||
|
||||
> **TODO:** Cập nhật VPS Production URL sau khi deploy.
|
||||
|
||||
---
|
||||
|
||||
## 8. Deploy lên VPS với PM2
|
||||
|
||||
### 8.1 Cài đặt môi trường trên VPS
|
||||
|
||||
```bash
|
||||
# 1. Cài Bun (JavaScript runtime)
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
source ~/.bashrc
|
||||
|
||||
# 2. Cài Node.js (cần cho PM2)
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
# 3. Cài PM2 globally
|
||||
sudo npm install -g pm2
|
||||
|
||||
# 4. Verify installations
|
||||
bun --version
|
||||
node --version
|
||||
pm2 --version
|
||||
```
|
||||
|
||||
### 8.2 Clone và setup project
|
||||
|
||||
```bash
|
||||
# Clone repo (hoặc copy folder mock/charging-station)
|
||||
cd /var/www
|
||||
git clone <repo-url> mbbank-mock
|
||||
cd mbbank-mock/mock/charging-station
|
||||
|
||||
# Cài dependencies
|
||||
bun install
|
||||
```
|
||||
|
||||
### 8.3 Chạy với PM2
|
||||
|
||||
```bash
|
||||
# Start server với PM2
|
||||
pm2 start ecosystem.config.js --env production
|
||||
|
||||
# Hoặc start trực tiếp
|
||||
pm2 start server.js --name "charging-station-mock" --interpreter bun
|
||||
|
||||
# Xem logs
|
||||
pm2 logs charging-station-mock
|
||||
|
||||
# Xem status
|
||||
pm2 status
|
||||
|
||||
# Restart
|
||||
pm2 restart charging-station-mock
|
||||
|
||||
# Stop
|
||||
pm2 stop charging-station-mock
|
||||
|
||||
# Delete
|
||||
pm2 delete charging-station-mock
|
||||
```
|
||||
|
||||
### 8.4 Auto-start khi reboot VPS
|
||||
|
||||
```bash
|
||||
# Generate startup script
|
||||
pm2 startup
|
||||
|
||||
# Save current process list
|
||||
pm2 save
|
||||
```
|
||||
|
||||
### 8.5 Cấu hình Nginx (reverse proxy)
|
||||
|
||||
```nginx
|
||||
# /etc/nginx/sites-available/charging-station-mock
|
||||
server {
|
||||
listen 80;
|
||||
server_name api-mock.example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3100;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
# Enable site
|
||||
sudo ln -s /etc/nginx/sites-available/charging-station-mock /etc/nginx/sites-enabled/
|
||||
|
||||
# Test config
|
||||
sudo nginx -t
|
||||
|
||||
# Reload nginx
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### 8.6 Cài SSL với Certbot (HTTPS)
|
||||
|
||||
```bash
|
||||
# Cài Certbot
|
||||
sudo apt install certbot python3-certbot-nginx
|
||||
|
||||
# Lấy SSL certificate
|
||||
sudo certbot --nginx -d api-mock.example.com
|
||||
|
||||
# Auto-renew (đã tự động setup)
|
||||
sudo certbot renew --dry-run
|
||||
```
|
||||
|
||||
### 8.7 PM2 Commands Reference
|
||||
|
||||
| Command | Mô tả |
|
||||
|---------|-------|
|
||||
| `pm2 start ecosystem.config.js` | Start với config file |
|
||||
| `pm2 start server.js --name app` | Start với tên custom |
|
||||
| `pm2 list` | Xem danh sách processes |
|
||||
| `pm2 logs [name]` | Xem logs |
|
||||
| `pm2 monit` | Monitor realtime |
|
||||
| `pm2 restart [name]` | Restart process |
|
||||
| `pm2 reload [name]` | Zero-downtime reload |
|
||||
| `pm2 stop [name]` | Stop process |
|
||||
| `pm2 delete [name]` | Xóa process |
|
||||
| `pm2 save` | Lưu process list |
|
||||
| `pm2 startup` | Setup auto-start |
|
||||
|
||||
### 8.8 Đổi Port
|
||||
|
||||
```bash
|
||||
# Cách 1: Environment variable
|
||||
PORT=3200 pm2 start server.js --name "charging-station-mock" --interpreter bun
|
||||
|
||||
# Cách 2: Sửa ecosystem.config.js
|
||||
# env_production: { PORT: 3200 }
|
||||
pm2 start ecosystem.config.js --env production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Troubleshooting
|
||||
|
||||
### PM2 không nhận Bun
|
||||
|
||||
```bash
|
||||
# Kiểm tra path của bun
|
||||
which bun
|
||||
# Output: /home/user/.bun/bin/bun
|
||||
|
||||
# Sử dụng full path
|
||||
pm2 start server.js --interpreter /home/user/.bun/bin/bun
|
||||
```
|
||||
|
||||
### Port đã được sử dụng
|
||||
|
||||
```bash
|
||||
# Tìm process đang dùng port
|
||||
sudo lsof -i :3100
|
||||
|
||||
# Kill process
|
||||
sudo kill -9 <PID>
|
||||
```
|
||||
|
||||
### Logs quá lớn
|
||||
|
||||
```bash
|
||||
# Rotate logs
|
||||
pm2 install pm2-logrotate
|
||||
|
||||
# Config logrotate
|
||||
pm2 set pm2-logrotate:max_size 10M
|
||||
pm2 set pm2-logrotate:retain 7
|
||||
```
|
||||
Reference in New Issue
Block a user