const express = require('express'); const crypto = require('crypto'); const bodyParser = require('body-parser'); const nodemailer = require('nodemailer'); const app = express(); app.use(bodyParser.json()); // Temporary storage for order tracking const orderTracking = new Map(); // Email configuration const transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 465, secure: true, // use SSL auth: { user: 'skelltechofficial@gmail.com', pass: 'rpymwovddmzfitdp' } }); // Function to send success email with retry logic async function sendSuccessEmail(email, orderId, amount, redemptionCode, retryCount = 0) { const maxRetries = 5; const retryDelay = 3000; // 3 seconds between retries try { console.log(`Attempt ${retryCount + 1} to send email to:`, email); console.log('Email details:', { orderId, amount, redemptionCode }); // Verify transporter configuration await transporter.verify(); console.log('SMTP connection verified successfully'); const result = await transporter.sendMail({ from: '"TypeGPT" ', to: email, subject: 'Your Recharge Code Is Ready! 🎉', text: `Your payment of $${amount} for order ${orderId} has been processed successfully.\nRedemption Code: ${redemptionCode}`, html: `

Payment Successful! 🎉

Dear Customer,

Thank you for your purchase! Your payment has been successfully processed.

Your Redemption Code:

${redemptionCode}

Transaction Details:

Order ID: ${orderId}

Amount Paid: $${amount}

API Credits: $${amount * 25}

Important:

  • Keep this code safe - it's your access to the API credits
  • The code can only be used once
  • If you have any issues, please contact our support team
Top Up Balance
` }); console.log('Email sent successfully:', result); return result; } catch (error) { console.error('Failed to send email:', error); console.error('Error details:', { code: error.code, command: error.command, response: error.response }); if (retryCount < maxRetries) { console.log(`Retrying in ${retryDelay/1000} seconds... (Attempt ${retryCount + 2}/${maxRetries + 1})`); await new Promise(resolve => setTimeout(resolve, retryDelay)); return sendSuccessEmail(email, orderId, amount, redemptionCode, retryCount + 1); } throw new Error(`Failed to send email after ${maxRetries + 1} attempts`); } } // Add function to generate order ID function generateOrderId() { const randomNum = Math.random().toString().slice(2, 18); // Get 16 digits return `hrmn-${randomNum}`; } // Update the merchant key constant const MERCHANT_KEY = '3H896K-W3LZEF-H4H957-ZDF5S4'; // Add the function to create redemption code async function createRedemptionCode(orderId, amount) { console.log('Creating redemption code...'); const quota = 25 * amount * 500000; // $1 = 500000 quota try { const response = await fetch('https://niansuh-redeem.hf.space/api/create', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'sk-niansuhaiburewala521' }, body: JSON.stringify({ username: 'admin', name: Math.random().toString(36).substring(2, 12), // Random name quota: quota, count: 1 }) }); const result = await response.json(); console.log('Redemption code created'); if (result.success && result.data?.data?.[0]) { return result.data.data[0]; // Return the redemption code } else { throw new Error('Invalid response format from redemption code API'); } } catch (error) { console.log('Failed to create redemption code:', error); throw error; } } // Update the webhook handler const webhookHandler = { validateHmacSignature(postData, hmacHeader, type) { const apiKey = MERCHANT_KEY; // Use the same key consistently const calculatedHmac = crypto .createHmac('sha512', apiKey) .update(postData) .digest('hex'); return calculatedHmac === hmacHeader; }, handleWaitingPayment(data) { console.log('Payment waiting'); }, handleConfirmingPayment(data) { console.log('Payment confirming'); }, async handlePaidPayment(data) { console.log('Payment received for order:', data.orderId); const orderData = orderTracking.get(data.orderId); if (orderData) { const { email, amount } = orderData; console.log(`Processing payment for email: ${email}, amount: $${amount}`); try { // Create redemption code and send email const redemptionCode = await createRedemptionCode(data.orderId, amount); console.log(`Generated redemption code for order ${data.orderId}: ${redemptionCode}`); try { await sendSuccessEmail(email, data.orderId, amount, redemptionCode); console.log(`Successfully sent email to ${email} with code: ${redemptionCode}`); } catch (emailError) { // Log failed email send but don't throw error console.error(`⚠️ FAILED EMAIL SEND - IMPORTANT DATA:`); console.error(`Email: ${email}`); console.error(`Order ID: ${data.orderId}`); console.error(`Amount: $${amount}`); console.error(`Redemption Code: ${redemptionCode}`); console.error(`Error:`, emailError); } console.log('Payment process completed'); } catch (error) { console.error(`❌ CRITICAL ERROR processing order ${data.orderId}:`, error); } finally { // Clean up stored data orderTracking.delete(data.orderId); } } else { console.error(`❌ No order data found for order ID: ${data.orderId}`); } }, handleExpiredPayment(data) { console.log('Payment expired'); }, handleCompletePayout(data) { console.log('Payout complete'); } }; // Serve the HTML directly from root endpoint app.get('/', (req, res) => { const html = `

