landings: clickable blue payload links under every QR (webextension)

Show the exact encoded URI (taler:// / https / payto://) as a blue
monospace link under each QR so wallet webextensions and desktop can
open it. Stop stripping :443 in the bank withdraw QR path. Shop pay
and exchange withdraw-exchange included.
This commit is contained in:
Hernâni Marques 2026-07-10 23:05:00 +02:00
parent eb640da64e
commit 2fb060f79a
No known key found for this signature in database
6 changed files with 134 additions and 15 deletions

View file

@ -363,22 +363,27 @@
text-align: center;
max-width: 100%;
}
/* Blue payload link under each QR (encoded content) */
a.meta-uri {
display: block;
font-size: 0.72rem;
color: #5eead4;
font-size: 0.68rem;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
color: #7eb6ff;
word-break: break-all;
margin: 0.35rem 0 0;
margin: 0.4rem auto 0;
text-align: center;
max-width: 22rem;
text-decoration: none;
border-bottom: 1px solid rgba(94, 234, 212, 0.35);
border-bottom: 1px solid rgba(126, 182, 255, 0.4);
line-height: 1.35;
cursor: pointer;
}
a.meta-uri:hover {
color: #99f6e4;
border-bottom-color: #5eead4;
color: #b8d6ff;
border-bottom-color: #7eb6ff;
}
.qr-taler-wrap a.meta-uri {
margin-top: 0.45rem;
}
a.meta-uri.disabled,
a.meta-uri[href="#"] {
@ -1250,11 +1255,11 @@ tw balance</pre>
<img class="goa-pay-taler-qr__logo" id="qr-withdraw-demo-logo" alt="" />
</div>
<div class="qr-label">Scan in wallet</div>
<a class="meta-uri" id="withdraw-demo-meta" href="#">Preparing withdraw…</a>
</div>
<a class="cta teal" id="open-withdraw-demo" href="#">
Open in wallet →
</a>
<a class="meta-uri" id="withdraw-demo-meta" href="#">Preparing withdraw…</a>
<button type="button" class="gen-own-acct" id="generate-own-account">
Generate own account
</button>
@ -1331,6 +1336,10 @@ tw balance</pre>
<dl class="own-acct-dl">
<div><dt>Username</dt><dd><code id="auto-account-user"></code></dd></div>
<div><dt>Password</dt><dd><code id="auto-account-pass"></code></dd></div>
<div>
<dt>payto</dt>
<dd><a class="meta-uri" id="auto-account-payto" href="#" style="margin:0;text-align:left;max-width:100%"></a></dd>
</div>
</dl>
<p class="meta" id="auto-account-status" style="margin:0.5rem 0 0"></p>
<div class="more-qr" id="auto-account-qr-block" style="margin-top:0.85rem" hidden>
@ -1340,6 +1349,7 @@ tw balance</pre>
<img class="goa-pay-taler-qr__logo" id="qr-auto-acct-logo" alt="" />
</div>
<div class="qr-label" id="qr-auto-acct-label">Your account · bank UI login</div>
<a class="meta-uri" id="qr-auto-acct-payload" href="https://bank.hacktivism.ch/webui/" target="_blank" rel="noopener noreferrer">https://bank.hacktivism.ch/webui/</a>
</div>
</div>
</div>
@ -1350,10 +1360,11 @@ tw balance</pre>
<img class="goa-pay-taler-qr__logo" id="qr-webui-logo" alt="" />
</div>
<div class="qr-label">Bank UI · open site</div>
<a class="meta-uri" id="qr-webui-payload" href="https://bank.hacktivism.ch/webui/" target="_blank" rel="noopener noreferrer">https://bank.hacktivism.ch/webui/</a>
</div>
</div>
<div class="more-actions">
<a class="cta-sec" href="/webui/" id="auto-account-webui">Open bank UI →</a>
<a class="cta-sec" href="https://bank.hacktivism.ch/webui/" id="auto-account-webui">Open bank UI →</a>
<button type="button" class="cta-sec" id="auto-account-again" hidden style="margin-top:0.45rem">
Generate another account
</button>
@ -1569,9 +1580,8 @@ tw balance</pre>
}
function setDemoWithdraw(uri, amount) {
uri = String(uri || "")
.replace(/:443\//g, "/")
.replace(/:443\?/g, "?");
/* Keep host:port (…:443) — required for taler-integration withdraw */
uri = String(uri || "").trim();
var open = document.getElementById("open-withdraw-demo");
var meta = document.getElementById("withdraw-demo-meta");
if (open) {
@ -1752,8 +1762,33 @@ tw balance</pre>
if (box) box.hidden = false;
var u = document.getElementById("auto-account-user");
var p = document.getElementById("auto-account-pass");
var payA = document.getElementById("auto-account-payto");
var webuiA = document.getElementById("auto-account-webui");
if (u) u.textContent = d.username || d.name || d.display_name || "—";
if (p) p.textContent = d.password || "—";
/* Absolute HTTPS bank UI (never relative under <base href=/intro/>) */
var webui = d.webui || d.account_url || WEBUI;
if (!/^https?:\/\//i.test(webui)) {
webui = WEBUI;
}
if (webuiA) {
webuiA.href = webui;
webuiA.setAttribute("target", "_blank");
webuiA.setAttribute("rel", "noopener noreferrer");
}
/* payto must include host:port (e.g. bank.hacktivism.ch:443) */
var payto = d.payto_uri || "";
if (payA) {
if (payto && payto.indexOf("payto://") === 0) {
payA.href = payto;
payA.textContent = payto;
payA.classList.remove("disabled");
} else {
payA.href = "#";
payA.textContent = "—";
payA.classList.add("disabled");
}
}
if (st) {
st.textContent =
"Account created for you · " +
@ -1763,12 +1798,18 @@ tw balance</pre>
/* Fancy QR_Taler: encode bank UI URL (login with credentials above) */
var qrBlock = document.getElementById("auto-account-qr-block");
var qrLabel = document.getElementById("qr-auto-acct-label");
var webui = d.webui || WEBUI;
if (qrBlock) qrBlock.hidden = false;
if (qrLabel) {
qrLabel.textContent =
"QR_Taler · open bank UI · login as " + (d.username || "you");
}
var autoPayload = document.getElementById("qr-auto-acct-payload");
if (autoPayload) {
autoPayload.href = webui;
autoPayload.textContent = webui;
autoPayload.setAttribute("target", "_blank");
autoPayload.setAttribute("rel", "noopener noreferrer");
}
makeQr(
document.getElementById("qr-auto-acct"),
webui,

View file

@ -138,6 +138,25 @@ button.shop-item {
background: #fff;
border-radius: 4px;
}
/* Full encoded payload under QR — clickable (wallet / webextension) */
.goa-pay-payload {
display: block;
margin: 0.45rem 0 0.55rem;
padding: 0 0.25rem;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 0.68rem;
line-height: 1.35;
color: #7eb6ff;
word-break: break-all;
text-align: center;
text-decoration: none;
border-bottom: 1px solid rgba(126, 182, 255, 0.4);
cursor: pointer;
}
.goa-pay-payload:hover {
color: #b8d6ff;
border-bottom-color: #7eb6ff;
}
/* Settlement: collapsed by default, expand on click */
.goa-pay-settle {

View file

@ -69,6 +69,7 @@
' <div class="goa-pay-taler-qr__inner" id="goa-pay-qr-pay"></div>' +
' <img class="goa-pay-taler-qr__logo" id="goa-pay-qr-pay-logo" alt="" />' +
" </div>" +
' <a class="goa-pay-payload" id="goa-pay-qr-payload" href="#">…</a>' +
' <a class="goa-pay-cta" id="goa-pay-open" href="#">Open payment link →</a>' +
' <p class="goa-pay-line">' +
' <a class="goa-pay-link" id="goa-pay-uri" href="#">taler:// URI</a>' +
@ -90,6 +91,7 @@
' <div class="goa-pay-payto-qr__caption">Settlement only</div>' +
' <div class="goa-pay-payto-qr__inner" id="goa-pay-qr-payto"></div>' +
" </div>" +
' <a class="goa-pay-payload" id="goa-pay-payto-payload" href="#">…</a>' +
' <p class="goa-pay-line">' +
' <a class="goa-pay-link" id="goa-pay-payto" href="#">payto:// URI</a>' +
' <span class="goa-pay-sep">·</span>' +
@ -127,6 +129,11 @@
if (open) {
// paint payto QR when first expanded
renderQr(document.getElementById("goa-pay-qr-payto"), SHOP_PAYTO, 140);
var pp = document.getElementById("goa-pay-payto-payload");
if (pp) {
pp.href = SHOP_PAYTO;
pp.textContent = SHOP_PAYTO;
}
}
};
document.addEventListener("keydown", function (e) {
@ -335,11 +342,17 @@
// Open first so layout exists, then paint wallet QR only
m.hidden = false;
m.classList.add("open");
var tpl = payTemplateUri(productId);
renderQr(
document.getElementById("goa-pay-qr-pay"),
payTemplateUri(productId),
tpl,
220
);
var payload = document.getElementById("goa-pay-qr-payload");
if (payload) {
payload.href = tpl;
payload.textContent = tpl;
}
createPayUri(productId)
.then(function (info) {
@ -355,6 +368,10 @@
uh.textContent = "HTTPS";
// Live unpaid taler://pay (fresh order each open)
renderQr(document.getElementById("goa-pay-qr-pay"), pay, 220);
if (payload) {
payload.href = pay;
payload.textContent = pay;
}
status.textContent = "Ready — scan in wallet";
})
.catch(function (err) {