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:
-
Encrypted Emails + sanitize_email() ≠ Compatibility
Using
sanitize_email()strips symbols — which breaks encrypted strings.✅ Instead, use
sanitize_text_field()for encrypted data. -
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 -
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 keywarnings.
🧠 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.