Pesanan menumpuk malam hari
Pembeli bayar jam 11 malam, pesanan baru diproses pagi karena menunggu admin.
Untuk penyedia hosting, domain, dan VPS yang ingin pelanggan bayar QRIS tanpa konfirmasi manual.
Halaman ini bagian dari layanan API QRIS gratis APIQris: pakai QRIS milik Anda sendiri, tanpa potongan dari kami, dana langsung ke rekening Anda.
| Hosting Pro 1 tahun | Rp540.000 |
| Domain .com | Rp165.000 |
| Total | Rp705.000 |
Jawaban singkatModul gateway WHMCS yang memakai API QRIS membuat tagihan QRIS sesuai jumlah invoice, lalu memanggil addInvoicePayment saat webhook lunas diterima. Layanan pelanggan aktif otomatis tanpa admin memeriksa mutasi.
Ingin tahu gambaran besarnya dulu? Baca juga pengertian QRIS API dan bagaimana API QRIS gratis APIQris menghubungkan QRIS Anda ke website, aplikasi, dan chatbot.
Pembeli bayar jam 11 malam, pesanan baru diproses pagi karena menunggu admin.
Biaya per transaksi plus biaya penarikan menggerus margin yang sudah tipis.
Admin harus membalas "sudah masuk kak" satu per satu.
Status bayar ada di aplikasi merchant, pesanan ada di sistem, rekap jadi kerja dua kali.
Solusinya: API QRIS WHMCS dari APIQris mengotomatiskan semuanya, tanpa mengganti QRIS yang sudah Anda punya.
Pelanggan hosting sering membayar di malam hari. Tanpa konfirmasi otomatis, layanan baru aktif keesokan pagi dan pelanggan kecewa. Dengan API QRIS, aktivasi berjalan dalam hitungan detik.
Yang ditangani modul gateway:
Margin bisnis hosting tipis. Menghapus fee gateway 0,7% sampai 1% per transaksi berarti keuntungan bersih langsung naik.
Dana dan data berjalan di jalur berbeda. Uang pembeli langsung ke QRIS Anda, APIQris hanya mengurus QRIS dinamis, pencocokan, dan webhook.
Buat akun APIQris dengan email, tanpa biaya dan tanpa dokumen perusahaan.
Unggah gambar QRIS merchant dari bank atau e-wallet Anda. Sistem membaca data QRIS secara otomatis.
Pasang aplikasi APIQris di HP Android yang menerima notifikasi dana masuk, lalu pindai kode pairing.
Salin API key, buat tagihan QRIS dinamis dari website atau chatbot, dan terima webhook saat lunas.
UMKM kuliner yang menerima pesanan lewat website dan WhatsApp. Ilustrasi alur kerja, bukan testimoni pelanggan.
Pembeli mengirim foto bukti bayar, admin mengecek mutasi, lalu mengubah status pesanan secara manual.
Lewat API QRIS WHMCS, QRIS bernominal dikirim otomatis. Status berubah lunas sendiri dan dapur langsung menerima pesanan.
| Aspek | QRIS statis manual | API QRIS WHMCS (APIQris) | Payment gateway |
|---|---|---|---|
| Nominal | Diketik pembeli | Terkunci otomatis | Terkunci otomatis |
| Konfirmasi bayar | Cek mutasi manual | Webhook otomatis | Webhook otomatis |
| Penerima dana | Rekening Anda | Rekening Anda | Rekening gateway |
| Potongan perantara | Rp0 | Rp0 | ±0,7% + biaya tarik |
| Bekerja 24 jam | Tergantung admin | Ya | Ya |
Kirim nominal dan order ID, terima QR dan total yang sudah ditambah kode unik.
<?php
$ch = curl_init('https://api.apiqris.com/v1/invoices');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('APIQRIS_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 50000,
'order_id' => 'INV-1024',
]),
]);
$qris = json_decode(curl_exec($ch), true);
echo $qris['qr_image_url']; // tampilkan ke pembelicurl -X POST https://api.apiqris.com/v1/invoices \
-H "Authorization: Bearer AQ_LIVE_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"amount":50000,"order_id":"INV-1024"}'use Illuminate\Support\Facades\Http;
$qris = Http::withToken(config('services.apiqris.key'))
->post('https://api.apiqris.com/v1/invoices', [
'amount' => $order->total,
'order_id' => $order->number,
])
->throw()
->json();
return view('checkout.qris', ['qris' => $qris]);const res = await fetch('https://api.apiqris.com/v1/invoices', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.APIQRIS_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ amount: 50000, order_id: 'INV-1024' }),
});
const qris = await res.json();
console.log(qris.total_amount, qris.qr_image_url);import os, requests
r = requests.post(
"https://api.apiqris.com/v1/invoices",
headers={"Authorization": f"Bearer {os.environ['APIQRIS_KEY']}"},
json={"amount": 50000, "order_id": "INV-1024"},
timeout=15,
)
r.raise_for_status()
qris = r.json()
print(qris["total_amount"], qris["qr_image_url"])body := strings.NewReader(`{"amount":50000,"order_id":"INV-1024"}`)
req, _ := http.NewRequest("POST", "https://api.apiqris.com/v1/invoices", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("APIQRIS_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()Hitung HMAC SHA-256 dari timestamp dan body mentah, bandingkan secara constant-time.
<?php
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_X_APIQRIS_SIGNATURE'] ?? ''), $sig);
$expected = hash_hmac('sha256', $sig['t'] . '.' . $body, getenv('APIQRIS_SECRET'));
if (!hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) $sig['t']) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
if ($event['event'] === 'invoice.paid') {
tandai_lunas($event['order_id']); // fungsi milik aplikasi Anda
}
http_response_code(200);# Header yang dikirim APIQris ke callback_url Anda
X-APIQris-Signature: t=1760670000,v1=5f2b...e9
Content-Type: application/json
{"event":"invoice.paid","id":"qr_9KX2T7","order_id":"INV-1024","total_amount":50123,"status":"paid"}Route::post('/webhook/qris', function (Request $request) {
parse_str(str_replace(',', '&', $request->header('X-APIQris-Signature')), $sig);
$expected = hash_hmac('sha256', $sig['t'].'.'.$request->getContent(), config('services.apiqris.secret'));
abort_unless(hash_equals($expected, $sig['v1'] ?? ''), 401);
if ($request->input('event') === 'invoice.paid') {
Order::where('number', $request->input('order_id'))->update(['status' => 'paid']);
}
return response()->noContent();
});import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhook/qris', express.raw({ type: 'application/json' }), (req, res) => {
const sig = Object.fromEntries(req.get('X-APIQris-Signature').split(',').map((p) => p.split('=')));
const expected = crypto.createHmac('sha256', process.env.APIQRIS_SECRET)
.update(`${sig.t}.${req.body}`).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig.v1 ?? ''))) return res.sendStatus(401);
const event = JSON.parse(req.body);
if (event.event === 'invoice.paid') markPaid(event.order_id);
res.sendStatus(200);
});import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/webhook/qris")
def webhook():
sig = dict(p.split("=", 1) for p in request.headers["X-APIQris-Signature"].split(","))
msg = f"{sig['t']}.".encode() + request.get_data()
expected = hmac.new(os.environ["APIQRIS_SECRET"].encode(), msg, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig.get("v1", "")):
abort(401)
event = request.get_json()
if event["event"] == "invoice.paid":
mark_paid(event["order_id"])
return "", 200func webhook(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
sig := map[string]string{}
for _, p := range strings.Split(r.Header.Get("X-APIQris-Signature"), ",") {
if k, v, ok := strings.Cut(p, "="); ok {
sig[k] = v
}
}
mac := hmac.New(sha256.New, []byte(os.Getenv("APIQRIS_SECRET")))
mac.Write([]byte(sig["t"] + "." + string(body)))
if !hmac.Equal([]byte(hex.EncodeToString(mac.Sum(nil))), []byte(sig["v1"])) {
http.Error(w, "invalid signature", http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
}Data tagihan dan API key selalu terenkripsi saat dikirim.
Kunci bocor? Buat kunci baru dari dashboard, kunci lama langsung mati.
Setiap callback ditandatangani agar server Anda bisa menolak yang palsu.
Tidak ada saldo yang bisa dibekukan, karena uang langsung ke QRIS Anda.
Modul ditulis untuk WHMCS 8.x dengan PHP 8.
Selisih kode unik dicatat sebagai bagian pembayaran sehingga invoice tetap lunas penuh.
Tidak. Pembeli membayar ke QRIS milik Anda sendiri, sehingga dana langsung masuk ke rekening atau saldo merchant Anda.
Daftar gratis dan APIQris tidak memotong fee per transaksi. MDR dari penyedia QRIS Anda (bila ada) mengikuti ketentuan penyedia.
Cukup satu HP Android yang terpasang aplikasi merchant penerbit QRIS Anda dan aplikasi pendamping APIQris. HP lama pun bisa selama notifikasinya stabil.
Semua panduan berinduk ke halaman utama API QRIS gratis tanpa fee.
Gratis, tanpa potongan per transaksi, dana langsung ke rekening Anda. Pelajari dulu API QRIS selengkapnya atau langsung daftar.