From 8f9484ec168ef2bf40b18ee9dbdd15f88e763503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 10 Jul 2026 19:58:59 +0200 Subject: [PATCH] merchant landing: pay popup script (template POST + payto + https) --- configs/merchant-landing/shop-pay.js | 158 +++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 configs/merchant-landing/shop-pay.js diff --git a/configs/merchant-landing/shop-pay.js b/configs/merchant-landing/shop-pay.js new file mode 100644 index 0000000..197ce98 --- /dev/null +++ b/configs/merchant-landing/shop-pay.js @@ -0,0 +1,158 @@ +/** + * GOA shop pay popup — public pay-template + payto (no merchant secrets). + * QR: white modules, centered official qr-logo (DD 90). + */ +(function () { + var MERCHANT_HOST = "taler.hacktivism.ch"; + var INSTANCE = "goa-demo-cp4zqk"; + var SHOP_PAYTO = + "payto://x-taler-bank/bank.hacktivism.ch/goa-demo-cp4zqk?receiver-name=GOA%20Demo%20Shop%20cp4zqk"; + var SHOP_PAYTO_HTTPS = + "https://bank.hacktivism.ch/webui/"; + + function payTemplateUri(productId) { + return ( + "taler://pay-template/" + + MERCHANT_HOST + + "/instances/" + + INSTANCE + + "/" + + encodeURIComponent(productId) + ); + } + + function payTemplateHttps(productId) { + return ( + "https://" + + MERCHANT_HOST + + "/instances/" + + INSTANCE + + "/templates/" + + encodeURIComponent(productId) + ); + } + + function introBase() { + var b = document.querySelector("base"); + return b && b.href ? b.href : "/intro/"; + } + + function ensureModal() { + var m = document.getElementById("goa-pay-modal"); + if (m) return m; + m = document.createElement("div"); + m.id = "goa-pay-modal"; + m.className = "goa-pay-modal"; + m.setAttribute("role", "dialog"); + m.setAttribute("aria-modal", "true"); + m.setAttribute("aria-labelledby", "goa-pay-title"); + m.hidden = true; + m.innerHTML = + '
' + + ' ' + + '

Pay with Taler

' + + '

' + + '
' + + '
' + + ' ' + + "
" + + '

Scan with GNU Taler Wallet

' + + ' Open payment link →' + + '

Payment URI (wallet)

' + + '

' + + ' (https)

' + + '

Merchant payto (settlement)

' + + '

' + + ' (https)

' + + ' Open payto:// link' + + ' ' + + "
"; + document.body.appendChild(m); + function close() { + m.classList.remove("open"); + m.hidden = true; + } + m.addEventListener("click", function (e) { + if (e.target === m) close(); + }); + document.getElementById("goa-pay-x").onclick = close; + document.getElementById("goa-pay-close").onclick = close; + document.addEventListener("keydown", function (e) { + if (e.key === "Escape" && m.classList.contains("open")) close(); + }); + return m; + } + + function showPay(productId, name, amount) { + var m = ensureModal(); + if (document.body && document.body.getAttribute("data-shop-theme") === "bank") { + m.classList.add("bank-theme"); + } else { + m.classList.remove("bank-theme"); + } + var uri = payTemplateUri(productId); + var httpsUri = payTemplateHttps(productId); + document.getElementById("goa-pay-title").textContent = name || productId; + document.getElementById("goa-pay-amount").textContent = amount || ""; + var open = document.getElementById("goa-pay-open"); + open.href = uri; + + document.getElementById("goa-pay-uri").textContent = uri; + var uriHttps = document.getElementById("goa-pay-uri-https"); + uriHttps.href = httpsUri; + uriHttps.textContent = "(https)"; + + document.getElementById("goa-pay-payto").textContent = SHOP_PAYTO; + var paytoHttps = document.getElementById("goa-pay-payto-https"); + paytoHttps.href = SHOP_PAYTO_HTTPS; + paytoHttps.textContent = "(https)"; + document.getElementById("goa-pay-payto-link").href = SHOP_PAYTO; + + var qrHost = document.getElementById("goa-pay-qr"); + qrHost.innerHTML = ""; + var logo = document.getElementById("goa-pay-logo"); + logo.src = introBase() + "qr-logo.svg"; + logo.onerror = function () { + logo.style.display = "none"; + }; + logo.style.display = ""; + + if (typeof QRCode === "undefined") { + qrHost.innerHTML = '

QR library missing

'; + } else { + new QRCode(qrHost, { + text: uri, + width: 220, + height: 220, + colorDark: "#000000", + colorLight: "#ffffff", + correctLevel: QRCode.CorrectLevel.M, + }); + } + + m.hidden = false; + m.classList.add("open"); + } + + function bind() { + document.querySelectorAll("[data-product]").forEach(function (el) { + el.addEventListener("click", function (e) { + e.preventDefault(); + var id = el.getAttribute("data-product"); + var nameEl = el.querySelector(".name"); + var priceEl = el.querySelector(".price"); + showPay( + id, + nameEl ? nameEl.textContent.trim() : id, + priceEl ? priceEl.textContent.trim() : "" + ); + }); + }); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", bind); + } else { + bind(); + } +})();