SEKALIPAY PAYMENT GATEWAY - DOKUMENTASI TERSTRUKTUR 1) TUJUAN Dokumen ini berisi: - Spesifikasi API Payment Gateway - Format autentikasi dan signature - Contoh request/response - Panduan testing Postman end-to-end 2) KREDENSIAL TEST Gunakan kredensial berikut untuk pengujian: - API Key: mk_HGFxRS181SSHDNPQKP1UMivRQbNG6R5bGZk3aNId - Secret Key: sk_W2OFEMPHHlEqKJT3i0jv4n4du8h6eKTQU7KqCC8qpEzVNMhAE0vN8nALFl5d Disarankan menyimpan key ini di Environment Postman, bukan hardcode di body/header request. 3) BASE URL - Production: https://yourdomain.com/api/v1/gateway - Sandbox: https://yourdomain.com/api/v1/gateway (merchant harus is_sandbox=true) 4) AUTENTIKASI Header wajib: - X-MERCHANT-KEY: your_api_key - Content-Type: application/json Header tambahan untuk POST: - X-SIGNATURE: calculated_signature 5) SIGNATURE Rumus signature POST payment: signature = md5(merchant_id:secret_key:merchant_ref_id:amount) Contoh Node.js: const crypto = require('crypto'); const merchantId = '123'; const secretKey = 'sk_xxx'; const merchantRefId = 'ORDER-001'; const amount = 50000; const signature = crypto .createHash('md5') .update(`${merchantId}:${secretKey}:${merchantRefId}:${amount}`) .digest('hex'); Contoh PHP: $merchantId = 123; $secretKey = 'sk_xxx'; $merchantRefId = 'ORDER-001'; $amount = 50000; $signature = md5($merchantId . ':' . $secretKey . ':' . $merchantRefId . ':' . $amount); Contoh Python: import hashlib merchant_id = '123' secret_key = 'sk_xxx' merchant_ref_id = 'ORDER-001' amount = 50000 signature = hashlib.md5(f'{merchant_id}:{secret_key}:{merchant_ref_id}:{amount}'.encode()).hexdigest() 6) ENDPOINTS 6.1) CREATE PAYMENT - Method: POST - Endpoint: /api/v1/gateway/payment - URL penuh: {{base_url}}/payment Header: - X-MERCHANT-KEY: {{api_key}} - X-SIGNATURE: {{signature}} - Content-Type: application/json Body: { "merchant_ref_id": "ORDER-12345", "amount": 50000, "payment_code": "BRIVA", "customer_name": "John Doe", "customer_email": "john@example.com", "customer_phone": "081234567890", "callback_url": "https://yoursite.com/webhook/payment", "metadata": { "order_id": "12345", "custom_field": "value" } } Parameter: - merchant_ref_id (string, wajib, max 191) - amount (integer, wajib, min 100) - payment_code (string, wajib) - customer_name (string, wajib, max 100) - customer_email (string, wajib) - customer_phone (string, wajib) - callback_url (string, opsional) - metadata (object, opsional) Success 201: { "status": true, "message": "OK", "data": { "merchant_ref_id": "ORDER-12345", "invoice": "INV-20241214-XXXX", "amount": 50000, "fee": 3500, "total": 53500, "payment_code": "BRIVA", "payment_link": "https://pay.tokopay.id/xxxx", "qr_link": null, "expired_at": "2024-12-14T16:00:00+07:00", "status": "pending", "is_sandbox": false } } Error contoh: - 400 AMOUNT_OUT_OF_RANGE - 400 PAYMENT_ALREADY_EXISTS (dengan data existing) - 401 INVALID_API_KEY - 401 INVALID_SIGNATURE 6.2) CHECK PAYMENT STATUS - Method: GET - Endpoint: /api/v1/gateway/payment/{merchant_ref_id} - URL penuh: {{base_url}}/payment/{{merchant_ref_id}} Header: - X-MERCHANT-KEY: {{api_key}} Success 200: { "status": true, "message": "OK", "data": { "merchant_ref_id": "ORDER-12345", "invoice": "INV-20241214-XXXX", "status": "completed", "amount": 50000, "fee": 3500, "total": 53500, "payment_code": "BRIVA", "payment_link": "https://pay.tokopay.id/xxxx", "qr_link": null, "expired_at": "2024-12-14T16:00:00+07:00", "created_at": "2024-12-14T15:30:00+07:00", "paid_at": "2024-12-14T15:45:00+07:00" } } Status pembayaran: - pending - paid - processed - completed - canceled Error 404: { "status": false, "message": "PAYMENT_NOT_FOUND" } 6.3) GET PAYMENT METHODS - Method: GET - Endpoint: /api/v1/gateway/payment-methods - URL penuh: {{base_url}}/payment-methods Header: - X-MERCHANT-KEY: {{api_key}} Success 200: daftar payment method + fee_info. 7) WEBHOOK CALLBACK Method: POST Header callback: - X-Merchant-ID: 123 - X-Signature: sha256_signature - Content-Type: application/json Payload callback: { "merchant_ref_id": "ORDER-12345", "invoice": "INV-20241214-XXXX", "status": "completed", "amount": 50000, "total_amount": 53500, "fees": 3500, "payment_code": "BRIVA", "payment_link": "https://pay.tokopay.id/xxxx", "qr_link": null, "expired_at": "2024-12-14T16:00:00+07:00", "paid_at": "2024-12-14T15:45:00+07:00", "created_at": "2024-12-14T15:30:00+07:00", "updated_at": "2024-12-14T15:45:00+07:00", "signature": "sha256_calculated_signature" } Validasi signature callback: $signature = hash('sha256', $data['merchant_ref_id'] . ':' . $data['invoice'] . ':' . $data['status'] . ':' . $your_secret_key ); if ($signature === $data['signature']) { // valid } else { // invalid } Respons endpoint callback yang diharapkan: { "success": true } Retry callback: maksimal 5 kali dengan backoff 1s, 2s, 4s, 8s, 16s. 8) SANDBOX MODE Untuk test aman: - Merchant harus is_sandbox=true - Tidak hit gateway real - Link pembayaran dummy - Alur full bisa dites tanpa transaksi real - Simulasi sukses bisa dilakukan lewat update status transaksi di database 9) ERROR CODES - 200 OK - 201 OK (payment created) - 400 AMOUNT_OUT_OF_RANGE - 400 PAYMENT_METHOD_NOT_AVAILABLE - 401 MISSING_API_KEY - 401 INVALID_API_KEY - 401 MISSING_SIGNATURE - 401 INVALID_SIGNATURE - 403 MERCHANT_INACTIVE - 403 MERCHANT_SUSPENDED - 403 IP_NOT_WHITELISTED - 404 PAYMENT_NOT_FOUND - 500 INTERNAL_SERVER_ERROR - 500 PAYMENT_GATEWAY_ERROR 10) TESTING POSTMAN (SIAP PAKAI) 10.1) Buat Environment Nama contoh: Sekalipay Local Test Variable: - base_url = https://yourdomain.com/api/v1/gateway - api_key = mk_HGFxRS181SSHDNPQKP1UMivRQbNG6R5bGZk3aNId - secret_key = sk_W2OFEMPHHlEqKJT3i0jv4n4du8h6eKTQU7KqCC8qpEzVNMhAE0vN8nALFl5d - merchant_id = 123 - merchant_ref_id = ORDER-{{timestamp}} - amount = 50000 - payment_code = BRIVA - signature = (kosong, diisi pre-request script) 10.2) Request 1 - Get Payment Methods - GET {{base_url}}/payment-methods Headers: - X-MERCHANT-KEY: {{api_key}} Test script saran: pm.test('Status code is 200', function () { pm.response.to.have.status(200); }); pm.test('Response status true', function () { const jsonData = pm.response.json(); pm.expect(jsonData.status).to.eql(true); }); 10.3) Request 2 - Create Payment - POST {{base_url}}/payment Headers: - X-MERCHANT-KEY: {{api_key}} - X-SIGNATURE: {{signature}} - Content-Type: application/json Body: { "merchant_ref_id": "{{merchant_ref_id}}", "amount": {{amount}}, "payment_code": "{{payment_code}}", "customer_name": "John Doe", "customer_email": "john@example.com", "customer_phone": "081234567890" } Pre-request Script: const merchantId = pm.environment.get('merchant_id'); const secretKey = pm.environment.get('secret_key'); const merchantRefId = pm.environment.get('merchant_ref_id'); const amount = pm.environment.get('amount'); const raw = `${merchantId}:${secretKey}:${merchantRefId}:${amount}`; const signature = CryptoJS.MD5(raw).toString(); pm.environment.set('signature', signature); Tests: pm.test('Status code is 201 or 200', function () { pm.expect([200, 201]).to.include(pm.response.code); }); pm.test('Payment created or already exists', function () { const jsonData = pm.response.json(); pm.expect(jsonData.status).to.eql(true); pm.expect(['OK', 'PAYMENT_ALREADY_EXISTS']).to.include(jsonData.message); }); pm.test('Save merchant_ref_id for next request', function () { const jsonData = pm.response.json(); if (jsonData.data && jsonData.data.merchant_ref_id) { pm.environment.set('merchant_ref_id', jsonData.data.merchant_ref_id); } }); 10.4) Request 3 - Check Payment Status - GET {{base_url}}/payment/{{merchant_ref_id}} Headers: - X-MERCHANT-KEY: {{api_key}} Tests: pm.test('Status code is 200', function () { pm.response.to.have.status(200); }); pm.test('Response status true', function () { const jsonData = pm.response.json(); pm.expect(jsonData.status).to.eql(true); }); 10.5) Urutan Test yang Disarankan 1. Get Payment Methods 2. Create Payment 3. Check Payment Status 4. Ulangi Check Payment Status setelah simulasi pembayaran 11) CONTOH cURL curl -X POST https://yourdomain.com/api/v1/gateway/payment \ -H "X-MERCHANT-KEY: mk_xxxxxxxxxxxxxxxxxxxx" \ -H "X-SIGNATURE: calculated_md5_signature" \ -H "Content-Type: application/json" \ -d '{ "merchant_ref_id": "ORDER-12345", "amount": 50000, "payment_code": "BRIVA", "customer_name": "John Doe", "customer_email": "john@example.com", "customer_phone": "081234567890" }'