Meertalige e-mails via Stripe webhooks
Het wereldwijd schalen van een SaaS kent verborgen valkuilen. We ontdekten er een in onze Stripe webhooks.
Ons systeem stuurde aankoopbevestigingen, verlengingen en foutmeldingen in het Japans naar Engelstalige gebruikers. Deze bug bleef maandenlang bestaan omdat hij onopgemerkt bleef.
We hebben het opgelost door de taal af te leiden uit de valuta.
We hebben drie ontwerpopties bekeken:
- Optie A: De taal opslaan in de database. Dit vereist migraties en backfills voor bestaande gebruikers.
- Optie B: Gegevens ophalen uit de Stripe API. Dit zorgt voor extra API-aanroepen en veel klanten stellen geen voorkeurstaal in.
- Optie C: De valuta in de webhook-payload gebruiken. Dit is gratis, vereist geen databasewijzigingen en werkt direct voor bestaande gebruikers.
We hebben voor Optie C gekozen. Valuta is een vast signaal op het moment van aankoop. Als een gebruiker in USD betaalt, krijgen ze Engels. Als ze in JPY betalen, krijgen ze Japans.
De logica is eenvoudig:
function lang_from_currency(string $currency): string {
$en_currencies = ['usd'];
return in_array(strtolower($currency), $en_currencies, true) ? 'en' : 'ja';
}
Dit werkt voor alle vier de belangrijke Stripe-events:
- checkout.session.completed
- invoice.payment_succeeded
- invoice.payment_failed
- customer.subscription.updated
We ontdekten ook een technische valkuil met PHP.
Het gebruik van mb_language('Japanese') codeert onderwerpregels in ISO-2022-JP. Als je een Engelse onderwerpregel verstuurt met deze instelling, zien Gmail en Outlook dit als een vreemde codering. Dit verhoogt je spamscore.
De oplossing is om de codering te wisselen op basis van de taal:
mb_language($lang === 'en' ? 'uni' : 'Japanese');
Het gebruik van 'uni' maakt gebruik van UTF-8 Base64. Hiermee blijven je e-mails uit de spammap.
Drie lessen van deze oplossing:
- Gebruik de event-payload. Als de gegevens al in de webhook zitten, raak dan je database niet aan. Dit vermindert risico's en onderhoud.
- Let op je codering. Als je meerdere talen ondersteunt, zorg er dan voor dat de codering van je onderwerpregel overeenkomt met de inhoud om spamfilters te vermijden.
- Controleer hardcoded waarden. Wanneer je internationaal gaat, controleer dan of je notificatiefuncties hardcoded taalinstellingen hebben.
Een stateless ontwerp maakt je systeem gemakkelijker te onderhouden en moeilijker te breken.
