Menulis generator QRIS dari nol
Parsing TLV, urutan tag, dan CRC-16 rawan salah dan memakan waktu.
Dari skrip kecil, bot Telegram, sampai backend Django.
Halaman ini bagian dari layanan API QRIS gratis APIQris: pakai QRIS milik Anda sendiri, tanpa potongan dari kami, dana langsung ke rekening Anda.
qris = requests.post(API, json={"amount": 75000},headers=auth,).json()
Jawaban singkatDi Python, buat QRIS dinamis dengan requests.post ke endpoint /invoices dan header Authorization Bearer. Untuk webhook, ambil body mentah (request.get_data di Flask atau request.body di Django), hitung hmac.new(secret, timestamp.body, sha256) lalu bandingkan dengan hmac.compare_digest.
Ingin tahu gambaran besarnya dulu? Baca juga pengertian QRIS API dan bagaimana API QRIS gratis APIQris menghubungkan QRIS Anda ke website, aplikasi, dan chatbot.
Parsing TLV, urutan tag, dan CRC-16 rawan salah dan memakan waktu.
Scraping internet banking rapuh, sering diblokir, dan butuh menyimpan password.
Endpoint callback yang tidak diverifikasi bisa dipalsukan siapa saja.
Tanpa sandbox, developer harus bayar sungguhan setiap kali mengetes alur checkout.
Solusinya: API QRIS Python dari APIQris mengotomatiskan semuanya, tanpa mengganti QRIS yang sudah Anda punya.
Buat view dengan dekorator csrf_exempt dan require_POST, baca request.body (bytes), lalu verifikasi tanda tangan seperti contoh Flask. Update model Order di dalam transaction.atomic.
Dengan python-telegram-bot atau aiogram, panggil API saat pengguna menekan tombol beli, kirim foto dari qr_image_url, lalu kirim pesan sukses ketika webhook invoice.paid masuk.
Jangan menaruh API key di kode bot yang dibagikan. Gunakan variabel lingkungan dan rotasi key dari dashboard bila bocor.
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.
Developer freelance yang membangun toko online untuk klien. Ilustrasi alur kerja, bukan testimoni pelanggan.
Setiap proyek dimulai dari nol: mencari gateway, mengurus dokumen klien, dan menulis ulang modul pembayaran.
Dengan API QRIS Python, satu modul yang sama dipakai di semua proyek. Klien cukup upload QRIS miliknya, dana langsung ke rekening klien.
| Aspek | QRIS statis manual | API QRIS Python (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.
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"])curl -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"}'<?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 pembeliuse 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);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.
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 "", 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"}<?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);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);
});func 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.
Contoh berjalan di Python 3.8 ke atas.
Contoh requests sudah cukup ringkas. SDK tambahan tersedia di dashboard.
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.