diff --git a/pass/app/PaymentReference.js b/pass/app/PaymentReference.js index 027ee6394ffb0a5e88f54cfb5494f82cb40eab3e..39cc5631d74cbc738ce05ba6a028d9ad64eac9cb 100644 --- a/pass/app/PaymentReference.js +++ b/pass/app/PaymentReference.js @@ -67,7 +67,7 @@ class PaymentReference { expiration = dayjs().add(PaymentReference.DEFAULT_EXPIRATION_HOURS, "hours") ) { // Calculate price from amount - let price = (amount / 300) * config.get("price.per_300"); + let price = amount * config.get("price.per_token"); price = price.toFixed(2); // Validate that Key can be charged with another order @@ -197,7 +197,7 @@ class PaymentReference { } resolve( parseInt(matcher[2]) - - config.get("price.number_range.payment_reference") + config.get("price.number_range.payment_reference") ); }); } diff --git a/pass/config/default.json b/pass/config/default.json index 4f915c1c538f689550961e7098a252a4323b4cd0..dad5b3abf4db99736c053fb90970273be3db4c87 100644 --- a/pass/config/default.json +++ b/pass/config/default.json @@ -43,10 +43,22 @@ } }, "price": { - "per_300": 10, + "per_token": 0.01, "vat": 7, - "purchasable": [300, 600, 900, 1200, 1800, 3600], - "allowed_currencies": ["EUR", "USD", "CAD", "GBP"], + "purchasable": [ + 1000, + 2000, + 3000, + 4000, + 6000, + 12000 + ], + "allowed_currencies": [ + "EUR", + "USD", + "CAD", + "GBP" + ], "number_range": { "payment_reference": 0, "invoices": 0, @@ -98,4 +110,4 @@ } } } -} +} \ No newline at end of file diff --git a/pass/lang/de/cost.json b/pass/lang/de/cost.json new file mode 100644 index 0000000000000000000000000000000000000000..dd9e062dd443722b24493db45f471dae6fd595d1 --- /dev/null +++ b/pass/lang/de/cost.json @@ -0,0 +1,40 @@ +{ + "headings": [ + "Das kostet Ihr MetaGer Schlüssel", + "Das Wichtigste zusammengefasst" + ], + "texts": [ + "Für jede werbefreie Websuche auf MetaGer werden <b>3 Token</b> berechnet. Sie haben aber auch die Möglichkeit weitere/andere kostenpflichtige Suchmaschinen zu Ihrer Suche hinzuzufügen. Die Kosten pro Suche können Sie dann jeweils der Einstellungsseite entnehmen.", + "Ihren Schlüssel können Sie jederzeit mit einem der folgenden Pakete aufladen.", + "Die angegebenen Zeiträume sind Schätzungen, die auf unseren Erfahrungswerten basieren und sollen einen Anhaltspunkt geben, wie viele Token benötigt werden." + ], + "months_one": "Monat", + "months_other": "Monate", + "short-info": [ + { + "heading": "Gekaufte Suchen bleiben 1 Jahr lang gültig", + "text": "Ihre gekauften Tokens sind darauf ausgelegt so lange gültig zu bleiben, bis sie verbraucht wurden. Es gibt kein Abo." + }, + { + "heading": "30 Tage Geld Zurück Garantie", + "text": "Sollten Sie mit Ihrem Schlüssel unzufrieden sein, haben Sie nach dem Kauf 30 Tage Zeit das nicht verbrauchte Guthaben wieder zurück zu geben." + }, + { + "heading": "Schlüssel wird automatisch im Browser eingerichtet und verwendet", + "text": "Um Ihren MetaGer Schlüssel bei der Suche zu verwenden brauchen Sie nichts weiter tun. Nach dem Auffüllen ist er automatisch in Ihrem Browser eingerichtet und Sie erhalten Informationen zur einfachen Einrichtung auf weiteren Geräten." + }, + { + "heading": "Genauso anonym wie eine Suche ohne Schlüssel", + "text": "Verwenden Sie unsere <a href=\"#\">Android App</a>, oder unsere Extension für <a href=\"#\">Firefox</a> und <a href=\"#\">Chrome</a> und seien Sie unter Verwendung von <a href=\"https://en.wikipedia.org/wiki/Blind_signature\"> blinden Signaturen </a> beweisbar genauso anonym untewegs, wie ohne Schlüssel." + } + ], + "payment-methods": { + "heading": "Zahlungsmethoden", + "texts": [ + "MetaGer Schlüssel wurden von uns so konzipiert, dass Sie per Design ohne personenbeziehbare Daten auskommen. Nichtsdestotrotz fallen spätestens bei der Durchführung einer Zahlung meist welche an. Sei es nun die IBAN des zahlenden Kontos, oder die E-Mail Adresse des verwendeten PayPal Kontos. Der SUMA-EV verarbeitet diese Daten nicht selbst und speichert sie auch nicht ab. Allerdings tut es je nach Zahlungsmethode der Zahlungsdienstleister. Dadurch verbleibt natürlich auf unseren Kontoauszügen eine entsprechende Buchung. Wir sind verpflichtet diese Kontoauszüge 10 Jahre lang aufzuheben.", + "Deshalb bieten wir zusätzlich zu den Standard-Zahlungsmethoden auch zwei an, bei denen Sie anonym bezahlen können." + ], + "anonymous": "Anonyme Zahlungsmethoden", + "more": "Weitere Zahlungsmethoden" + } +} \ No newline at end of file diff --git a/pass/public/styles/cost.less b/pass/public/styles/cost.less index 52fd0585c051bbece65699c29c3a76d575c5706e..43f07473b5c706780aee09d64dc8cedd9f3ba4e7 100644 --- a/pass/public/styles/cost.less +++ b/pass/public/styles/cost.less @@ -2,7 +2,27 @@ #content { max-width: @max-content-width; margin: 0 auto; - padding: 1rem; + + h1 { + font-size: clamp(1rem, 5vw, 2rem); + } + + h2 { + font-size: clamp(1rem, 4vw, 1.5rem); + } + + h3 { + font-size: clamp(1rem, 3vw, 1.2rem); + } + + .hint { + position: relative; + &::before { + content: "*"; + position: absolute; + left: -1em; + } + } #price-tiers { margin-top: 2rem; display: grid; @@ -12,20 +32,29 @@ gap: 1rem; color: @font-color-on-white; - @media (max-width: 530px) { + @media (max-width: 640px) { grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr; } + @media (max-width: 375px) { + grid-template-rows: 1fr 1fr 1fr 1fr 1fr; + grid-template-columns: 1fr; + } + > .price-tier { display: grid; grid-template-rows: 1fr auto; - grid-template-columns: 1fr 3.5em; - max-width: 150px; + grid-template-columns: 6em 4em; place-items: stretch; border: 1px solid @color-main; border-radius: 10px; + @media (max-width: 375px) { + width: 100%; + grid-template-columns: 1fr 4em; + } + > div { display: grid; place-items: center; @@ -93,14 +122,15 @@ } .payment-methods-container { - &#more-payment-methods { - justify-content: space-between; - } - display: flex; + display: grid; + grid-template-columns: repeat(auto-fill, 10em); + place-content: center; flex-wrap: wrap; gap: 1rem; - @media (max-width: 350px) { - justify-content: center; + + @media (max-width: 368px) { + grid-template-columns: 10em; + width: 100%; } > .payment-method { display: grid; @@ -116,6 +146,7 @@ place-content: center; > img { max-width: 100%; + max-height: 44px; } } } diff --git a/pass/routes/api.js b/pass/routes/api.js index f2703892b876dbe7921a4304f8dcc4ee87b30a46..4ec5e6fb8afe95b956ae9d586776b219430e7ef6 100644 --- a/pass/routes/api.js +++ b/pass/routes/api.js @@ -22,7 +22,7 @@ router.post("/key/create", (req, res) => { // Calculate amount from price let price = req.body.price; if (price) { - amount = Math.ceil((price / config.get("price.per_300")) * 300); + amount = Math.ceil(price / config.get("price.per_token")); } else { res.status(403).json({ code: 403, @@ -69,7 +69,7 @@ router.post("/key/:key/discharge", (req, res) => { // Calculate amount from price let price = req.body.price; if (price) { - amount = Math.ceil((price / config.get("price.per_300")) * 300); + amount = Math.ceil(price / config.get("price.per_token")); } else { res.status(403).json({ code: 403, @@ -102,7 +102,7 @@ router.post("/key/:key/charge", (req, res) => { // Calculate amount from price let price = req.body.price; if (price) { - amount = Math.ceil((price / config.get("price.per_300")) * 300); + amount = Math.ceil(price / config.get("price.per_token")); } else { res.status(403).json({ code: 403, diff --git a/pass/views/checkout/charge.ejs b/pass/views/checkout/charge.ejs index 1253686eaf09160f44be04dd2950cc6447f68858..d1561018ce2cf6bec16902e30cefd2af55a09681 100644 --- a/pass/views/checkout/charge.ejs +++ b/pass/views/checkout/charge.ejs @@ -3,7 +3,7 @@ <div class="checkout-amounts"> <a href="<%= change_url.amount %>" class="checkout-amount" title="Menge ändern"> <span class="checkout-amount"><%= checkout.amount %></span> - <span class="checkout-cost"><%= checkout.amount / 300 * price.per_300%>€</span> + <span class="checkout-cost"><%= (checkout.amount * price.per_token).toFixed(2) %>€</span> <span class="checkout-duration"><%= req.t("charge.includes-vat", {ns: "checkout"}) _%></span> </a> </div> @@ -35,7 +35,7 @@ <%_ for(let i = 0; i < price.purchasable.length; i++) { _%> <a href="<%= baseDir _%>/key/<%= key.key.get_key() %>/checkout/<%= price.purchasable[i] _%>#payment" class="checkout-amount"> <span class="checkout-amount"><%= price.purchasable[i] _%></span> - <span class="checkout-cost"><%= (price.purchasable[i] / 300) * price.per_300 _%>€</span> + <span class="checkout-cost"><%= (price.purchasable[i] * price.per_token).toFixed(2) _%>€</span> <span class="checkout-duration">> <%= req.t("charge.month", {ns: "checkout", count: price.purchasable[i] / 300}) _%>*</span> </a> <%_ } _%> diff --git a/pass/views/cost.ejs b/pass/views/cost.ejs index 6d15fe828c251cc3e440ce33df38775969f052fc..0b4683730c42a49a172fdd1dbaaad1f311e539ac 100644 --- a/pass/views/cost.ejs +++ b/pass/views/cost.ejs @@ -1,94 +1,48 @@ <%- include('templates/page_header', {css: [`${baseDir}/styles/cost.css`], js:[]}); %> <div id="content"> - <h1>Das kostet Ihr MetaGer Schlüssel</h1> - <p> - Für jede werbefreie Suche auf MetaGer wird <b>1 Token</b> berechnet. Sie - haben aber auch die Möglichkeit weitere kostenpflichtige Suchmaschinen zu - Ihrer Suche hinzuzufügen. Die Kosten pro Suche können Sie dann jeweils der - Einstellungsseite entnehmen. - </p> - <p> - Ihren Schlüssel können Sie jederzeit mit einem der folgenden Pakete - aufladen. - </p> + <h1><%= req.t("headings.0", {ns: "cost"}) _%></h1> + <p><%- req.t("texts.0", {ns: "cost"}) _%></p> + <p><%= req.t("texts.1", {ns: "cost"}) _%></p> <div id="price-tiers"> <%_ for(let i = 0; i < price.purchasable.length; i++) { _%> <div class="price-tier"> <div class="amount"><%= price.purchasable[i] _%></div> <div class="price"> - <%= (price.purchasable[i] / 300) * price.per_300 _%>€ - </div> - <div class="lasts-for"> - > <%= price.purchasable[i] / 300 %> Monat<%_ if(price.purchasable[i] > - 300) { _%>e<%_ } _%>* + <%= (price.purchasable[i] * price.per_token).toFixed(0) _%>€ </div> + <div class="lasts-for">> <%= req.t("months", {ns: "cost", count: Math.floor(price.purchasable[i] / 900)}) %> *</div> </div> <%_ } _%> </div> - <p> - * Die angegebenen Zeiträume sind Schätzungen, die auf unseren - Erfahrungswerten basieren und sollen einen Anhaltspunkt geben, wie viele - Token benötigt werden. - </p> - <h2>Das Wichtigste zusammengefasst:</h2> + <p class="hint"><%= req.t("texts.2", {ns: "cost"}) _%></p> + <h2><%= req.t("headings.1", {ns: "cost"}) _%>:</h2> <ol id="short-info"> <li> <img src="<%= baseDir _%>/images/calendar-365.svg" alt="" /> - <h3>Gekaufte Suchen bleiben 1 Jahr lang gültig</h3> - <div> - Ihre gekauften Tokens sind darauf ausgelegt so lange gültig zu bleiben, - bis sie verbraucht wurden. Es gibt kein Abo. - </div> + <h3><%= req.t("short-info.0.heading", {ns: "cost"}) _%></h3> + <div><%= req.t("short-info.0.text", {ns: "cost"}) _%></div> </li> <li> <img src="<%= baseDir _%>/images/money.svg" alt="" /> - <h3>30 Tage Geld Zurück Garantie</h3> - <div> - Sollten Sie mit Ihrem Schlüssel unzufrieden sein, haben Sie nach dem - Kauf 30 Tage Zeit das nicht verbrauchte Guthaben wieder zurück zu geben. - </div> + <h3><%= req.t("short-info.1.heading", {ns: "cost"}) _%></h3> + <div><%= req.t("short-info.1.text", {ns: "cost"}) _%></div> </li> <li> <img src="<%= baseDir _%>/images/cogwheel.svg" alt="" /> - <h3>Schlüssel wird automatisch im Browser eingerichtet und verwendet</h3> - <div> - Um Ihren MetaGer Schlüssel bei der Suche zu verwenden brauchen Sie - nichts weiter tun. Nach dem Auffüllen ist er automatisch in Ihrem - Browser eingerichtet und Sie erhalten Informationen zur einfachen - Einrichtung auf weiteren Geräten. - </div> + <h3><%= req.t("short-info.2.heading", {ns: "cost"}) _%></h3> + <div><%= req.t("short-info.2.text", {ns: "cost"}) _%></div> </li> <li> <img src="<%= baseDir _%>/images/metager-schloss-orange.svg" alt="" /> - <h3>Genauso anonym wie eine Suche ohne Schlüssel</h3> - <div> - Verwenden Sie unsere <a href="#">Android App</a>, oder unsere Extension - für <a href="#">Firefox</a> und <a href="#">Chrome</a> und seien Sie - unter Verwendung von - <a href="https://en.wikipedia.org/wiki/Blind_signature"> - blinden Signaturen - </a> - beweisbar genauso anonym untewegs, wie ohne Schlüssel. - </div> + <h3><%= req.t("short-info.3.heading", {ns: "cost"}) _%></h3> + <div><%- req.t("short-info.3.text", {ns: "cost"}) _%></div> </li> </ol> - <h2 id="payment-methods">Zahlungsmethoden</h2> - <p> - MetaGer Schlüssel wurden von uns so konzipiert, dass Sie per Design ohne - personenbeziehbare Daten auskommen. Nichtsdestotrotz fallen spätestens bei - der Durchführung einer Zahlung meist welche an. Sei es nun die IBAN des - zahlenden Kontos, oder die E-Mail Adresse des verwendeten PayPal Kontos. Der - SUMA-EV verarbeitet diese Daten nicht selbst und speichert sie auch nicht - ab. Allerdings tut es je nach Zahlungsmethode der Zahlungsdienstleister. - Dadurch verbleibt natürlich auf unseren Kontoauszügen eine entsprechende - Buchung. Wir sind verpflichtet diese Kontoauszüge 10 Jahre lang aufzuheben. - </p> - <p> - Deshalb bieten wir zusätzlich zu den Standard-Zahlungsmethoden auch zwei an, - bei denen Sie anonym bezahlen können. - </p> - <h3>Anonyme Zahlungsmethoden</h3> + <h2 id="payment-methods"><%= req.t("payment-methods.heading", {ns: "cost"}) _%></h2> + <p><%= req.t("payment-methods.texts.0", {ns: "cost"}) _%></p> + <p><%= req.t("payment-methods.texts.1", {ns: "cost"}) _%></p> + <h3><%= req.t("payment-methods.anonymous", {ns: "cost"}) _%></h3> <div class="payment-methods-container"> <div class="payment-method"> <div> @@ -101,7 +55,7 @@ js:[]}); %> </div> </div> </div> - <h3>Weitere Zahlungsmethoden</h3> + <h3><%= req.t("payment-methods.more", {ns: "cost"}) _%></h3> <div id="more-payment-methods" class="payment-methods-container"> <div class="payment-method"> <div>