@gasskeuntopup/partner-sdk
v1.0.5
Published
Official TypeScript SDK for Partner API integration
Downloads
469
Readme
@gasskeuntopup/partner-sdk
TypeScript SDK resmi untuk integrasi Partner API. Mendukung Node.js dan browser modern.
Instalasi
npm install @gasskeuntopup/partner-sdk
# atau
yarn add @gasskeuntopup/partner-sdkQuick Start
Semua method di SDK ini bisa melempar error — pastikan selalu gunakan try/catch. Kalau salah satu step gagal (misal inquiry gagal), step berikutnya (confirm, polling) tidak akan jalan.
import { PartnerClient, PartnerApiError, PartnerNetworkError, OrderStatus } from "@gasskeuntopup/partner-sdk";
const client = new PartnerClient({
apiKey: "your-api-key",
secretKey: "your-secret-key",
baseUrl: "your-base-url",
});
try {
// 1. Cek saldo
const { balance } = await client.getBalance();
console.log(`Saldo: Rp${balance.toLocaleString("id-ID")}`);
// 2. Inquiry produk
const inquiry = await client.inquiry({
refId: "ORDER-001", // ID unik dari sistem kamu
productCode: "ML-86-DIAMOND",
userId: "123456789", // wajib untuk game
zoneId: "1234", // wajib untuk ML, dll
});
console.log(`${inquiry.username} — Rp${inquiry.price.toLocaleString("id-ID")}`);
// 3. Konfirmasi transaksi (balance dideduct di sini)
const result = await client.confirm({
refId: "ORDER-001",
inquiryId: inquiry.inquiryId,
});
if (result.status === OrderStatus.COMPLETED) {
console.log("Transaksi selesai!");
} else if (result.status === OrderStatus.PENDING) {
// Produk masih diproses, lakukan polling
const final = await client.pollUntilSettled({
refId: "ORDER-001",
intervalMs: 3000, // cek setiap 3 detik
maxAttempts: 20, // maksimal 20x (60 detik)
onPoll: (attempt, data) => console.log(`Polling #${attempt}`, data),
});
console.log("Final status:", final);
}
} catch (err) {
if (err instanceof PartnerApiError) {
// Error dari API — cek code untuk handle spesifik
console.error(`[${err.code}] ${err.message}`);
} else if (err instanceof PartnerNetworkError) {
// Error jaringan / timeout
console.error(`[NETWORK] ${err.message}`);
} else {
// Error tidak terduga — lempar ulang
throw err;
}
}API Reference
new PartnerClient(config)
| Parameter | Tipe | Wajib | Keterangan |
| ----------- | -------- | ----- | ------------------------------ |
| apiKey | string | ✅ | API key dari dashboard partner |
| secretKey | string | ✅ | Secret key untuk signing |
| baseUrl | string | ✅ | Base URL API |
| timeout | number | ❌ | Timeout ms (default: 30000) |
client.getBalance()
Mengambil saldo partner saat ini.
const { balance, currency } = await client.getBalance();
// → { balance: 500000, currency: "IDR" }client.inquiry(req)
Melakukan inquiry produk. Wajib dipanggil sebelum confirm().
const data = await client.inquiry({
refId: string, // ID unik (max 100 char)
productCode: string, // Kode SKU produk
userId?: string, // User ID pemain (game)
zoneId?: string, // Zone ID pemain (game)
});
// → { inquiryId, denomName, productCode, price, username?, userId?, zoneId? }client.confirm(req)
Mengkonfirmasi transaksi. Balance akan dideduct di sini.
const data = await client.confirm({
refId: string, // Sama dengan yang dipakai di inquiry
inquiryId: string, // Dari response inquiry
});
// → { orderId, refId, denomName, productCode, price, status, voucher?, sn? }client.getStatus(req)
Mengecek status transaksi berdasarkan refId.
const data = await client.getStatus({ refId: "ORDER-001" });
// → { refId, orderId, status, denomName, price, ... }client.pollUntilSettled(options)
Polling otomatis sampai transaksi selesai (COMPLETED/FAILED). Hanya perlu dipanggil kalau status dari confirm() masih PENDING.
const final = await client.pollUntilSettled({
refId: "ORDER-001",
intervalMs: 3000, // default: 3000ms
maxAttempts: 20, // default: 20
onPoll?: (attempt, data) => void,
});Error Handling
Semua method melempar error jika gagal. Ada dua jenis error yang perlu di-handle:
import { PartnerApiError, PartnerNetworkError, PartnerErrorCode } from "@gasskeuntopup/partner-sdk";
try {
const inquiry = await client.inquiry({ refId: "X", productCode: "Y" });
} catch (err) {
if (err instanceof PartnerApiError) {
// Error dari API (response success: false)
console.log(err.code); // e.g. "PRODUCT_NOT_FOUND"
console.log(err.message); // pesan error dari server
console.log(err.httpStatus); // HTTP status code
// Shorthand checks
if (err.isInsufficientBalance) {
/* top up saldo */
}
if (err.isInvalidPlayer) {
/* userId/zoneId salah */
}
if (err.isDuplicateRefId) {
/* refId sudah dipakai */
}
if (err.isProductNotFound) {
/* produk tidak tersedia */
}
// Atau gunakan .is()
if (err.is(PartnerErrorCode.ProviderError)) {
/* error dari provider */
}
} else if (err instanceof PartnerNetworkError) {
// Error jaringan / timeout
console.log(err.message);
console.log(err.cause);
} else {
// Error tidak terduga — lempar ulang agar tidak ditelan diam-diam
throw err;
}
}Kode Error
| Code | Keterangan |
| ---------------------- | ------------------------------------------ |
| INVALID_PLAYER | userId atau zoneId salah/tidak valid |
| PRODUCT_NOT_FOUND | Produk tidak ditemukan atau tidak tersedia |
| INSUFFICIENT_BALANCE | Saldo tidak mencukupi |
| PROVIDER_ERROR | Error dari provider upstream |
| DUPLICATE_REF_ID | refId sudah pernah dipakai |
| INQUIRY_NOT_FOUND | Inquiry tidak ditemukan |
| INQUIRY_FAILED | Inquiry gagal, tidak bisa dikonfirmasi |
| INQUIRY_NOT_SUCCESS | Inquiry belum selesai |
Flow Transaksi
getBalance() → cek saldo cukup?
↓
inquiry() → validasi produk & pemain, dapat inquiryId
↓
confirm() → potong saldo, kirim ke provider
↓
status PENDING? → pollUntilSettled() / getStatus() manual
↓
COMPLETED / FAILED