const express = require('express'); const paypalService = require('../services/paypal'); const woocommerceService = require('../services/woocommerce'); const router = express.Router(); // PayPal webhook handler router.post('/paypal', async (req, res) => { try { const webhookBody = req.body; const headers = req.headers; console.log('PayPal Webhook Received:', { event_type: webhookBody.event_type, resource_id: webhookBody.resource?.id, timestamp: new Date().toISOString() }); // Verify webhook signature (simplified for development) const isValid = paypalService.verifyWebhookSignature(headers, webhookBody, process.env.PAYPAL_WEBHOOK_ID); if (!isValid) { console.warn('Invalid PayPal webhook signature'); return res.status(401).json({ error: 'Invalid signature' }); } // Handle different webhook events switch (webhookBody.event_type) { case 'PAYMENT.CAPTURE.COMPLETED': await handlePaymentCaptured(webhookBody.resource); break; case 'PAYMENT.CAPTURE.DENIED': await handlePaymentDenied(webhookBody.resource); break; case 'PAYMENT.CAPTURE.REFUNDED': await handlePaymentRefunded(webhookBody.resource); break; default: console.log('Unhandled PayPal webhook event:', webhookBody.event_type); } res.status(200).json({ status: 'success' }); } catch (error) { console.error('PayPal Webhook Error:', error); res.status(500).json({ error: 'Webhook processing failed' }); } }); // Handle payment captured async function handlePaymentCaptured(resource) { try { console.log('Processing payment capture webhook:', { capture_id: resource.id, amount: resource.amount?.value, custom_id: resource.custom_id }); const customId = resource.custom_id; if (!customId) { console.warn('No custom_id found in payment capture'); return; } // Extract WooCommerce order ID from custom_id const wcOrderId = parseInt(customId); if (isNaN(wcOrderId)) { console.warn('Invalid WooCommerce order ID in custom_id:', customId); return; } // Prepare payment data const paymentData = { transaction_id: resource.id, payer: { email_address: resource.payer?.email_address || 'N/A' } }; // Update WooCommerce order const result = await woocommerceService.completePayment(wcOrderId, paymentData); if (result.success) { console.log('Payment capture webhook processed successfully'); } else { console.error('Failed to update WooCommerce order from webhook:', result.error); } } catch (error) { console.error('Handle Payment Captured Error:', error); } } // Handle payment denied async function handlePaymentDenied(resource) { try { console.log('Processing payment denied webhook:', { capture_id: resource.id, custom_id: resource.custom_id }); const customId = resource.custom_id; if (!customId) { console.warn('No custom_id found in payment denial'); return; } const wcOrderId = parseInt(customId); if (isNaN(wcOrderId)) { console.warn('Invalid WooCommerce order ID in custom_id:', customId); return; } // Mark order as failed const result = await woocommerceService.failPayment(wcOrderId, 'Payment was denied by PayPal'); if (result.success) { console.log('Payment denial webhook processed successfully'); } else { console.error('Failed to update WooCommerce order from denial webhook:', result.error); } } catch (error) { console.error('Handle Payment Denied Error:', error); } } // Handle payment refunded async function handlePaymentRefunded(resource) { try { console.log('Processing payment refund webhook:', { refund_id: resource.id, amount: resource.amount?.value, custom_id: resource.custom_id }); const customId = resource.custom_id; if (!customId) { console.warn('No custom_id found in payment refund'); return; } const wcOrderId = parseInt(customId); if (isNaN(wcOrderId)) { console.warn('Invalid WooCommerce order ID in custom_id:', customId); return; } // Add refund note to WooCommerce order const noteText = `Payment refunded via PayPal. Refund ID: ${resource.id}. Amount: ${resource.amount?.value} ${resource.amount?.currency_code}`; await woocommerceService.addOrderNote(wcOrderId, noteText, true); console.log('Payment refund webhook processed successfully'); } catch (error) { console.error('Handle Payment Refunded Error:', error); } } // Health check for webhooks router.get('/health', (req, res) => { res.json({ status: 'OK', service: 'webhooks', timestamp: new Date().toISOString() }); }); module.exports = router;