6.9 KiB
Déploiement Cloudflare Worker — Double opt-in MVA via Resend
Ce Worker gère le flow double opt-in du formulaire de contact :
requestVerification— génère un token, stocke les données du formulaire en KV, envoie un email de validation via Resend.verifyToken— appelé quand le client clique sur le lien dans l'email. Crée le contact dans HubSpot (avec une référence à la volée) et envoie le welcome email avec la référence + l'adresse du dépôt Paris.
Le Worker est aussi un proxy HubSpot pour la vérification de doublon par email et la génération du prochain numéro de référence séquentiel.
L'email de bienvenue contient le numéro de référence client ET l'adresse du dépôt à Paris. Ces infos ne sont jamais envoyées avant validation de l'email — protection contre les bots et les expéditions de cartons vides.
Étapes de déploiement (Phase D du plan WordPress → static)
1. Mettre à jour le code du Worker
Préférer wrangler :
cd cloudflare-worker
wrangler deploy
Ou via le dashboard Cloudflare :
- Aller sur https://dash.cloudflare.com/
- Workers & Pages → cliquer sur
mva-hubspot-proxy - Onglet Modifier le code (ou Quick edit)
- Tout sélectionner et remplacer par le contenu de
cloudflare-worker/hubspot-proxy.js - Cliquer Déployer / Save and deploy
2. Secrets
Dans Paramètres → Variables et secrets (ou via CLI : wrangler secret put <name>) :
| Nom | Valeur |
|---|---|
HUBSPOT_TOKEN |
pat-eu1-... (scope read+write contacts) |
RESEND_API_KEY |
re_... (compte Resend partagé avec m4s-auth) |
RESEND_FROM_EMAIL |
adresse expéditrice (domaine vérifié chez Resend) |
RESEND_FROM_NAME |
nom affiché à l'expéditeur (ex: MVA Global Fret) |
PARIS_DEPOT_ADDRESS |
Ton adresse exacte à Paris (rue, code postal, ville, étage, nom à indiquer sur le carton…) |
TURNSTILE_SECRET |
secret Cloudflare Turnstile (anti-bot) |
SITE_URL |
base URL du site (ex: https://mva-globalfret.com) |
PARIS_DEPOT_ADDRESSest l'info la plus sensible — c'est l'adresse à protéger. Elle ne quitte jamais Cloudflare/Resend et n'arrive au client que dans le mail de bienvenue, qui n'est envoyé qu'aux contacts qui ont confirmé leur email.
3. Stockage KV (idempotence — empêche de spammer le welcome)
Dans Paramètres → Stockage et bases de données → Bindings KV :
- Cliquer Ajouter un binding
- Variable name :
WELCOME_KV - Namespace : Créer un nouveau namespace nommé
mva-welcome-tracker - Sauvegarder
Si déployé via wrangler : mettre à jour wrangler.toml avec l'ID du namespace KV créé (remplacer REPLACE_AT_DEPLOY_TIME).
4. Vérifier le scope HubSpot
Le token HubSpot doit avoir :
crm.objects.contacts.readcrm.objects.contacts.writecrm.lists.read
Si tu obtiens des erreurs 403, regénère le token sur https://app-eu1.hubspot.com/private-apps/148163754/
5. Resend — vérifier le domaine expéditeur
Le compte Resend (partagé avec m4s-auth) doit avoir le domaine de RESEND_FROM_EMAIL vérifié (DNS records SPF + DKIM). Voir https://resend.com/domains.
Test manuel
Une fois tout déployé, tu peux tester le flow requestVerification (token de test, ne pas réutiliser en prod) :
curl -X POST https://mva-hubspot-proxy.<account>.workers.dev \
-H "Content-Type: application/json" \
-d '{
"action": "requestVerification",
"firstname": "Test",
"lastname": "User",
"email": "test@example.com",
"phone": "+33000000000",
"address": "Test address",
"turnstile_token": "<token from Turnstile widget>"
}'
Réponse attendue :
{ "ok": true }
Le client reçoit alors un email de validation. En cliquant sur le lien, il déclenche verifyToken, qui crée le contact dans HubSpot et envoie le welcome email avec la référence + l'adresse Paris.
Logs en production
Cloudflare → ton Worker → Logs (en temps réel) : tu verras chaque exécution du Worker.
En cas de problème
| Symptôme | Cause probable | Fix |
|---|---|---|
Resend 401: API key invalid |
Mauvaise valeur dans RESEND_API_KEY |
Re-vérifier la clé sur https://resend.com/api-keys |
Resend 422: domain is not verified |
Domaine de RESEND_FROM_EMAIL pas vérifié |
Vérifier le domaine sur https://resend.com/domains |
HubSpot 403 |
Token n'a pas le scope write | Regénérer token avec scope contacts.write |
HubSpot 401 |
Token invalide / expiré | Regénérer un Private App token |
KV not bound |
Binding WELCOME_KV pas créé |
Vérifier Storage & Databases → KV bindings |
Turnstile validation failed |
Secret côté Worker ne match pas la sitekey côté front | Re-vérifier TURNSTILE_SECRET et la sitekey HTML |
Architecture
┌──────────────────────────────────────────────────────────────────┐
│ 1. User remplit le formulaire sur contact.html │
│ ↓ │
│ 2. form-handler.js → POST action: requestVerification │
│ ↓ │
│ 3. Worker valide Turnstile, génère un token, stocke les │
│ données du formulaire en KV (TTL 24h), envoie l'email │
│ de validation via Resend │
│ ↓ │
│ ─────── User clique sur « Confirmer » ─────── │
│ ↓ │
│ 4. confirmation.html → POST action: verifyToken │
│ ↓ │
│ 5. Worker récupère les données du KV, génère la prochaine │
│ référence client, soumet via HubSpot Forms API (= contact │
│ créé dans le CRM), envoie le welcome email via Resend │
│ (avec la référence + adresse Paris), marque le token │
│ consommé en KV (TTL 7j pour idempotence). │
│ ↓ │
│ 6. Le client reçoit son welcome email avec sa référence ET │
│ l'adresse de dépôt à Paris. │
└──────────────────────────────────────────────────────────────────┘
Conclusion : il est impossible pour un bot de récupérer la référence client ou l'adresse Paris sans avoir au préalable un email valide ET cliqué sur le lien de confirmation. Anti-spam blindé.