Recharge Balance

Add funds to your account

You will receive \${{ amount * 25 }} in API credits

A redemption code will be sent to your email after payment.

Please make sure to enter a valid email address!

`; res.send(html); }); // Update payment creation endpoint app.post('/create-payment', async (req, res) => { const { email, amount } = req.body; if (!email || !amount) { return res.status(400).json({ error: 'Email and amount are required' }); } const baseUrl = `${req.protocol}://${req.get('host')}`; const orderId = generateOrderId(); // Store email with orderId orderTracking.set(orderId, { email, amount, timestamp: Date.now() }); const paymentData = { merchant: MERCHANT_KEY, // Use the same key here amount: amount, currency: "USD", lifeTime: 15, feePaidByPayer: 1, underPaidCover: "", callbackUrl: `${baseUrl}/callback`, returnUrl: "https://harmon.tr", description: "", orderId: orderId, email: "" }; try { const response = await fetch('https://harmon.com.tr/cp.php?endpoint=/merchants/request', { method: 'POST', headers: { 'accept': '*/*', 'content-type': 'application/json', 'origin': 'https://harmon.com.tr', 'referer': 'https://harmon.com.tr/payment?id=create', 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/131.0.0.0' }, body: JSON.stringify(paymentData) }); const responseData = await response.json(); res.json(responseData); } catch (error) { console.error('Error creating payment:', error); orderTracking.delete(orderId); res.status(500).json({ error: 'Failed to create payment' }); } }); // Update the callback endpoint app.post('/callback', (req, res) => { console.log('Callback received:', { headers: req.headers, body: req.body, method: req.method }); if (req.method !== 'POST') { console.log('Invalid request method:', req.method); return res.status(200).send('ok'); } const hmacHeader = req.headers['hmac']; if (!hmacHeader) { console.log('Missing HMAC signature'); return res.status(200).send('ok'); } const postData = JSON.stringify(req.body); let data; try { data = JSON.parse(postData); } catch (error) { console.log('Invalid JSON data:', error); return res.status(200).send('ok'); } // Validate HMAC signature if (!webhookHandler.validateHmacSignature(postData, hmacHeader, data.type)) { console.log('Invalid HMAC signature:', { received: hmacHeader, data: postData }); return res.status(200).send('ok'); } // Process different payment statuses switch (data.status) { case 'Waiting': webhookHandler.handleWaitingPayment(data); break; case 'Confirming': webhookHandler.handleConfirmingPayment(data); break; case 'Paid': webhookHandler.handlePaidPayment(data); break; case 'Expired': webhookHandler.handleExpiredPayment(data); break; case 'Complete': webhookHandler.handleCompletePayout(data); break; default: console.log('Unhandled status:', data.status, data); } return res.status(200).send('ok'); }); // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'healthy' }); }); // Start the server const PORT = process.env.PORT || 3002; app.listen(PORT, () => { console.log(`Payment server listening on port ${PORT}`); }); // Error handling - add this before the general error handler app.use((req, res, next) => { // Handle 404 errors res.redirect('/'); }); // General error handling app.use((err, req, res, next) => { console.error('Server error:', err); res.status(500).json({ error: 'Internal server error' }); }); // Cleanup old entries periodically (every hour) setInterval(() => { const oneHourAgo = Date.now() - (60 * 60 * 1000); for (const [orderId, data] of orderTracking.entries()) { if (data.timestamp < oneHourAgo) { orderTracking.delete(orderId); } } }, 60 * 60 * 1000);