Mailen kom en søndag morgen, videresendt af driftsdirektøren for en europæisk almennyttig fond med en enkelt linje: se venligst nedenfor til orientering og handling. Nedenunder var en automatisk besked fra Stripe. Den havde i flere dage ikke kunnet levere webhook-hændelser til fondens donationsside, nitten forsøg var fejlet, og hvis intet ændrede sig, ville Stripe helt stoppe med at sende notifikationer til det endpoint inden for en uge.
For en velgørenhedsorganisation, der modtager enkeltdonationer og månedlige donationer via WordPress, er det ikke en kosmetisk advarsel. Webhooks er den måde, hjemmesiden får at vide, at en betaling faktisk lykkedes. Uden dem bliver donationer stående som pending, donorerne får ikke deres kvitteringer, og månedlige fornyelser bliver aldrig registreret, selvom pengene bliver ved med at komme ind i Stripe.
Dette er historien om, hvordan vi sporede fejlen, hvorfor det første problem, vi fandt, var reelt, men ikke årsagen, og den lille ændring, der rettede det uden at slå nogen af sidens sikkerhedsfunktioner fra.
Hvad en Stripe-webhook gør, og hvorfor en fejl betyder noget
Når en donor betaler, sendes browseren til Stripe og tilbage. Hjemmesiden kan ikke stole på, hvad browseren siger om betalingen, så Stripe kalder også siden direkte, server til server, med en hændelse som payment_intent.succeeded. Siden skal svare med en HTTP-status mellem 200 og 299. Alt andet tæller som en fejl, og Stripe prøver igen med stigende mellemrum i op til tre dage, før den giver op på den hændelse.
I dette tilfælde var donationspluginet GiveWP, som lytter på en adresse, der ender på ?give-listener=stripe. Siden er flersproget, så der var to aktive endpoints, et under /de/ and one under /fr/. Begge fejlede, selvom Stripes mail kun nævnte det ene.

Første fund: et reelt problem, men ikke årsagen
WordPress-dashboardet viste med det samme en aktiveringsfejl. Udvidelsen Recurring Donations var blevet slået fra, fordi den krævede en nyere version af GiveWP-hovedpluginet end den installerede. Udvidelsen var blevet opdateret, kernepluginet ikke, og WordPress havde i stilhed deaktiveret udvidelsen. Dens licens var også sat til ikke at blive fornyet, så den havde ikke længere fået opdateringer.
Det lignede en perfekt forklaring, og det var værd at rette under alle omstændigheder. Vi tog en fuld backup, opdaterede GiveWP og genaktiverede udvidelsen. Sidens forside gik prompte ned med en fatal fejl. Stakspor pegede på en popup, der indlejrede en gammel shortcode til en donationsformular, og udvidelsen til tilbagevendende donationer kunne ikke håndtere en formular, den ikke kunne finde. Vi deaktiverede udvidelsen for at få siden op igen, rettede popuppen, genaktiverede den og tjekkede forsiden, donationssiden og alle sprogversioner.
Siden var sund igen, og muligheden for månedlige donationer var tilbage. Webhooks fejlede stadig.
Læs den faktiske fejl i stedet for at gætte
Den hurtigste måde at stoppe med at gætte på er at åbne én fejlet levering i Stripe-dashboardet under Developers, Webhooks og læse to ting: HTTP-statuskoden og svarets indhold. Her var status 403 Forbidden, og indholdet var slet ikke en WordPress-fejl. Det var en HTML-side med titlen Just a moment…, der indlæste scripts fra challenges.cloudflare.com.

Den side er Cloudflares browserudfordring. Den beder den besøgendes browser bevise, at den er et menneske, før forespørgslen sendes videre. En person i Chrome klarer den på et sekund. Stripes servere er ikke en browser og kan ikke køre udfordringen, så hver webhook blev stoppet ved kanten. Forespørgslen nåede aldrig WordPress, og derfor dukkede intet op i sidens logs.
Find ud af, hvilken Cloudflare-funktion der blokerede Stripe
Cloudflare kan udfordre trafik fra flere funktioner, og løsningen afhænger af, hvilken der er ansvarlig. I zonens visning Security, Analytics, Events filtrerede vi på query string give-listener. Hver matchende forespørgsel viste handlingen Managed Challenge og tjenesten Security level.

Den samme liste viste noget andet, der er værd at vide: almindelige besøgende fra Schweiz, Frankrig og Tyskland blev også udfordret på helt normale sider. Zonens sikkerhedsniveau var sat meget højt, sandsynligvis som reaktion på et tidligere angreb, og ingen havde bemærket, at det også ramte betalingsudbyderen.
Løsningen: en snæver Skip-regel, ikke en svagere side
At sænke sikkerhedsniveauet ville have virket, men det ville have ændret beskyttelsen for hele siden for at løse et problem med én URL. Den renere løsning er en egen regel, der kun lukker webhook-adressen igennem og lader alt andet være, som det er.
- Gå til Security, Security rules og opret en ny custom rule.
- Giv den et tydeligt navn, for eksempel Allow Stripe webhooks.
- Sæt match til URI Query String, contains,
give-listener=stripe. - Vælg handlingen Skip og sæt flueben ved All remaining custom rules.
- Åbn More components to skip og sæt flueben ved både Security Level og Placér reglen.
- først på listen, og udrul den. in the list and deploy it.
Cloudflare-regel af typen Skip for give-listener=stripe med Security Level markeret

