Endpoint: /api/qris/orderkuota
API ini digunakan untuk mengelola pembayaran QRIS, termasuk membuat QR baru dan memeriksa status transaksi. Endpoint ini terintegrasi dengan bot WhatsApp untuk memproses pembelian seperti panel pterodactyl dan kuota.
Memerlukan kunci API valid sebagai parameter query.
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| merchant | String | Ya | Identifikasi merchant untuk transaksi |
| keyorkut | String | Ya | Kunci unik untuk transaksi |
| amount | Number | Ya* | Nominal pembayaran dalam rupiah + fee acak (contoh: 15001 untuk Rp15.000 + fee Rp1) |
| codeqr | String | Ya* | Kode QRIS untuk pembayaran |
| apikey | String | Ya | Kunci API untuk autentikasi |
* Wajib saat membuat QR
Dikembalikan saat membuat QR:
{
"status": true,
"creator": "Fahri - OfficiaL",
"result": {
"transactionId": "FAHRI-BCSKMN5L",
"amount": "2900",
"expirationTime": "2025-06-11T19:06:19.103Z",
"qrImageUrl": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=88383833",
"qrString": "838838"
},
"paymentStatus": {
"status": "pending",
"message": "Transaksi belum ditemukan."
}
}
Dikembalikan saat memeriksa status transaksi:
{
"status": true,
"creator": "Fahri - OfficiaL",
"result": {
"transactionId": "FAHRI-5QDN9GF7",
"amount": "45",
"expirationTime": "2025-06-11T19:06:52.665Z",
"qrImageUrl": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=88383883",
"qrString": "000027"
},
"paymentStatus": {
"status": "success",
"transaction": {
"date": "2025-06-12 01:36:33",
"brand_name": "Seabank",
"amount": "45"
}
}
}
Dikembalikan saat terjadi kesalahan:
{
"error": "Isi Parameter Amount."
}
Membuat QRIS baru dengan amount dan codeqr. Mengembalikan URL gambar QR dan status awal pending.
Memeriksa status transaksi menggunakan merchant dan keyorkut.
Mengirim notifikasi ke Telegram saat QR dibuat.
Berikut adalah kode untuk perintah buyresellerpanelv2 pada bot WhatsApp yang menggunakan endpoint ini.
case "buyresellerpanelv2": {
if (m.isGroup) return m.reply("Pembelian panel pterodactyl hanya bisa di dalam private chat");
if (db.users[m.sender].status_deposit) return m.reply("Masih ada transaksi yang belum diselesaikan, ketik *.batalbeli* untuk membatalkan transaksi sebelumnya!");
let us = crypto.randomBytes(4).toString("hex");
let Obj = {};
Obj.harga = 45; // Harga dalam ribuan (Rp42.000)
Obj.username = us;
const UrlQr = "8383838";
const merchant = "88282";
const keyorkut = "883838";
const randomFee = Math.floor(Math.random() * 100) + 1; // Fee acak antara 1-100 rupiah
const amount = Number(Obj.harga) + randomFee; // Konversi ke rupiah + fee acak
try {
// Create payment
const get = await axios.get(`https://simpelz.fahriofficial.my.id/api/qris/orderkuota?apikey=tess&amount=${amount}&codeqr=${encodeURIComponent(UrlQr)}&merchant=${merchant}&keyorkut=${keyorkut}`);
const response = get.data;
if (!response.status || !response.result.qrImageUrl) return m.reply("Gagal membuat pembayaran, coba lagi nanti!");
// Get initial payment status
const initialStatus = response.paymentStatus?.status || "pending";
const initialMessage = response.paymentStatus?.message || "Menunggu konfirmasi pembayaran.";
// Debugging: Log initial API response
console.log("Initial API response:", JSON.stringify(response, null, 2));
const teks3 = `
*乂 INFORMASI PEMBAYARAN*
*• ID :* ${merchant}-${keyorkut}
*• Total Pembayaran :* Rp${await toIDR(amount)}
*• Barang :* Admin Panel Pterodactyl
*• Status :* ${initialStatus === "success" ? "Sukses" : "Pending"}
*• Expired :* 5 menit
*Note :*
Qris pembayaran hanya berlaku dalam 5 menit, jika sudah melewati 5 menit pembayaran dinyatakan tidak valid!
Jika pembayaran berhasil bot akan otomatis mengirim notifikasi status pembayaran kamu.
Ketik *.batalbeli* untuk membatalkan
Ketik *.updateqr * untuk memperbarui QR dengan nominal baru
`;
let msgQr = await conn.sendMessage(m.chat, {
footer: `© 2024 ${botname}`,
image: { url: response.result.qrImageUrl },
caption: teks3,
contextInfo: {
mentionedJid: [m.sender],
},
});
// If payment is already successful, send confirmation and exit
if (initialStatus === "success") {
db.users[m.sender].status_deposit = false;
await conn.sendMessage(m.chat, {
text: `
*PEMBAYARAN BERHASIL DITERIMA ✅*
*• ID :* ${merchant}-${keyorkut}
*• Total Pembayaran :* Rp${await toIDR(amount)}
*• Barang :* Admin Panel Pterodactyl
\`Group Reseller Anda Silahkan Minta Add Ke Admin\`
${global.linkreseller}
`,
}, { quoted: msgQr });
await conn.sendMessage(m.chat, { delete: msgQr.key });
return;
}
// Store transaction details in db
db.users[m.sender].status_deposit = true;
db.users[m.sender].saweria = {
msg: msgQr,
chat: m.sender,
idDeposit: `${merchant}-${keyorkut}`,
amount: amount.toString(),
merchant: merchant,
keyorkut: keyorkut,
codeqr: UrlQr,
transactionId: response.result.transactionId,
exp: function () {
setTimeout(async () => {
if (
db.users[m.sender].status_deposit &&
db.users[m.sender].saweria &&
db.users[m.sender].saweria.amount === amount.toString()
) {
await conn.sendMessage(m.chat, { text: "QRIS Pembayaran telah expired!" }, { quoted: msgQr });
await conn.sendMessage(m.chat, { delete: msgQr.key });
db.users[m.sender].status_deposit = false;
delete db.users[m.sender].saweria;
}
}, 300000); // 5 menit
},
};
await db.users[m.sender].saweria.exp();
// Polling function to check payment status
const checkPaymentStatus = async () => {
try {
// Ideally, use a dedicated status check endpoint if available
// Example: Replace with actual status check endpoint
const statusCheck = await axios.get(`https://simpelz.fahriofficial.my.id/api/qris/orderkuota?apikey=tess&amount=${amount}&codeqr=${encodeURIComponent(UrlQr)}&merchant=${merchant}&keyorkut=${keyorkut}`);
const statusResponse = statusCheck.data;
// Debugging: Log status check response
console.log("Status check response:", JSON.stringify(statusResponse, null, 2));
if (statusResponse.status && statusResponse.paymentStatus) {
const paymentStatus = statusResponse.paymentStatus.status;
// Convert amounts to numbers for comparison
const transactionAmount = Number(statusResponse.paymentStatus.transaction?.amount);
const expectedAmount = Number(amount);
if (paymentStatus === "success" && transactionAmount === expectedAmount) {
db.users[m.sender].status_deposit = false;
await conn.sendMessage(db.users[m.sender].saweria.chat, {
text: `
*PEMBAYARAN BERHASIL DITERIMA ✅*
*• ID :* ${db.users[m.sender].saweria.idDeposit}
*• Total Pembayaran :* Rp${await toIDR(db.users[m.sender].saweria.amount)}
*• Barang :* Admin Panel Pterodactyl
\`Group Reseller Anda Silahkan Minta Add Ke Admin\`
${global.linkreseller}
`,
}, { quoted: db.users[m.sender].saweria.msg });
await conn.sendMessage(db.users[m.sender].saweria.chat, { delete: db.users[m.sender].saweria.msg.key });
delete db.users[m.sender].saweria;
clearInterval(pollingInterval);
} else if (paymentStatus === "error" || paymentStatus === "expired" || paymentStatus === "failed") {
await conn.sendMessage(db.users[m.sender].saweria.chat, { text: `Pembayaran gagal: ${statusResponse.paymentStatus.message || statusResponse.paymentStatus.error}` }, { quoted: db.users[m.sender].saweria.msg });
await conn.sendMessage(db.users[m.sender].saweria.chat, { delete: db.users[m.sender].saweria.msg.key });
db.users[m.sender].status_deposit = false;
delete db.users[m.sender].saweria;
clearInterval(pollingInterval);
}
}
} catch (error) {
console.error("Error checking payment status:", error.message);
errorCounter++;
if (errorCounter > 5) {
clearInterval(pollingInterval);
await conn.sendMessage(db.users[m.sender].saweria.chat, { text: "Gagal memeriksa status pembayaran setelah beberapa percobaan. Silakan coba lagi nanti." });
db.users[m.sender].status_deposit = false;
delete db.users[m.sender].saweria;
}
}
};
let errorCounter = 0;
const pollingInterval = setInterval(checkPaymentStatus, 30000); // Check every 30 seconds
// Stop polling after 5 minutes
setTimeout(() => {
clearInterval(pollingInterval);
if (db.users[m.sender].status_deposit) {
conn.sendMessage(db.users[m.sender].saweria.chat, { text: "Pemeriksaan status pembayaran dihentikan karena waktu habis." });
db.users[m.sender].status_deposit = false;
delete db.users[m.sender].saweria;
}
}, 300000); // 5 menit
} catch (error) {
console.error("Error in buyresellerpanel:", error.message);
return m.reply("Terjadi kesalahan saat membuat pembayaran, coba lagi nanti!");
}
break;
}
{
"status": true,
"creator": "Fahri - OfficiaL",
"result": {
"transactionId": "FAHRI-BCSKMN5L",
"amount": "2900",
"expirationTime": "2025-06-11T19:06:19.103Z",
"qrImageUrl": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=88383833",
"qrString": "838838"
},
"paymentStatus": {
"status": "pending",
"message": "Transaksi belum ditemukan."
}
}
{
"status": true,
"creator": "Fahri - OfficiaL",
"result": {
"transactionId": "FAHRI-5QDN9GF7",
"amount": "45",
"expirationTime": "2025-06-11T19:06:52.665Z",
"qrImageUrl": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=88383883",
"qrString": "000027"
},
"paymentStatus": {
"status": "success",
"transaction": {
"date": "2025-06-12 01:36:33",
"brand_name": "Seabank",
"amount": "45"
}
}
}
amount wajib menyertakan fee acak (Rp1-100) untuk verifikasi unik
pending akan dihapus dari server