Saweria Top-Up ( Game Mobile opsional)
JavaScriptPublicby zx-apiAug 10, 2026, 04:53 AMExpires: Never274 views
1/**
2 * Name: Saweria Top-Up Game ( Opsional Game ML )
3 * Bisa Di Ganti Game ya, streamerId wajib di isi supaya saldo komisi nya masuk ke saweria kita , cara dapatin nya tinggal cek di Saweria nya buat seperti pesanan palsu dan cek log request ya biasanya ada
4 * Credit By Zx
5 *
6 * Sumber: https://whatsapp.com/channel/0029VbDLqe7EquiSF4STU13o
7 * Kalau Mau Di Sher Jangan hapus sumber / Credit nya
8**/
9
10const axios = require('axios');
11const QRCode = require('qrcode');
12const path = require('path');
13
14class SaweriaAutomation {
15 constructor(username = 'zixvorx') {
16 this.username = username;
17 this.streamerId = ''; // ( wajib: supaya qris nya masuk ke qris donasi kita ambil dsri request dsri Saweria)
18
19 this.backend = axios.create({
20 baseURL: 'https://backend.saweria.co',
21 headers: {
22 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
23 'Accept': 'application/json, text/plain, */*',
24 'Content-Type': 'application/json',
25 'Origin': 'https://saweria.co',
26 'Referer': `https://saweria.co/${this.username}/toko-top-up/mobile-legends-bang-bang`
27 },
28 timeout: 15000
29 });
30 }
31
32 // AMBIL PRODUK
33 async getProducts(gameSlug = 'mobile-legends-bang-bang') {
34 const res = await this.backend.get(`/game-vouchers/${gameSlug}`, {
35 params: { streamer_id: this.streamerId, username: this.username }
36 });
37 return res.data.data.game_vouchers.products
38 .filter(p => p.status === 'ACTIVE')
39 .map(p => ({
40 id: p.product_id,
41 sku: p.sku,
42 name: p.product_name,
43 slug: p.slug,
44 sellingPrice: Number(p.pricing.selling_price),
45 donationAmount: Number(p.donation_amount),
46 thumbnail: p.image.thumbnail,
47 vat: p.vat?.rate || 0
48 }));
49 }
50
51 // HITUNG FEE
52 async calculateFee(amount, paymentType = 'qris', message = 'pesanan') {
53 const res = await this.backend.post(
54 `/game-vouchers/${this.username}/calculate_pg_amount`,
55 { amount: Number(amount), payment_type: paymentType, message: String(message) }
56 );
57 return res.data.data;
58 }
59
60 // BUAT ORDER
61 async createOrder({
62 product,
63 userId = '1151655541', // id akun game
64 zoneId = '13664', <zone id akun ml > ( bisa berubah kapan aja ๐ฟ๐น)
65 donatorEmail = 'pribadiarep@gmail.com',
66 donatorName = 'zixvorx',
67 message = 'pesanan 1'
68 }) {
69 const feeData = await this.calculateFee(product.sellingPrice, 'qris', message);
70
71 const payload = {
72 product_id: product.id,
73 product_sku: String(product.sku),
74 amount: Number(product.sellingPrice),
75 payment_type: 'qris',
76 vat: product.vat,
77 vatAmount: feeData.vat_amount || 0,
78 message: String(message),
79 digital_form: [
80 { key: "userId", value: String(userId) },
81 { key: "zoneId", value: String(zoneId) }
82 ],
83 customer_info: {
84 first_name: String(donatorName).trim(),
85 email: String(donatorEmail).trim(),
86 phone: ""
87 }
88 };
89
90 try {
91 const res = await this.backend.post(`/game-vouchers/snap/${this.streamerId}`, payload);
92
93 return {
94 orderId: res.data.data.id,
95 amount: res.data.data.amount,
96 status: res.data.data.status,
97 qrString: res.data.data.etc.qr_string,
98 expiredAt: res.data.data.etc.payment_expired_at,
99 productName: res.data.data.etc.game_voucher.product_name
100 };
101 } catch (err) {
102 console.error('\n๐ด Detail Error Create Order:', err.response?.data || err.message);
103 throw new Error(`Gagal buat order: ${err.response?.statusText || err.message}`);
104 }
105 }
106
107 // FORMAT WAKTU
108 formatWaktu(dateString, pakaiPukul = false) {
109 const date = new Date(dateString);
110 const bulanArr = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'];
111 const bulanArrFull = ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'];
112
113 const tgl = date.getDate();
114 const bln = pakaiPukul ? bulanArrFull[date.getMonth()] : bulanArr[date.getMonth()];
115 const thn = date.getFullYear();
116 const jam = String(date.getHours()).padStart(2, '0');
117 const mnt = String(date.getMinutes()).padStart(2, '0');
118
119 if (pakaiPukul) {
120 return `${tgl} ${bln} ${thn} pukul ${jam}.${mnt} WIB`;
121 }
122 return `${tgl} ${bln} ${thn}, ${jam}.${mnt} WIB`;
123 }
124
125 hitungSisaWaktu(expiredString) {
126 const expired = new Date(expiredString).getTime();
127 const sekarang = new Date().getTime();
128 const selisih = expired - sekarang;
129 if (selisih <= 0) return "Kedaluwarsa";
130 const menit = Math.floor(selisih / (1000 * 60));
131 const detik = Math.floor((selisih % (1000 * 60)) / 1000);
132 return `${menit}m ${detik}d`;
133 }
134
135 // GENERATE GAMBAR QRIS
136 async generateQRImage(qrString, orderId) {
137 const fileName = `QRIS_${orderId.split('-')[0]}.png`;
138 const filePath = path.join(__dirname, fileName);
139 await QRCode.toFile(filePath, qrString, {
140 color: { dark: '#000000', light: '#FFFFFF' },
141 width: 400,
142 margin: 2
143 });
144 return fileName;
145 }
146
147 // LACAK ORDER & TAMPILKAN HASIL
148 async trackOrder(orderId) {
149 try {
150 const res = await this.backend.get(`/game-vouchers/tracking-order/${orderId}`);
151 const data = res.data.data;
152
153 const berlakuHingga = this.formatWaktu(data.expired_at, true);
154 const tanggalDibuat = this.formatWaktu(data.created_at, false);
155
156 let tanggalDiselesaikan = "-";
157 let statusPengiriman = "Belum Diproses";
158
159 if (data.status === 'SUCCESS' || data.payment_status === 'PAID' || data.payment_status === 'SETTLED') {
160 statusPengiriman = "Berhasil";
161 tanggalDiselesaikan = this.formatWaktu(data.payment_updated_at, false);
162 }
163
164 let outputText = `Berlaku Hingga: ${berlakuHingga}\n\n`;
165 outputText += `${this.hitungSisaWaktu(data.expired_at)}\n\n`;
166 outputText += `Dukungan untuk ${data.username}: Rp${data.amount_raw.toLocaleString('id-ID')}\n\n`;
167 outputText += `ID: ${data.id}\n\n`;
168 outputText += `Detail Transaksi\n\n`;
169 outputText += `Status pengiriman\n\n${statusPengiriman}\n\n`;
170 outputText += `Tanggal dibuat\n\n${tanggalDibuat}\n\n`;
171 outputText += `Tanggal diselesaikan\n\n${tanggalDiselesaikan}`;
172
173 console.log(outputText);
174
175 if (data.etc && data.etc.qr_string) {
176 const savedFile = await this.generateQRImage(data.etc.qr_string, data.id);
177 console.log(`\n=========================================`);
178 console.log(`โ
String QRIS berhasil diconvert menjadi gambar!`);
179 console.log(`๐ File tersimpan sebagai: ${savedFile}`);
180 console.log(`=========================================\n`);
181 return { success: true, text: outputText, qrPath: savedFile, data };
182 } else {
183 console.log(`\nโ ๏ธ QR String tidak ditemukan, pesanan mungkin sudah dibayar atau kedaluwarsa.`);
184 return { success: false, text: outputText, message: "QR String tidak ada", data };
185 }
186 } catch (err) {
187 console.error('โ Gagal melacak pesanan:', err.message);
188 return { success: false, message: err.message };
189 }
190 }
191}
192
193async function main() {
194 const scraper = new SaweriaAutomation('zixvorx');
195
196 try {
197 console.log('๐ฎ [1/5] Mengambil produk...');
198 const products = await scraper.getProducts();
199 const product = products[0];
200 console.log(` โ
Dipilih: ${product.name} (Rp${product.sellingPrice.toLocaleString('id-ID')})`);
201
202 console.log('\n๐ฐ [2/5] Menghitung biaya...');
203 const fee = await scraper.calculateFee(product.sellingPrice);
204 console.log(` โ
Total Bayar: Rp${fee.amount_to_pay.toLocaleString('id-ID')} (Fee: Rp${fee.pg_fee.toLocaleString('id-ID')})`);
205
206 console.log('\n๐ [3/5] Membuat pesanan QRIS...');
207 const order = await scraper.createOrder({
208 product: product,
209 userId: '1151655541', // ID game emel kalian
210 zoneId: '13664', // ini zona id emel kalian ( bisa bisa sesuaikan dengan game yang di pilih )
211 donatorEmail: 'zixvorx@gmail.com', // Gmail Akun Saweria kalian
212 donatorName: 'zixvorx', // username Saweria Pukimak Kalian๐น
213 message: 'pesanan 1'
214 });
215
216 console.log(` โ
Order ID : ${order.orderId}`);
217 console.log(` โ
Total : Rp${order.amount.toLocaleString('id-ID')}`);
218 console.log(` โ
Expired : ${new Date(order.expiredAt).toLocaleString('id-ID')}`);
219 console.log(` โ
Status : ${order.status}`);
220
221 console.log('\n๐ [4/5] Melacak pesanan & mengambil data QRIS...\n');
222 const trackResult = await scraper.trackOrder(order.orderId);
223
224 if (trackResult.success) {
225 console.log('๐ก [5/5] Selesai! Buka file gambar QRIS yang tersimpan di folder project dan scan menggunakan e-wallet kamu.');
226 } else {
227 console.log('โ ๏ธ Gagal mendapatkan QRIS. Silakan cek log di atas.');
228 }
229
230 } catch (err) {
231 console.error('\nโ ERROR FATAL:', err.message);
232 }
233}
234
235main();
236236 linesยท9,274 charsยท9.1 KB
WwrapยทFfullscreen