150 lines
7.1 KiB
Markdown
150 lines
7.1 KiB
Markdown
# Déploiement Cloudflare Worker — Double opt-in MVA via Resend
|
|
|
|
Ce Worker gère le flow double opt-in du formulaire de contact :
|
|
|
|
1. **`requestVerification`** — génère un token, stocke les données du formulaire en KV, envoie un email de validation via Resend.
|
|
2. **`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` :
|
|
|
|
```bash
|
|
cd cloudflare-worker
|
|
wrangler deploy
|
|
```
|
|
|
|
Ou via le dashboard Cloudflare :
|
|
|
|
1. Aller sur https://dash.cloudflare.com/
|
|
2. Workers & Pages → cliquer sur **`mva-hubspot-proxy`**
|
|
3. Onglet **Modifier le code** (ou *Quick edit*)
|
|
4. Tout sélectionner et remplacer par le contenu de `cloudflare-worker/hubspot-proxy.js`
|
|
5. 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_ADDRESS` est 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** :
|
|
|
|
1. Cliquer **Ajouter un binding**
|
|
2. Variable name : **`WELCOME_KV`**
|
|
3. Namespace : **Créer** un nouveau namespace nommé `mva-welcome-tracker`
|
|
4. Sauvegarder
|
|
|
|
Si déployé via `wrangler` : `wrangler.toml` contient déjà l'ID du namespace KV (`c02656ba22064923ab1c6db06b0f4a56` sur le compte CF `sergemind4s@gmail.com`). Pour un autre compte, recréer le namespace via `wrangler kv namespace create WELCOME_KV` puis remplacer l'ID dans `wrangler.toml`.
|
|
|
|
### 4. Vérifier le scope HubSpot
|
|
|
|
Le token HubSpot doit avoir :
|
|
|
|
- `crm.objects.contacts.read`
|
|
- `crm.objects.contacts.write`
|
|
- `crm.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) :
|
|
|
|
```bash
|
|
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 :
|
|
```json
|
|
{ "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é.
|