Malawali Payment Malawali Payment
Bantuan
Documentation
Malawali Payment · REST API v1

Integrasi Pembayaran QRIS

Buat order dari server Anda, tampilkan QR ke pelanggan, lalu terima callback order.paid setelah pembayaran terdeteksi otomatis. API Key dibuat per Project dan hanya aktif selama langganan berjalan.

Base URL http://localhost:3001/api
Autentikasi Header x-api-key: pk_live_…
Format JSON (request & response)
Webhook HMAC-SHA256, retry maksimal 3×, timeout 10 detik

Webhook

Malawali Payment mengirim event ke URL webhook project saat status order berubah. Setiap request ditandatangani dengan HMAC-SHA256 agar dapat diverifikasi.

Signature

x-malawali-timestampTimestamp pengiriman (detik/detik-ISO).
x-malawali-signaturev1=<hex> hasil HMAC_SHA256(secret, timestamp + "." + raw_body).
Prioritas URLorder.webhook_url → Webhook Project → notify_url akun.
RetryMaksimal 3× dengan timeout 10 detik per percobaan.
# Verifikasi signature webhook (Node.js)
const crypto = require("crypto");

const ts = req.headers["x-malawali-timestamp"];
const raw = JSON.stringify(req.body);
const expected = crypto
  .createHmac("sha256", process.env.MALAWALI_WEBHOOK_SECRET)
  .update(ts + "." + raw)
  .digest("hex");

const ok = req.headers["x-malawali-signature"] === "v1=" + expected;
app.post("/webhook/malawali", express.json(), (req, res) => {
  const ts = req.headers["x-malawali-timestamp"];
  const raw = JSON.stringify(req.body);
  const expected = crypto
    .createHmac("sha256", process.env.MALAWALI_WEBHOOK_SECRET)
    .update(ts + "." + raw)
    .digest("hex");

  if (req.headers["x-malawali-signature"] !== "v1=" + expected) {
    return res.status(401).end();
  }

  const { event, data } = req.body;
  if (event === "order.paid") {
    // aktifkan pesanan {data.id}
  }
  res.json({ ok: true });
});
<?php
$ts = $_SERVER["HTTP_X_MALAWALI_TIMESTAMP"];
$raw = file_get_contents("php://input");
$expected = hash_hmac("sha256", $ts . "." . $raw, getenv("MALAWALI_WEBHOOK_SECRET"));

if (($_SERVER["HTTP_X_MALAWALI_SIGNATURE"] ?? "") !== "v1=" . $expected) {
  http_response_code(401);
  exit;
}

$payload = json_decode($raw, true);
if ($payload["event"] === "order.paid") {
  // aktifkan pesanan
}
echo json_encode(["ok" => true]);
import hmac, hashlib, os
from flask import Flask, request, abort

app = Flask(__name__)

@app.post("/webhook/malawali")
def malawali_webhook():
    ts = request.headers["x-malawali-timestamp"]
    raw = request.get_data(as_text=True)
    expected = hmac.new(
        os.environ["MALAWALI_WEBHOOK_SECRET"].encode(),
        f"{ts}.{raw}".encode(),
        hashlib.sha256,
    ).hexdigest()
    if request.headers.get("x-malawali-signature") != f"v1={expected}":
        abort(401)
    payload = request.get_json()
    return {"ok": True}

order.paid

JSON
{
  "event": "order.paid",
  "created_at": "2026-09-27T09:30:11.000Z",
  "data": {
    "id": "ord_7f3k9d2m",
    "status": "paid",
    "base_amount": 25000,
    "pay_amount": 25000,
    "reference_id": "INV-2026-0001",
    "paid_at": "2026-09-27T09:30:10.000Z"
  }
}