Quickstart

Integrasi end-to-end di sandbox: buat order, kunci kurs, tampilkan QR, terima pembayaran, dan verifikasi webhook. Semua contoh memakai API key merchant Anda.

Sebelum mulai

  • Akun merchant aktif di dashboard.hashpay.id.
  • API key dari Settings → API Key (dapat dirotasi kapan saja).
  • Base URL sandbox: https://api.hashpay.id/api/v2/testnet/
  • Token uji gratis dari faucet testnet.
Simpan sebagai environment variable
export HASHPAY_BASE="https://api.hashpay.id/api/v2/testnet"
export HASHPAY_API_KEY="hp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export MERCHANT_ID="10001"

1. Buat order

POST/merchant/fiat/order

order_no adalah nomor unik dari sistem Anda. amount dalam satuan fiat terkecil-nya (IDR tanpa desimal).

bash
curl -X POST "$HASHPAY_BASE/merchant/fiat/order" \
  -H "api-key: $HASHPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_id": "'"$MERCHANT_ID"'",
    "order_no": "INV-2026-0001",
    "amount": "150000",
    "name": "Budi Santoso",
    "email": "budi@example.com"
  }'
Respons
{
  "status_code": 201,
  "message": "success",
  "data": {
    "request": {
      "order_no": "INV-2026-0001",
      "merchant_id": "10001",
      "amount": "150000",
      "currency": "IDR",
      "status": "Created"
    },
    "url": "https://pay.hashpay.io?key=...",
    "key": "...",
    "expired_at": 1821387856
  }
}

2. Kunci kurs & hitung fee

POST/merchant/fiat/checkOrderRate

Tentukan token dan jaringan, lalu kami mengunci kurs dan menghitung fee. Nominal crypto yang harus dibayar pelanggan sudah final di langkah ini — QR nanti tidak akan berubah.

bash
curl -X POST "$HASHPAY_BASE/merchant/fiat/checkOrderRate" \
  -H "api-key: $HASHPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_id": "'"$MERCHANT_ID"'",
    "transactionID": "INV-2026-0001",
    "tokenAddress": "0xaD322e530C15330442841b4C400D730103B0af87",
    "network": "ETHEREUM"
  }'
Respons (ringkas)
{
  "data": {
    "amount_crypto": "5.616189",
    "crypto_rate": "17805.23",
    "fees": [
      { "name": "Platform Fee", "fee_amount_crypto": "0.112324", "is_included": true }
    ],
    "total_fee_amount_crypto": "0.112324",
    "total_amount_crypto": "5.616189"
  }
}

3. Buat QR & alamat deposit

POST/pgqr/fiat/create

Respons berisi qrValue (EIP-681 / deep link wallet) dan destinationAddress — alamat deposit unik yang hanya berlaku untuk order ini. Tampilkan QR dan nominal totalAmount ke pelanggan.

bash
curl -X POST "$HASHPAY_BASE/pgqr/fiat/create" \
  -H "api-key: $HASHPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_id": "'"$MERCHANT_ID"'",
    "transactionID": "INV-2026-0001",
    "tokenAddress": "0xaD322e530C15330442841b4C400D730103B0af87",
    "network": "ETHEREUM",
    "walletType": "METAMASK"
  }'
Respons (ringkas)
{
  "data": {
    "request": {
      "amount": "5.616189",
      "feeAmount": "0.112324",
      "feeIsIncluded": true,
      "uniqueCode": "470",
      "uniqueCodeAmount": "0.000470",
      "totalAmount": "5.616659",
      "totalAmountFiat": "100000.00",
      "destinationAddress": "0x2AC2223419f32a6Aab57D9d4cb3210C97Bc62d51",
      "qrValue": "ethereum:0xaD32...@11155111/transfer?address=0x2AC2...&uint256=5616659",
      "expiredAt": 1789854291
    },
    "qrValue": "..."
  }
}

4. Pantau status order

POST/merchant/fiat/getOrder

Polling berguna sebagai fallback, tetapi produksi sebaiknya mengandalkan webhook.

bash
curl -X POST "$HASHPAY_BASE/merchant/fiat/getOrder" \
  -H "api-key: $HASHPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"merchant_id": "'"$MERCHANT_ID"'", "order_no": "INV-2026-0001"}'

5. Terima webhook

Setelah order Success, kami mengirim POST ke notification_url merchant dengan header X-Hashpay-Signature. Verifikasi tanda tangan sebelum memproses:

Node.js — verifikasi tanda tangan
import crypto from "node:crypto";

export function verifyHashpaySignature(rawBody, signatureHeader, apiKey) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", apiKey).update(rawBody).digest("hex");

  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// app.post("/hashpay/webhook", express.raw({ type: "*/*" }), (req, res) => {
//   if (!verifyHashpaySignature(req.body, req.header("X-Hashpay-Signature"), process.env.HASHPAY_API_KEY)) {
//     return res.status(401).send("invalid signature");
//   }
//   const event = JSON.parse(req.body.toString());
//   // idempotent: gunakan X-Hashpay-Idempotency-Key
//   res.status(200).send("ok");
// });

Contoh lengkap (Node.js)

flow.js
const BASE = process.env.HASHPAY_BASE;
const KEY = process.env.HASHPAY_API_KEY;
const MERCHANT = process.env.MERCHANT_ID;

const call = async (path, body) => {
  const res = await fetch(`${BASE}${path}`, {
    method: "POST",
    headers: { "api-key": KEY, "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const json = await res.json();
  if (json.status_code >= 400) throw new Error(json.message);
  return json.data;
};

const orderNo = `INV-${Date.now()}`;
const TOKEN = "0xaD322e530C15330442841b4C400D730103B0af87"; // USDT testnet

await call("/merchant/fiat/order", {
  merchant_id: MERCHANT,
  order_no: orderNo,
  amount: "150000",
});

await call("/merchant/fiat/checkOrderRate", {
  merchant_id: MERCHANT,
  transactionID: orderNo,
  tokenAddress: TOKEN,
  network: "ETHEREUM",
});

const qr = await call("/pgqr/fiat/create", {
  merchant_id: MERCHANT,
  transactionID: orderNo,
  tokenAddress: TOKEN,
  network: "ETHEREUM",
  walletType: "METAMASK",
});

console.log("Kirim tepat:", qr.request.totalAmount, "USDT");
console.log("Ke alamat :", qr.request.destinationAddress);
console.log("QR value  :", qr.request.qrValue);

Selesai — langkah berikutnya