case 'trx': { const nomor = sender.split("@")[0]; const Data = JSON.parse(fs.readFileSync(pathUser)); const userProfile = Data.find((user) => user.nomor === nomor); if (!userProfile) return m.reply(`Kamu belum terdaftar, silahkan ketik : *Daftar* untuk bisa mengakses`); if (global.pendingTransactions && global.pendingTransactions[nomor]) { const pendingTrx = global.pendingTransactions[nomor]; let pendingMsg = `*TRANSAKSI MENUNGGU*\n\n`; pendingMsg += `*Produk:* ${pendingTrx.product.nama_layanan}\n`; pendingMsg += `*Jenis:* ${pendingTrx.product.kategori}\n`; pendingMsg += `*ID Game:* ${pendingTrx.customer_no}`; if (pendingTrx.customer_zone) pendingMsg += ` (${pendingTrx.customer_zone})`; pendingMsg += `\n`; if (pendingTrx.nickInfo && pendingTrx.nickInfo.success) { pendingMsg += `*Nickname:* ${pendingTrx.nickInfo.data.nickname}\n`; if (pendingTrx.nickInfo.data.region) { pendingMsg += `*Region:* ${pendingTrx.nickInfo.data.region}\n`; } } pendingMsg += `*Harga:* ${rupiah(pendingTrx.adjustedPrice)}\n\n`; pendingMsg += `Ketik *Y* untuk melanjutkan atau *N* untuk membatalkan`; return m.reply(pendingMsg); } if (args.length < 2) { const example = `Contoh penggunaan:\n` + `• *${command} MLH5 123456789 1234* (Mobile Legends)\n` + `• *${command} FF456 987654321* (Free Fire)\n` + `• *${command} PUBG789 555666777* (PUBG Mobile)\n` + `• *${command} GI999 111222333 os_asia* (Genshin Impact)`; return m.reply(`Format salah!\n\n${example}`); } const buyer_sku_code = args[0]; const productData = JSON.parse(fs.readFileSync('./db/datagz.json', 'utf8')); const product = productData.find(prod => prod.kode && prod.kode.toLowerCase() === buyer_sku_code.toLowerCase() ); if (!product) return m.reply(`❌ Produk dengan kode *${buyer_sku_code}* tidak ditemukan`); let customer_no, customer_zone; const hasServerInfo = args.length >= 3; if (hasServerInfo) { customer_no = args[1]; customer_zone = args.slice(2).join(' '); } else { customer_no = args[1]; customer_zone = ''; } const userData = JSON.parse(fs.readFileSync('./db/users.json')); const userSaldo = userData.find(saldo => saldo.nomor === nomor); if (!userSaldo) return m.reply(`❌ Kamu belum terdaftar, ketik *Daftar* untuk memulai`); try { const userRole = userData.find(role => role.nomor === nomor)?.role || 'BRONZE'; function calculatePrice(product, userRole) { const defaultMarkupPercentage = 0.015; let markupConfig; try { const markupData = fs.readFileSync('./db/markup.json', 'utf8'); markupConfig = JSON.parse(markupData); } catch (error) { console.error('Error loading markup configuration:', error); markupConfig = { bronze: 0.015, // 1.5% markup gold: 0.01, // 1% markup platinum: 0.005, // 0.5% markup owner: 0.001 // 0.1% markup }; } const originalPrice = parseFloat(product.harga); let markupPercentage = defaultMarkupPercentage; if (userRole === "GOLD") { markupPercentage = markupConfig.gold; } else if (userRole === "PLATINUM") { markupPercentage = markupConfig.platinum; } else if (userRole === "BRONZE") { markupPercentage = markupConfig.bronze; } else if (userRole === "OWNER") { markupPercentage = markupConfig.owner; } const increasedPrice = originalPrice * (1 + markupPercentage); return Math.round(increasedPrice); } const adjustedPrice = calculatePrice(product, userRole); let nickInfo = null; if (product.kategori.toLowerCase().includes('ml') || product.kategori.toLowerCase().includes('mobile legends')) { nickInfo = await checkNickname('mobile legends', customer_no, customer_zone); } else if (product.kategori.toLowerCase().includes('ff') || product.kategori.toLowerCase().includes('free fire')) { nickInfo = await checkNickname('free fire', customer_no); } else if (product.kategori.toLowerCase().includes('pubg')) { nickInfo = await checkNickname('pubg', customer_no); } if (nickInfo && !nickInfo.success && nickInfo.message.includes("404")) { return m.reply(`❌ *ID Game tidak ditemukan*\n\nMohon periksa kembali ID Game yang dimasukkan.`); } const trxPreview = generateTransactionPreview( product, customer_no, customer_zone, adjustedPrice, nickInfo ); await xstbot.sendMessage(m.chat, { text: trxPreview }, { quoted: m }); savePendingTransaction( nomor, buyer_sku_code, customer_no, customer_zone, product, adjustedPrice, userSaldo, userData, nickInfo ); } catch (error) { console.error('Transaction Error:', error); if (error.toString().includes("Request failed with status code 404")) { return m.reply(`❌ *ID Game tidak valid*\n\nMohon periksa kembali ID Game yang dimasukkan.`); } else { m.reply('⚠️ Terjadi kesalahan saat memproses transaksi. Silakan coba lagi.'); } } } break; // ========================================================= case 'y': { const nomor = sender.split("@")[0]; if (!global.pendingTransactions || !global.pendingTransactions[nomor]) { return m.reply(`Tidak ada transaksi yang menunggu konfirmasi.`); } const transaction = global.pendingTransactions[nomor]; delete global.pendingTransactions[nomor]; const { product, customer_no, customer_zone, adjustedPrice, userSaldo, userData, nickInfo } = transaction; let modalPrice = product.harga || 0; if (!userSaldo.saldo || userSaldo.saldo < adjustedPrice) { return m.reply(`Total saldo kamu (${rupiah(userSaldo.saldo || 0)}) tidak cukup untuk transaksi senilai ${rupiah(adjustedPrice)}.\n\nSilakan isi saldo terlebih dahulu.`); } else { userSaldo.saldo -= adjustedPrice; fs.writeFileSync('./db/users.json', JSON.stringify(userData, null, 2)); await processGZStoreTransaction(); } async function processGZStoreTransaction() { const ref_id = Invoice(); // Menggunakan fungsi Invoice() untuk generate invoice const apikey = global.GriezSt; try { let invo = `*── 「 TRANSAKSI PROSES 」 ──*\n\n`; invo += `> *Produk :* ${product.nama_layanan}\n`; invo += `> *Kategori :* ${product.kategori}\n`; invo += `> *Tujuan :* ${customer_no}${customer_zone ? ' ' + customer_zone : ''}\n`; if (nickInfo && nickInfo.success) { invo += `> *Nickname :* ${nickInfo.data.nickname}\n`; if (nickInfo.data.region) { invo += `> *Region :* ${nickInfo.data.region}\n`; } } invo += `> *Harga :* ${rupiah(adjustedPrice)}\n`; invo += `> *Invoice :* ${ref_id}\n`; await xstbot.sendText(m.chat, invo, m); const requestBody = { api_key: apikey, user_id: customer_no, zone: customer_zone || '', service: product.kode, quantity: "1", kontak: "6285380779466" }; const orderResponse = await axios.post( 'https://gzstore.id/api/v1/Order', requestBody, { headers: { 'Content-Type': 'application/json' } } ); console.log("GZ Store Order Response:", orderResponse.data); if (!orderResponse.data || !orderResponse.data.status || !orderResponse.data.data || !orderResponse.data.data.id) { userSaldo.saldo += adjustedPrice; fs.writeFileSync('./db/users.json', JSON.stringify(userData, null, 2)); return m.reply(orderResponse.data?.message || "Gagal memproses pesanan"); } const orderId = orderResponse.data.data.id; let transactionCompleted = false; // Real-time status checking - tanpa batasan retry while (!transactionCompleted) { await new Promise(resolve => setTimeout(resolve, 5000)); // Polling setiap 5 detik try { const statusResponse = await axios.post( 'https://gzstore.id/api/v1/status', { api_key: apikey, order_id: orderId }, { headers: { 'Content-Type': 'application/json' } } ); console.log("GZ Store Status Response:", statusResponse.data); if (!statusResponse.data || !statusResponse.data.status || !statusResponse.data.data) { continue; // Lanjutkan polling jika respons tidak valid } const statusData = statusResponse.data.data; if (statusData && statusData.status) { // Transaksi sukses if (statusData.status === 'Success') { let responseMsg = `*── 「 TRANSAKSI SUKSES 」 ──*\n\n`; responseMsg += `*» Produk :* ${statusData.layanan || product.nama_layanan}\n`; responseMsg += `*» Kategori :* ${product.kategori}\n`; responseMsg += `*» Tujuan :* ${statusData.user_id || customer_no}${statusData.zone ? ' ' + statusData.zone : (customer_zone ? ' ' + customer_zone : '')}\n`; const displayUsername = (statusData.username && statusData.username !== '-') ? statusData.username : (nickInfo && nickInfo.success ? nickInfo.data.nickname : ""); if (displayUsername) { responseMsg += `*» Nickname :* ${displayUsername}\n`; if (nickInfo && nickInfo.success && nickInfo.data.region) { responseMsg += `*» Region :* ${nickInfo.data.region}\n`; } } responseMsg += `*» Harga :* ${rupiah(adjustedPrice)}\n`; responseMsg += `*» Invoice :* ${ref_id}\n`; if (statusData.keterangan) { responseMsg += `*» Info :* ${statusData.keterangan}\n`; } await xstbot.sendMessage(m.chat, { text: responseMsg }, { quoted: m }); // Simpan transaksi sukses saveTransaction( nomor, "Berhasil", ref_id, statusData.layanan || product.nama_layanan, product.kategori, "00", statusData.user_id || customer_no, statusData.zone || customer_zone || "", displayUsername, adjustedPrice, product.harga, nickInfo && nickInfo.success ? nickInfo.data.region : null ); transactionCompleted = true; break; } // Status gagal else if ( statusData.status === 'Cancelled' || statusData.status === 'Canceled' || statusData.status === 'Failed' || statusData.status === 'Error' ) { const failedInvoice = Invoice(); let responseMsg = `*── 「 TRANSAKSI GAGAL 」 ──*\n\n`; responseMsg += `Pesananmu *${statusData.layanan || product.nama_layanan}* Gagal\n`; responseMsg += `Kategori: *${product.kategori}*\n`; responseMsg += `Tujuan: *${statusData.user_id || customer_no}${statusData.zone ? ' ' + statusData.zone : (customer_zone ? ' ' + customer_zone : '')}*\n`; // Tambahkan nickname jika ada, dari status atau pengecekan awal const displayUsername = (statusData.username && statusData.username !== '-') ? statusData.username : (nickInfo && nickInfo.success ? nickInfo.data.nickname : ""); if (displayUsername) { responseMsg += `Nickname: *${displayUsername}*\n`; // Tambahkan region jika tersedia dari pengecekan awal if (nickInfo && nickInfo.success && nickInfo.data.region) { responseMsg += `Region: *${nickInfo.data.region}*\n`; } } responseMsg += `Invoice: *${failedInvoice}*\n`; responseMsg += `Pesan: ${statusData.keterangan || "Terjadi kesalahan pada sistem"}\n\n`; responseMsg += `Saldo telah dikembalikan ke akun Anda.`; await xstbot.sendMessage(m.chat, { text: responseMsg }, { quoted: m }); // Kembalikan saldo userSaldo.saldo += adjustedPrice; fs.writeFileSync('./db/users.json', JSON.stringify(userData, null, 2)); // Simpan transaksi gagal saveTransaction( nomor, "Gagal", failedInvoice, statusData.layanan || product.nama_layanan, product.kategori, "99", statusData.user_id || customer_no, statusData.zone || customer_zone || "", displayUsername, adjustedPrice, product.harga, nickInfo && nickInfo.success ? nickInfo.data.region : null ); transactionCompleted = true; break; } // Status masih pending atau processing - lanjutkan polling tanpa memberikan respon else if (statusData.status === 'Pending' || statusData.status === 'Processing') { console.log(`Order ${orderId} masih ${statusData.status}. Menunggu perubahan status...`); continue; } // Status yang tidak dikenali - tetap lanjutkan polling else { console.log(`Status tidak dikenali: ${statusData.status}. Menunggu perubahan status...`); continue; } } } catch (error) { console.log("Error checking order status:", error); // Terus mencoba jika terjadi error pada pengecekan await new Promise(resolve => setTimeout(resolve, 10000)); // Tunggu lebih lama jika terjadi error } } } catch (error) { console.log("Transaction processing error:", error); m.reply("Terjadi kesalahan saat memproses transaksi. Silakan coba lagi nanti."); // Kembalikan saldo jika terjadi error userSaldo.saldo += adjustedPrice; fs.writeFileSync('./db/users.json', JSON.stringify(userData, null, 2)); } } // Fungsi untuk menyimpan transaksi ke file trx.json function saveTransaction(nomor, status, invoice, item, category, rc, tujuan, zone, username, harga, harga_modal, region = null) { try { let transactions = []; if (fs.existsSync("./db/trx.json")) { const rawData = fs.readFileSync("./db/trx.json", "utf8"); transactions = JSON.parse(rawData); } const newTransaction = { nomor: nomor, status: status, invoice: invoice, item: item, category: category, rc: rc, tujuan: `${tujuan}${zone ? ' ' + zone : ''}`, username: username, region: region, harga: harga, harga_modal: harga_modal, waktu: `${time1} | ${hariini}` }; transactions.push(newTransaction); fs.writeFileSync("./db/trx.json", JSON.stringify(transactions, null, 2)); return true; } catch (error) { console.error("Error saving transaction:", error); return false; } } } break case 'n': { const nomor = sender.split("@")[0]; if (!global.pendingTransactions || !global.pendingTransactions[nomor]) { return m.reply(`Tidak ada transaksi yang menunggu konfirmasi.`); } const transaction = global.pendingTransactions[nomor]; delete global.pendingTransactions[nomor]; return m.reply(`Transaksi dibatalkan. Terima kasih.`); } break; // =========================================================