ShoppePay Partner
API Gateway Docs
Gateway 100% Stateless (tanpa database & tanpa polling) untuk verifikasi mutasi ShopeePay, validasi token, riwayat bulanan, dan pembuatan Dynamic QRIS EMVCo dengan CRC16-CCITT recalculation — polling hanya saat checkout aktif sehingga aman dari rate-limit.
Introduction
Gateway ini membaca data dari ShopeePay Partner Portal menggunakan sesi akun merchant Anda (token internal B:...) — mirip cara kerja extension browser. Desain stateless / client-polled: gateway hanya hit Shopee saat ada pembeli aktif di halaman checkout (poll tiap 10–15 detik), sehingga trafik nol ketika toko sepi dan terhindar dari blokir rate-limit.
Toko → Gateway: POST /create-qris {amount} (X-API-Key)
Gateway: parse QRIS_STATIC, inject amount, calc CRC → return qris_url + expiry (15 menit)
Toko → Pelanggan: tampilkan QR
Pelanggan → Shopee: scan & bayar
loop tiap 10-15s selama checkout aktif:
Toko → Gateway: POST /check-payment {amount, startTime}
Gateway → Shopee: POST /get-transaction-list (range startTime→now)
Shopee → Gateway: list transaksi
if paid → Gateway → Shopee: get-transaction-detail → return {paid:true, transaction{...issuer: Seabank/OVO/DANA/BCA...}}
else → {paid:false}
Base URL & Domain
https://sppg.ioi.my.id
Semua endpoint di bawah ini relatif terhadap base ini. Contoh: https://sppg.ioi.my.id/api/health
Authentication
Semua endpoint sensitif wajib kirim API Key via header X-API-Key: <API_KEY> atau query ?api_key=<API_KEY>. Multi-store: tambahkan X-Shopee-Token: B:... per-request untuk override token .env.
X-Shopee-Token: B:EWznmVD... (opsional)
Content-Type: application/json
API_KEY="shopee-secret-key-2026"
PORT=4000
QRIS_STATIC="000201010211266..."
TELEGRAM_BOT_TOKEN="..."
TELEGRAM_CHAT_ID="..."
Quick Start — 5 Menit
# 1) Health (no auth)
curl https://sppg.ioi.my.id/api/health
# 2) Create QRIS — dynamic amount
curl -X POST https://sppg.ioi.my.id/create-qris \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount":15000}'
# 3) Poll verify — startTime = unix detik saat create QRIS
curl -X POST https://sppg.ioi.my.id/check-payment \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount":15000,"startTime": 1715660000}'
transactionId dari /check-payment ke DB toko & tolak jika sudah pernah dipakai. Gateway juga dedup in-memory 24 jam.
/create-qris — Generate Dynamic QRIS
Parsing QRIS statis (TLV), inject nominal ke Tag 54, hitung ulang CRC16-CCITT in-memory. Return URL redirect QR + expiry 15 menit.
{
"amount": 15000
}
{
"success": true,
"data": {
"qris_url": "https://sppg.ioi.my.id/qr/f3f050d4",
"amount": 15000,
"expires_at": "2026-07-15 09:29:25",
"expires_in": "15 menit"
}
}
curl -X POST https://sppg.ioi.my.id/create-qris \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount":15000}'
/qr/:id — Tampilkan QR Image
Redirect QR image untuk pelanggan. Tanpa auth (publik). Contoh: https://sppg.ioi.my.id/qr/f3f050d4 → image/png QRIS.
/check-payment — Verifikasi Pembayaran (Stateless)
Polling tiap 10–15 detik hanya selama checkout aktif. Gateway hit /get-transaction-list dengan rentang startTime → now, lalu /get-transaction-detail untuk issuer (Seabank/OVO/DANA/BCA/Mandiri). In-memory dedup mencegah double claim.
{
"amount": 1008,
"startTime": 1784050000
}
{
"success": true,
"paid": true,
"transaction": {
"transactionId": "264693445089687719",
"amount": 1008,
"status": "success",
"time": "2026-07-15 00:42:21",
"issuer": "Seabank"
}
}
{"success":true,"paid":false}/transactions — Mutasi Terbaru
curl -H "X-API-Key: YOUR_API_KEY" https://sppg.ioi.my.id/transactions
{
"success": true,
"total_amount": "409.662",
"data": {
"transactions": [
{ "amount": 9600, "status": "success", "time": "2026-07-13 14:12:41", "issuer": "OVO" }
]
}
}
/transactions/all — Mutasi Sebulan Penuh
Mengambil seluruh mutasi dalam sebulan (paginasi internal ke Shopee). Gunakan X-Shopee-Token untuk filter per-merchant.
curl -H "X-API-Key: YOUR_API_KEY" https://sppg.ioi.my.id/transactions/all
/api/logs — In-Memory Logs (100 terakhir)
curl -H "X-API-Key: YOUR_API_KEY" https://sppg.ioi.my.id/api/logs
// → { "logs": [ { "timestamp": "...", "level": "info", "message": "..." } ] }
/token-status — Cek Validitas Token
curl -H "X-API-Key: YOUR_API_KEY" https://sppg.ioi.my.id/token-status
{"success":true,"data":{"token_status":"valid","message":"Token is working"}}
// jika mati → token_status: invalid + Telegram alert (cek tiap 5 menit)
/update-token — Perbarui Token Live
Update tanpa restart. Ambil token baru dari DevTools → Network → get-transaction-list → payload → metadata → token (B:...).
curl -X POST https://sppg.ioi.my.id/update-token \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"token":"B:NEW_TOKEN_DI_SINI"}'
/api/health — Health Check (public)
curl https://sppg.ioi.my.id/api/health
{"success":true,"message":"ShopeePay API Service is running","timestamp":"2026-07-15T02:14:10.091Z"}
Errors & Codes
| Status / Code | Arti | Solusi |
|---|---|---|
| 200 OK | Sukses | Baca data response |
| 401 Unauthorized | API Key salah/kosong | Cek header X-API-Key |
| 400 Bad Request | Param salah | Cek JSON body |
| 200020 (Shopee) | Token mati/invalid | POST /update-token + cek Telegram |
| EADDRINUSE | Port bentrok | Kill proses di PORT 4000 |
Deployment — sppg.ioi.my.id (VPS + Nginx + PM2)
Domain sudah pointing ke VPS ini (38.47.92.20). Gateway jalan di 127.0.0.1:4000 via PM2, Nginx reverse-proxy + SSL Let’s Encrypt.
pm2 start server.js --name sppg-gateway -- --port 4000
pm2 save
pm2 startup
pm2 logs sppg-gateway
server_name sppg.ioi.my.id;
location / { root /root/shoppepay-api-gateway/docs; try_files $uri $uri/ =404; }
location ~ ^/(api/health|create-qris|check-payment|transactions|token-status|update-token|qr|api/logs) {
proxy_pass http://127.0.0.1:4000;
}
get-transaction-list → Payload → data → metadata → token (awalan B:).