├── img ├── update └── buktitrx.jpg ├── qriss.png ├── .github └── FUNDING.yml ├── LICENSE ├── README.md ├── README.go.md ├── kodebot.js ├── README.py.md └── README.js.md /img/update: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /qriss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutoFTbot/Qris-OrderKuota/HEAD/qriss.png -------------------------------------------------------------------------------- /img/buktitrx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutoFTbot/Qris-OrderKuota/HEAD/img/buktitrx.jpg -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: FighterTunnel 2 | custom: ['https://trakteer.id/FighterTunnel'] 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 AutoFTbot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | QRIS Logo 3 |

4 | 5 |

🚀 QRIS Payment Package

6 | 7 |

8 | Paket powerful untuk generate QRIS dan cek status pembayaran secara real-time 🔄 9 |

10 | 11 |

12 | 13 | npm version 14 | 15 | 16 | PyPI version 17 | 18 | 19 | Go version 20 | 21 |

22 | 23 |

24 | 25 | License 26 | 27 | 28 | Stars 29 | 30 | 31 | Forks 32 | 33 | 34 | Issues 35 | 36 |

37 | 38 |

39 | Fitur • 40 | Cara Penggunaan • 41 | Dokumentasi • 42 | Dukungan 43 |

44 | 45 | --- 46 | 47 | ## 🌟 Fitur Utama 48 | 49 |
50 | 51 | | Fitur | Deskripsi | 52 | |:---:|:---| 53 | | ✅ Generate QRIS | Generate QRIS untuk nominal tertentu | 54 | | 🖼️ Custom Logo | Tambah logo custom di tengah QR | 55 | | 📡 Real-time Status | Cek status pembayaran dari API | 56 | | 🛡️ Validasi | Validasi format QRIS | 57 | | 📊 Checksum | Hitung checksum CRC16 | 58 | 59 |
60 | 61 | --- 62 | 63 | ## 🧾 Cara Mendapatkan `YOUR_BASE_QR_STRING` 64 | 65 | Untuk menggunakan package ini, kamu membutuhkan **QR base string** dari QRIS. Ikuti langkah berikut: 66 | 67 | 1. **Siapkan Gambar QRIS** yang kamu miliki. 68 | 2. Buka situs: 69 | 👉 [https://www.imagetotext.info/qr-code-scanner](https://www.imagetotext.info/qr-code-scanner) 70 | 3. Upload gambar QRIS ke situs tersebut. 71 | 4. Tunggu hingga proses scan selesai. 72 | 5. Salin hasil **output QR string** yang muncul. 73 | 6. Gunakan hasil tersebut sebagai nilai `YOUR_BASE_QR_STRING`. 74 | 75 | > 💡 **Contoh hasil:** 76 | > ``` 77 | > 00020101021226690014ID.CO.QRIS.WWW01189360091311520010303120123456789040415ID10203040506070809051003UME51440014ID.CO.BANK90203123456303201234567890503... 78 | > ``` 79 | 80 | --- 81 | 82 | ## 🤖 Cara Mendapatkan Token & Username untuk Mutasi 83 | 84 | Untuk mengakses fitur mutasi OrderKuota, kamu membutuhkan **auth_token** dan **auth_username**. Dapatkan melalui bot Telegram: 85 | 86 | ### **Via Bot Telegram:** 87 | 1. **Buka Bot:** [@orderkuotaBot](https://t.me/orderkuotaBot) 88 | 2. **Login:** `/login username password` 89 | 3. **Verifikasi OTP:** `/otp kode_otp` 90 | 4. **Dapatkan Token:** Bot akan menampilkan `auth_token` setelah login berhasil 91 | 92 | > ⚠️ **Penting:** Token akan expired setelah 1 jam. Login ulang jika diperlukan. 93 | 94 | --- 95 | 96 | ## 📚 Dokumentasi 97 | 98 |
99 | 100 | | Bahasa | Dokumentasi | 101 | |:---:|:---| 102 | | JavaScript | [`README.js.md`](README.js.md) | 103 | | Python | [`README.py.md`](README.py.md) | 104 | | Go | [`README.go.md`](README.go.md)
⚠️ Fitur Custom Logo tidak tersedia | 105 | 106 |
107 | 108 | > 📖 **Dokumentasi Lengkap:** 109 | > 👉 [https://orkut.ftvpn.me](https://orkut.ftvpn.me) 110 | 111 | --- 112 | ## Star History 113 | 114 | [![Star History Chart](https://api.star-history.com/svg?repos=AutoFTbot/Qris-OrderKuota&type=Date)](https://www.star-history.com/#AutoFTbot/Qris-OrderKuota&Date) 115 | ## ❤️ Dukungan 116 | 117 | Jika kamu suka proyek ini dan ingin mendukung pengembangannya, kamu bisa: 118 | 119 | - ⭐ Memberi bintang repo ini 120 | - 🔄 Share ke teman-teman developer lainnya 121 | - 💰 Donasi melalui QRIS berikut: 122 | 123 |

124 | Donasi via QRIS 125 |

126 | 127 | --- 128 | 129 |
130 | Built with ❤️ by AutoFTbot 131 |
132 | -------------------------------------------------------------------------------- /README.go.md: -------------------------------------------------------------------------------- 1 | # 🚀 Paket Pembayaran QRIS untuk Go 2 | 3 | Paket Go yang menyediakan integrasi pembayaran QRIS (Quick Response Code Indonesian Standard) untuk aplikasi Anda. 4 | 5 | ## 🎯 Fitur Utama 6 | 7 | - Generate QRIS dengan format standar 8 | - Pengecekan status pembayaran secara real-time 9 | - Validasi format QRIS 10 | - Kalkulasi checksum CRC16 11 | - Dukungan base QRIS string 12 | - Penanganan error yang lebih baik 13 | - QR code dengan tingkat koreksi error tinggi 14 | 15 | ## 📦 Instalasi 16 | 17 | ```bash 18 | go get github.com/AutoFTbot/OrderKuota-go 19 | ``` 20 | 21 | ## 🚀 Penggunaan 22 | 23 | ### Inisialisasi 24 | 25 | ```go 26 | import "github.com/AutoFTbot/OrderKuota-go/qris" 27 | 28 | config := qris.QRISConfig{ 29 | MerchantID: "123456789", 30 | APIKey: "your-api-key", 31 | BaseQrString: "your-base-qr-string", 32 | } 33 | 34 | qrisInstance, err := qris.NewQRIS(config) 35 | if err != nil { 36 | // handle error 37 | } 38 | ``` 39 | 40 | ### Generate QR Code 41 | 42 | ```go 43 | data := qris.QRISData{ 44 | Amount: 100000, 45 | TransactionID: "TRX123", 46 | } 47 | 48 | qrCode, err := qrisInstance.GenerateQRCode(data) 49 | if err != nil { 50 | // handle error 51 | } 52 | 53 | // Simpan QR code ke file 54 | err = qrCode.Save("qris.png") 55 | ``` 56 | 57 | ### Generate QRIS String 58 | 59 | ```go 60 | data := qris.QRISData{ 61 | Amount: 100000, 62 | TransactionID: "TRX123", 63 | } 64 | 65 | qrString, err := qrisInstance.GetQRISString(data) 66 | if err != nil { 67 | // handle error 68 | } 69 | ``` 70 | 71 | ### Cek Status Pembayaran 72 | 73 | ```go 74 | status, err := qrisInstance.CheckPaymentStatus("TRX123", 100000) 75 | if err != nil { 76 | // handle error 77 | } 78 | 79 | if status.Status == "PAID" { 80 | // Pembayaran berhasil 81 | fmt.Printf("Pembayaran diterima dari %s pada %s\n", 82 | status.BrandName, status.Date) 83 | } 84 | ``` 85 | 86 | ### Validasi String QRIS 87 | 88 | ```go 89 | err := qrisInstance.ValidateQRISString(qrString) 90 | if err != nil { 91 | // handle error 92 | } 93 | ``` 94 | 95 | ## 📝 Dokumentasi 96 | 97 | ### QRISConfig 98 | 99 | ```go 100 | type QRISConfig struct { 101 | MerchantID string // ID merchant dari payment gateway 102 | APIKey string // API key untuk autentikasi 103 | BaseQrString string // Base QRIS string dari merchant 104 | } 105 | ``` 106 | 107 | ### QRISData 108 | 109 | ```go 110 | type QRISData struct { 111 | Amount int64 // Nominal pembayaran 112 | TransactionID string // ID transaksi unik 113 | } 114 | ``` 115 | 116 | ### PaymentStatus 117 | 118 | ```go 119 | type PaymentStatus struct { 120 | Status string // Status pembayaran (PAID/UNPAID) 121 | Amount int64 // Nominal pembayaran 122 | Reference string // Referensi pembayaran 123 | Date string // Tanggal pembayaran (jika PAID) 124 | BrandName string // Nama brand pembayar (jika PAID) 125 | BuyerRef string // Referensi pembeli (jika PAID) 126 | } 127 | ``` 128 | 129 | ### Contoh Kode 130 | 131 | ```go 132 | package main 133 | 134 | import ( 135 | "fmt" 136 | "log" 137 | "time" 138 | 139 | "github.com/autoftbot/orderkuota-go/qris" 140 | ) 141 | 142 | func main() { 143 | // Inisialisasi QRIS dengan konfigurasi 144 | config := qris.QRISConfig{ 145 | MerchantID: "#", 146 | APIKey: "#", 147 | BaseQrString: "#", 148 | } 149 | 150 | // Buat instance QRIS 151 | qrisInstance := qris.NewQRIS(config) 152 | 153 | // Generate QR Code 154 | data := qris.QRISData{ 155 | Amount: 1000, 156 | TransactionID: "TRX123", 157 | } 158 | 159 | qrCode, err := qrisInstance.GenerateQRCode(data) 160 | if err != nil { 161 | log.Fatalf("Error generating QR code: %v", err) 162 | } 163 | 164 | // Simpan QR code ke file 165 | err = qrCode.WriteFile(256, "qris.png") 166 | if err != nil { 167 | log.Fatalf("Error saving QR code: %v", err) 168 | } 169 | 170 | fmt.Println("QR Code berhasil dibuat dan disimpan sebagai qris.png") 171 | fmt.Println("Silahkan scan QR code untuk melakukan pembayaran...") 172 | 173 | // Cek status pembayaran secara berulang 174 | for { 175 | fmt.Println("\nMengecek status pembayaran...") 176 | status, err := qrisInstance.CheckPaymentStatus("TRX123", 1000) 177 | if err != nil { 178 | log.Printf("Error checking payment status: %v", err) 179 | time.Sleep(5 * time.Second) 180 | continue 181 | } 182 | 183 | // Tampilkan detail status 184 | fmt.Printf("Status Pembayaran: %s\n", status.Status) 185 | fmt.Printf("Amount yang diharapkan: %d\n", 1000) 186 | fmt.Printf("Amount yang diterima: %d\n", status.Amount) 187 | fmt.Printf("Reference: %s\n", status.Reference) 188 | 189 | if status.Status == "PAID" { 190 | fmt.Printf("Pembayaran berhasil!\n") 191 | fmt.Printf("Date: %s\n", status.Date) 192 | fmt.Printf("Brand: %s\n", status.BrandName) 193 | fmt.Printf("Buyer Ref: %s\n", status.BuyerRef) 194 | break 195 | } else { 196 | fmt.Println("Menunggu pembayaran...") 197 | } 198 | 199 | // Tunggu 5 detik sebelum cek lagi 200 | time.Sleep(5 * time.Second) 201 | } 202 | } 203 | ``` 204 | 205 | ## 🔍 Penanganan Error 206 | 207 | Paket ini menyediakan penanganan error yang lebih baik dengan pesan error yang jelas: 208 | 209 | - Validasi input saat inisialisasi 210 | - Validasi format QRIS 211 | - Validasi checksum 212 | - Error saat generate QR code 213 | - Error saat cek status pembayaran 214 | 215 | ## 🛠️ Praktik Terbaik 216 | 217 | 1. Selalu cek error saat inisialisasi QRIS 218 | 2. Gunakan ID transaksi unik untuk setiap transaksi 219 | 3. Validasi string QRIS sebelum digunakan 220 | 4. Gunakan penanganan error yang tepat 221 | 5. Simpan QR code dalam format PNG untuk kualitas terbaik 222 | -------------------------------------------------------------------------------- /kodebot.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 2 | const TelegramBot = require('node-telegram-bot-api'); 3 | const { processApiRequest } = require('./lib/orderkuota-logic'); 4 | 5 | const TELEGRAM_TOKEN = '#'; 6 | 7 | const bot = new TelegramBot(TELEGRAM_TOKEN, { polling: true }); 8 | 9 | const userStates = {}; 10 | 11 | async function deleteLastBotMessage(chatId) { 12 | const state = userStates[chatId]; 13 | if (state && state.lastBotMessageId) { 14 | try { 15 | await bot.deleteMessage(chatId, state.lastBotMessageId); 16 | } catch (e) { 17 | } 18 | state.lastBotMessageId = null; 19 | } 20 | } 21 | 22 | bot.onText(/\/start/, async (msg) => { 23 | await deleteLastBotMessage(msg.chat.id); 24 | const sent = await bot.sendMessage( 25 | msg.chat.id, 26 | 'Selamat datang di OrderKuota Bot!\nKetik /otp untuk login OrderKuota.\n\n*Privasi Anda aman!* Semua proses dan data yang Anda kirim _tidak disimpan di database manapun_. Hanya Anda dan bot yang tahu data yang dikirimkan.', 27 | { parse_mode: 'Markdown' } 28 | ); 29 | userStates[msg.chat.id] = { lastBotMessageId: sent.message_id }; 30 | }); 31 | 32 | bot.onText(/\/otp/, async (msg) => { 33 | await deleteLastBotMessage(msg.chat.id); 34 | userStates[msg.chat.id] = { step: 'awaiting_username' }; 35 | const sent = await bot.sendMessage(msg.chat.id, 'Masukkan username OrderKuota Anda untuk request OTP:'); 36 | userStates[msg.chat.id].lastBotMessageId = sent.message_id; 37 | }); 38 | 39 | bot.onText(/\/verify/, async (msg) => { 40 | await deleteLastBotMessage(msg.chat.id); 41 | userStates[msg.chat.id] = { step: 'verify_awaiting_username' }; 42 | const sent = await bot.sendMessage(msg.chat.id, 'Masukkan username OrderKuota Anda untuk verifikasi OTP:'); 43 | userStates[msg.chat.id].lastBotMessageId = sent.message_id; 44 | }); 45 | 46 | bot.on('message', async (msg) => { 47 | const chatId = msg.chat.id; 48 | const state = userStates[chatId]; 49 | if (!state) return; 50 | 51 | // OTP flow 52 | if (state.step === 'awaiting_username' && !msg.text.startsWith('/')) { 53 | state.username = msg.text.trim(); 54 | state.step = 'awaiting_password'; 55 | await deleteLastBotMessage(chatId); 56 | const sent = await bot.sendMessage(chatId, 'Masukkan password OrderKuota Anda:'); 57 | state.lastBotMessageId = sent.message_id; 58 | return; 59 | } 60 | if (state.step === 'awaiting_password' && !msg.text.startsWith('/')) { 61 | state.password = msg.text.trim(); 62 | state.step = 'processing_otp'; 63 | await deleteLastBotMessage(chatId); 64 | const sentReq = await bot.sendMessage(chatId, 'Meminta OTP...'); 65 | state.lastBotMessageId = sentReq.message_id; 66 | try { 67 | const result = await processApiRequest({ 68 | action: 'request_otp', 69 | username: state.username, 70 | password: state.password 71 | }); 72 | if (result && result.success === false) { 73 | await deleteLastBotMessage(chatId); 74 | const sent = await bot.sendMessage(chatId, `❌ *Gagal request OTP!* 75 | _${result.message || 'Terjadi kesalahan.'}_`, { parse_mode: 'Markdown' }); 76 | state.lastBotMessageId = sent.message_id; 77 | delete userStates[chatId]; 78 | return; 79 | } 80 | await deleteLastBotMessage(chatId); 81 | const sent = await bot.sendMessage(chatId, `✅ *OTP berhasil dikirim!* 82 | Silakan cek email/nomor Anda dan masukkan kode OTP di bawah ini.\n\n_Respon server:_ \`${JSON.stringify(result)}\``, { parse_mode: 'Markdown' }); 83 | state.lastBotMessageId = sent.message_id; 84 | state.step = 'verify_awaiting_otp'; 85 | const sentOtp = await bot.sendMessage(chatId, 'Masukkan kode OTP yang Anda terima:'); 86 | state.lastBotMessageId = sentOtp.message_id; 87 | } catch (err) { 88 | await deleteLastBotMessage(chatId); 89 | const sent = await bot.sendMessage(chatId, `❌ *Gagal request OTP!* 90 | _${err.message}_`, { parse_mode: 'Markdown' }); 91 | state.lastBotMessageId = sent.message_id; 92 | delete userStates[chatId]; 93 | } 94 | return; 95 | } 96 | 97 | if (state.step === 'verify_awaiting_otp' && !msg.text.startsWith('/')) { 98 | state.otp = msg.text.trim(); 99 | state.step = 'processing_verify'; 100 | await deleteLastBotMessage(chatId); 101 | const sentVer = await bot.sendMessage(chatId, '🔄 Memverifikasi OTP...'); 102 | state.lastBotMessageId = sentVer.message_id; 103 | try { 104 | const result = await processApiRequest({ 105 | action: 'verify_otp', 106 | username: state.username, 107 | otp: state.otp 108 | }); 109 | if (result && result.success === false) { 110 | await deleteLastBotMessage(chatId); 111 | const sent = await bot.sendMessage(chatId, `❌ *Gagal verifikasi OTP!* 112 | _${result.message || 'Terjadi kesalahan.'}_`, { parse_mode: 'Markdown' }); 113 | state.lastBotMessageId = sent.message_id; 114 | delete userStates[chatId]; 115 | return; 116 | } 117 | await deleteLastBotMessage(chatId); 118 | const token = result?.results?.token || '-'; 119 | const sent = await bot.sendMessage(chatId, `🎉 *Verifikasi Berhasil!* 120 | Berikut token Anda (jaga kerahasiaannya): 121 | \`${token}\` 122 | \n_Respon server:_ \`${JSON.stringify(result)}\``, { parse_mode: 'Markdown' }); 123 | state.lastBotMessageId = sent.message_id; 124 | } catch (err) { 125 | await deleteLastBotMessage(chatId); 126 | const sent = await bot.sendMessage(chatId, `❌ *Gagal verifikasi OTP!* 127 | _${err.message}_`, { parse_mode: 'Markdown' }); 128 | state.lastBotMessageId = sent.message_id; 129 | } 130 | delete userStates[chatId]; 131 | return; 132 | } 133 | }); 134 | -------------------------------------------------------------------------------- /README.py.md: -------------------------------------------------------------------------------- 1 | # QRIS Payment Python Package 2 | 3 | Package Python untuk generate QRIS dan cek status pembayaran dengan fitur monitoring realtime. 4 | 5 | ## 🚀 Fitur Terbaru (v1.1.3) 6 | 7 | - ✅ **Generate QRIS** dengan nominal tertentu 8 | - ✅ **Tambah logo** di tengah QR 9 | - ✅ **Cek status pembayaran** realtime 10 | - ✅ **Filter waktu 10 menit** (lebih fleksibel) 11 | - ✅ **Debug mode** untuk monitoring detail 12 | - ✅ **Validasi format QRIS** yang robust 13 | - ✅ **Perhitungan checksum CRC16** 14 | - ✅ **Error handling** yang informatif 15 | - ✅ **Type hints** untuk development yang lebih baik 16 | 17 | ## 📦 Instalasi 18 | 19 | ```bash 20 | pip install qris-payment==1.1.3 21 | ``` 22 | 23 | ## 🔑 Cara Mendapatkan Auth Token 24 | 25 | Untuk mendapatkan `auth_username` dan `auth_token`, hubungi bot Telegram: 26 | 27 | **@AutoFtBot** - Bot resmi untuk mendapatkan kredensial QRIS Payment 28 | 29 | ### Langkah-langkah: 30 | 1. Buka Telegram dan cari **@AuutooFtBot** 31 | 2. Kirim pesan `/start` 32 | 3. Ikuti instruksi untuk mendapatkan kredensial 33 | 4. Bot akan memberikan `auth_username` dan `auth_token` 34 | 35 | ## 🛠️ Penggunaan 36 | 37 | ### Inisialisasi 38 | 39 | ```python 40 | from qris_payment import QRISPayment 41 | 42 | config = { 43 | 'auth_username': 'YOUR_AUTH_USERNAME', # Dapat dari @AutoFtBot 44 | 'auth_token': 'YOUR_AUTH_TOKEN', # Dapat dari @AutoFtBot 45 | 'base_qr_string': 'YOUR_BASE_QR_STRING', 46 | 'logo_path': 'path/to/logo.png' # Opsional 47 | } 48 | 49 | qris = QRISPayment(config) 50 | ``` 51 | 52 | ### Generate QRIS 53 | 54 | ```python 55 | def generate_qr(): 56 | try: 57 | result = qris.generate_qr(10000) 58 | 59 | # Simpan QR ke file 60 | result['qr_image'].save('qr.png') 61 | print('QR String:', result['qr_string']) 62 | except Exception as e: 63 | print(f"Error: {str(e)}") 64 | ``` 65 | 66 | ### Cek Status Pembayaran 67 | 68 | ```python 69 | def check_payment(): 70 | try: 71 | # Reference tidak dipakai untuk pengecekan, hanya amount 72 | result = qris.check_payment('REF123', 10000) 73 | print('Status pembayaran:', result) 74 | except Exception as e: 75 | print(f"Error: {str(e)}") 76 | ``` 77 | 78 | ### Debug Mode 79 | 80 | ```python 81 | # Untuk monitoring detail proses pengecekan 82 | from qris_payment.payment_checker import PaymentChecker 83 | 84 | checker = PaymentChecker({ 85 | 'auth_username': 'YOUR_AUTH_USERNAME', 86 | 'auth_token': 'YOUR_AUTH_TOKEN' 87 | }, debug=True) 88 | 89 | result = checker.check_payment_status(None, 10000) 90 | ``` 91 | 92 | ## 📋 Konfigurasi 93 | 94 | | Parameter | Tipe | Deskripsi | Wajib | 95 | |-----------|------|-----------|-------| 96 | | auth_username | string | Username dari @AutoFtBot | Ya | 97 | | auth_token | string | Token dari @AutoFtBot | Ya | 98 | | base_qr_string | string | String dasar QRIS | Ya | 99 | | logo_path | string | Path ke file logo (opsional) | Tidak | 100 | 101 | ## 📊 Response 102 | 103 | ### Generate QR 104 | 105 | ```python 106 | { 107 | 'qr_string': "000201010212...", # String QRIS dengan checksum 108 | 'qr_image': # Objek gambar QR 109 | } 110 | ``` 111 | 112 | ### Cek Pembayaran 113 | 114 | ```python 115 | { 116 | 'success': True, 117 | 'data': { 118 | 'status': 'PAID' | 'UNPAID', 119 | 'amount': int, 120 | 'date': str, # Hanya jika status PAID 121 | 'brand_name': str, # Hanya jika status PAID 122 | 'buyer_reff': str # Hanya jika status PAID 123 | } 124 | } 125 | ``` 126 | 127 | ## ⚡ Contoh Realtime Payment 128 | 129 | ```python 130 | import time 131 | import random 132 | from qris_payment import QRISPayment 133 | 134 | config = { 135 | 'auth_username': 'YOUR_AUTH_USERNAME', 136 | 'auth_token': 'YOUR_AUTH_TOKEN', 137 | 'base_qr_string': 'YOUR_BASE_QR_STRING', 138 | 'logo_path': './logo.png' 139 | } 140 | 141 | def realtime_payment_test(): 142 | qris = QRISPayment(config) 143 | 144 | # Generate QR dengan nominal random 145 | amount = 100 + random.randint(1, 99) 146 | result = qris.generate_qr(amount) 147 | result['qr_image'].save('qr.png') 148 | 149 | print(f'Amount: {amount}') 150 | print('QR saved as: qr.png') 151 | print('Silakan scan dan transfer tepat Rp', amount) 152 | 153 | # Monitor pembayaran (10 menit terakhir) 154 | start_time = time.time() 155 | while time.time() - start_time < 300: # 5 menit timeout 156 | payment_result = qris.check_payment('REF', amount) 157 | if payment_result['success'] and payment_result['data']['status'] == 'PAID': 158 | print('🎉 Pembayaran berhasil!') 159 | print('Detail:', payment_result['data']) 160 | return 161 | time.sleep(3) 162 | print('Menunggu pembayaran...') 163 | 164 | print('Timeout: Pembayaran tidak diterima') 165 | 166 | if __name__ == '__main__': 167 | realtime_payment_test() 168 | ``` 169 | 170 | ## 🔍 Error Handling 171 | 172 | Package ini akan melempar exception dengan pesan yang jelas: 173 | 174 | - **Format QRIS tidak valid** - Pastikan base_qr_string mengandung "5802ID" 175 | - **Nominal harus > 0** - Amount harus positif 176 | - **Auth credentials tidak valid** - Cek username dan token dari @AutoFtBot 177 | - **API tidak dapat diakses** - Cek koneksi internet 178 | - **Response tidak valid** - Ada masalah dengan server API 179 | 180 | ## 📝 Changelog 181 | 182 | ### v1.1.3 (Latest) 183 | - ✅ Filter waktu diperpanjang dari 5 menit ke 10 menit 184 | - ✅ Debug mode untuk monitoring detail 185 | - ✅ Error handling yang lebih robust 186 | - ✅ Type hints untuk development 187 | - ✅ Dokumentasi yang lebih lengkap 188 | 189 | ### v1.1.2 190 | - Perbaikan bug minor 191 | - Optimasi performa 192 | 193 | ### v1.1.1 194 | - Fitur QRIS generation 195 | - Payment checking 196 | 197 | ## 🖥️ Persyaratan Sistem 198 | 199 | - **Python** >= 3.6 200 | - **Dependencies:** 201 | - qrcode >= 7.4.2 202 | - Pillow >= 9.0.0 203 | - requests >= 2.28.0 204 | 205 | ## 📞 Support 206 | 207 | - **Bot Telegram:** @AutoFtBot (untuk kredensial) 208 | - **Repository:** [GitHub](https://github.com/AutoFtBot/qris-payment-py) 209 | - **Email:** autoftbot@gmail.com 210 | 211 | ## 📄 Lisensi 212 | 213 | MIT License 214 | 215 | ## 🤝 Kontribusi 216 | 217 | Silakan buat pull request untuk kontribusi. Untuk perubahan besar, buka issue terlebih dahulu untuk mendiskusikan perubahan yang diinginkan. 218 | 219 | --- 220 | 221 | **Dibuat dengan ❤️ oleh AutoFtBot Team** 222 | -------------------------------------------------------------------------------- /README.js.md: -------------------------------------------------------------------------------- 1 | # AutoFT QRIS Generator 2 | 3 | Node.js package untuk generate QRIS, cek status pembayaran, dan otomatis generate PDF receipt menggunakan API OrderKuota. 4 | 5 | [![npm version](https://badge.fury.io/js/autoft-qris.svg)](https://badge.fury.io/js/autoft-qris) 6 | [![Downloads](https://img.shields.io/npm/dw/autoft-qris.svg)](https://www.npmjs.com/package/autoft-qris) 7 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 8 | 9 | **Updated by AlfiDev as contributor - Version 0.0.9** 10 | 11 | ## 🚀 Pembaruan Terbaru v0.0.9 12 | 13 | - ✨ **Dual Module Support**: ESM dan CommonJS 14 | - 🔧 **Clean Code**: Code tanpa komentar dan lebih bersih 15 | - 🎨 **2 Tema QRIS**: Default (biru) dan Meta Style (hijau) 16 | - 🏷️ **Logo Support**: Tambah logo di tengah QR code 17 | - 💰 **Payment Checker**: Realtime status pembayaran 18 | - 🧾 **Receipt Generator**: PDF receipt otomatis 19 | - 💳 **Balance Checker**: Cek saldo akun API 20 | - 🔒 **CRC16 Validation**: Checksum validation 21 | - 📱 **QRIS Indonesia**: Format standar Indonesia 22 | 23 | ## Fitur 24 | 25 | - Generate QRIS dengan nominal tertentu 26 | - **2 Tema QRIS**: Tema (default) dan Tema style Meta 27 | - Tambah logo di tengah QR 28 | - Cek status pembayaran (realtime polling) menggunakan API OrderKuota 29 | - Cek saldo API akun (endpoint saldo) 30 | - Generate PDF bukti transaksi otomatis saat pembayaran sukses 31 | - Support ESM dan CommonJS module systems 32 | - Node.js version compatibility checking 33 | 34 | ## Contoh Output Receipt 35 | 36 | Contoh Receipt QRIS 37 | 38 | ## Instalasi 39 | 40 | ```bash 41 | npm install autoft-qris 42 | ``` 43 | 44 | ## Penggunaan 45 | 46 | ### ESM (ES Modules) 47 | 48 | ```javascript 49 | import { QRISGenerator, PaymentChecker, ReceiptGenerator } from 'autoft-qris'; 50 | import { writeFileSync } from 'fs'; 51 | 52 | const config = { 53 | storeName: 'Nama Toko Contoh', 54 | auth_username: '#', 55 | auth_token: '#', 56 | baseQrString: '#', 57 | logoPath: './logo-agin.png' 58 | }; 59 | 60 | const qrisGen = new QRISGenerator(config, 'theme1'); 61 | const paymentChecker = new PaymentChecker({ 62 | auth_token: config.auth_token, 63 | auth_username: config.auth_username 64 | }); 65 | const receiptGen = new ReceiptGenerator(config); 66 | 67 | const amount = 50000; 68 | const qrString = qrisGen.generateQrString(amount); 69 | const qrBuffer = await qrisGen.generateQRWithLogo(qrString); 70 | writeFileSync('qris.png', qrBuffer); 71 | 72 | const paymentResult = await paymentChecker.checkPaymentStatus('REF123', amount); 73 | if (paymentResult.success && paymentResult.data.status === 'PAID') { 74 | const receipt = await receiptGen.generateReceipt(paymentResult.data); 75 | console.log('Receipt generated:', receipt.filePath); 76 | } 77 | ``` 78 | 79 | ### CommonJS 80 | 81 | ```javascript 82 | const { QRISGenerator, PaymentChecker, ReceiptGenerator } = require('autoft-qris'); 83 | const fs = require('fs'); 84 | 85 | const config = { 86 | storeName: 'Nama Toko Contoh', 87 | auth_username: '#', 88 | auth_token: '#', 89 | baseQrString: '#', 90 | logoPath: './logo-agin.png' 91 | }; 92 | 93 | const qrisGen = new QRISGenerator(config, 'theme1'); 94 | const paymentChecker = new PaymentChecker({ 95 | auth_token: config.auth_token, 96 | auth_username: config.auth_username 97 | }); 98 | const receiptGen = new ReceiptGenerator(config); 99 | 100 | async function main() { 101 | const amount = 50000; 102 | const qrString = qrisGen.generateQrString(amount); 103 | const qrBuffer = await qrisGen.generateQRWithLogo(qrString); 104 | fs.writeFileSync('qris.png', qrBuffer); 105 | 106 | const paymentResult = await paymentChecker.checkPaymentStatus('REF123', amount); 107 | if (paymentResult.success && paymentResult.data.status === 'PAID') { 108 | const receipt = await receiptGen.generateReceipt(paymentResult.data); 109 | console.log('Receipt generated:', receipt.filePath); 110 | } 111 | } 112 | 113 | main(); 114 | ``` 115 | 116 | ## Penggunaan dengan Tema 117 | 118 | ### Tema yang Tersedia 119 | 120 | 1. **Theme 1 (Default)**: QRIS dengan aksen warna biru 121 | 2. **Theme 2 (Meta Style)**: QRIS dengan aksen warna meta 122 | 123 | ### Contoh Penggunaan Tema 124 | 125 | ```javascript 126 | const { QRISGenerator } = require('autoft-qris'); 127 | const fs = require('fs'); 128 | 129 | const config = { 130 | storeName: 'Nama Toko Contoh', 131 | auth_username: '#', 132 | auth_token: '#', 133 | baseQrString: '#', 134 | logoPath: './logo-agin.png' 135 | }; 136 | 137 | const qrGenerator1 = new QRISGenerator(config, 'theme1'); 138 | const qrString1 = qrGenerator1.generateQrString(50000); 139 | const qrBuffer1 = await qrGenerator1.generateQRWithLogo(qrString1); 140 | fs.writeFileSync('qris-theme1.png', qrBuffer1); 141 | 142 | const qrGenerator2 = new QRISGenerator(config, 'theme2'); 143 | const qrString2 = qrGenerator2.generateQrString(50000); 144 | const qrBuffer2 = await qrGenerator2.generateQRWithLogo(qrString2); 145 | fs.writeFileSync('qris-theme2.png', qrBuffer2); 146 | 147 | const qrGenerator = new QRISGenerator(config, 'theme1'); 148 | qrGenerator.setTheme('theme2'); 149 | 150 | const themes = QRISGenerator.getAvailableThemes(); 151 | console.log(themes); 152 | ``` 153 | 154 | ## Penggunaan Complete Example 155 | 156 | ```javascript 157 | const { QRISGenerator, PaymentChecker, ReceiptGenerator } = require('autoft-qris'); 158 | const fs = require('fs'); 159 | 160 | const config = { 161 | storeName: 'Nama Toko Contoh', 162 | auth_username: '#', 163 | auth_token: '#', 164 | baseQrString: '#', 165 | logoPath: './logo-agin.png' 166 | }; 167 | 168 | const qrisGen = new QRISGenerator(config, 'theme1'); 169 | const paymentChecker = new PaymentChecker({ 170 | auth_token: config.auth_token, 171 | auth_username: config.auth_username 172 | }); 173 | const receiptGen = new ReceiptGenerator(config); 174 | 175 | async function main() { 176 | try { 177 | console.log('=== TEST REALTIME QRIS PAYMENT ===\n'); 178 | const randomAmount = Math.floor(Math.random() * 99) + 1; 179 | const amount = 100 + randomAmount; 180 | const reference = 'REF' + Date.now(); 181 | 182 | const qrString = qrisGen.generateQrString(amount); 183 | const qrBuffer = await qrisGen.generateQRWithLogo(qrString); 184 | fs.writeFileSync('qr.png', qrBuffer); 185 | 186 | console.log('=== TRANSACTION DETAILS ==='); 187 | console.log('Reference:', reference); 188 | console.log('Amount:', amount); 189 | console.log('QR Image:', 'qr.png'); 190 | console.log('\nSilakan scan QR code dan lakukan pembayaran'); 191 | console.log('\nMenunggu pembayaran...\n'); 192 | 193 | const startTime = Date.now(); 194 | const timeout = 5 * 60 * 1000; 195 | 196 | while (Date.now() - startTime < timeout) { 197 | const result = await paymentChecker.checkPaymentStatus(reference, amount); 198 | if (result.success && result.data.status === 'PAID') { 199 | console.log('✓ Pembayaran berhasil!'); 200 | 201 | const receipt = await receiptGen.generateReceipt(result.data); 202 | console.log('✓ Bukti transaksi:', receipt.filePath); 203 | return; 204 | } 205 | await new Promise(resolve => setTimeout(resolve, 3000)); 206 | console.log('Menunggu pembayaran...'); 207 | } 208 | throw new Error('Timeout: Pembayaran tidak diterima dalam 5 menit'); 209 | } catch (error) { 210 | console.error('Error:', error.message); 211 | } 212 | } 213 | 214 | main(); 215 | ``` 216 | 217 | ## API Reference 218 | 219 | ### QRISGenerator 220 | 221 | ```javascript 222 | const qrisGen = new QRISGenerator(config, theme) 223 | 224 | qrisGen.generateQrString(amount) 225 | await qrisGen.generateQRWithLogo(qrString) 226 | qrisGen.calculateCRC16(str) 227 | qrisGen.setTheme(theme) 228 | qrisGen.getCurrentTheme() 229 | QRISGenerator.getAvailableThemes() 230 | ``` 231 | 232 | ### PaymentChecker 233 | 234 | ```javascript 235 | const paymentChecker = new PaymentChecker(config) 236 | 237 | await paymentChecker.checkPaymentStatus(reference, amount) 238 | await paymentChecker.checkSaldo() 239 | ``` 240 | 241 | ### ReceiptGenerator 242 | 243 | ```javascript 244 | const receiptGen = new ReceiptGenerator(config) 245 | 246 | await receiptGen.generateReceipt(transactionData) 247 | ``` 248 | 249 | ## Cek Saldo 250 | 251 | ```javascript 252 | const paymentChecker = new PaymentChecker({ 253 | auth_token: 'your_token', 254 | auth_username: 'your_username' 255 | }); 256 | 257 | const saldo = await paymentChecker.checkSaldo(); 258 | if (saldo.success) { 259 | console.log('Saldo:', saldo.data.saldo); 260 | } 261 | ``` 262 | 263 | ## Module Support 264 | 265 | Package ini mendukung both ESM dan CommonJS: 266 | 267 | - **ESM**: Menggunakan `.mjs` files dan `import` statements 268 | - **CommonJS**: Menggunakan `.cjs` files dan `require()` statements 269 | - **Auto-detect**: Package otomatis mendeteksi module system yang digunakan 270 | 271 | ## Node.js Version Compatibility 272 | 273 | Package ini akan menampilkan warning jika menggunakan Node.js 21+ karena masalah kompatibilitas dengan chalk package. Recommended menggunakan Node.js 20.18.3 LTS. 274 | 275 | ## Konfigurasi API 276 | 277 | Package ini menggunakan API OrderKuota untuk cek status pembayaran. Pastikan Anda memiliki: 278 | 279 | - `auth_username`: Username autentikasi 280 | - `auth_token`: Token autentikasi 281 | 282 | **Untuk mendapatkan kredensial API, hubungi [@AutoFtBot69](https://t.me/AutoFtBot69)** 283 | 284 | ## FAQ 285 | 286 | **Q: Apakah receipt bisa custom logo dan nama toko?** 287 | A: Bisa, cukup atur `logoPath` dan `storeName` di config. 288 | 289 | **Q: Apakah receipt otomatis dibuat saat pembayaran sukses?** 290 | A: Ya, receipt PDF otomatis dibuat dan path-nya bisa diambil dari `paymentResult.receipt.filePath`. 291 | 292 | **Q: Apakah bisa polling pembayaran lebih cepat/lebih lama?** 293 | A: Bisa, atur parameter `interval` dan `maxAttempts` pada fungsi polling. 294 | 295 | **Q: Bagaimana cara mendapatkan kredensial API OrderKuota?** 296 | A: Hubungi [@AutoFtBot69](https://t.me/AutoFtBot69) untuk mendapatkan username dan token autentikasi. 297 | 298 | **Q: Apakah support ESM dan CommonJS?** 299 | A: Ya, package ini fully support both module systems dengan auto-detection. 300 | 301 | ## Requirements 302 | 303 | - Node.js >= 20.18.3 LTS (recommended) 304 | - Canvas support untuk image generation 305 | 306 | ## Contributors 307 | 308 | - **AutoFTbot** - Original author & maintainer 309 | - **AlfiDev** - ESM/CommonJS dual support contributor 310 | - GitHub: [github.com/cloudkuimages](https://github.com/cloudkuimages) 311 | - Telegram: [@cloudkudev](https://t.me/cloudkudev) 312 | 313 | ## Kontribusi 314 | 315 | Pull request sangat diterima! 316 | Buka issue untuk diskusi fitur/bug sebelum submit PR. 317 | 318 | ## Support 319 | 320 | Jika ada pertanyaan, silakan buka [issue di GitHub](https://github.com/AutoFTbot/Qris-OrderKuota/issues) 321 | 322 | ## Repository 323 | 324 | [GitHub Repository](https://github.com/AutoFTbot/Qris-OrderKuota) 325 | 326 | ## License 327 | 328 | MIT # AutoFT QRIS Generator 329 | 330 | Package untuk generate QRIS dengan 2 tema (Biru & Hijau) dan cek payment status secara realtime dengan API OrderKuota. 331 | 332 | **Updated by AlfiDev as contributor - Version 0.0.7** 333 | 334 | ## Features 335 | 336 | - ✨ Dual module support (ESM & CommonJS) 337 | - 🎨 2 tema QR code yang dapat disesuaikan 338 | - 🏷️ Logo support pada QR code 339 | - 🔒 CRC16 checksum validation 340 | - 📱 QRIS format support untuk Indonesia 341 | 342 | ## Installation 343 | 344 | ```bash 345 | npm install autoft-qris 346 | ``` 347 | 348 | ## Usage 349 | 350 | ### ESM (ES Modules) 351 | 352 | ```javascript 353 | import { QRISGenerator } from 'autoft-qris'; 354 | 355 | const config = { 356 | baseQrString: 'your_base_qris_string_here', 357 | logoPath: './path/to/logo.png' // optional 358 | }; 359 | 360 | const qrisGen = new QRISGenerator(config, 'theme1'); 361 | 362 | const amount = 50000; 363 | const qrString = qrisGen.generateQrString(amount); 364 | const qrImage = await qrisGen.generateQRWithLogo(qrString); 365 | 366 | console.log('QR String:', qrString); 367 | ``` 368 | 369 | ### CommonJS 370 | 371 | ```javascript 372 | const { QRISGenerator } = require('autoft-qris'); 373 | 374 | const config = { 375 | baseQrString: 'your_base_qris_string_here', 376 | logoPath: './path/to/logo.png' // optional 377 | }; 378 | 379 | const qrisGen = new QRISGenerator(config, 'theme2'); 380 | 381 | const amount = 50000; 382 | const qrString = qrisGen.generateQrString(amount); 383 | const qrImage = await qrisGen.generateQRWithLogo(qrString); 384 | 385 | console.log('QR String:', qrString); 386 | ``` 387 | 388 | ### Available Themes 389 | 390 | ```javascript 391 | // Get available themes 392 | const themes = QRISGenerator.getAvailableThemes(); 393 | console.log(themes); 394 | 395 | // Switch theme 396 | qrisGen.setTheme('theme2'); 397 | console.log('Current theme:', qrisGen.getCurrentTheme()); 398 | ``` 399 | 400 | ### Individual Theme Classes 401 | 402 | #### ESM Import 403 | 404 | ```javascript 405 | import QRISGeneratorTheme1 from 'autoft-qris/src/qr-generator.mjs'; 406 | import QRISGeneratorTheme2 from 'autoft-qris/src/qr-generator2.mjs'; 407 | ``` 408 | 409 | #### CommonJS Require 410 | 411 | ```javascript 412 | const QRISGeneratorTheme1 = require('autoft-qris/src/qr-generator.cjs'); 413 | const QRISGeneratorTheme2 = require('autoft-qris/src/qr-generator2.cjs'); 414 | ``` 415 | 416 | ## API Reference 417 | 418 | ### Constructor 419 | 420 | ```javascript 421 | new QRISGenerator(config, theme) 422 | ``` 423 | 424 | - `config` (Object): Configuration object 425 | - `baseQrString` (String): Base QRIS string (required) 426 | - `logoPath` (String): Path to logo image (optional) 427 | - `theme` (String): Theme selection ('theme1' or 'theme2', default: 'theme1') 428 | 429 | ### Methods 430 | 431 | #### `generateQrString(amount)` 432 | Generate QRIS string with specified amount. 433 | 434 | **Parameters:** 435 | - `amount` (Number): Payment amount 436 | 437 | **Returns:** String - Complete QRIS string with checksum 438 | 439 | #### `generateQRWithLogo(qrString)` 440 | Generate QR code image with optional logo. 441 | 442 | **Parameters:** 443 | - `qrString` (String): QRIS string to encode 444 | 445 | **Returns:** Promise - PNG image buffer 446 | 447 | #### `calculateCRC16(str)` 448 | Calculate CRC16 checksum for QRIS string. 449 | 450 | **Parameters:** 451 | - `str` (String): String to calculate checksum for 452 | 453 | **Returns:** String - 4-character uppercase hex checksum 454 | 455 | #### `setTheme(theme)` 456 | Switch between themes. 457 | 458 | **Parameters:** 459 | - `theme` (String): 'theme1' or 'theme2' 460 | 461 | #### `getCurrentTheme()` 462 | Get current active theme. 463 | 464 | **Returns:** String - Current theme name 465 | 466 | #### `static getAvailableThemes()` 467 | Get list of available themes. 468 | 469 | **Returns:** Array - Available themes with descriptions 470 | 471 | ## Module Support 472 | 473 | This package supports both ESM and CommonJS: 474 | 475 | - **ESM**: Uses `.mjs` files and `import` statements 476 | - **CommonJS**: Uses `.cjs` files and `require()` statements 477 | - **Automatic**: Package automatically detects your module system 478 | 479 | ## Requirements 480 | 481 | - Node.js >= 20.18.3 482 | - Canvas support for image generation 483 | 484 | ## License 485 | 486 | MIT 487 | 488 | ## Contributors 489 | 490 | - **AutoFTbot** - Original author 491 | - **AlfiDev** - ESM/CommonJS dual support contributor 492 | 493 | ## Repository 494 | 495 | [GitHub Repository](https://github.com/AutoFTbot/Qris-OrderKuota) 496 | --------------------------------------------------------------------------------