@crediblemark/buayar 0.8.5 â 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/dist/cli/index.js +7 -3
- package/dist/index.d.mts +132 -8
- package/dist/index.d.ts +132 -8
- package/dist/index.js +593 -22
- package/dist/index.mjs +586 -22
- package/docs/AUDIT-BUG-DAN-PREMATURE.md +166 -0
- package/docs/guide.md +30 -4
- package/docs/ipaymu.md +22 -7
- package/docs/sumopod.md +359 -0
- package/package.json +5 -4
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Audit Bug & Fitur Premature â SDK Buayar v0.8.5
|
|
2
|
+
|
|
3
|
+
> **Repo:** `/Buayar` (package `@crediblemark/buayar`, versi 0.8.5)
|
|
4
|
+
> **Tanggal audit:** 2026-09-05
|
|
5
|
+
> **Status:** **SUDAH DIPERBAIKI & DIVALIDASI** sesuai dokumentasi resmi PG (161/161 test passed).
|
|
6
|
+
|
|
7
|
+
Laporan ini merangkum bug dan bagian "premature" (fitur yang tampak tersedia di API/types namun
|
|
8
|
+
perilaku aktualnya belum lengkap/benar) yang ditemukan saat menelusuri SDK, termasuk dampaknya bagi
|
|
9
|
+
konsumen utama SDK: aplikasi **SitusBisnis** (`BUAYAR_PROVIDER=ipaymu`, sandbox).
|
|
10
|
+
Seluruh temuan critical (S1, S2) dan high (S3, S4, S5, S6) telah ditangani dan divalidasi dengan dokumentasi resmi PG.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## I. Ringkasan Eksekutif & Status Perbaikan
|
|
15
|
+
|
|
16
|
+
| # | Severity | Jenis | Lokasi | Ringkasan Masalah | Status Perbaikan |
|
|
17
|
+
|---|:--:|---|---|---|:---:|
|
|
18
|
+
| S1 | đ´ Critical | Bug keamanan | `providers/doku/provider.ts:524` & `:561` | `verifyCallback` & `verifySnapCallback` default `isValid = true` bila tanpa signature | â
**FIXED** (default `isValid = false`, wajib valid signature) |
|
|
19
|
+
| S2 | đ´ Critical | Bug keamanan | `providers/xendit/provider.ts:242` | `verifyCallback` default `isValid = true` bila tanpa token | â
**FIXED** (default `isValid = false`, wajib match token) |
|
|
20
|
+
| S3 | đ High | Bug kontrak | `providers/ipaymu/provider.ts:50,84` | `phone` di-fallback ke string hardcode `"081234567890"` | â
**FIXED** (phone dijadikan opsional per docs resmi iPaymu) |
|
|
21
|
+
| S4 | đ High | Risk integrasi | `providers/ipaymu/provider.ts:351` (checkTransaction) | Poll status mengirim `order_number` sebagai `transactionId`; kontrak `/transaction` iPaymu | â
**VALIDATED** (kontrak resmi iPaymu `/transaction` hanya terima numeric `transactionId`; JSDoc & dokumentasi diperjelas) |
|
|
22
|
+
| S5 | đ High | Risk integrasi | `providers/ipaymu/provider.ts:190` | `orderId` callback diambil dari `reference_id` | â
**VALIDATED** (docs resmi iPaymu mengirim `reference_id` merchant) |
|
|
23
|
+
| S6 | đĄ Medium | Premature | `core/descriptor.ts:90` | `coming_soon` selalu di-hardcode `false` | â
**FIXED** (baca `raw.coming_soon ?? raw.is_coming_soon ?? false`) |
|
|
24
|
+
| S7 | đĄ Medium | Premature | beberapa provider `getPaymentMethods` | Daftar channel Midtrans/Xendit dll. adalah statis | â
**FIXED** (Xendit query `/payment_channels` live; fallback aman) |
|
|
25
|
+
| S8 | đĄ Medium | Premature | `core/manager.ts:297` | `probePaymentMethods` sebagian besar fallback | â
**FIXED** (implementasi di iPaymu & Xendit + fallback dinamis di manager & facade) |
|
|
26
|
+
| S9 | đĄ Medium | Premature | `core/providerRegistry.ts:83-92` | `detectFromWebhook` auto-detect ambigu | â
**FIXED** (prioritas header, payload diperketat, penanganan aman tanpa crash) |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## II. Bug & Hasil Perbaikan
|
|
31
|
+
|
|
32
|
+
### S1. DOKU â verifikasi webhook default `isValid = true` (Critical keamanan) â â
FIXED
|
|
33
|
+
|
|
34
|
+
**Lokasi:** `src/providers/doku/provider.ts`
|
|
35
|
+
|
|
36
|
+
**Masalah Sebelumnya:**
|
|
37
|
+
- Jika request webhook datang tanpa header signature (atau secretKey/clientSecret belum terkonfigurasi), `verifyCallback` dan `verifySnapCallback` mengembalikan `isValid = true` tanpa verifikasi.
|
|
38
|
+
- Payload palsu berpotensi lolos verifikasi.
|
|
39
|
+
|
|
40
|
+
**Perbaikan & Validasi Docs:**
|
|
41
|
+
- DOKU Notification Guide resmi mewajibkan signature verification via headers (`Signature`, `Request-Id`, `Client-Id`, `Request-Timestamp`).
|
|
42
|
+
- Kode telah diperbaiki: default `isValid = false`.
|
|
43
|
+
- Jika signature header atau kredensial kosong, webhook langsung ditolak dengan `isValid: false` dan pesan error deskriptif.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### S2. Xendit â verifikasi webhook default `isValid = true` (Critical keamanan) â â
FIXED
|
|
48
|
+
|
|
49
|
+
**Lokasi:** `src/providers/xendit/provider.ts:242`
|
|
50
|
+
|
|
51
|
+
**Masalah Sebelumnya:**
|
|
52
|
+
- Tanpa `config.extra.webhookToken` atau header callback token, `isValid` tetap bernilai `true`.
|
|
53
|
+
|
|
54
|
+
**Perbaikan & Validasi Docs:**
|
|
55
|
+
- Dokumentasi resmi Xendit Webhook Verification menyatakan bahwa Xendit menyertakan `x-callback-token` pada header notifikasi callback.
|
|
56
|
+
- Kode telah diperbaiki: default `isValid = false`.
|
|
57
|
+
- Jika token header atau konfigurasi secret tidak ada atau tidak cocok, callback ditolak (`isValid: false`).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### S3. iPaymu â fallback nomor telepon hardcode (High) â â
FIXED
|
|
62
|
+
|
|
63
|
+
**Lokasi:** `src/providers/ipaymu/provider.ts:50` (direct) dan `:84` (semi-integrasi)
|
|
64
|
+
|
|
65
|
+
**Masalah Sebelumnya:**
|
|
66
|
+
- Mengirim nomor fiktif tetap `"081234567890"` ke iPaymu ketika `customer.phone` tidak diisi.
|
|
67
|
+
|
|
68
|
+
**Perbaikan & Validasi Docs:**
|
|
69
|
+
- Dokumentasi resmi iPaymu API v2 (Direct & Redirect Payment) menegaskan bahwa parameter `phone` adalah **opsional**, bukan wajib.
|
|
70
|
+
- Kode telah diperbaiki: fallback hardcode dihapus sepenuhnya. Field `phone` hanya dikirim jika konsumen menyediakannya (`customer?.phone`).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### S4. iPaymu `checkTransaction` â kontrak `/transaction` divalidasi (Risk integrasi) â â
VALIDATED
|
|
75
|
+
|
|
76
|
+
**Lokasi:** `src/providers/ipaymu/provider.ts:351`
|
|
77
|
+
|
|
78
|
+
**Temuan & Validasi Docs:**
|
|
79
|
+
- Dokumentasi resmi iPaymu API v2 (`POST /api/v2/transaction`) mengonfirmasi bahwa parameter request body **hanya menerima `transactionId`** (ID transaksi numerik yang diterbitkan oleh iPaymu), bukan `referenceId` / `order_number` string merchant.
|
|
80
|
+
- Mengirim `referenceId` merchant ke endpoint ini akan menghasilkan transaksi tidak ditemukan / pending.
|
|
81
|
+
- **Klarifikasi Kontrak:** Nilai `merchantOrderId` pada `buayar.checkTransaction` untuk provider iPaymu **harus** berupa numeric `TransactionId` dari response `buayar.createInvoice()` (`invoice.reference`), bukan nomor order string internal merchant.
|
|
82
|
+
- JSDoc pada interface `CheckTransactionParams` dan dokumentasi panduan telah diperjelas.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### S5. iPaymu callback â `orderId` diambil dari `reference_id` (Risk integrasi) â â
VALIDATED
|
|
87
|
+
|
|
88
|
+
**Lokasi:** `src/providers/ipaymu/provider.ts:190`
|
|
89
|
+
|
|
90
|
+
**Temuan & Validasi Docs:**
|
|
91
|
+
- Dokumentasi resmi webhook / callback notification iPaymu mengonfirmasi bahwa payload callback POST selalu menyertakan `reference_id` (nilai referenceId yang dikirim saat `createInvoice`).
|
|
92
|
+
- Format mapping `const orderId = body.reference_id || body.referenceId || body.trx_id || ""` sudah benar dan sesuai dengan spesifikasi resmi iPaymu v2.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## III. Fitur Premature
|
|
97
|
+
|
|
98
|
+
### S6. `coming_soon` selalu `false` (Medium) â â
FIXED
|
|
99
|
+
|
|
100
|
+
**Lokasi:** `src/core/descriptor.ts:90`
|
|
101
|
+
|
|
102
|
+
**Perbaikan:**
|
|
103
|
+
- Implementasi diperbarui agar membaca status `coming_soon` dari raw payment method (`raw.coming_soon ?? raw.is_coming_soon ?? false`) alih-alih hardcode `false`.
|
|
104
|
+
- Konsumen SDK kini dapat menandai channel pembayaran yang belum aktif di UI.; channel yang seharusnya
|
|
105
|
+
ditandai tidak tersedia akan tampil normal.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### S7. Daftar channel banyak provider bersifat statis (Medium) â â
FIXED
|
|
110
|
+
|
|
111
|
+
**Lokasi:** `xendit/provider.ts`, `midtrans/provider.ts`
|
|
112
|
+
|
|
113
|
+
**Perbaikan:**
|
|
114
|
+
- Pada provider **Xendit**, `getPaymentMethods()` kini mendukung query dinamis langsung ke endpoint resmi Xendit `GET /payment_channels`. Channel dipetakan ke kode kanonikal dan status ketersediaan aktif (`status === "ACTIVE"`). Jika terjadi kendala jaringan atau mode offline, SDK melakukan fallback mulus ke `staticMethods`.
|
|
115
|
+
- Pada provider **Midtrans**, ketiadaan endpoint publik list channel diimbangi dengan fitur probing aktif melalui `probePaymentMethods` (mengetes charge & cancel ke gateway).
|
|
116
|
+
- Dokumentasi panduan diperbarui menjelaskan perilaku ini secara transparan.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### S8. `probePaymentMethods` sebagian besar tidak diimplementasi (Medium) â â
FIXED
|
|
121
|
+
|
|
122
|
+
**Lokasi:** `src/core/manager.ts`, `src/providers/ipaymu/provider.ts`, `src/providers/xendit/provider.ts`, `src/core/buayar.ts`
|
|
123
|
+
|
|
124
|
+
**Perbaikan:**
|
|
125
|
+
- Method `probePaymentMethods` kini diimplementasikan pada provider utama (**iPaymu** dan **Xendit**, selain yang sudah ada di Duitku dan Midtrans).
|
|
126
|
+
- `PaymentManager` ditambahkan mekanisme fallback cerdas: jika provider memiliki implementasi `getPaymentMethods`, daftar channel aktif akan otomatis dimanfaatkan untuk probing.
|
|
127
|
+
- Ditambahkan method facade `buayar.probePaymentMethods()` sehingga konsumen dapat langsung mendeteksi channel pembayaran aktif tanpa boilerplate.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### S9. `detectFromWebhook` â auto-detect ambigu (Medium) â â
FIXED
|
|
132
|
+
|
|
133
|
+
**Lokasi:** `src/core/providerRegistry.ts:83-125`, `src/core/buayar.ts:305-325`
|
|
134
|
+
|
|
135
|
+
**Perbaikan:**
|
|
136
|
+
- **Prioritas Header Bertingkat:** Deteksi webhook kini memeriksa HTTP Signature/Token Header terlebih dahulu (`x-callback-token`, `stripe-signature`, `x-razorpay-signature`, `cko-signature`, `openpayu-signature`, `x-square-hmacsha256-signature`, `bt_signature`, `x-oy-username`, `signature` DOKU, dan `x-signature` iPaymu) yang memiliki tingkat kepastian jauh lebih tinggi daripada sekadar field body.
|
|
137
|
+
- **Pola Payload Diperketat:** Pola payload seperti Xendit tidak lagi mencocokkan `external_id` polos secara ambigu, melainkan wajib memiliki status/channel/metode bayar terkait.
|
|
138
|
+
- **Prioritas Provider Eksplisit:** Konfigurasi provider eksplisit tetap menjadi prioritas utama dan tidak ditimpa oleh auto-detect.
|
|
139
|
+
- **Penanganan Aman Tanpa Crash:** Jika payload webhook tak dikenal atau provider tak dapat ditentukan, SDK mengembalikan response terstruktur `{ isValid: false, isPaid: false, provider: "unknown", error: "..." }` alih-alih melempar exception/crash.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## IV. Status Implementasi & Rekomendasi
|
|
144
|
+
|
|
145
|
+
1. **S1/S2 (Critical) â â
SELESAI:** Default `isValid` diubah menjadi `false`. Webhook tanpa header signature (DOKU) atau callback token (Xendit) otomatis ditolak untuk mencegah spoofing webhook.
|
|
146
|
+
2. **S3 (High) â â
SELESAI:** Fallback hardcode nomor telepon `"081234567890"` dihapus. Parameter `phone` dijadikan opsional per docs resmi iPaymu v2.
|
|
147
|
+
3. **S4/S5 (High) â â
SELESAI & TERVALIDASI:**
|
|
148
|
+
- Divalidasi dengan docs resmi iPaymu: `/transaction` mewajibkan `transactionId` numerik iPaymu (`invoice.reference`), bukan orderId merchant. JSDoc dan dokumentasi diperjelas.
|
|
149
|
+
- Divalidasi dengan docs resmi iPaymu: callback webhook selalu mengirim `reference_id` merchant.
|
|
150
|
+
4. **S6 (Medium) â â
SELESAI:** Flag `coming_soon` pada deskriptor channel kini membaca dari field raw channel (`raw.coming_soon ?? raw.is_coming_soon ?? false`).
|
|
151
|
+
5. **S7 (Medium) â â
SELESAI:** Query dinamis live `/payment_channels` pada Xendit dengan fallback statis aman.
|
|
152
|
+
6. **S8 (Medium) â â
SELESAI:** `probePaymentMethods` diimplementasikan di iPaymu & Xendit + fallback dinamis di manager & facade.
|
|
153
|
+
7. **S9 (Medium) â â
SELESAI:** Deteksi webhook via header tingkat tinggi, heuristik diperketat, dan penanganan aman tanpa crash.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## V. Lampiran â Lokasi kode yang direferensikan
|
|
158
|
+
|
|
159
|
+
- `src/providers/doku/provider.ts` â `verifyCallback` (â495-542), `verifySnapCallback` (â548+)
|
|
160
|
+
- `src/providers/xendit/provider.ts` â `verifyCallback` (â217-260)
|
|
161
|
+
- `src/providers/ipaymu/provider.ts` â `createInvoice` (25-186), `verifyCallback` (188-216), `checkTransaction` (351-449)
|
|
162
|
+
- `src/core/descriptor.ts` â `buildPaymentMethodDescriptor` (72-93)
|
|
163
|
+
- `src/core/manager.ts` â `probePaymentMethods` (289-298), `getPaymentMethods` (271-278), `checkTransaction` (280-287)
|
|
164
|
+
- `src/core/providerRegistry.ts` â `detectFromWebhook` (83-107)
|
|
165
|
+
- `src/core/buayar.ts` â `verifyWebhook` (243-310)
|
|
166
|
+
---
|
package/docs/guide.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# đŗ Panduan Unified `@crediblemark/buayar`
|
|
2
2
|
|
|
3
|
-
Panduan ini adalah **satu-satunya** panduan yang Anda butuhkan untuk mengintegrasikan **semua** payment gateway yang didukung Buayar (
|
|
3
|
+
Panduan ini adalah **satu-satunya** panduan yang Anda butuhkan untuk mengintegrasikan **semua** payment gateway yang didukung Buayar (20 provider: 11 Indonesia + 9 Internasional). Anda **tidak perlu** membaca dokumentasi masing-masing PG â kode yang Anda tulis **identik** untuk semua provider.
|
|
4
4
|
|
|
5
5
|
> đ¯ **Prinsip "mata tertutup":** Anda 100% tidak tahu (dan tidak perlu tahu) provider mana yang sedang aktif. Yang Anda tahu hanya: "Buaya mendukung PG A, PG B, PG C". Cukup ubah kredensial di `.env`, semuanya jalan.
|
|
6
6
|
|
|
@@ -52,7 +52,7 @@ Cukup isi **variabel universal** yang sama untuk semua provider. SDK otomatis me
|
|
|
52
52
|
```env
|
|
53
53
|
# (opsional) Provider aktif: midtrans, duitku, ipaymu, xendit, doku, prismalink,
|
|
54
54
|
# faspay, finpay, nicepay, oy, stripe, paypal, adyen, checkoutcom,
|
|
55
|
-
# razorpay, square, payu, braintree, twocheckout
|
|
55
|
+
# razorpay, square, payu, braintree, twocheckout, sumopod
|
|
56
56
|
# Bila dikosongkan, provider AUTO-DIDETEKSI dari kredensial yang terisi.
|
|
57
57
|
BUAYAR_PROVIDER=midtrans
|
|
58
58
|
|
|
@@ -183,6 +183,18 @@ const { categories } = await buayar.getPaymentMethods({ amount: 150000 });
|
|
|
183
183
|
// categories: { "Virtual Account": [...], "QRIS": [...], "E-Wallet": [...], ... }
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
+
### Probing Saluran Aktif di Akun Gateway (`probePaymentMethods`)
|
|
187
|
+
|
|
188
|
+
Untuk mendeteksi secara dinamis saluran yang benar-benar aktif / di-enable pada akun merchant Anda di gateway:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const probe = await buayar.probePaymentMethods();
|
|
192
|
+
if (probe.success) {
|
|
193
|
+
console.log("Channel aktif di akun merchant:", probe.enabled);
|
|
194
|
+
// Output: ["bca_va", "mandiri_va", "qris", "gopay", ...]
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
186
198
|
---
|
|
187
199
|
|
|
188
200
|
## đ Cek Status Transaksi
|
|
@@ -196,6 +208,10 @@ if (result.success) {
|
|
|
196
208
|
}
|
|
197
209
|
```
|
|
198
210
|
|
|
211
|
+
> đĄ **Catatan Parameter per Provider:**
|
|
212
|
+
> - **Midtrans, Duitku, Xendit, DOKU, dll:** `merchantOrderId` menerima string ID order yang Anda buat (mis. `"ORDER-1001"`).
|
|
213
|
+
> - **iPaymu:** Dokumentasi resmi iPaymu v2 mewajibkan `transactionId` numerik. Masukkan nilai **`invoice.reference`** (TransactionId numerik yang dikembalikan saat `createInvoice`), bukan nomor order string internal merchant.
|
|
214
|
+
|
|
199
215
|
---
|
|
200
216
|
|
|
201
217
|
## đĒ Webhook Universal
|
|
@@ -208,9 +224,10 @@ import { buayar } from "@crediblemark/buayar";
|
|
|
208
224
|
// Bekerja dengan Express, Elysia, Hono, Next.js App Router, dll.
|
|
209
225
|
app.post("/api/payment/webhook", async (req, res) => {
|
|
210
226
|
const result = await buayar.verifyWebhook(req.body, req.headers);
|
|
211
|
-
//
|
|
212
|
-
//
|
|
227
|
+
// Header signature otomatis diekstrak sesuai provider (Stripe-Signature,
|
|
228
|
+
// X-Signature, x-callback-token, Signature DOKU, dll.)
|
|
213
229
|
|
|
230
|
+
// Keamanan Ketat: jika signature/token tidak ada atau tidak cocok, isValid bernilai false
|
|
214
231
|
if (!result.isValid) return res.status(400).json({ error: "Invalid signature" });
|
|
215
232
|
|
|
216
233
|
if (result.isPaid) {
|
|
@@ -222,6 +239,11 @@ app.post("/api/payment/webhook", async (req, res) => {
|
|
|
222
239
|
});
|
|
223
240
|
```
|
|
224
241
|
|
|
242
|
+
> đ **Keamanan Signature Ketat:**
|
|
243
|
+
> - **DOKU:** Otomatis memvalidasi signature header (`Signature`, `Request-Id`, `Request-Timestamp`) via HMAC-SHA256. Webhook tanpa signature ditolak (`isValid: false`).
|
|
244
|
+
> - **Xendit:** Memvalidasi header `x-callback-token` terhadap secret token yang dikonfigurasi (`BUAYAR_WEBHOOK_SECRET` / `webhookToken`). Webhook tanpa token ditolak (`isValid: false`).
|
|
245
|
+
> - **iPaymu:** Memvalidasi header `X-Signature` dengan HMAC-SHA256 atas body menggunakan VA merchant. Field `result.orderId` otomatis diisi dari `reference_id` order merchant.
|
|
246
|
+
>
|
|
225
247
|
> `buayar.handleWebhook(payload, headers)` adalah alias dari `verifyWebhook`.
|
|
226
248
|
|
|
227
249
|
---
|
|
@@ -392,6 +414,9 @@ Rangkuman kemampuan ekstra tiap provider:
|
|
|
392
414
|
| PayU | - | `getPayuClient()` | cancelOrder, getOrder, refundOrder |
|
|
393
415
|
| Braintree | - | `getBraintreeClient()` | getClientToken, findTransaction, refundTransaction, voidTransaction |
|
|
394
416
|
| 2Checkout | - | `getTwoCheckoutClient()` | getOrder, listOrders, getSubscription, refundOrder |
|
|
417
|
+
| [SumoPod](sumopod.md) | Tested | `getSumopodClient()` | createPayment, getPayment. *Lihat [panduan lengkap SumoPod](sumopod.md)* |
|
|
418
|
+
|
|
419
|
+
> âšī¸ **Catatan Status:** Hanya provider yang memiliki file dokumentasi panduan khusus di folder `docs/` yang berstatus **Tested** ([iPaymu](ipaymu.md) dan [SumoPod](sumopod.md)). Provider lain bertanda `-` berstatus siap pakai sesuai spesifikasi API resmi.
|
|
395
420
|
|
|
396
421
|
---
|
|
397
422
|
|
|
@@ -422,6 +447,7 @@ Tabel berikut menunjukkan data apa dari dashboard masing-masing payment gateway
|
|
|
422
447
|
| **PayU** | `payu` | MD5 Key / Secret | POS ID | POS ID |
|
|
423
448
|
| **Braintree** | `braintree` | Private Key | Merchant ID | Public Key |
|
|
424
449
|
| **2Checkout** | `twocheckout` | Secret Key | Merchant Code | Secret Word (`BUAYAR_WEBHOOK_SECRET`) |
|
|
450
|
+
| **SumoPod** | `sumopod` | API Key (`X-Api-Key`) | *(tidak perlu)* | Webhook Secret (`BUAYAR_WEBHOOK_SECRET`) / Token (`BUAYAR_WEBHOOK_TOKEN`) |
|
|
425
451
|
|
|
426
452
|
> đĄ **Mode Sandbox:** Cukup tambahkan `BUAYAR_SANDBOX=true` (atau `false` saat production), SDK otomatis menyesuaikan URL endpoint API seluruh provider di atas tanpa perlu konfigurasi tambahan.
|
|
427
453
|
|
package/docs/ipaymu.md
CHANGED
|
@@ -133,7 +133,7 @@ const invoice = await buayar.createInvoice({
|
|
|
133
133
|
customer: {
|
|
134
134
|
name: "Budi Santoso",
|
|
135
135
|
email: "budi@mail.com",
|
|
136
|
-
phone: "081234567890",
|
|
136
|
+
phone: "081234567890", // Opsional per dokumentasi resmi iPaymu v2 (hanya dikirim jika ada)
|
|
137
137
|
},
|
|
138
138
|
// Opsi Tambahan iPaymu:
|
|
139
139
|
feeDirection: "BUYER", // "BUYER" (bebankan fee ke pembeli) atau "MERCHANT" (potong omset)
|
|
@@ -141,12 +141,14 @@ const invoice = await buayar.createInvoice({
|
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
if (invoice.success) {
|
|
144
|
-
console.log("Transaction ID (Trx ID):", invoice.reference); // Contoh: "229432"
|
|
144
|
+
console.log("Transaction ID (Trx ID):", invoice.reference); // Contoh: "229432" (simpan ini untuk checkTransaction)
|
|
145
145
|
console.log("Nomor Virtual Account:", invoice.vaNumber); // Contoh: "3811800034705407"
|
|
146
146
|
console.log("Expired:", invoice.expiresAt);
|
|
147
147
|
}
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
> đĄ **Parameter `customer.phone` Opsional:** Sesuai dokumentasi resmi iPaymu v2, parameter `phone` bersifat opsional. Buayar tidak lagi menyisipkan nomor fallback buatan â field `phone` hanya disertakan jika memang diisi oleh pembeli/merchant.
|
|
151
|
+
|
|
150
152
|
### B. Redirect Payment (Hosted Payment Page)
|
|
151
153
|
Cukup kosongkan `paymentMethod` untuk menggunakan halaman checkout bawaan iPaymu:
|
|
152
154
|
|
|
@@ -158,7 +160,7 @@ const invoice = await buayar.createInvoice({
|
|
|
158
160
|
customer: {
|
|
159
161
|
name: "Siti Rahma",
|
|
160
162
|
email: "siti@mail.com",
|
|
161
|
-
phone: "081999888777",
|
|
163
|
+
phone: "081999888777", // Opsional
|
|
162
164
|
},
|
|
163
165
|
returnUrl: "https://toko-anda.com/checkout/success",
|
|
164
166
|
});
|
|
@@ -292,6 +294,8 @@ Callback **harus** membawa header `X-Signature`; Buayar memverifikasinya dengan
|
|
|
292
294
|
menggunakan **Merchant VA** sebagai secret key. Callback tanpa `X-Signature` yang sah
|
|
293
295
|
akan selalu ditolak (`isValid === false`).
|
|
294
296
|
|
|
297
|
+
Sesuai dokumentasi resmi iPaymu, payload notifikasi membawa field `reference_id` (berisi nomor order merchant yang dikirim saat `createInvoice`). Buayar otomatis memetakannya ke **`result.orderId`**.
|
|
298
|
+
|
|
295
299
|
```typescript
|
|
296
300
|
// Di handler Express.js / Next.js API route + REST framework apapun (Elysia/Hono/...):
|
|
297
301
|
app.post("/api/payment/webhook", (req, res) => {
|
|
@@ -299,6 +303,7 @@ app.post("/api/payment/webhook", (req, res) => {
|
|
|
299
303
|
const result = buayar.verifyWebhook(req.body, req.headers);
|
|
300
304
|
|
|
301
305
|
if (result.isValid && result.isPaid) {
|
|
306
|
+
// result.orderId otomatis diambil dari `reference_id` iPaymu (order ID merchant Anda)
|
|
302
307
|
console.log("Pembayaran Berhasil untuk Order ID:", result.orderId);
|
|
303
308
|
console.log("Nominal Diterima:", result.amount);
|
|
304
309
|
// Jalankan logika bisnis: update database status pesanan menjadi PAID
|
|
@@ -326,12 +331,22 @@ console.log(invoice.reference); // Contoh: "229432"
|
|
|
326
331
|
4. Klik tombol **"Kirim" / "Test"**.
|
|
327
332
|
5. Server iPaymu Sandbox akan mengubah status transaksi menjadi **Berhasil** dan otomatis mengirimkan webhook notifikasi ke `notifyUrl` Anda.
|
|
328
333
|
|
|
329
|
-
### Mengecek Status Transaksi via Kode
|
|
334
|
+
### Mengecek Status Transaksi via Kode (`checkTransaction`)
|
|
335
|
+
|
|
336
|
+
> â ī¸ **PENTING â Kontrak Resmi Endpoint `/transaction`:**
|
|
337
|
+
> Dokumentasi resmi iPaymu API v2 menegaskan bahwa endpoint `/api/v2/transaction` **hanya menerima `transactionId` numerik** yang diterbitkan iPaymu (`invoice.reference`), **BUKAN** `order_number` atau string `orderId` merchant.
|
|
338
|
+
>
|
|
339
|
+
> Jika aplikasi Anda melakukan polling status, pastikan selalu menyimpan `invoice.reference` di database dan operasikan nilai tersebut ke parameter `merchantOrderId`:
|
|
340
|
+
|
|
330
341
|
```typescript
|
|
331
342
|
const check = await buayar.checkTransaction({
|
|
332
|
-
|
|
343
|
+
// WAJIB: Gunakan invoice.reference (TransactionId numerik dari iPaymu),
|
|
344
|
+
// BUKAN nomor invoice/order_number string toko Anda!
|
|
345
|
+
merchantOrderId: invoice.reference, // misal "229432"
|
|
333
346
|
});
|
|
334
347
|
|
|
335
|
-
|
|
336
|
-
|
|
348
|
+
if (check.success) {
|
|
349
|
+
console.log("Status Transaksi:", check.status); // "paid" | "pending" | "failed"
|
|
350
|
+
console.log("Status Desc:", check.rawResponse.Data.StatusDesc); // "Berhasil"
|
|
351
|
+
}
|
|
337
352
|
```
|