TRXGZ
by P
17
Raw
// ========================================
// Respon konfirmasi transaksi
function generateTransactionPreview(product, customerId, zoneId, price) {
let preview = `*KONFIRMASI TRANSAKSI*\n\n`;
preview += `*Produk:* ${product.nama_layanan}\n`;
preview += `*Jenis:* ${product.kategori}\n`;
preview += `*ID:* ${customerId}`;
if (zoneId) preview += ` (${zoneId})`;
preview += `\n`;
preview += `*Harga:* ${rupiah(price)}\n\n`;
preview += `> Apakah data di atas sudah benar?\n`;
preview += `> Ketik *Y* untuk konfirmasi\n> Ketik *N* untuk membatalkan`;
return preview;
}
function savePendingTransaction(
nomor,
buyer_sku_code,
customer_no,
customer_zone,
product,
adjustedPrice,
userSaldo,
userData
) {
if (!global.pendingTransactions) global.pendingTransactions = {};
global.pendingTransactions[nomor] = {
buyer_sku_code,
customer_no,
customer_zone,
product,
adjustedPrice,
userSaldo,
userData,
timestamp: Date.now()
};
for (const userNomor in global.pendingTransactions) {
const trx = global.pendingTransactions[userNomor];
if (Date.now() - trx.timestamp > 5 * 60 * 1000) {
delete global.pendingTransactions[userNomor];
}
}
}
function generateUniqueRefID() {
const timestamp = new Date().getTime().toString();
const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
return `TRX${timestamp}${random}`;
}
function calculatePrice(product, userRole) {
const originalPrice = parseFloat(product.price);
let markupPercentage = defaultMarkupPercentage;
switch(userRole) {
case "GOLD":
markupPercentage = markupConfig.gold;
break;
case "PLATINUM":
markupPercentage = markupConfig.platinum;
break;
case "BRONZE":
markupPercentage = markupConfig.bronze;
break;
case "OWNER":
markupPercentage = markupConfig.owner;
break;
default:
markupPercentage = defaultMarkupPercentage;
}
const increasedPrice = originalPrice * (1 + markupPercentage);
return Math.round(increasedPrice);
}
// =====================================================================
// validasi nickname game
async function checkNickname(game, userId, zoneId = null) {
try {
let nickname = null;
let region = null;
let apiUrl = '';
if (game.toLowerCase().includes('ml') || game.toLowerCase().includes('mobile legends')) {
// Mobile Legends
apiUrl = `https://ceknickname.com/api/mlbb/region?userId=${userId}&zoneId=${zoneId || ''}`;
} else if (game.toLowerCase().includes('ff') || game.toLowerCase().includes('free fire')) {
// Free Fire
apiUrl = `https://ceknickname.com/api/free-fire-region?id=${userId}`;
} else if (game.toLowerCase().includes('pubg')) {
// PUBG Mobile
apiUrl = `https://ceknickname.com/api/game/pubg-mobile-global-vc?id=${userId}`;
} else {
// Jika Game tidak terdeteksi
return { success: false, message: "Game tidak didukung untuk cek nickname" };
}
const response = await axios.get(apiUrl);
if (response.data && response.data.status) {
if (game.toLowerCase().includes('ml') || game.toLowerCase().includes('mobile legends')) {
nickname = response.data.data.nickname;
region = response.data.data.region;
} else if (game.toLowerCase().includes('ff') || game.toLowerCase().includes('free fire')) {
nickname = response.data.result.username;
region = response.data.result.region;
} else if (game.toLowerCase().includes('pubg')) {
nickname = response.data.data.username;
region = null;
}
return {
success: true,
data: {
nickname: nickname,
region: region
}
};
} else {
return {
success: false,
message: "Nickname tidak ditemukan",
statusCode: response.status || "Unknown"
};
}
} catch (error) {
const statusCode = error.response?.status || "Unknown";
return {
success: false,
message: `Error checking nickname: ${error.message}`,
statusCode: statusCode
};
}
}
// =====================================================================
function generateTransactionPreview(product, customer_no, customer_zone, adjustedPrice, nickInfo = null) {
let preview = `╭───═[ *DETAIL TRANSAKSI* ]═─────⋆\n`;
preview += `│╭───────────────···\n`;
preview += `││» *Produk:* ${product.nama_layanan}\n`;
preview += `││» *Jenis:* ${product.kategori}\n`;
preview += `││» *ID Game:* ${customer_no}`;
if (customer_zone) preview += ` (${customer_zone})`;
preview += `\n`;
if (nickInfo && nickInfo.success) {
preview += `││» *Nickname:* ${nickInfo.data.nickname}\n`;
if (nickInfo.data.region) {
preview += `││» *Region:* ${nickInfo.data.region}\n`;
}
}
preview += `││» *Harga:* ${rupiah(adjustedPrice)}\n`;
preview += `│╰───────────────···\n`;
preview += `│ Ketik *Y* untuk menkonfirmasi.\n`;
preview += `│ Ketik *N* untuk membatalkan.\n`;
preview += `╰─────────────────────⋆`;
return preview;
}
function savePendingTransaction(nomor, buyer_sku_code, customer_no, customer_zone, product, adjustedPrice, userSaldo, userData, nickInfo = null) {
if (!global.pendingTransactions) {
global.pendingTransactions = {};
}
global.pendingTransactions[nomor] = {
buyer_sku_code,
customer_no,
customer_zone,
product,
adjustedPrice,
userSaldo,
userData,
nickInfo
};
setTimeout(() => {
if (global.pendingTransactions && global.pendingTransactions[nomor]) {
delete global.pendingTransactions[nomor];
}
}, 6 * 60 * 1000); // 5 menit
}
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;
// =========================================================