(() => { const MIN_AMOUNT = 5000; // 50 € const MAX_AMOUNT = 300000; // 3000 € const LOG = true; const PARACHUTE = true; const IDS = { WRAP_ID: "alma-wrap", BTN2_ID: "alma-btn-2x", BTN3_ID: "alma-btn-3x", BTN4_ID: "alma-btn-4x", BTN10_ID: "alma-btn-10x" }; const ENDPOINT = "https://almakey191125.60saas60.workers.dev"; const RETURN_URL = "https://www.treuil-service.com/mag/fr/validation.php?alma=1"; const FAILURE_URL= "https://www.treuil-service.com/echec.htm"; const CANCEL_URL = "https://www.treuil-service.com/annule.htm"; const log = (...a) => { if (LOG) console.log("[Alma Bloc1]", ...a); }; function toCents(numStr){ let s = String(numStr).replace(/\u00a0/g," ").replace(/\s/g,""); if (s.includes(",") && s.includes(".")) s = s.replace(/\./g,"").replace(",","."); else s = s.replace(",","."); const v = Math.round(parseFloat(s) * 100); return Number.isFinite(v) ? v : null; } function extractAllCents(txt){ if (!txt) return []; const s = String(txt).replace(/\u00a0/g," "); const re = /(\d{1,3}(?:[ \u00a0.,]\d{3})*|\d+)([.,]\d{1,2})?(?=\s*€)?/g; const out = []; let m; while ((m = re.exec(s))) { const cents = toCents(m[0]); if (cents != null) out.push(cents); } return out; } function bestCentsFromText(node){ const text = node?.innerText || node?.textContent || ""; if (!text) return null; const euroRe = /(\d{1,3}(?:[ \u00a0.,]\d{3})*|\d+)([.,]\d{1,2})?\s*€/g; let e, euroCand = []; while ((e = euroRe.exec(text))) { const c = toCents(e[1] + (e[2]||"")); if (c != null) euroCand.push(c); } if (euroCand.length) return Math.max(...euroCand); const all = extractAllCents(text); return all.length ? Math.max(...all) : null; } function getAmount(){ const priceNodes = [ document.querySelector("#validation_totalpay .col4 .price"), document.querySelector("#validation_total .col4 .price"), document.querySelector("#basket_tab tr.footer:last-child .col4 .price") ].filter(Boolean); for (const n of priceNodes) { const cents = bestCentsFromText(n); if (cents != null) { log("getAmount: price node ->", cents); return cents; } } const cellNodes = [ document.querySelector("#validation_totalpay .col4"), document.querySelector("#validation_total .col4"), document.querySelector("#basket_tab tr.footer:last-child .col4") ].filter(Boolean); for (const n of cellNodes) { const cents = bestCentsFromText(n); if (cents != null) { log("getAmount: cell node ->", cents); return cents; } } const table = document.querySelector("#basket_tab"); if (table) { const cents = bestCentsFromText(table); if (cents != null) { log("getAmount: table max ->", cents); return cents; } } log("getAmount: NOT FOUND"); return null; } const isEligibleAmount = v => v != null && v >= MIN_AMOUNT && v <= MAX_AMOUNT; const findAnchorFieldset = () => document.querySelector("fieldset.canvas_vad_in.vad_422165"); const isVisible = (el) => el && getComputedStyle(el).display !== "none" && getComputedStyle(el).visibility !== "hidden" && el.offsetParent !== null; function clickRedirectBnk(){ const scopes = [ document.getElementById("validation"), document.querySelector("#formulaire"), document ]; const cgv = document.getElementById("ctx_accept_cgv"); if (cgv && !cgv.checked) cgv.checked = true; for (const scope of scopes) { if (!scope) continue; const links = Array.from(scope.querySelectorAll('a[onclick*="redirectbnk("]')) .filter(el => !el.closest(".pop_up") && !el.closest("#popup0")) .filter(isVisible); if (links.length) { const target = links[links.length - 1]; try { target.scrollIntoView({behavior:"smooth", block:"center"}); target.click(); return true; } catch(e){ log("redirectbnk error", e); } } } return false; } function startAlmaFromClick(installmentsCount) { const amountInCents = getAmount(); if (!isEligibleAmount(amountInCents)) { log("Montant non eligible:", amountInCents); alert("Montant non eligible au paiement Alma."); return; } if (!amountInCents || amountInCents < MIN_AMOUNT) { log("Montant invalide pour Alma:", amountInCents); alert("Montant trop bas pour Alma."); return; } const orderRef = "TS-" + Date.now(); const customerEmail = (document.querySelector('input[name="email"]')?.value) || (document.querySelector("#email")?.value) || null; sessionStorage.setItem("almaPlan", String(installmentsCount)); sessionStorage.setItem("almaAmount", String(amountInCents)); sessionStorage.setItem("almaOrderRef", orderRef); log("create ->", { amountInCents, installmentsCount, orderRef }); console.log("ENDPOINT =", ENDPOINT); const payload = { amountInCents, installmentsCount, orderRef, customerEmail, returnUrl: RETURN_URL, failureUrl: FAILURE_URL, cancelUrl: CANCEL_URL, ipnUrl: ENDPOINT + "/ipn" }; console.log("Payload envoyé =", payload); fetch(ENDPOINT + "/create", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify(payload) }) .then(async (r) => { if (!r.ok) throw new Error("Create failed " + r.status + " " + (await r.text())); return r.json(); }) .then((data) => { const url = data.paymentUrl || data.url; if (!url) throw new Error("No paymentUrl in response"); log("redirection Alma:", url); location.href = url; }) .catch((err) => { console.error("[Alma Bloc1] erreur /create:", err); alert("Impossible d'ouvrir Alma pour le moment. Merci de reessayer."); }); } function createBtn(n){ const b = document.createElement("button"); const MAP = { 2: IDS.BTN2_ID, 3: IDS.BTN3_ID, 4: IDS.BTN4_ID, 10: IDS.BTN10_ID }; b.id = MAP[n] || `alma-btn-${n}`; b.type = "button"; b.textContent = `Payer en ${n}x`; Object.assign(b.style,{ display:"inline-block", padding:"10px 22px", background:"rgb(18 66 130)", color:"#fff", border:"none", borderRadius:"8px", cursor:"pointer", fontSize:"15px", transition:"all .25s ease", letterSpacing:"0.3px", boxShadow:"0 3px 6px rgba(0,0,0,.15)", marginLeft:"12px" }); b.addEventListener("click",(e)=>{ e.preventDefault(); e.stopPropagation(); startAlmaFromClick(n); }); return b; } function createWrapperAfterFieldset(){ const anchor = findAnchorFieldset(); if (!anchor || !anchor.parentNode) { log("fieldset cible introuvable"); return null; } const wrap = document.createElement("div"); wrap.id = IDS.WRAP_ID; const label = document.createElement("span"); label.className = "alma-label"; label.textContent = "Paiement en plusieurs fois :"; const btn2 = createBtn(2); const btn3 = createBtn(3); const btn4 = createBtn(4); const btn10 = createBtn(10); wrap.appendChild(label); wrap.appendChild(btn2); wrap.appendChild(btn3); wrap.appendChild(btn4); wrap.appendChild(btn10); anchor.insertAdjacentElement("afterend", wrap); return wrap; } const destroyWrapper = () => { const w = document.getElementById(IDS.WRAP_ID); if (w) w.remove(); }; function evaluateVisibility(){ const amount = getAmount(); const ok = isEligibleAmount(amount); log("amount=", amount, "-> eligible?", ok); if (ok) { const wrap = document.getElementById(IDS.WRAP_ID) || createWrapperAfterFieldset(); if (!wrap) return; wrap.style.setProperty("display", "flex", "important"); } else { destroyWrapper(); } } let evalQueued = false; const scheduleEval = () => { if (evalQueued) return; evalQueued = true; requestAnimationFrame(()=> setTimeout(()=>{ evalQueued=false; evaluateVisibility(); },0)); }; function attachObservers(){ const targets = [ document.querySelector("#basket_tab"), document.querySelector("#validation_totalpay"), document.querySelector("#validation_total"), document.querySelector("fieldset.canvas_vad_in.vad_422165") ].filter(Boolean); if (!targets.length) return null; const mo = new MutationObserver(scheduleEval); for (const t of targets){ mo.observe(t, { childList:true, subtree:true, characterData:true }); } return mo; } document.addEventListener("DOMContentLoaded", scheduleEval, {once:true}); window.addEventListener("load", scheduleEval, {once:true}); document.addEventListener("visibilitychange", () => { if (document.visibilityState==="visible") scheduleEval(); }, {passive:true}); attachObservers(); setTimeout(scheduleEval, 300); setTimeout(scheduleEval, 1000); setTimeout(scheduleEval, 2500); (function(){ const LOG_AUTO = true; function logAuto() { if (!LOG_AUTO) return; console.log.apply(console, ["[Alma AutoVirement]"].concat([].slice.call(arguments))); } const path = (location.pathname || "").toLowerCase(); if (!/\/mag\/fr\/validation\.php$/.test(path)) { return; // on ne fait ça QUE sur validation.php } const params = new URLSearchParams(location.search || ""); const fromAlma = params.get("alma") === "1"; if (!fromAlma) { logAuto("Pas un retour Alma (pas de alma=1), on ne fait rien."); return; } if (sessionStorage.getItem("almaOrderCreated") === "1") { logAuto("Commande deja declenchee via Alma, on ne refait pas redirectbnk."); return; } window.addEventListener("load", function(){ setTimeout(function(){ logAuto("Retour Alma detecte sur validation.php, tentative de clickRedirectBnk()"); try { const ok = (typeof clickRedirectBnk === "function") ? clickRedirectBnk() : false; logAuto("clickRedirectBnk retour =", ok); if (ok) { sessionStorage.setItem("almaOrderCreated", "1"); } } catch(e) { console.error("[Alma AutoVirement] erreur:", e); } }, 500); }, { once: true }); })(); })();