The detail that is easy to miss is step five. The first version of the rule skipped only Browser Integrity Check, the API preview showed , og webhooks ville have blevet ved med at fejle. Hændelsesloggen havde fortalt os, at det, der blokerede, var, så det er den komponent, der skal springes over. En bemærkning til gratis planer: hvis hændelsesloggen i stedet nævner Security level, so that is the component that has to be skipped. One note for free plans: if the events log names , kan en Skip-regel ikke omgå den, og selve indstillingen skal slås fra. Er det sikkert? Reglen stoler ikke blindt på forespørgslen. GiveWP verificerer stadig hver webhook mod Stripes signeringsnøgle, så en forfalsket forespørgsel, der når lytteren, afvises af WordPress. Cloudflares opgave her var aldrig at autentificere Stripe; det er signaturens opgave.
Bekræft rettelsen, og genvind mistede donationer
Vi sendte én fejlet hændelse igen fra Stripe-dashboardet, og den kom tilbage med
We resent one failed event from the Stripe Dashboard and it came back . Inden for en time begyndte Stripes egne genforsøg at lykkes, og dashboardet markerede tidligere fejl som. Within the hour Stripe’s own retries began to succeed and the dashboard marked earlier failures as . Dagen efter sendte Stripe en separat mail, der bekræftede, at endpointet var genoprettet.Leveringer af webhooks, der returnerer 200 OK efter rettelsen

Lærdomme for enhver WordPress-side, der modtager betalinger
Læs svarets indhold først.
- En 403, der indeholder HTML fra dit CDN, er ikke en fejl i applikationen, og ingen mængde fejlsøgning i plugins vil rette den. Sikkerhedsindstillinger og betalingswebhooks skal være enige.
- At hæve Cloudflares sikkerhedsniveau efter et angreb er rimeligt; at glemme, at det også gælder for kald mellem servere, er sådan donationer forsvinder. Tillad stien, ikke hele verden.
- En snæver Skip-regel på lytteren holder resten af siden beskyttet. Udløbne licenser til udvidelser er en snigende risiko.
- De stopper opdateringer, og den næste opdatering af kernen kan deaktivere udvidelsen uden varsel. Hold øje med advarslerne.
- Stripe giver cirka en uges advarsler, før et endpoint slås fra. Sørg for, at de mails når frem til en, der kan handle på dem. Vi har skrevet om et lignende særtilfælde, hvor en cache og WordPress var uenige om tiden, i
en 403-fejl, der kom og gik, forårsaget af cache-TTL , og om de rutinemæssige tjek, der fanger den slags problemer tidligt, ihvad vedligeholdelse af en hjemmeside reelt dækker what website maintenance actually covers.
Hvorfor returnerer mine Stripe-webhooks 403, når siden virker i min browser?
Fordi din browser kan klare en Cloudflare-udfordring, og det kan Stripes servere ikke. Hvis indholdet af den fejlede levering nævner
Because your browser can pass a Cloudflare challenge and Stripe’s servers cannot. If the failed delivery’s response body mentions Just a moment , bliver forespørgslen stoppet hos Cloudflare, før den når WordPress. challenges.cloudflare.comSkal jeg i stedet hvidliste Stripes IP-adresser?
Det kan du, med den IP-liste, Stripe offentliggør, men listen ændrer sig og skal vedligeholdes. En Skip-regel på webhook-stien er enklere, og fordi pluginet verificerer webhookens signatur, er den i praksis lige så sikker.
Mister jeg donationer, mens webhooks fejler?
Pengene bliver normalt opkrævet af Stripe, men hjemmesiden registrerer dem ikke. Donationer forbliver afventende, kvitteringer sendes ikke, og tilbagevendende fornyelser mangler i dine registreringer, indtil hændelserne leveres eller registreringerne rettes manuelt.
Hvor længe bliver Stripe ved med at prøve igen?
Hændelser i live-tilstand prøves igen i op til tre dage med stigende mellemrum. Hvis et endpoint bliver ved med at fejle, sender Stripe en advarsel på mail og slår det til sidst fra.
Har du donationer, en butik eller medlemskaber på WordPress og får betalingsadvarsler, du ikke er sikker på? Vi håndterer netop den type undersøgelser som en del af vores arbejde med
WordPress-udvikling vedligeholdelse og . work. så fortæller vi dig ligeud, hvad der er galt, og hvad der skal til for at rette det. and we will tell you plainly what is wrong and what it takes to fix it.