Vintech Payment
Secure Checkout
API v1

Dokumentasi Vintech Payment

Terima pembayaran untuk bisnis apa pun dalam 3 langkah: buat order → arahkan pelanggan ke payment_url → terima webhook saat lunas.

1. Autentikasi

Setiap bisnis punya Secret Key (vp_sk_…) di panel admin → Bisnis & API. Kirim di header, hanya dari server Anda — jangan pernah di JavaScript browser.

Authorization: Bearer vp_sk_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

2. Buat order

POST https://payments.vintech.cloud/api/v1/orders/

curl -X POST https://payments.vintech.cloud/api/v1/orders/ \
  -H "Authorization: Bearer vp_sk_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "external_ref": "ORDER-1042",
    "amount": 150000,
    "description": "Cetak spanduk 3x1m",
    "customer": { "name": "Budi", "email": "budi@email.com", "phone": "0812xxxx" },
    "return_url": "https://tokoanda.com/terima-kasih",
    "expires_in_minutes": 1440,
    "metadata": { "cabang": "Bandung" }
  }'
FieldWajibKeterangan
amountYaTotal dalam Rupiah (bilangan bulat, 1.000 – 100.000.000)
descriptionYaJudul tagihan yang dilihat pelanggan
external_refDisarankanNomor order di sistem Anda. Mengirim ulang ref yang sama mengembalikan order yang sama (idempotent)
customerTidakname, email, phone
itemsTidakArray {name, price, quantity}. Totalnya harus sama dengan amount
return_urlTidakPelanggan diarahkan ke sini setelah bayar (default: pengaturan bisnis)
expires_in_minutesTidak5 – 10080 (default 1440 = 24 jam)
metadataTidakObjek bebas, dikembalikan apa adanya di webhook

Respons 201:

{
  "id": "PAY-A1B2C3D4E5",
  "status": "pending",
  "amount": 150000,
  "payment_url": "https://payments.vintech.cloud/pay/PAY-A1B2C3D4E5/",
  "expires_at": "2026-10-19T10:00:00+07:00",
  "external_ref": "ORDER-1042", ...
}

Arahkan pelanggan ke payment_url — selesai. Halaman bayar, QRIS/VA/E-Wallet, dan verifikasi ditangani Vintech Payment.

3. Webhook payment.paid

Saat lunas, kami mengirim POST ke Webhook URL bisnis Anda (diatur di panel admin). Balas dengan HTTP 2xx. Jika gagal, kami mengulang otomatis (1m, 5m, 30m, 2j, 12j).

POST https://tokoanda.com/webhook/vintech
X-VintechPay-Event: payment.paid
X-VintechPay-Signature: t=1760000000,v1=9f2c...e1

{
  "event": "payment.paid",
  "id": "PAY-A1B2C3D4E5",
  "external_ref": "ORDER-1042",
  "status": "paid",
  "amount": 150000,
  "currency": "IDR",
  "paid_at": "2026-10-18T10:15:00+07:00",
  "customer": { "name": "Budi", "email": "...", "phone": "..." },
  "payment": { "type": "bank_transfer", "channel": "bca" },
  "metadata": { "cabang": "Bandung" }
}

Verifikasi tanda tangan (wajib): HMAC-SHA256(secret_key, "<t>.<body mentah>") harus sama dengan v1. Tolak jika selisih t > 5 menit.

# Python
import hmac, hashlib, time
def valid(secret, header, raw_body):
    parts = dict(p.split("=", 1) for p in header.split(","))
    expected = hmac.new(secret.encode(), f"{parts['t']}.{raw_body}".encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) < 300
// PHP
[$t, $v1] = array_map(fn($p) => explode('=', $p, 2)[1], explode(',', $_SERVER['HTTP_X_VINTECHPAY_SIGNATURE']));
$raw = file_get_contents('php://input');
$ok = hash_equals(hash_hmac('sha256', "$t.$raw", $secret), $v1) && abs(time() - (int)$t) < 300;

4. Cek status & batalkan

GET  https://payments.vintech.cloud/api/v1/orders/PAY-A1B2C3D4E5/          # status terkini
POST https://payments.vintech.cloud/api/v1/orders/PAY-A1B2C3D4E5/cancel/   # hanya jika masih pending

Status: pending, paid, expired, cancelled.

Penting: parameter di return_url hanya informasi tampilan. Tandai pesanan lunas hanya berdasarkan webhook yang tervalidasi atau hasil GET order dari server Anda.

Kode error

Semua error berformat {"error": {"code": "...", "message": "..."}} dengan status 400 (permintaan tidak valid), 401 (API key salah), 404 (tidak ditemukan), 409 (konflik status).