// ============================================================ // MVA Global Fret — Cloudflare Worker : Proxy HubSpot // ============================================================ // Ce Worker contourne le CORS en faisant l'appel HubSpot // côté serveur (Cloudflare), puis renvoie le résultat // au navigateur avec les bons en-têtes CORS. // // DÉPLOIEMENT (gratuit, sans CLI) : // 1. Aller sur https://dash.cloudflare.com/ → Workers & Pages // 2. Créer un Worker → coller ce code → Enregistrer et déployer // 3. Copier l'URL du Worker (ex: https://mva-proxy.xxx.workers.dev) // 4. Coller cette URL dans js/form-handler.js à la constante WORKER_PROXY_URL // // SÉCURITÉ : // - Stocker le token dans une variable d'environnement Cloudflare : // Workers & Pages → Votre Worker → Paramètres → Variables et secrets // Nom : HUBSPOT_TOKEN Valeur : pat-eu1-e3c92146-bb17-45fe-8d77-0c665fc4df3b // - Ce token est en lecture seule (crm.objects.contacts.read uniquement) // ============================================================ export default { async fetch(request, env) { // En-têtes CORS autorisés const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; // Réponse au preflight CORS (OPTIONS) if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } // Seule la méthode POST est acceptée if (request.method !== 'POST') { return new Response('Method Not Allowed', { status: 405 }); } // Lecture du token (variable d'env Cloudflare ou fallback hardcodé) const token = (env && env.HUBSPOT_TOKEN) ? env.HUBSPOT_TOKEN : 'pat-eu1-e3c92146-bb17-45fe-8d77-0c665fc4df3b'; try { const { email } = await request.json(); if (!email || typeof email !== 'string') { return new Response( JSON.stringify({ error: 'Email requis' }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } // Appel HubSpot CRM (pas de CORS côté Worker) const hsResponse = await fetch( 'https://api.hubapi.com/crm/v3/objects/contacts/search', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, body: JSON.stringify({ filterGroups: [{ filters: [{ propertyName: 'email', operator: 'EQ', value: email.toLowerCase().trim(), }] }], properties: ['firstname', 'lastname', 'email', 'reference_client'], }), } ); if (!hsResponse.ok) { return new Response( JSON.stringify({ error: `HubSpot error: ${hsResponse.status}` }), { status: 502, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } const data = await hsResponse.json(); return new Response(JSON.stringify(data), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } catch (err) { return new Response( JSON.stringify({ error: err.message }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } } ); } }, };