paivana

HTTP paywall reverse proxy
Log | Files | Refs | README | LICENSE

commit e035546a0bc48131bffded1229f4f0bcf6413774
parent 7d45401feda856622a440a5bb1b4404488a1b771
Author: Florian Dold <florian@dold.me>
Date:   Thu, 27 Nov 2025 00:12:48 +0100

paywall.html

Diffstat:
Acontrib/paywall.html | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+), 0 deletions(-)

diff --git a/contrib/paywall.html b/contrib/paywall.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> + +<html lang="en"> + <head> + <meta charset="utf-8" /> + <script> + function makeBadInsecureId(length) { + var result = ""; + var characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt( + Math.floor(Math.random() * charactersLength) + ); + } + return result; + } + function waitMs(n) { + return new Promise((resolve, reject) => { + setTimeout(() => resolve(), n); + }); + } + addEventListener("DOMContentLoaded", async (event) => { + // Bad for testing, only works with http + //const paivana_id = crypto.randomUUID(); + + const paivanaId = makeBadInsecureId(16); + const proto = window.location.protocol; + const suffix = proto === "http:" ? "+http" : ""; + + const host = window.location.host; + document + .getElementById("talerlink") + .setAttribute( + "href", + `taler${suffix}://pay-template/${host}/.well-known/paivana/paywall?session_id=${paivanaId}` + ); + + while (true) { + const start = performance.now(); + try { + const res = await fetch( + `${proto}//${host}/.well-known/paivana/paivanas/${paivanaId}?timeout_ms=30000` + ); + if (res.status === 200) { + location.reload(); + } else { + console.log("payment not ready yet"); + } + } catch (e) { + console.log("oops", e); + } + // FIXME: Wait depending on how long we needed + const durMs = performance.now() - start; + const remMs = Math.round(30000 - durMs); + if (remMs > 0) { + console.log(`long-poller returned early, waiting for ${remMs}ms`); + await waitMs(remMs); + } else { + console.log(`trying again immediately`); + } + } + }); + </script> + </head> + <body> + <h1>Payment Required</h1> + <a id="talerlink" href="...">Taler Payment</a> + </body> +</html>