Function Create & Cek Status
by Payku
15
Raw
const PAYKU_API_KEY = 'PAYKU_1234567890';
const PAYKU_SECRET_KEY = '11111aaaaa22222bbbbbb333333cccccccc';
const PAYKU_BASE_URL = 'https://payku.my.id';
const PREMIUM_PRICE = 15000;
const PAYMENT_TIMEOUT = 10 * 60 * 1000;
const pendingPayments = {};
function isPremium(userId) {
return !!botData.premium[userId];
}
async function createTransactionComplete(transactionData) {
const timestamp = Date.now().toString();
const payload = { ...transactionData, timestamp };
const sortedKeys = Object.keys(payload).sort();
const stringToSign = sortedKeys.map(k => `${k}=${payload[k]}`).join('&');
const signature = crypto.createHmac('sha256', PAYKU_SECRET_KEY).update(stringToSign).digest('hex');
try {
const response = await axios.post(`${PAYKU_BASE_URL}/api/create-transaction`, transactionData, {
headers: {
'x-api-key': PAYKU_API_KEY,
'x-signature': signature,
'x-timestamp': timestamp,
'Content-Type': 'application/json'
}
});
if (response.data && response.data.success) {
return {
success: true,
data: response.data.data,
message: response.data.message || 'Transaction created successfully'
};
} else {
throw new Error(response.data?.message || 'Unknown error from API');
}
} catch (error) {
if (error.response) {
const errorMsg = error.response.data?.message || error.response.statusText || 'API Error';
throw new Error(`API Error [${error.response.status}]: ${errorMsg}`);
} else if (error.request) {
throw new Error('Network Error: Unable to connect to payment gateway');
} else {
throw new Error(`Transaction failed: ${error.message}`);
}
}
}
async function createPayment(userId, chatId) {
try {
const timestamp = Date.now().toString();
const transactionData = {
external_id: `PREMIUM_${userId}_${timestamp}`,
amount: PREMIUM_PRICE,
description: "Premium Bot Access",
customer_name: `User ${userId}`,
customer_email: `user${userId}@telegram.bot`,
customer_phone: "08123456789", // Default phone or get from user data
webhook_url: process.env.WEBHOOK_URL || "https://your-bot-webhook.com/webhook"
};
const result = await createTransactionComplete(transactionData);
if (result.success && result.data) {
return {
success: true,
qrUrl: result.data.qris_url,
paymentUrl: result.data.payment_url,
transactionId: result.data.transaction_id,
externalId: transactionData.external_id
};
} else {
throw new Error(result.message || 'Failed to create transaction');
}
} catch (error) {
console.error('Error creating Payku payment:', error);
return {
success: false,
error: error.message || 'Gagal membuat pembayaran, coba lagi nanti'
};
}
}
async function checkPaymentStatus(transactionId) {
try {
const timestamp = Date.now().toString();
const payload = { transaction_id: transactionId, timestamp };
const sortedKeys = Object.keys(payload).sort();
const stringToSign = sortedKeys.map(k => `${k}=${payload[k]}`).join('&');
const signature = crypto.createHmac('sha256', PAYKU_SECRET_KEY).update(stringToSign).digest('hex');
const response = await axios.get(`${PAYKU_BASE_URL}/api/transaction/${transactionId}`, {
headers: {
'x-api-key': PAYKU_API_KEY,
'x-signature': signature,
'x-timestamp': timestamp
}
});
if (response.data && response.data.success && response.data.data) {
const transactionData = response.data.data;
return {
transaction_id: transactionData.transaction_id,
external_id: transactionData.external_id,
amount: transactionData.amount,
total_amount: transactionData.total_amount,
status: transactionData.status, // 'pending', 'paid', 'expired', 'cancelled'
created_at: transactionData.created_at,
expired_at: transactionData.expired_at,
paid_at: transactionData.paid_at,
payment_method: transactionData.payment_method,
transaction_ref: transactionData.transaction_ref
};
} else {
return null;
}
} catch (error) {
console.error('Error checking payment status:', error);
if (error.response) {
console.error('API Response Error:', error.response.data);
}
return null;
}
}
setInterval(async () => {
for (const [userId, payment] of Object.entries(pendingPayments)) {
if (Date.now() - payment.timestamp > PAYMENT_TIMEOUT) {
try {
await bot.deleteMessage(payment.chatId, payment.messageId);
} catch (e) {
console.log('Gagal menghapus pesan timeout:', e);
}
delete pendingPayments[userId];
continue;
}
const transactionStatus = await checkPaymentStatus(payment.transactionId);
if (transactionStatus) {
if (transactionStatus.status === 'paid') {
botData.premium[userId] = {
activated: new Date().toISOString(),
transactionId: payment.transactionId,
externalId: transactionStatus.external_id,
amount: transactionStatus.amount,
totalAmount: transactionStatus.total_amount,
paidAt: transactionStatus.paid_at,
paymentMethod: transactionStatus.payment_method,
transactionRef: transactionStatus.transaction_ref,
permanent: true
};
try {
await bot.editMessageText(
`✅ *PEMBAYARAN BERHASIL!*\n\n` +
`Anda sekarang memiliki akses *PREMIUM PERMANEN*.\n` +
`Seluruh konten premium sekarang dapat diakses.\n\n` +
`💳 *Detail Pembayaran:*\n` +
`• Transaction ID: ${transactionStatus.transaction_id}\n` +
`• Amount: Rp ${transactionStatus.amount.toLocaleString('id-ID')}\n` +
`• Total: Rp ${transactionStatus.total_amount.toLocaleString('id-ID')}\n` +
`• Method: ${transactionStatus.payment_method}\n` +
`• Paid: ${new Date(transactionStatus.paid_at).toLocaleString('id-ID')}`,
{
chat_id: payment.chatId,
message_id: payment.messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '🔓 LIHAT MEDIA PREMIUM', url: CHANNEL_LINK }],
[{ text: '💎 INFO PREMIUM', callback_data: 'premium_info' }]
]
}
}
);
} catch (e) {
console.log('Gagal update pesan pembayaran:', e);
}
simpanData();
delete pendingPayments[userId];
}
else if (transactionStatus.status === 'expired' || transactionStatus.status === 'cancelled') {
try {
await bot.editMessageText(
`❌ *PEMBAYARAN ${transactionStatus.status.toUpperCase()}*\n\n` +
`Transaksi telah ${transactionStatus.status === 'expired' ? 'kedaluwarsa' : 'dibatalkan'}.\n` +
`Silakan buat pembayaran baru untuk mengakses premium.\n\n` +
`Transaction ID: ${transactionStatus.transaction_id}`,
{
chat_id: payment.chatId,
message_id: payment.messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '🔄 BUAT PEMBAYARAN BARU', callback_data: 'create_payment' }]
]
}
}
);
} catch (e) {
console.log('Gagal update pesan pembayaran expired/cancelled:', e);
}
delete pendingPayments[userId];
}
}
}
}, 30000);
function handleWebhook(req, res) {
try {
const { transaction_id, status, external_id, amount, total_amount, payment_method, paid_at, transaction_ref } = req.body;
const userId = Object.keys(pendingPayments).find(uid =>
pendingPayments[uid].transactionId === transaction_id
);
if (userId && status === 'paid') {
const payment = pendingPayments[userId];
botData.premium[userId] = {
activated: new Date().toISOString(),
transactionId: transaction_id,
externalId: external_id,
amount: amount,
totalAmount: total_amount,
paidAt: paid_at,
paymentMethod: payment_method,
transactionRef: transaction_ref,
permanent: true
};
bot.editMessageText(
`✅ *PEMBAYARAN BERHASIL!*\n\n` +
`Anda sekarang memiliki akses *PREMIUM PERMANEN*.\n` +
`Seluruh konten premium sekarang dapat diakses.\n\n` +
`💳 *Detail Pembayaran:*\n` +
`• Transaction ID: ${transaction_id}\n` +
`• Amount: Rp ${amount.toLocaleString('id-ID')}\n` +
`• Total: Rp ${total_amount.toLocaleString('id-ID')}\n` +
`• Method: ${payment_method}\n` +
`• Paid: ${new Date(paid_at).toLocaleString('id-ID')}`,
{
chat_id: payment.chatId,
message_id: payment.messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '🔓 LIHAT MEDIA PREMIUM', url: CHANNEL_LINK }],
[{ text: '💎 INFO PREMIUM', callback_data: 'premium_info' }]
]
}
}
).catch(console.error);
simpanData();
delete pendingPayments[userId];
}
else if (userId && (status === 'expired' || status === 'cancelled')) {
const payment = pendingPayments[userId];
bot.editMessageText(
`❌ *PEMBAYARAN ${status.toUpperCase()}*\n\n` +
`Transaksi telah ${status === 'expired' ? 'kedaluwarsa' : 'dibatalkan'}.\n` +
`Silakan buat pembayaran baru untuk mengakses premium.\n\n` +
`Transaction ID: ${transaction_id}`,
{
chat_id: payment.chatId,
message_id: payment.messageId,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '🔄 BUAT PEMBAYARAN BARU', callback_data: 'create_payment' }]
]
}
}
).catch(console.error);
delete pendingPayments[userId];
}
res.status(200).json({ success: true });
} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ success: false, error: error.message });
}
}
async function getTransactionDetails(transactionId) {
try {
const transactionData = await checkPaymentStatus(transactionId);
if (transactionData) {
return {
success: true,
data: transactionData
};
} else {
return {
success: false,
error: 'Transaction not found'
};
}
} catch (error) {
return {
success: false,
error: error.message
};
}
}