Initial commit
This commit is contained in:
173
backend/routes/webhook.js
Normal file
173
backend/routes/webhook.js
Normal file
@@ -0,0 +1,173 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user