Cloudflare Pages 403 Error for Stripe Webhook

For Workes & Pages, what is the name of the domain?

https://backpackbrawlpro.com

What is the error number?

403

What is the error message?

{ "truncated": false, "outcome": "ok", "scriptName": "pages-worker--3234905-production", "diagnosticsChannelEvents": [], "exceptions": [], "logs": [], "eventTimestamp": 1724742568231, "event": { "request": { "url": "https://backpackbrawlpro.com/api/payment-webhook", "method": "POST", "headers": { "accept": "*/*; q=0.5, application/xml", "accept-encoding": "gzip, br", "cache-control": "no-cache", "cf-connecting-ip": "54.187.205.235", "cf-connecting-o2o": "1", "cf-ipcountry": "US", "cf-ray": "8b9a3c7b3a1e2844", "cf-visitor": "{\"scheme\":\"https\"}", "connection": "Keep-Alive", "content-length": "3160", "content-type": "application/json; charset=utf-8", "host": "backpackbrawlpro.com", "stripe-signature": "t=1724742568,v1=bf3bd1ff13d98e675605e7c5ef709eed0065231696d1ba231d71023295e49e99,v0=50a95da2b6382bf492f4a7887679a1d915ddcb229167c1992b88d578e83ef1f0", "user-agent": "Stripe/1.0 (+https://stripe.com/docs/webhooks)", "x-forwarded-for": "54.187.205.235", "x-forwarded-proto": "https", "x-real-ip": "54.187.205.235" }, "cf": { "longitude": "-119.72570", "httpProtocol": "HTTP/1.1", "tlsCipher": "AEAD-AES256-GCM-SHA384", "continent": "NA", "asn": 16509, "clientAcceptEncoding": "gzip", "country": "US", "verifiedBotCategory": "Webhooks", "tlsClientAuth": { "certIssuerDNLegacy": "", "certIssuerSKI": "", "certSubjectDNRFC2253": "", "certSubjectDNLegacy": "", "certFingerprintSHA256": "", "certNotBefore": "", "certSKI": "", "certSerial": "", "certIssuerDN": "", "certVerified": "NONE", "certNotAfter": "", "certSubjectDN": "", "certPresented": "0", "certRevoked": "0", "certIssuerSerial": "", "certIssuerDNRFC2253": "", "certFingerprintSHA1": "" }, "tlsClientHelloLength": "", "tlsVersion": "TLSv1.3", "city": "Boardman", "timezone": "America/Los_Angeles", "tlsClientExtensionsSha1": "", "region": "Oregon", "edgeRequestKeepAliveStatus": 1, "requestPriority": "", "latitude": "45.82340", "postalCode": "97818", "tlsClientRandom": "", "regionCode": "OR", "asOrganization": "Amazon.com", "metroCode": "810", "colo": "SEA", "pagesHostName": "backpackbrawl.pages.dev", "botManagement": { "corporateProxy": false, "verifiedBot": false, "jsDetection": { "passed": false }, "staticResource": false, "detectionIds": {}, "score": 99 } } }, "response": { "status": 403 } }, "id": 6 }

What is the issue or error you’re encountering

My Stripe webhooks (after a succesfull payment) get a 403 error on Cloudflare Pages.

What steps have you taken to resolve the issue?

I’ve added a custom WAF rule to Skip WAF features for the specific webhook URL & I’ve added a rule to allow the IP address of Stripe.

Screenshot of the error

It looks like it’s your Worker returning 403, WAF isn’t stopping it - it’s hitting the Worker (Pages Function) and then returning

This is what my Stripe webhook code looks like. I would expect to always see " console.log(‘[Webhook] Received POST request’);" in the logs, but it does not show up. Do you see anything wrong with my code?

export const prerender = false;
import type { APIRoute } from "astro";
import Stripe from 'stripe';

export const POST: APIRoute = async ({ request, locals }) => {
  console.log('[Webhook] Received POST request');

  const stripe = new Stripe(locals.runtime.env.STRIPE_SECRET_KEY, {
    apiVersion: '2024-06-20',
  });

  const sig = request.headers.get('stripe-signature');
  const body = await request.text();

  try {
    const event = stripe.webhooks.constructEvent(
      body,
      sig,
      locals.runtime.env.STRIPE_WEBHOOK_SECRET
    );

    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        // Handle successful payment
        break;
      // ... handle other event types
      default:
        console.log(`Unhandled event type ${event.type}`);
    }

    return new Response(JSON.stringify({ received: true }), {
      status: 200,
      headers: { 'Content-Type': 'application/json' }
    });
  } catch (err) {
    console.error(`Webhook Error: ${err.message}`);
    return new Response(JSON.stringify({ error: err.message }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' }
    });
  }
};