Cek Status Transaksi
Endpoint untuk mengecek status transaksi yang telah dilakukan menggunakan ref_id.
Endpoint: POST /v1/status
Lebih baik gunakan Webhook untuk notifikasi otomatis daripada polling endpoint ini. Jika harus polling, jangan lebih sering dari setiap 10 detik.
Parameter Request
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
api_id | string | ✅ | API ID |
timestamp | integer | ✅ | Unix timestamp |
signature | string | ✅ | HMAC-SHA256 — lihat cara membuat signature |
ref_id | string | ✅ | ID referensi transaksi yang ingin dicek |
Contoh Request
- PHP
- JavaScript
- Python
- Java
- C#
- cURL
<?php
header('Content-Type: application/json');
$api_id = 'your_api_id';
$api_key = 'your_api_key';
$secret_key = 'your_secret_key';
$timestamp = time();
// Business params
$businessParams = ['ref_id' => 'TRX12345asdxxx'];
// Urutkan A ke Z (ksort)
ksort($businessParams);
$canonicalBody = json_encode($businessParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$bodyHash = hash('sha256', $canonicalBody);
$stringToSign = implode('|', [$api_id, $api_key, $timestamp, $bodyHash]);
$signature = hash_hmac('sha256', $stringToSign, $secret_key);
$payload = array_merge($businessParams, [
'api_id' => $api_id,
'timestamp' => $timestamp,
'signature' => $signature,
]);
$ch = curl_init('https://api.isikuota.com/v1/status');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = json_decode(curl_exec($ch), true);
// print_r($response);
echo json_encode($response, JSON_PRETTY_PRINT);
const crypto = require('crypto');
const api_id = 'your_api_id';
const api_key = 'your_api_key';
const secret_key = 'your_secret_key';
const timestamp = Math.floor(Date.now() / 1000);
// Business params — urutkan A ke Z
const businessParams = { ref_id: 'TRX12345asdxxx' };
const sorted = Object.fromEntries(
Object.keys(businessParams).sort().map(k => [k, businessParams[k]])
);
const canonicalBody = JSON.stringify(sorted);
const bodyHash = crypto.createHash('sha256').update(canonicalBody).digest('hex');
const stringToSign = `${api_id}|${api_key}|${timestamp}|${bodyHash}`;
const signature = crypto.createHmac('sha256', secret_key).update(stringToSign).digest('hex');
const response = await fetch('https://api.isikuota.com/v1/status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...sorted, api_id, timestamp, signature }),
});
const data = await response.json();
import hmac, hashlib, time, json, requests
api_id = 'your_api_id'
api_key = 'your_api_key'
secret_key = 'your_secret_key'
timestamp = int(time.time())
# Business params — urutkan A ke Z
business_params = {'ref_id': 'TRX12345asdxxx'}
sorted_params = dict(sorted(business_params.items()))
canonical_body = json.dumps(sorted_params, ensure_ascii=False, separators=(',', ':'))
body_hash = hashlib.sha256(canonical_body.encode()).hexdigest()
string_to_sign = f'{api_id}|{api_key}|{timestamp}|{body_hash}'
signature = hmac.new(secret_key.encode(), string_to_sign.encode(), hashlib.sha256).hexdigest()
payload = {**sorted_params, 'api_id': api_id, 'timestamp': timestamp, 'signature': signature}
response = requests.post('https://api.isikuota.com/v1/status', json=payload)
data = response.json()
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.http.*;
import java.net.URI;
public class StatusExample {
static String sha256(String input) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
return sb.toString();
}
static String hmacSha256(String data, String key) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
return sb.toString();
}
public static void main(String[] args) throws Exception {
String apiId = "your_api_id";
String apiKey = "your_api_key";
String secretKey = "your_secret_key";
long timestamp = Instant.now().getEpochSecond();
// Business params — TreeMap otomatis urut A ke Z
TreeMap<String, String> businessParams = new TreeMap<>();
businessParams.put("ref_id", "TRX12345asdxxx");
ObjectMapper mapper = new ObjectMapper();
String canonicalBody = mapper.writeValueAsString(businessParams);
String bodyHash = sha256(canonicalBody);
String stringToSign = apiId + "|" + apiKey + "|" + timestamp + "|" + bodyHash;
String signature = hmacSha256(stringToSign, secretKey);
Map<String, Object> payload = new LinkedHashMap<>(businessParams);
payload.put("api_id", apiId);
payload.put("timestamp", timestamp);
payload.put("signature", signature);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.isikuota.com/v1/status"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class StatusExample
{
static string Sha256(string input)
{
using var sha = SHA256.Create();
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
static string HmacSha256(string data, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
static async Task Main()
{
var apiId = "your_api_id";
var apiKey = "your_api_key";
var secretKey = "your_secret_key";
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// Business params — SortedDictionary otomatis urut A ke Z
var businessParams = new SortedDictionary<string, string>
{
{ "ref_id", "TRX12345asdxxx" },
};
var canonicalBody = JsonSerializer.Serialize(businessParams);
var bodyHash = Sha256(canonicalBody);
var stringToSign = $"{apiId}|{apiKey}|{timestamp}|{bodyHash}";
var signature = HmacSha256(stringToSign, secretKey);
var payload = new Dictionary<string, object>(
businessParams.Select(x => new KeyValuePair<string, object>(x.Key, x.Value)))
{
{ "api_id", apiId },
{ "timestamp", timestamp },
{ "signature", signature },
};
using var client = new HttpClient();
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.isikuota.com/v1/status", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
API_ID="your_api_id"
API_KEY="your_api_key"
SECRET="your_secret_key"
TIMESTAMP=$(date +%s)
# Business params — key wajib urut A ke Z
CANONICAL_BODY='{"ref_id":"TRX12345asdxxx"}'
BODY_HASH=$(echo -n "$CANONICAL_BODY" | sha256sum | awk '{print $1}')
STRING_TO_SIGN="${API_ID}|${API_KEY}|${TIMESTAMP}|${BODY_HASH}"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -X POST https://api.isikuota.com/v1/status \
-H "Content-Type: application/json" \
-d "{
\"api_id\": \"$API_ID\",
\"timestamp\": $TIMESTAMP,
\"signature\": \"$SIGNATURE\",
\"ref_id\": \"TRX12345asdxxx\"
}"
Contoh Response
code selalu ORDER_SUCCESS selama transaksi ditemukanEndpoint ini mengembalikan code: ORDER_SUCCESS untuk setiap transaksi yang ditemukan, apapun status transaksinya. Baca data.status untuk mengetahui hasil transaksi sebenarnya (success / pending / failed). code: ORDER_NOT_FOUND (success: false) hanya muncul jika ref_id tidak ditemukan.
- ✅ Success
- ⏳ Pending
- ⚠️ Failed
- Pascabayar
- ❌ Tidak Ditemukan
{
"success": true,
"code": "ORDER_SUCCESS",
"message": "Status transaksi berhasil didapatkan",
"data": {
"ref_id": "ORDER-2025-001",
"code": "TSEL10",
"name": "Telkomsel 10.000",
"customer_no": "081234567890",
"price": 10955,
"status": "success",
"created_at": "2024-01-15 14:30:00",
"sn": "1234-5678-9012-3456"
},
"errors": null,
"meta": null
}
{
"success": true,
"code": "ORDER_SUCCESS",
"message": "Status transaksi berhasil didapatkan",
"data": {
"ref_id": "ORDER-2025-001",
"code": "TSEL10",
"name": "Telkomsel 10.000",
"customer_no": "081234567890",
"price": 10955,
"status": "pending",
"created_at": "2024-01-15 14:30:00",
"sn": null
},
"errors": null,
"meta": null
}
{
"success": true,
"code": "ORDER_SUCCESS",
"message": "Status transaksi berhasil didapatkan",
"data": {
"ref_id": "ORDER-2025-001",
"code": "TSEL10",
"name": "Telkomsel 10.000",
"customer_no": "081234567890",
"price": 10955,
"status": "failed",
"created_at": "2024-01-15 14:30:00",
"sn": null
},
"errors": null,
"meta": null
}
Saldo untuk transaksi berstatus failed sudah dikembalikan otomatis oleh sistem.
{
"success": true,
"code": "ORDER_SUCCESS",
"message": "Status transaksi berhasil didapatkan",
"data": {
"ref_id": "INQ-001",
"code": "MPBPJS",
"name": "Bpjs Kesehatan",
"customer_no": "1234567890",
"price": 25200,
"status": "success",
"created_at": "2024-01-15 14:30:00",
"sn": "S1234554321N",
"customer_name": "Demo Member",
"admin": 2700
},
"errors": null,
"meta": null
}
Field customer_name dan admin hanya muncul untuk transaksi pascabayar (hasil dari Bayar Tagihan) — tidak ada pada transaksi prabayar/game.
{
"success": false,
"code": "ORDER_NOT_FOUND",
"message": "Order tidak ditemukan",
"data": null,
"errors": null,
"meta": null
}
Field Response
| Field | Tipe | Keterangan |
|---|---|---|
ref_id | string | ID referensi transaksi |
code | string | Kode produk |
name | string | Nama produk |
customer_no | string | Nomor tujuan transaksi |
sn | string/null | Serial Number / kode voucher (hanya tersedia jika status: success) |
price | integer | Harga yang dibayarkan (Rp) |
status | string | Status transaksi |
created_at | string | Waktu transaksi dibuat |
customer_name | string | Hanya muncul untuk transaksi pascabayar — nama pelanggan sesuai tagihan |
admin | integer | Hanya muncul untuk transaksi pascabayar — biaya admin (Rp) |
Status Transaksi
| Status | Keterangan | Tindakan |
|---|---|---|
pending | Sedang diproses | Tunggu callback atau cek ulang dalam beberapa saat |
success | Berhasil — sn tersedia | Update status di sistem Anda |
failed | Gagal — saldo dikembalikan | Notifikasi user, tawarkan coba lagi |
Jika sebuah request timeout, cek status dulu via endpoint ini menggunakan ref_id sebelum membuat transaksi baru. Transaksi mungkin sudah berhasil meski response tidak diterima.
Cek Status via Request Ulang (Topup Ulang)
Selain lewat endpoint /v1/status, status transaksi prabayar/game juga bisa dicek dengan mengirim ulang request POST /v1/transaction menggunakan ref_id yang sama dengan transaksi sebelumnya.
Sistem akan mengenali ref_id tersebut dan mengembalikan detail transaksi yang sudah tercatat. Saldo tidak dipotong lagi dan transaksi tidak dikirim ulang ke provider, jadi aman dilakukan berkali-kali.
Syaratnya, parameter berikut harus sama persis dengan request awal:
ref_idcustomer_noproduct_code
Jika ref_id sudah dipakai oleh request yang berbeda (misalnya customer_no atau product_code berbeda), sistem menolak dengan HTTP 409 (Reference ID sudah digunakan).
Untuk transaksi pascabayar (cmd: pay), request ulang dengan ref_id yang sama tidak mengembalikan status. Sesi inquiry hanya berlaku sekali pakai dan dihapus setelah pembayaran diproses, sehingga request ulang akan ditolak dengan pesan sesi inquiry telah kedaluwarsa. Gunakan endpoint /v1/status untuk mengecek status transaksi pascabayar.
Request ulang diproses seperti request biasa, jadi validasi umum tetap berjalan lebih dulu: cut-off, maintenance, produk, PIN, dan saldo. Jika saldo Anda sudah tidak mencukupi untuk harga produk tersebut, Anda akan menerima error saldo tidak cukup meski transaksi sebelumnya sudah ada. Untuk pengecekan yang paling andal, tetap gunakan endpoint /v1/status.