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
        };
    }
}