Changing Crowns

Stripe Webhooks in WordPress (Nginx): Real Problems I Solved

Stripe Webhooks in WordPress (Nginx): Real Problems I Solved

Stripe Webhook Debugging – What Went Wrong & How I Fixed It

After hours of debugging a custom Stripe webhook in my WordPress plugin, I finally got it fully functional.

Here’s a breakdown of what went wrong — and how I fixed it — in case it helps another engineer avoid the wall I hit. 💥

✅ Problems I Ran Into & Fixes That Worked:

  1. Encrypted Emails + sanitize_email() ≠ Compatibility

    Using sanitize_email() strips symbols — which breaks encrypted strings.

    ✅ Instead, use sanitize_text_field() for encrypted data.

  2. Missing Stripe-Signature Header on Nginx

    Stripe needs this header to verify authenticity, but Nginx doesn’t pass it to PHP by default.

    fastcgi_pass_header Stripe-Signature;

    Apache fix:

    SetEnvIf Stripe-Signature \"(.*)\" HTTP_STRIPE_SIGNATURE=$1
  3. Metadata Not Mapping in PHP

    Stripe metadata arrives as an object.

    This doesn’t work:

    $m = (array) $session->metadata;

    ✅ Instead, use:

    $m = json_decode(json_encode($session->metadata), true);

    This ensures you get a proper associative array in all cases — and avoids Undefined array key warnings.

🧠 Takeaway

When building your own booking/payment system on WordPress, these low-level bugs are invisible until everything almost works. Be meticulous with header handling, data sanitization, and data type conversion — especially in Stripe’s webhooks.