[FEAT-SIMPONI-V3-ISOLATION] Pembaruan Protokol API Simponi Kemenkeu & Isolasi Arsitektur V3 (Dukungan Multi-K/L & Multi-Satker)
Modul: Single Billing | Tipe: Feature | Stage Saat Ini:
PRODUCTION| Tanggal Dokumen: 2026-09-07
PRODUCTION RELEASED
Dokumen ini telah berada dalam tahap PRODUCTION. Perubahan logika backend, migrasi skema/konfigurasi, dan rilis v1.9.2 telah diterapkan secara penuh di lingkungan Production via MR !232.
LIFECYCLE GUIDE — UPDATE BERTAHAP:
- Buat file ini saat selesai development. Isi semua section kecuali Staging & Production.
- Tanggal Dokumen (Header) & Riwayat Update Log: Gunakan tanggal hari ini (pembuatan dokumen).
- Baris Development (Lifecycle): Gunakan tanggal & jam commit terakhir terkait di branch development.
- Update baris Staging saat naik ke UAT. Ubah "Stage Saat Ini" di header menjadi STAGING.
- Update baris Production saat naik ke Prod. Ubah "Stage Saat Ini" di header menjadi PRODUCTION.
- Update entry di README.md setiap kali status berubah. -->
1. Informasi Tugas & Referensi Bisnis
Task ID / Nomor Referensi:
FEAT-SIMPONI-V3-ISOLATIONSumber Instruksi: Pembaruan Protokol API Simponi Kemenkeu & Isolasi Arsitektur V3
Dokumen Referensi / Lampiran:
Task / Dependensi Terkait (Cross-Service):
-Modul Terkait:
Single BillingService / Repository:
single-billing-BEPIC Pengembang: Hermansyah Efendi
Latar Belakang & Ringkasan Kebutuhan: Pembaruan protokol API Simponi V3 Kemenkeu memperkenalkan kapabilitas krusial berupa dukungan Multi-K/L (Kemenhub & Kemenkes) serta Multi-Satker (Kantor Kesyahbandaran dan Otoritas Pelabuhan / KSOP serta Distrik Navigasi / Disnav) dalam satu transaksi bundle single billing terpadu. Pada implementasi Simponi V1/V2 sebelumnya, satu request penerbitan billing dibatasi hanya untuk 1 Satker tunggal. Protokol Simponi V3 mewajibkan format payload terstruktur
simponi_reqdengan detail 19 elemen (mencakup atributkode_kl,kode_unit_riil, danketerangan_detail), header 13 elemen, serta metadata agregasiinformation(billInfo 1-9) dan mekanisme respons JSON langsung. Hal ini memungkinkan tagihan PNBP dari satker Ditjen Hubla (Disnav Palembang, KSOP Pangkal Balam, KSOP Banjarmasin, KSOP Tanjung Emas, KSOP Teluk Palu, Disnav Ujung Pandang) dan satker Kemenkes (Balai Kekarantinaan Kesehatan / BKK) dikonsolidasikan dalam satu siklus billing code. Agar arsitektur baru ini tidak merusak (breaking change) alur Simponi V1/V2 eksisting yang sedang aktif beroperasi, integrasi Simponi V3 diisolasi secara modular pada rute/api/v3. Seluruh pengujian QA playbook dirancang untuk melakukan hit langsung ke gateway Simponi Kemenkeu (Live Gateway Sandbox, tanpa mock) guna memastikan validitas transaksi secara end-to-end sebelum rilis.Ruang Lingkup & Rincian Sub-Pekerjaan (Technical Scope & Milestones):
- [x] Pembuatan modul routing
/api/v3diapp/routes/v3/index.jsdan mounting prefix diserver.js(isolasi arsitektur) - [x] Penambahan skema validasi Joi
schemasSimponiV3untuk payload detail 19 elemen, header 13 elemen, dan validasi format multi-satker / multi-K/L - [x] Pembuatan controller
rekapTagihanINSW_V3danrequest_billing_V3berkemampuan agregasi invoice variasi Multi-Satker (KSOP & Disnav) serta Multi-K/L - [x] Penambahan fungsi helper komunikasi
sendSingleBillingV3dansendInquiryBillingV3 - [x] Implementasi mock handler
handleSimponiMockhanya sebagai fallback lokal unit test DEV (dinonaktifkan pada eksekusi QA) - [x] Ekstraksi konstanta Simponi (
SIMPONI_REQUEST_BILLING_METHOD,SIMPONI_KODE_SATKER,SIMPONI_KODE_KL,SIMPONI_KODE_ESELON_1)
- [x] Pembuatan modul routing
2. Deployment Lifecycle
| # | Environment | Tanggal & Waktu | PIC | Status | Catatan |
|---|---|---|---|---|---|
| 1 | Development | 2026-07-15 11:21 | Hermansyah Efendi | DEPLOYED | Branch: development (Merged from feat/simponi-v3) |
| 2 | Staging (UAT) | 2026-10-14 13:00 | Hermansyah Efendi / QA | DEPLOYED | Release Candidate via MR Staging !229. Co-deployed: [FEAT-SIMPONI-V3-ISOLATION, TASK-SET-EXPIRED-BILLING-V3, FEAT-BILLING-REKAP-EXPIRED-DATE-PAYLOAD, REFACTOR-TAGIHAN-CONTROLLER-DEDUPLICATION, FIX-PAYMENT-WEBHOOK-RACE-CONDITION, FIX-TAGIHAN-PREVENT-PAID-INVOICE-REORDER, FEAT-REQUEST-LOGGER-POSTMAN, TEST-DRAGONFLY-VITEST-SUITE, FEAT-RUNTIME-ENV-VALIDATION, TASK-NON-BLOCKING-BILLING-DISPATCH-AND-RETRY-CONFIG] |
| 3 | Production | 2026-10-14 20:06 | achmad fauzi | DEPLOYED | Branch: prod via MR !232 (Release v1.9.2). Co-deployed: [FEAT-SIMPONI-V3-ISOLATION, TASK-SET-EXPIRED-BILLING-V3, FEAT-BILLING-REKAP-EXPIRED-DATE-PAYLOAD, REFACTOR-TAGIHAN-CONTROLLER-DEDUPLICATION, FIX-PAYMENT-WEBHOOK-RACE-CONDITION, FIX-TAGIHAN-PREVENT-PAID-INVOICE-REORDER, FEAT-REQUEST-LOGGER-POSTMAN, TEST-DRAGONFLY-VITEST-SUITE, FEAT-RUNTIME-ENV-VALIDATION, TASK-NON-BLOCKING-BILLING-DISPATCH-AND-RETRY-CONFIG] |
Riwayat Update Log
| Tanggal | Environment | Perubahan | PIC |
|---|---|---|---|
| 2026-10-14 | Production | Status diupdate ke PRODUCTION (DEPLOYED, CLOSED), rilis Release v1.9.2 via MR !232 | Hermansyah Efendi |
| 2026-09-07 | Development | Inisialisasi draft audit log dari context block backend (commit 086cd2a) | Hermansyah Efendi |
| 2026-09-07 | Development | Pembaruan dokumentasi kapabilitas Multi-Satker Hubla (KSOP & Disnav), pembersihan asosiasi entitas Wajib Bayar, dan penyelarasan QA Playbook berbasis Postman Collection | Hermansyah Efendi |
| 2026-09-07 | Development | Standardisasi payload riil simponi_req (header 13 elemen, detail 19 elemen multi-K/L, metadata information) dan penegasan pengujian QA wajib Live Hit ke Gateway Simponi (tanpa mock) | Hermansyah Efendi |
3. Analisis Teknis & Rincian Perubahan
Alur Logika & Bisnis:
- Dukungan Multi-K/L & Multi-Satker: Single Billing V3 menerima bundle tagihan yang terdiri dari multi invoice lintas K/L (Kemenhub
022dan Kemenkes024) serta lintas Satker (Disnav Palembang413293, KSOP Pangkal Balam413262, KSOP Kelas I Banjarmasin287171, KSOP Kelas I Tanjung Emas412823, KSOP Kelas III Teluk Palu287370, Disnav Ujung Pandang287473, BKK Kemenkes416108). - Struktur Payload Fisik Simponi V3 (
simponi_req):header(13 elemen):no_aju_layanan, dua hardcoded empty string"",expired_date, hardcoded"000","00","SB0001", jenis penerimaan"F"(PNBP), mata uang"1"(IDR),total_nominal,nama_wajib_bayar,npwp_wajib_bayar, danketerangan_header.detail(19 elemen per baris): hardcoded"",no_aju_layanan,expired_date,nama_wajib_bayar,npwp,kode_tarif_simponi,kode_pp_simponi,kode_akun,nominal_tarif_pnbp,volume,satuan_tarif,total_tarif_per_record,kode_lokasi,kode_kabkota,kode_satker_riil,fl_blu,kode_kl,kode_eselon_1, danketerangan_detail.information(billInfo 1–9): Metadata agregasi layanan (misal SSm Pengangkut Kedatangan vs Keberangkatan, nomor aju, nominal parsial, nomor PKK, nama kapal, dan pelabuhan).
- Penegasan Pengujian QA (No Mock): Pada proses validasi QA dan UAT, pengetesan wajib melakukan koneksi langsung (live hit) ke Gateway Sandbox Simponi Kemenkeu untuk memvalidasi respons otentik dari sistem Simponi (termasuk verifikasi format satker, akun PNBP, dan penomoran billing 820xxxxxxx). Mock handler hanya difungsikan untuk isolasi unit test pada level internal development.
- Penambahan Environment Gateway Simponi V3: Penambahan variabel lingkungan
SIMPONI_BILLING_V3sebagai URL gateway endpoint Simponi V3 resmi Kemenkeu pada container runtime backend. - Penghapusan Environment Variabel (Deprecated / Converted to Constants): Variabel lingkungan
SIMPONI_BILLING_METHOD,SIMPONI_BILLING_METHOD_V2, danSIMPONI_BILLING_METHOD_V3telah dihapus (deprecated/removed) dari file environment dan digantikan sepenuhnya oleh konstanta internalSIMPONI_REQUEST_BILLING_METHOD(v1: 'single_billing',v2: 'single_billing_v2',v3: 'single_billing_v3') diapp/helpers/simponi.jskarena metode pemanggilan Simponi bersifat deterministik. - Isolasi Modular Rute: Rute V3 dipisahkan secara eksklusif pada
app/routes/v3/index.jsdan dimounting pada prefix/api/v3diserver.jsguna menjamin zero-regression terhadap endpoint Simponi V1/V2 eksisting. - Daftar File yang Berubah:
app/routes/v3/index.js(API Route — isolasi rute v3)app/controllers/tagihan_controller.js(Controller — handler rekap tagihan V3)app/controllers/billing_controller.js(Controller — handler request billing V3)app/models/tagihan_models.js(Validation / Schema — schema Joi V3 19 elemen & validasi multi-satker)app/models/billing_models.js(Model / Query — query getDataDetailV3)app/helpers/simponi.js(Helper / External Integration — client API Simponi V3 & mock handler)server.js(Bootstrap — registrasi prefix /api/v3)
- Dukungan Multi-K/L & Multi-Satker: Single Billing V3 menerima bundle tagihan yang terdiri dari multi invoice lintas K/L (Kemenhub
Perubahan Database (DDL / DML):
sql-- Tidak ada migration file yang terdeteksi — penambahan logic routing dan integrasi API.Kontrak API & Response Payload:
POST/api/v3/terima-rekap-tagihan- Deskripsi: Menerima rekap tagihan terpadu (mendukung Multi-K/L Kemenhub & Kemenkes serta Multi-Satker Hubla) dan meneruskannya ke Simponi V3, Inaportnet, dan Sinkarkes.
- Autentikasi / Guard:
Bearer Token(doIntrospection),validateSchemaSimponi(schemasSimponiV3.body) - Request Header / Content-Type:
Authorization:Bearer <token>Content-Type:application/json
- Request Body (Struktur Riil Simponi V3):jsonc
{ "simponi_req": { "method": "single_billing", "data": { "header": [ "1020195BA8E65", // [0] no_aju_layanan "", // [1] hardcode empty string "", // [2] hardcode empty string "2026-09-11 23:59:59", // [3] expired_date billing "000", // [4] hardcode "000" (spesifikasi Simponi V3) "00", // [5] hardcode "00" (spesifikasi Simponi V3) "SB0001", // [6] hardcode "SB0001" (kode prefix Single Billing) "F", // [7] jenis_penerimaan ("F" = PNBP) "1", // [8] mata_uang ("1" = IDR) 53511808, // [9] total_nominal_billing (akumulasi detail) "PT LAYAR SENTOSA SHIPPING", // [10] nama_wajib_bayar "0011358389631000", // [11] npwp_wajib_bayar (16 digit) "Single Billing SSm Pengangkut pada pelabuhan IDJKT - TANJUNG PRIOK" // [12] keterangan_header ], "detail": [ [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "MCABLEIDPGXPT BANGKA JAYA LINE", // [3] nama_wajib_bayar per item null, // [4] npwp_wajib_bayar (null jika tidak ada) "000899", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425517", // [7] kode_akun (PNBP Kenavigasian) 0.6, // [8] nominal_tarif_pnbp 12, // [9] volume / kuantitas "Per Kata", // [10] satuan_tarif 51062, // [11] total_tarif_per_record "11", // [12] kode_lokasi "51", // [13] kode_kabkota "413293", // [14] kode_satker_riil (Disnav Palembang) "0", // [15] fl_blu (Flag BLU: "0" = Non-BLU) "022", // [16] kode_kl ("022" = Kemenhub) "04", // [17] kode_eselon_1 ("04" = Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "MCABLEIDPGXPT BANGKA JAYA LINE", // [3] nama_wajib_bayar null, // [4] npwp "000900", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425517", // [7] kode_akun 0.15, // [8] nominal_tarif_pnbp 12, // [9] volume "Per Kata", // [10] satuan_tarif 12766, // [11] total_tarif_per_record "11", // [12] kode_lokasi "51", // [13] kode_kabkota "413293", // [14] kode_satker_riil (Disnav Palembang) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "DNPUIDPGXPT BANGKA JAYA LINE", // [3] nama_wajib_bayar null, // [4] npwp "000878", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425514", // [7] kode_akun (PNBP Kepelabuhanan) 250, // [8] nominal_tarif_pnbp 1483, // [9] volume "Per GT per 30 Hari", // [10] satuan_tarif 370750, // [11] total_tarif_per_record "30", // [12] kode_lokasi "02", // [13] kode_kabkota "413262", // [14] kode_satker_riil (KSOP Pangkal Balam) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "LNPUIDBDJPT TERA LOGISTIC INDONESIA",// [3] nama_wajib_bayar null, // [4] npwp "000877", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425514", // [7] kode_akun (PNBP Kepelabuhanan) 0.034, // [8] nominal_tarif_pnbp 45229, // [9] volume "Per GT per 30 Hari", // [10] satuan_tarif 27815474, // [11] total_tarif_per_record "15", // [12] kode_lokasi "51", // [13] kode_kabkota "287171", // [14] kode_satker_riil (KSOP Kelas I Banjarmasin) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "LabuhPUPT SAMUDERA AGENCIES INDONESIA",// [3] nama_wajib_bayar null, // [4] npwp "000395", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425513", // [7] kode_akun (PNBP Jasa Labuh) 1452, // [8] nominal_tarif_pnbp 16856, // [9] volume "Per GT/15 Hari", // [10] satuan_tarif 24474912, // [11] total_tarif_per_record "03", // [12] kode_lokasi "51", // [13] kode_kabkota "412823", // [14] kode_satker_riil (KSOP Kelas I Tanjung Emas) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "LabuhTuksPT PELAYARAN SURYA BINTANG TIMUR",// [3] nama_wajib_bayar null, // [4] npwp "000447", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425513", // [7] kode_akun (PNBP Jasa Labuh) 84, // [8] nominal_tarif_pnbp 141, // [9] volume "Per GT/15 Hari", // [10] satuan_tarif 11844, // [11] total_tarif_per_record "18", // [12] kode_lokasi "02", // [13] kode_kabkota "287370", // [14] kode_satker_riil (KSOP Kelas III Teluk Palu) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan "2026-09-04", // [2] expired_date "VTSPUIDMAKPT MERATUS LINE", // [3] nama_wajib_bayar null, // [4] npwp "000930", // [5] kode_tarif_simponi "201615C", // [6] kode_pp_simponi "425517", // [7] kode_akun (PNBP VTS) 175000, // [8] nominal_tarif_pnbp 1, // [9] volume "Per Kapal", // [10] satuan_tarif 175000, // [11] total_tarif_per_record "19", // [12] kode_lokasi "51", // [13] kode_kabkota "287473", // [14] kode_satker_riil (Disnav Ujung Pandang) "0", // [15] fl_blu "022", // [16] kode_kl (Kemenhub) "04", // [17] kode_eselon_1 (Ditjen Hubla) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "1020195BA8E65", // [1] no_aju_layanan (Kedatangan) "2026-09-04", // [2] expired_date "SAMUDERA SUKSES MAKMUR", // [3] nama_wajib_bayar null, // [4] npwp "001744", // [5] kode_tarif_simponi "2019064", // [6] kode_pp_simponi "425314", // [7] kode_akun (PNBP Karantina Kesehatan) 300000, // [8] nominal_tarif_pnbp 1, // [9] volume "Per Pemeriksaan Kapal", // [10] satuan_tarif 300000, // [11] total_tarif_per_record "01", // [12] kode_lokasi "52", // [13] kode_kabkota "416108", // [14] kode_satker_riil (BKK Kemenkes) "0", // [15] fl_blu "024", // [16] kode_kl ("024" = Kemenkes) "05", // [17] kode_eselon_1 ("05" = Ditjen P2P) "" // [18] keterangan_detail ], [ "", // [0] hardcode empty string "101018FB7DA54", // [1] no_aju_layanan (Keberangkatan) "2026-09-04", // [2] expired_date "SAMUDERA SUKSES MAKMUR", // [3] nama_wajib_bayar null, // [4] npwp "001744", // [5] kode_tarif_simponi "2019064", // [6] kode_pp_simponi "425314", // [7] kode_akun (PNBP Karantina Kesehatan) 300000, // [8] nominal_tarif_pnbp 1, // [9] volume "Per Pemeriksaan Kapal", // [10] satuan_tarif 300000, // [11] total_tarif_per_record "01", // [12] kode_lokasi "52", // [13] kode_kabkota "416108", // [14] kode_satker_riil (BKK Kemenkes) "0", // [15] fl_blu "024", // [16] kode_kl ("024" = Kemenkes) "05", // [17] kode_eselon_1 ("05" = Ditjen P2P) "" // [18] keterangan_detail ] ] }, "information": { "billInfo1": "SSm Pengangkut - Kedatangan", "billInfo2": "101018FB7DA54", "billInfo3": "300000", "billInfo4": "SSm Pengangkut - Keberangkatan", "billInfo5": "1020195BA8E65", "billInfo6": "53211808", "billInfo7": "PKK.LN.IDJKT.2411.000002", "billInfo8": "SPIL NITA", "billInfo9": "IDJKT - TANJUNG PRIOK" }, "jenis_layanan": "8", "no_aju_layanan": "1020195BA8E65" } }
Kamus Struktur Data Array Simponi V3:
Array Header (13 Elemen):
[0]no_aju_layanan: Nomor pengajuan dokumen layanan SSm Pengangkut[1]empty_string: Hardcoded""[2]empty_string: Hardcoded""[3]expired_date: Batas akhir masa berlaku kode billing (YYYY-MM-DD HH:mm:ss)[4]kode_aplikasi: Hardcoded"000"(spesifikasi teknis Simponi V3)[5]kode_fungsi: Hardcoded"00"(spesifikasi teknis Simponi V3)[6]kode_prefix: Hardcoded"SB0001"(prefix layanan Single Billing)[7]jenis_penerimaan:"F"untuk Penerimaan Negara Bukan Pajak (PNBP)[8]mata_uang:"1"untuk mata uang Rupiah (IDR)[9]total_nominal: Total akumulasi tagihan (wajib sama dengan penjumlahan detail)[10]nama_wajib_bayar: Nama wajib bayar induk / pemohon billing[11]npwp_wajib_bayar: NPWP wajib bayar 16 digit angka[12]keterangan_header: Deskripsi ringkas peruntukan billing layanan
Array Detail (19 Elemen per Baris):
[0]empty_string: Hardcoded""[1]no_aju_layanan: Nomor pengajuan transaksi layanan[2]expired_date: Batas akhir tanggal pembayaran rincian tagihan (YYYY-MM-DD)[3]nama_wajib_bayar: Nama wajib bayar sub-item tagihan[4]npwp: NPWP sub-item (opsional /nulljika tidak ada)[5]kode_tarif_simponi: 6 digit kode tarif penerimaan Simponi[6]kode_pp_simponi: 7 karakter kode Peraturan Pemerintah penetapan tarif[7]kode_akun: 6 digit kode akun bagan akun standar (BAS) penerimaan[8]nominal_tarif_pnbp: Tarif satuan per unit/volume[9]volume: Kuantitas / volume layanan[10]satuan_tarif: Satuan kuantitas (misal "Per Kata", "Per GT/15 Hari", "Per Kapal")[11]total_tarif_per_record: Total nilai per baris tagihan[12]kode_lokasi: 2 digit kode lokasi provinsi[13]kode_kabkota: 2 digit kode kabupaten/kota[14]kode_satker_riil: 6 digit kode Satker resmi penerima PNBP (UPT Hubla / BKK Kemenkes)[15]fl_blu: Flag status instansi BLU ("0"= Non-BLU,"1"= BLU)[16]kode_kl: 3 digit kode K/L ("022"= Kemenhub,"024"= Kemenkes)[17]kode_eselon_1: 2 digit kode unit eselon I ("04"= Ditjen Hubla,"05"= Ditjen P2P)[18]keterangan_detail: Informasi catatan tambahan spesifik tagihan (string kosong jika tidak ada)
Response Payload (
200 OK):json{ "status": 200, "trx_id_insw": "TRX-123456", "kode_billing": { "kodeBillingInduk": "820260729744850", "kodeBillingPnbp": "820260729744851" } }Response Error (
400 Bad Request):json{ "status": 400, "message": "Validation Failed: Satker must be numeric / Total nominal header does not match detail sum" }
4. Bukti Teknis (Technical Proof & Audit Trail)
- Repository:
single-billing-BE - Branch Utama:
development - Merge Request / PR: !232 (Release v1.9.2 — Merged to prod) | Staging: !229
Daftar Commit Terkait (Multi-Commit Trail)
| Commit ID | Branch | Author | Tanggal & Jam | Ringkasan Perubahan |
|---|---|---|---|---|
d8c6e35 | feat/simponi-v3 | Hermansyah Efendi | 2026-05-25 10:12 | feat(simponi-v3): isolate simponi v3 integration under /api/v3 routes |
925037d | feat/simponi-v3 | Hermansyah Efendi | 2026-05-25 10:36 | refactor(simponi): implement reusable mock handler for DEV environment |
6acadbf | development | Hermansyah Efendi | 2026-07-14 13:29 | refactor(simponi): use constants instead of env for billing methods |
2200580 | development | Hermansyah Efendi | 2026-07-14 13:40 | refactor(simponi): extract simponi v3 metadata to constants |
086cd2a | development | Hermansyah Efendi | 2026-07-15 11:21 | fix(simponi): replace Math.random with crypto.randomInt in mock handler |
Cuplikan Kode / Query Migration
// app/helpers/simponi.js
const handleSimponiMock = () => {
if (process.env.STATUS_APP !== 'DEV') {
return null;
}
const mockMode = process.env.MOCK_MODE;
if (!mockMode) {
return null;
}
if (mockMode === 'true') {
return {
response: {
code: "00",
message: "Sukses",
data: [
`820${crypto.randomInt(100000000, 1000000000)}`,
`820${crypto.randomInt(1000000, 10000000)}`,
moment().format('YYYY-MM-DD HH:mm:ss'),
moment().add(7, 'days').format('YYYY-MM-DD HH:mm:ss')
]
}
};
}
const errors = [
{ code: "IX", message: "Satker Layanan dengan Satker Riil tidak ada keterkaitan." },
{ code: "IN", message: "Nama wajib bayar tidak boleh mengandung karakter khusus seperti !@#$%^&" },
{ code: "IR", message: "Kode Satker Riil tidak valid." },
{ code: "ID", message: "Tanggal tidak valid." },
{ code: "M2", message: "Proses pengiriman data billing ke MPN gagal." },
{ code: "IM", message: "Satker Riil dengan Akun Penerimaan tidak ada keterkaitan." },
{ code: "IS", message: "Kode Satker Layanan tidak valid." }
];
if (mockMode === 'error') {
const randomError = errors[crypto.randomInt(0, errors.length)];
return {
response: {
code: randomError.code,
message: randomError.message,
data: []
}
};
}
return null;
};5. Bukti Verifikasi Pengujian (QA / Unit Test / API Verification)
A. Verifikasi Unit Test (Development Stage)
- Test Suite File:
tests/helpers/simponi.test.js - Status Eksekusi CLI:
PASSED
describe("mock mode via sendSingleBilling", () => {
it("ignores MOCK_MODE when STATUS_APP is not DEV", async () => {
process.env.STATUS_APP = "PROD";
process.env.MOCK_MODE = "true";
process.env.SIMPONI_BILLING_V1 = "http://v1";
axios.mockResolvedValueOnce({ data: '{"response":{"code":"00"}}' });
const result = await sendSingleBilling("x");
expect(axios).toHaveBeenCalledTimes(1);
expect(result).toEqual({ response: { code: "00" } });
});
}); RUN v4.1.11 D:/WORK/LNSW/single-billing-BE
✓ tests/helpers/simponi.test.js (28 tests) 23ms
Test Files 1 passed (1)
Tests 28 passed (28)
Start at 10:59:53
Duration 388ms (transform 74ms, setup 78ms, import 83ms, tests 23ms, environment 0ms)B. Panduan Pengujian QA & Verifikasi Staging (QA Playbook)
Disesuaikan secara komprehensif berdasarkan Postman Collection:
Single Billing V3 - Multi Satker.postman_collection.json.PRINSIP QA: Live Gateway Simponi (Tanpa Mock). Seluruh eksekusi QA wajib melakukan koneksi langsung ke sandbox Simponi Kemenkeu untuk memastikan sistem eksternal Simponi merespons sukses.
- Cakupan / Surface Pengujian:
API / Postman Only(Direct Single Billing API & Live Gateway Simponi Sandbox) - Kebutuhan Akses / Role Akun: Token Bearer valid (
), Postman Environment Dev/Staging dengan konfigurasi direct live hit ke endpoint Simponi Kemenkeu (MOCK_MODE=off). - Hasil Pengujian UAT:
PASSED - Catatan QA: Seluruh 10 skenario pengujian QA multi-satker dan isolasi Simponi V3 via Live Gateway Simponi Sandbox berhasil lolos validasi UAT.
Skenario Pengujian QA (Test Scenarios)
Skenario 1 — Happy Path: Agregasi Multi-Satker Ekstrem (7 Satker Hubla Lintas Wilayah):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub 1 - Pre-kondisi: Environment DEV/Staging terhubung langsung ke Live Gateway Simponi Sandbox (Mock dinonaktifkan), Token Bearer valid.
- Trigger / Request:
POST/api/pengangkut/tagihanmembawa bundle 7 tagihan dari 7 Satker Hubla (KSOP dan Distrik Navigasi) yang berbeda secara simultan:- Satker
413293: Distrik Navigasi (Disnav) Palembang - Satker
413262: KSOP Pangkal Balam - Satker
287171: KSOP Kelas I Banjarmasin - Satker
412823: KSOP Kelas I Tanjung Emas (Semarang) - Satker
287370: KSOP Kelas III Teluk Palu - Satker
287473: Distrik Navigasi (Disnav) Ujung Pandang (Makassar) - Satker
412801: Distrik Navigasi (Disnav) Tanjung Priok
- Satker
- Ekspektasi Response: HTTP
200 OKlangsung dari Gateway Simponi, response body memuatcode: "00"dan mengembalikan kode billing konsolidasi (820xxxxxxx) tanpa terjadi error penolakan relasi antar-satker. - Verifikasi Database / Log: Seluruh 7 data tagihan tersimpan dengan asosiasi kode satker riil masing-masing dan status disposisi billing aktif.
- Postman Request:
Skenario 2 — Happy Path: Baseline Single Satker (1 Satker Tunggal):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub 2&Uji Multisatker - Tagihan Kemenhub 4 - Pre-kondisi: Live Gateway Simponi Sandbox aktif, Token Bearer valid.
- Trigger / Request:
POST/api/pengangkut/tagihanmembawa tagihan yang seluruhnya berasal dari 1 Satker yang sama (misal Satker287260[Distrik Navigasi Samarinda / Balikpapan] atau287211[KSOP Samarinda]). - Ekspektasi Response: HTTP
200 OK,code: "00", membuktikan backward compatibility terhadap alur penerbitan billing single-satker reguler di Gateway Simponi.
- Postman Request:
Skenario 3 — Happy Path: Agregasi Multi-Satker Moderat (Kombinasi 2 Satker Berbeda):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub 3 - Pre-kondisi: Live Gateway Simponi Sandbox aktif, Token Bearer valid.
- Trigger / Request:
POST/api/pengangkut/tagihanmenggabungkan tagihan dari 2 Satker berbeda: Satker287260(Disnav Samarinda) dan Satker287211(KSOP Samarinda). - Ekspektasi Response: HTTP
200 OK,code: "00", kode billing diterbitkan secara sukses untuk kedua entitas satker dari Gateway Simponi.
- Postman Request:
Skenario 4 — Happy Path: Agregasi Multi-Satker Kompleks (9 Tagihan Lintas 7 Satker Hubla):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub 5 - Pre-kondisi: Live Gateway Simponi Sandbox aktif, Token Bearer valid.
- Trigger / Request:
POST/api/pengangkut/tagihanmembawa 9 tagihan yang mencakup variasi Satker Hubla:- Satker
413591: KSOP Kuala Tungkal - Satker
412879: Distrik Navigasi Semarang - Satker
412823: KSOP Kelas I Tanjung Emas (Semarang) - Satker
413293: Distrik Navigasi Palembang - Satker
413256: KSOP Palembang - Satker
287260: Distrik Navigasi Samarinda - Satker
287228: KSOP Balikpapan
- Satker
- Ekspektasi Response: HTTP
200 OK,code: "00", gateway Simponi berhasil menerima dan memproses seluruh array detail 19 elemen dari 9 tagihan tersebut.
- Postman Request:
Skenario 5 — Negative Test: Penolakan Nilai Nominal Negatif (Minus):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub (Minus) - Pre-kondisi: Payload sengaja dikonfigurasi dengan nominal minus pada total header (
-63828) dan baris detail (-0.6,-51062). - Trigger / Request:
POST/api/pengangkut/tagihan - Ekspektasi Response: HTTP
400 Bad Request, validasi Joi memblokir request dan mengembalikan pesan error validasi sebelum request diteruskan ke gateway Simponi.
- Postman Request:
Skenario 6 — Negative Test: Penolakan Kode Satker Alphanumeric pada Header:
- Postman Request:
Uji Multisatker - Tagihan Kemenhub (Satker Alhpanumeric - Header) - Pre-kondisi: Elemen satker pada header berisi karakter alphanumeric (
4132X3). - Trigger / Request:
POST/api/pengangkut/tagihan - Ekspektasi Response: HTTP
400 Bad Request, sistem menolak format kode satker yang tidak strictly numeric.
- Postman Request:
Skenario 7 — Negative Test: Penolakan Karakter Alphanumeric pada Detail:
- Postman Request:
Uji Multisatker - Tagihan Kemenhub (Satker Alhpanumeric - Header Detail) - Pre-kondisi: Kode akun penerimaan pada baris detail memuat karakter non-angka (
42X517,425X17). - Trigger / Request:
POST/api/pengangkut/tagihan - Ekspektasi Response: HTTP
400 Bad Request, skema validasischemasSimponiV3menggagalkan proses dengan rincian field akun invalid.
- Postman Request:
Skenario 8 — Negative Test: Integritas Nilai Mismatch (Header vs Detail):
- Postman Request:
Uji Multisatker - Tagihan Kemenhub (Nominal Tidak Sesuai Detail) - Pre-kondisi: Header mencatat total nilai
63827, sedangkan hasil penjumlahan matematis detail adalah63828(51062 + 12766). - Trigger / Request:
POST/api/pengangkut/tagihan - Ekspektasi Response: HTTP
400 Bad Request, sistem mendeteksi diskrepansi akumulasi dan menolak transaksi demi mencegah ketidaksesuaian pembukuan PNBP Simponi.
- Postman Request:
Skenario 9 — Integration / Error Handling: Penanganan Penolakan Riil Gateway Simponi:
- Pre-kondisi: Live Gateway Simponi Sandbox aktif, dikirimkan request dengan relasi satker/akun yang tidak terdaftar di Simponi Kemenkeu.
- Trigger / Request:
POST/api/v3/terima-rekap-tagihan - Ekspektasi Response: Gateway Simponi merespons dengan kode penolakan resmi (seperti kode
IX[Satker Layanan & Riil tidak terkait],IR[Kode Satker Riil tidak valid],IM[Satker Riil & Akun tidak terkait],IS[Kode Satker Layanan tidak valid]) dan service Single Billing meneruskan respons error terstruktur ke caller tanpa crash.
Skenario 10 — Integration: Pelunasan Pembayaran Billing DJA (
activeinquiry_v2):- Postman Request:
Uji Multisatker - Kirim Payment - Pre-kondisi: Kode billing aktif telah terbentuk di sistem Single Billing dan terdaftar di Simponi.
- Trigger / Request:
POSThttps://dev-backend.insw.go.id/single-billing/dja/activeinquiry_v2membawa payload pelunasan DJA (termasuk nomor billing820260729744850dan NTPN). - Ekspektasi Response: HTTP
200 OK, status pembayaran billing berhasil diperbarui menjadi lunas (fl_paid = true).
- Postman Request:
Bukti Response Verifikasi Staging (Diisi saat UAT)
{
"status": "PASSED",
"note": "Pengujian verifikasi UAT dan validasi integrasi berhasil lolos, rilis production v1.9.2 telah live."
}