Case v1 - Javascript
by PayKu
16
Raw
case 'qris2': {
const CONFIG = {
apiKey: 'PAYKU_1234567890', // Apikey
secretKey: '11111aaaaa22222bbbbb33333ccccc44444dddddd55555eeeee',
baseURL: 'https://payku.my.id',
minAmount: 1000, // minimal deposit
maxChecks: 10,
checkInterval: 5000
};
if (!global.activeTransactions) {
global.activeTransactions = new Map();
}
const generateSignature = (data, secretKey) => {
const sortedKeys = Object.keys(data).sort();
const stringToSign = sortedKeys.map(k => `${k}=${data[k]}`).join('&');
return crypto.createHmac('sha256', secretKey).update(stringToSign).digest('hex');
};
const createHeaders = (data, timestamp) => {
const signature = generateSignature(data, CONFIG.secretKey);
return {
'x-api-key': CONFIG.apiKey,
'x-signature': signature,
'x-timestamp': timestamp,
'Content-Type': 'application/json'
};
};
const sanitizeUserId = (userId) => userId.replace(/[^0-9]/g, '');
const createTransaction = async (nominal, userId, pushname) => {
const timestamp = Date.now().toString();
const sanitizedUserId = sanitizeUserId(userId);
const transactionData = {
external_id: `BOT-${sanitizedUserId}`,
amount: nominal,
description: `Top Up QRIS Rp${nominal.toLocaleString()}`,
customer_name: pushname || userId.split('@')[0],
customer_email: `${sanitizedUserId}@gmail.com`,
customer_phone: sanitizedUserId,
timestamp
};
const headers = createHeaders(transactionData, timestamp);
try {
const response = await axios.post(`${CONFIG.baseURL}/api/create-transaction`, transactionData, { headers });
if (!response.data.success) {
throw new Error(response.data.message || 'Gagal membuat transaksi');
}
return response.data.data;
} catch (error) {
throw new Error(`API Error: ${error.response?.data?.message || error.message}`);
}
};
const checkTransactionStatus = async (transactionId) => {
const timestamp = Date.now().toString();
const data = { transaction_id: transactionId, timestamp };
const headers = createHeaders(data, timestamp);
try {
const response = await axios.get(`${CONFIG.baseURL}/api/transaction/${transactionId}`, { headers });
if (!response.data.success) {
throw new Error(response.data.message || 'Gagal mengecek status transaksi');
}
return response.data.data;
} catch (error) {
throw new Error(`API Error: ${error.response?.data?.message || error.message}`);
}
};
const cancelTransaction = async (transactionId) => {
const timestamp = Date.now().toString();
const data = { transaction_id: transactionId, timestamp };
const headers = createHeaders(data, timestamp);
try {
const response = await axios.post(`${CONFIG.baseURL}/api/transaction/${transactionId}/cancel`, {}, { headers });
if (!response.data.success) {
throw new Error(response.data.message || 'Gagal membatalkan transaksi');
}
return response.data.message;
} catch (error) {
throw new Error(`API Error: ${error.response?.data?.message || error.message}`);
}
};
const formatQRISMessage = (transaction) => {
return `✅ *QRIS Siap Digunakan*
• ID: ${transaction.transaction_id}
• Nominal: Rp${transaction.amount.toLocaleString()}
• Fee: Rp${transaction.fee.toLocaleString()}
• Total Bayar: Rp${transaction.total_amount.toLocaleString()}
📥 Klik untuk bayar via QRIS
🔗 ${transaction.qris_url}
_Selama belum dibayar, bot akan cek otomatis..._
_Ketik "cancel" untuk membatalkan pembayaran._`;
};
const formatSuccessMessage = (statusData) => {
return `✅ *Pembayaran Berhasil!*
• Nominal yang akan ditambahkan: Rp${statusData.amount.toLocaleString()}
• Total Dibayar: Rp${statusData.total_amount.toLocaleString()}
• Metode: ${statusData.payment_method}
• Dibayar: ${statusData.paid_at}
*Catatan:* Fee adalah pajak layanan dan tidak ditambahkan ke saldo Anda.`;
};
const pollPaymentStatus = async (transactionId, userId) => {
let status = 'pending';
let checkCount = 0;
while (status === 'pending' && checkCount < CONFIG.maxChecks) {
await new Promise(resolve => setTimeout(resolve, CONFIG.checkInterval));
if (!global.activeTransactions.has(userId)) {
console.log(`Transaction ${transactionId} was cancelled by user`);
return false;
}
try {
const statusData = await checkTransactionStatus(transactionId);
status = statusData.status;
checkCount++;
if (status === 'paid') {
global.activeTransactions.delete(userId);
await Ditss.sendMessage(m.chat, {
text: formatSuccessMessage(statusData)
}, { quoted: m });
return true;
}
} catch (error) {
console.error(`Error checking status (attempt ${checkCount + 1}):`, error);
checkCount++;
}
}
if (status !== 'paid' && global.activeTransactions.has(userId)) {
global.activeTransactions.delete(userId);
await Ditss.sendMessage(m.chat, {
text: `⚠️ Pembayaran belum diterima setelah ${CONFIG.maxChecks} kali pengecekan. QRIS telah expired.`
}, { quoted: m });
}
return false;
};
if (!text) return m.reply('❌ Format salah!\n\nContoh:\n• .qris2 15000\n• Ketik "cancel" untuk membatalkan');
if (text.toLowerCase() === 'cancel') {
const userId = m.sender;
const activeTransaction = global.activeTransactions.get(userId);
if (!activeTransaction) {
return m.reply('❌ Tidak ada transaksi QRIS yang sedang aktif untuk dibatalkan.');
}
try {
const message = await cancelTransaction(activeTransaction.transactionId);
global.activeTransactions.delete(userId);
m.reply(`✅ Transaksi berhasil dibatalkan dan QR QRIS telah dihapus!\n\n${message}`);
} catch (error) {
console.error('Cancel transaction error:', error);
global.activeTransactions.delete(userId);
m.reply(`⚠️ QR QRIS telah dihapus. ${error.message}`);
}
break;
}
if (text.startsWith('cancel ')) {
const transactionId = text.split(' ')[1];
if (!transactionId) {
return m.reply('❌ Masukkan ID transaksi yang ingin dibatalkan.\nContoh: .qris2 cancel TRX123456');
}
try {
const message = await cancelTransaction(transactionId);
global.activeTransactions.delete(m.sender);
m.reply(`✅ ${message}`);
} catch (error) {
console.error('Cancel transaction error:', error);
m.reply(`❌ Gagal membatalkan transaksi: ${error.message}`);
}
break;
}
const nominal = parseInt(text);
if (isNaN(nominal) || nominal < CONFIG.minAmount) {
return m.reply(`❌ Masukkan nominal minimal Rp${CONFIG.minAmount.toLocaleString()}\nContoh: .qris2 15000`);
}
if (global.activeTransactions.has(m.sender)) {
const activeTransaction = global.activeTransactions.get(m.sender);
return m.reply(`❌ Anda masih memiliki transaksi QRIS yang aktif!\n\nID: ${activeTransaction.transactionId}\nNominal: Rp${activeTransaction.amount.toLocaleString()}\n\nKetik "cancel" untuk membatalkan transaksi sebelumnya, atau tunggu hingga selesai.`);
}
try {
const transaction = await createTransaction(nominal, m.sender, pushname);
global.activeTransactions.set(m.sender, {
transactionId: transaction.transaction_id,
amount: transaction.amount,
createdAt: Date.now()
});
await Ditss.sendMessage(m.chat, {
image: { url: transaction.qris_url },
caption: formatQRISMessage(transaction)
}, { quoted: m });
pollPaymentStatus(transaction.transaction_id, m.sender).catch(error => {
console.error('Polling payment status error:', error);
global.activeTransactions.delete(m.sender);
});
} catch (error) {
console.error('Create transaction error:', error);
m.reply(`❌ Gagal membuat transaksi: ${error.message}`);
}
}
break;