Troubleshooting

Guide to resolving common webhook issues like signature verification, SSL certificate problems, rate limiting, and order retrieval.

Common Issues

1. Signature Verification Fails

Symptoms:

  • 401 Unauthorized errors
  • Signature verification fails

Debugging Steps:

function debugSignatureVerification(payload, signature, privateKeyPath) {
  console.log('=== Debugging Signature Verification ===');
  console.log('Payload length:', payload.length);
  console.log('Payload snippet:', payload.substring(0, 100));
  console.log('Signature:', signature.substring(0, 50) + '...');
  
  try {
    const privateKey = fs.readFileSync(privateKeyPath, 'utf8');
    const publicKey = crypto.createPublicKey(privateKey);
    const signatureBuffer = Buffer.from(signature, 'base64');
    const verifier = crypto.createVerify('SHA256');
    verifier.update(payload);
    const isValid = verifier.verify({
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      saltLength: crypto.constants.RSA_PSS_SALTLEN_AUTO
    }, signatureBuffer);
    return isValid;
  } catch (error) {
    console.error('Verification error:', error.message);
    return false;
  }
}

Common Causes:

  • Incorrect private key
  • Payload altered before verification
  • Signature encoding issues

Solutions:

  • Use the correct private key
  • Verify with raw body buffer
  • Ensure proper base64 decoding

2. Endpoint SSL Certificate Issues

Check SSL Certificate:

const https = require('https');
const url = require('url');

function checkSSLCertificate(webhookUrl) {
  const parsedUrl = url.parse(webhookUrl);
  const options = { hostname: parsedUrl.hostname, port: 443, method: 'GET' };

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      const cert = res.socket.getPeerCertificate();
      const now = new Date();
      const validTo = new Date(cert.valid_to);
      if (validTo < now) {
        console.log('❌ Certificate expired!');
      } else {
        console.log('✅ Certificate valid');
      }
      resolve(cert);
    });

    req.on('error', (error) => reject(error));
    req.end();
  });
}

Test Webhook Endpoint:

async function testWebhookEndpoint(url) {
  try {
    const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ test: true }) });
    if (response.ok || response.status === 405) {
      console.log('✅ Endpoint accessible');
    } else {
      console.log('❌ Endpoint not accessible');
    }
  } catch (error) {
    console.error('❌ Endpoint test failed:', error.message);
  }
}

3. Rate Limiting Issues

Symptoms:

  • Delayed or failed webhooks
  • HTTP 429 responses

Solutions:

  • Optimize processing time
  • Implement queuing

Monitor Rate Limits:

async function checkRateLimits() {
  const response = await fetch('https://backend.sa.amwal.tech/api/webhook-endpoints/', { method: 'HEAD', headers: { 'X-API-Key': 'YOUR_API_KEY_FINGERPRINT' } });
  console.log('Rate Limit Headers:', response.headers.get('X-RateLimit-Limit'), response.headers.get('X-RateLimit-Remaining'), response.headers.get('X-RateLimit-Reset'));
}

4. Order Not Found

Debugging Steps:

async function debugOrderLookup(webhookPayload) {
  const orderData = webhookPayload.data;
  const lookupMethods = [
    { name: 'Amwal ID', url: `https://your-api.com/orders/search?amwal_id=${orderData.id}` },
    { name: 'Merchant Order ID', url: `https://your-api.com/orders/${orderData.merchant_order_id}` },
    { name: 'Ref ID', url: `https://your-api.com/orders/search?ref_id=${orderData.ref_id}` }
  ];

  for (const method of lookupMethods) {
    try {
      const response = await fetch(method.url);
      if (response.ok) {
        console.log(`✅ Order found using ${method.name}`);
        return await response.json();
      }
    } catch (error) {
      console.error(`Error looking up by ${method.name}:`, error);
    }
  }
  console.log('Order not found');
  return null;
}