- Added 'Inter' font to global CSS and Tailwind config for improved typography. - Deleted unused test files related to payment link creation and Snap token testing. - Created comprehensive README for server setup, API endpoints, and payment flow. - Added testing documentation for easier integration and usage of the payment system. |
||
|---|---|---|
| .. | ||
| README.md | ||
| index.cjs | ||
README.md
Simaya Midtrans Payment Server
Backend Express.js server untuk integrasi pembayaran Midtrans dengan sistem ERP.
📋 Daftar Isi
🚀 Fitur Utama
1. Dual Mode Payment
- CORE API: Bank Transfer, Credit Card, GoPay/QRIS, Convenience Store
- SNAP: Hosted payment interface dengan UI Midtrans
2. Payment Link Generation
- Generate secure payment link dengan signature validation
- Configurable TTL (Time To Live)
- Token-based authentication
3. ERP Integration
- Notifikasi otomatis ke sistem ERP setelah pembayaran sukses
- Multi-endpoint support (comma-separated URLs)
- Signature verification untuk keamanan
4. Webhook Handler
- Unified webhook untuk CORE dan SNAP
- Signature verification
- Idempotent notification handling
5. Advanced Logging
- Level-based logging (debug, info, warn, error)
- In-memory log buffer
- Payload masking untuk sensitive data
- Jakarta timezone (WIB/UTC+7)
⚙️ Konfigurasi Environment
Midtrans Configuration
# Required
MIDTRANS_SERVER_KEY=your-server-key
MIDTRANS_CLIENT_KEY=your-client-key
MIDTRANS_IS_PRODUCTION=false
# Payment Method Toggles
ENABLE_BANK_TRANSFER=true
ENABLE_CREDIT_CARD=true
ENABLE_GOPAY=true
ENABLE_CSTORE=true
Payment Link Configuration
# External API Access
EXTERNAL_API_KEY=your-api-key
# Payment Link Settings
PAYMENT_LINK_SECRET=your-secret-for-signing
PAYMENT_LINK_TTL_MINUTES=1440
PAYMENT_LINK_BASE=http://localhost:5174/pay
ERP Integration
# Single URL (legacy)
ERP_NOTIFICATION_URL=https://your-erp.com/api/payment-notification
ERP_CLIENT_SECRET=your-erp-client-secret
# Multi-URL (recommended)
ERP_NOTIFICATION_URLS=https://erp1.com/api/notif,https://erp2.com/api/notif
# Toggle
ERP_ENABLE_NOTIF=true
Logging Configuration
# Logging Level: debug, info, warn, error
LOG_LEVEL=info
# Expose /api/logs endpoint (dev only)
LOG_EXPOSE_API=true
# In-memory buffer size
LOG_BUFFER_SIZE=1000
Server Configuration
PORT=8000
NODE_ENV=development
📡 API Endpoints
Health & Config
GET /api/health
Health check endpoint.
Response:
{
"ok": true,
"env": {
"isProduction": false,
"hasServerKey": true,
"hasClientKey": true
}
}
GET /api/config
Get current payment configuration.
Response:
{
"paymentToggles": {
"bank_transfer": true,
"credit_card": true,
"gopay": true,
"cstore": true
},
"midtransEnv": "sandbox",
"clientKey": "SB-Mid-client-xxx"
}
POST /api/config (Dev Only)
Update payment toggles at runtime.
Request:
{
"paymentToggles": {
"bank_transfer": false
}
}
Payment Operations
POST /api/payments/charge
Create payment transaction via Midtrans Core API.
Headers:
Content-Type: application/json
Request Body:
{
"payment_type": "bank_transfer",
"transaction_details": {
"order_id": "order-123",
"gross_amount": 150000
},
"bank_transfer": {
"bank": "bca"
}
}
Response:
{
"status_code": "201",
"status_message": "Success",
"transaction_id": "xxx",
"order_id": "order-123",
"va_numbers": [
{
"bank": "bca",
"va_number": "12345678901"
}
]
}
POST /api/payments/snap/token
Generate Snap token for hosted payment.
Request:
{
"transaction_details": {
"order_id": "order-123",
"gross_amount": 150000
},
"customer_details": {
"first_name": "John",
"email": "john@example.com"
}
}
Response:
{
"token": "snap-token-xxx"
}
GET /api/payments/:orderId/status
Check payment status.
Response:
{
"status_code": "200",
"transaction_status": "settlement",
"order_id": "order-123",
"gross_amount": "150000.00"
}
Payment Link
POST /createtransaksi
Generate payment link (external ERP endpoint).
Headers:
X-API-KEY: your-external-api-key
Content-Type: application/json
Request:
{
"mercant_id": "merchant-001",
"nominal": 150000,
"nama": "John Doe",
"email": "john@example.com",
"no_telepon": "081234567890",
"item": [
{
"item_id": "product-123",
"nama": "Product Name",
"harga": 150000,
"qty": 1
}
],
"allowed_methods": ["bank_transfer", "gopay"]
}
Response:
{
"status": "200",
"messages": "SUCCESS",
"data": {
"url": "http://localhost:5174/pay/eyJ2Ijox..."
}
}
GET /api/payment-links/:token
Resolve payment link token.
Response:
{
"order_id": "merchant-001:product-123",
"nominal": 150000,
"customer": {
"name": "John Doe",
"email": "john@example.com",
"phone": "081234567890"
},
"expire_at": 1733280000000,
"allowed_methods": ["bank_transfer", "gopay"]
}
Webhook
POST /api/payments/notification
Midtrans webhook handler (unified for CORE & SNAP).
Request (from Midtrans):
{
"order_id": "order-123",
"transaction_status": "settlement",
"gross_amount": "150000.00",
"signature_key": "xxx"
}
Response:
{
"ok": true
}
Logging (Dev Only)
GET /api/logs?limit=100&level=info&q=payment
Get recent logs.
Query Parameters:
limit: Max entries (1-1000, default: 100)level: Filter by level (debug|info|warn|error)q: Search keyword
Response:
{
"count": 50,
"items": [
{
"ts": "2024-12-04T12:00:00.000+07:00",
"level": "info",
"msg": "charge.request",
"meta": {
"id": "abc123",
"payment_type": "bank_transfer"
}
}
]
}
Testing (Dev Only)
POST /api/echo
Echo endpoint untuk testing ERP notification.
POST /api/test/notify-erp
Manual trigger ERP notification.
Request:
{
"orderId": "order-123",
"nominal": "150000",
"mercant_id": "merchant-001"
}
🔄 Payment Flow
1. Payment Link Creation Flow
ERP System → POST /createtransaksi → Server generates token → Payment URL
2. Payment Execution Flow
Customer → Payment URL → Frontend resolves token →
Choose method → POST /api/payments/charge or SNAP → Midtrans
3. Payment Completion Flow
Midtrans → Webhook → Verify signature → Update ledger →
Notify ERP → Mark order complete
4. ERP Notification Format
{
"mercant_id": "merchant-001",
"status_code": "200",
"nominal": "150000",
"signature": "sha512-hash"
}
Signature Calculation:
SHA512(mercant_id + status_code + nominal + ERP_CLIENT_SECRET)
🧪 Testing
Lihat folder tests/ untuk file-file testing:
# Test create payment link
node tests/test-create-payment-link.cjs
# Test frontend payload
node tests/test-frontend-payload.cjs
# Test snap token
node tests/test-snap-token.cjs
Lihat tests/README.md untuk detail lengkap.
📝 Logging
Log Levels
- debug: Detailed information, typically of interest only when diagnosing problems
- info: General informational messages
- warn: Warning messages for potentially harmful situations
- error: Error events that might still allow the application to continue running
Log Format
[2024-12-04T12:00:00.000+07:00] [info] charge.request {"id": "abc123", "payment_type": "bank_transfer"}
Important Log Events
Payment Lifecycle
charge.request: Payment charge initiatedcharge.success: Charge successfulcharge.error: Charge failedstatus.request: Status check requestedwebhook.received: Webhook notification received
ERP Integration
erp.notify.start: ERP notification startederp.notify.success: ERP notified successfullyerp.notify.error: ERP notification failederp.notify.skip: Notification skipped (already sent or disabled)
Security
webhook.signature.invalid: Invalid webhook signaturecreatetransaksi.unauthorized: Unauthorized API key
🔒 Security Features
-
Signature Verification
- Webhook signature validation
- Payment link token signing
- ERP notification signing
-
Idempotency
- Prevent duplicate order creation
- Prevent duplicate ERP notifications
- Block re-charge for pending orders
-
API Key Authentication
- External API key for
/createtransaksi - Dev mode fallback for easier local testing
- External API key for
-
Payload Masking
- Sensitive fields masked in logs
- Card numbers, CVV, tokens automatically hidden
🚀 Running the Server
# Install dependencies
npm install
# Start server
node server/index.cjs
# Server runs on http://localhost:8000
📚 Related Documentation
- Tests README - Testing documentation
- Temp Files README - Temporary files info
- Frontend README - Main project README
🐛 Common Issues
Issue: "Transaction already pending"
Cause: Order ID already has pending transaction in Midtrans Solution: Use existing payment instructions or create new order with different ID
Issue: "ERP notification failed"
Cause: ERP endpoint unreachable or signature mismatch
Solution: Check ERP_NOTIFICATION_URLS and ERP_CLIENT_SECRET configuration
Issue: "Invalid signature on webhook"
Cause: Incorrect server key or webhook from unauthorized source
Solution: Verify MIDTRANS_SERVER_KEY matches your Midtrans account
📞 Support
Untuk bantuan lebih lanjut, hubungi tim development atau lihat dokumentasi Midtrans: