aboutsummaryrefslogtreecommitdiff
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/checkout.php136
-rw-r--r--src/frontend/execute.js33
-rw-r--r--src/frontend/execute.php56
-rw-r--r--src/frontend/execute.tsx41
-rw-r--r--src/frontend/fulfillment.php (renamed from src/frontend/fullfillment.php)48
-rw-r--r--src/frontend/generate_taler_contract.php34
-rw-r--r--src/frontend/index.html324
-rw-r--r--src/frontend/pay.php85
-rw-r--r--src/frontend/style.css123
9 files changed, 603 insertions, 277 deletions
diff --git a/src/frontend/checkout.php b/src/frontend/checkout.php
index 157bd25f..21d4d8c4 100644
--- a/src/frontend/checkout.php
+++ b/src/frontend/checkout.php
@@ -1,7 +1,8 @@
<!DOCTYPE html>
<html>
<head>
-<title>Taler's "Demo" Shop: Choose payment method</title>
+ <title>Toy Store - Payment method - Taler Demo</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
<script>
/*
@licstart The following is the entire license notice for the
@@ -31,7 +32,7 @@
</head>
<body onload="signal_taler_wallet_onload()">
<!--
- This page's main aim is to show to the customer all the accepted
+ This main goal of this page is to show to the customer all the accepted
payments methods and actually implementing just Taler; technically
the steps are:
@@ -50,52 +51,78 @@
$donation_currency = $_POST['donation_currency'];
// get frational part
- list ($donation_value, $donation_fraction) = split ("\.", $donation_amount, 2);
+ list ($donation_value, $donation_fraction) = explode (".", $donation_amount, 2);
// create PHP session and store donation information in session
$donation_fraction = (float) ("0." . $donation_fraction);
session_start();
+ session_unset();
$_SESSION['receiver'] = $donation_receiver;
$_SESSION['amount_value'] = (int) $donation_amount;
$_SESSION['amount_fraction'] = (int) ($donation_fraction * 1000000);
$_SESSION['currency'] = $donation_currency;
?>
-<h2>Select your payment option</h2>
-<div>
-This is an example for a "checkout" page of a Web shop.
-On the previous page, you have created the shopping cart
-and decided which product to buy (i.e. which project to
-donate KUDOS to). Now in this page, you are asked to
-select a payment option. As Taler is not yet universally
-used, we expect merchants will offer various payment options.
-<p>
-The page also demonstrates how to only enable (or show) the Taler
-option if Taler is actually supported by the browser. For example,
-if you disable the Taler extension now, the Taler payment option
-will be disabled in the page. Naturally, you could also trivially
-hide the Taler option entirely by changing the visibility instead.
-<p>
-Note that you MUST select Taler here for the demo to continue,
-as the other payment options are just placeholders and not
-really working in the demonstration. Also, it is of course
-possible to ask the user to make this choice already on the
-previous page (with the shopping cart), we just separated the
-two steps to keep each step as simple as possible.
-</div>
-<form name="tform" action="" method="POST">
- <div id="opt-form" align="left"><br>
- <input type="radio" name="payment_system" value="lisa"
- id="lisa-radio-button-id">Lisa</input>
- <br>
- <input type="radio" name="payment_system" value="ycard">You Card</input>
- <br>
- <input type="radio" name="payment_system" value="cardme">Card Me</input>
- <br>
- <input type="radio" name="payment_system" value="taler"
- id="taler-radio-button-id" disabled="true">Taler</input>
- <br>
- <input type="button" onclick="pay(this.form)" value="Ok">
- </div>
-</form>
+
+ <header>
+ <div id="logo">
+ <svg height="100" width="100">
+ <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" fill="white" />
+ <text x="19" y="82" font-family="Verdana" font-size="90" fill="darkcyan">S</text>
+ </svg>
+ </div>
+
+ <h1>Toy Store - Select payment method</h1>
+ </header>
+
+ <aside class="sidebar" id="left">
+ </aside>
+
+ <section id="main">
+ <article>
+
+ <h1>Select your payment method</h1>
+
+ <p>
+ This is an example for a "checkout" page of a Web shop.
+ On the previous page, you have created the shopping cart
+ and decided which product to buy (i.e. which project to
+ donate KUDOS to). Now in this page, you are asked to
+ select a payment option. As Taler is not yet universally
+ used, we expect merchants will offer various payment options.
+ </p>
+ <p>
+ The page also demonstrates how to only enable (or show) the Taler
+ option if Taler is actually supported by the browser. For example,
+ if you disable the Taler extension now, the Taler payment option
+ will be disabled in the page. Naturally, you could also trivially
+ hide the Taler option entirely by changing the visibility instead.
+ </p>
+ <p>
+ Note that you MUST select Taler here for the demo to continue,
+ as the other payment options are just placeholders and not
+ really working in the demonstration. Also, it is of course
+ possible to ask the user to make this choice already on the
+ previous page (with the shopping cart), we just separated the
+ two steps to keep each step as simple as possible.
+ </p>
+
+ <form name="tform" action="" method="POST">
+ <div id="opt-form" align="left"><br>
+ <input type="radio" name="payment_system" value="lisa"
+ id="lisa-radio-button-id">Lisa</input>
+ <br/>
+ <input type="radio" name="payment_system" value="ycard">You Card</input>
+ <br/>
+ <input type="radio" name="payment_system" value="cardme">Card Me</input>
+ <br/>
+ <input type="radio" name="payment_system" value="taler"
+ id="taler-radio-button-id" disabled="true">Taler</input>
+ <br/>
+ <input type="button" onclick="pay(this.form)" value="Ok"></input>
+ </div>
+ </form>
+
+ </article>
+ </section>
<script type="text/javascript">
@@ -106,7 +133,7 @@ function handle_contract(json_contract)
{
var cEvent = new CustomEvent('taler-contract', { detail: json_contract });
- document.body.dispatchEvent(cEvent);
+ document.dispatchEvent(cEvent);
};
@@ -121,7 +148,7 @@ function taler_pay(form)
have its own way of generating and transmitting the
contract, there just must be a way to get the contract
and to pass it to the wallet when the user selects 'Pay'. */
- contract_request.open("GET", "/generate_taler_contract.php", true);
+ contract_request.open("GET", "generate_taler_contract.php", true);
contract_request.onload = function (e)
{
if (contract_request.readyState == 4)
@@ -129,9 +156,9 @@ function taler_pay(form)
if (contract_request.status == 200)
{
/* display contract_requestificate (i.e. it sends the JSON string
- to the extension) alert (contract_request.responseText); */
+ to the extension) alert (contract_request.responseText); */
+ console.log("response text:", contract_request.responseText);
handle_contract(contract_request.responseText);
-
}
else
{
@@ -211,7 +238,7 @@ function taler_wallet_unload_cb(aEvent)
function signal_taler_wallet_onload()
{
var eve = new Event('taler-checkout-probe');
- document.body.dispatchEvent(eve);
+ document.dispatchEvent(eve);
};
@@ -228,21 +255,20 @@ function test_without_wallet(){
// Register event to be triggered by the wallet as a response to our
// first event
-document.body.addEventListener("taler-wallet-present",
- has_taler_wallet_cb,
- false);
+document.addEventListener("taler-wallet-present",
+ has_taler_wallet_cb,
+ false);
// Register event to be triggered by the wallet when it gets enabled while
// the user is on the payment page
-document.body.addEventListener("taler-load",
- signal_taler_wallet_onload,
- false);
+document.addEventListener("taler-load",
+ signal_taler_wallet_onload,
+ false);
// Register event to be triggered by the wallet when it is unloaded
-document.body.addEventListener("taler-unload",
- taler_wallet_unload_cb,
- false);
-
+document.addEventListener("taler-unload",
+ taler_wallet_unload_cb,
+ false);
</script>
</body>
</html>
diff --git a/src/frontend/execute.js b/src/frontend/execute.js
new file mode 100644
index 00000000..a9045cb5
--- /dev/null
+++ b/src/frontend/execute.js
@@ -0,0 +1,33 @@
+"use strict";
+// JSX literals are compiled to calls to React.createElement calls.
+let React = {
+ createElement: function (tag, props, ...children) {
+ let e = document.createElement(tag);
+ for (let k in props) {
+ e.setAttribute(k, props[k]);
+ }
+ for (let child of children) {
+ if ("string" === typeof child || "number" == typeof child) {
+ child = document.createTextNode(child);
+ }
+ e.appendChild(child);
+ }
+ return e;
+ }
+};
+document.addEventListener("DOMContentLoaded", function (e) {
+ var eve = new CustomEvent('taler-execute-payment', { detail: { H_contract: h_contract } });
+ document.dispatchEvent(eve);
+});
+function replace(el, r) {
+ el.parentNode.replaceChild(r, el);
+}
+document.addEventListener("taler-payment-result", function (e) {
+ if (!e.detail.success) {
+ alert("Payment failed\n" + JSON.stringify(e.detail));
+ return;
+ }
+ console.log("finished payment");
+ let msg = React.createElement("div", null, "Payment successful. View your ", React.createElement("a", {"href": e.detail.fulfillmentUrl}, "product"), ".");
+ replace(document.getElementById("loading"), msg);
+});
diff --git a/src/frontend/execute.php b/src/frontend/execute.php
new file mode 100644
index 00000000..33021fd3
--- /dev/null
+++ b/src/frontend/execute.php
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Toy Store - Taler Demo</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ <script> /* @licstart The following is the entire license notice for the
+ JavaScript code in this page.
+
+ Copyright (C) 2015 GNUnet e.V.
+
+ The JavaScript code in this page is free software: you can
+ redistribute it and/or modify it under the terms of the GNU
+ Lesser General Public License (GNU LGPL) as published by the Free Software
+ Foundation, either version 2.1 of the License, or (at your option)
+ any later version. The code is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU LGPL for more details.
+
+ As additional permission under GNU LGPL version 2.1 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU LGPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ @licend The above is the entire license notice
+ for the JavaScript code in this page.
+ */
+ </script>
+ <script type="text/javascript">
+<?php
+session_start();
+echo "var h_contract=\"$_SESSION[H_contract]\";\n";
+?>
+ </script>
+ <script type="text/javascript" src="execute.js"></script>
+</head>
+
+<body>
+ <header>
+ <div id="logo">
+ <svg height="100" width="100">
+ <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" fill="white" />
+ <text x="19" y="82" font-family="Verdana" font-size="90" fill="darkcyan">S</text>
+ </svg>
+ </div>
+ <h1>Toy Store - Taler Demo</h1>
+ </header>
+
+ <aside class="sidebar" id="left">
+ </aside>
+
+ <section id="main">
+ <h1>Executing Payment ...</h1>
+ <div id="loading">Loading...</div>
+</body>
+</html>
diff --git a/src/frontend/execute.tsx b/src/frontend/execute.tsx
new file mode 100644
index 00000000..67cf8e06
--- /dev/null
+++ b/src/frontend/execute.tsx
@@ -0,0 +1,41 @@
+"use strict";
+
+
+// JSX literals are compiled to calls to React.createElement calls.
+let React = {
+ createElement: function(tag, props, ...children) {
+ let e = document.createElement(tag);
+ for (let k in props) {
+ e.setAttribute(k, props[k]);
+ }
+ for (let child of children) {
+ if ("string" === typeof child || "number" == typeof child) {
+ child = document.createTextNode(child);
+ }
+ e.appendChild(child);
+ }
+ return e;
+ }
+};
+
+declare var h_contract: string;
+
+document.addEventListener("DOMContentLoaded", function (e) {
+ var eve = new CustomEvent('taler-execute-payment', {detail: {H_contract: h_contract}});
+ document.dispatchEvent(eve);
+});
+
+function replace(el, r) {
+ el.parentNode.replaceChild(r, el);
+}
+
+document.addEventListener("taler-payment-result", function (e: CustomEvent) {
+ if (!e.detail.success) {
+ alert("Payment failed\n" + JSON.stringify(e.detail));
+ return;
+ }
+ console.log("finished payment");
+ let msg =
+ <div>Payment successful. View your <a href={e.detail.fulfillmentUrl}>product</a>.</div>;
+ replace(document.getElementById("loading"), msg);
+});
diff --git a/src/frontend/fullfillment.php b/src/frontend/fulfillment.php
index d7677aa7..32f3c0cd 100644
--- a/src/frontend/fullfillment.php
+++ b/src/frontend/fulfillment.php
@@ -6,7 +6,23 @@
</head>
<body>
-<?php
+ <header>
+ <div id="logo">
+ <svg height="100" width="100">
+ <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" fill="white" />
+ <text x="19" y="82" font-family="Verdana" font-size="90" fill="darkcyan">S</text>
+ </svg>
+ </div>
+
+ <h1>Toy Store - Payment succeeded</h1>
+ </header>
+
+ <aside class="sidebar" id="left">
+ </aside>
+
+ <section id="main">
+ <article>
+<?php
/*
This file is part of GNU TALER.
Copyright (C) 2014, 2015 GNUnet e.V.
@@ -27,6 +43,13 @@
$cli_debug = false;
$backend_test = true;
+function generate_msg ($link){
+ $msg = "<p>Thanks for donating to " . $_SESSION['receiver'] . ".</p>";
+ if (false != $link)
+ $msg .= "<p>Check our latest <a href=\"" . $link . "\">news!</a></p>";
+ return $msg;
+}
+
if ($_GET['cli_debug'] == 'yes')
$cli_debug = true;
@@ -38,13 +61,26 @@ if ($_GET['backend_test'] == 'no')
session_start();
-
if (! isset ($_SESSION['payment_ok']))
- echo "Please land here after a successful payment!";
-else
- echo "Thanks for donating to " . $_SESSION['receiver'];
+ echo "<p>Please land here after a successful payment!</p>";
+else{
+ $news = false;
+ switch ($_SESSION['receiver']){
+ case "Taler":
+ $news = "https://taler.net/news";
+ break;
+ case "GNUnet":
+ $news = "https://gnunet.org/";
+ break;
+ case "Tor":
+ $news = "https://www.torproject.org/press/press.html.en";
+ break;
+ }
+ echo generate_msg ($news);
+}
?>
-
+ </article>
+ </section>
</body>
</html>
diff --git a/src/frontend/generate_taler_contract.php b/src/frontend/generate_taler_contract.php
index c71542c8..14add359 100644
--- a/src/frontend/generate_taler_contract.php
+++ b/src/frontend/generate_taler_contract.php
@@ -35,10 +35,10 @@
$cli_debug = false;
$backend_test = true;
-if ($_GET['cli_debug'] == 'yes')
+if (isset($_GET['cli_debug']) && $_GET['cli_debug'] == 'yes')
$cli_debug = true;
-if ($_GET['backend_test'] == 'no')
+if (isset($_GET['backend_test']) && $_GET['backend_test'] == 'no')
{
$cli_debug = true;
$backend_test = false;
@@ -90,9 +90,12 @@ $teatax = array ('value' => 1,
// Take a timestamp
$now = new DateTime('now');
+$PAY_URL = "pay.php";
+$EXEC_URL = "execute.php";
+
// pack the JSON for the contract
// --- FIXME: exact format needs review!
-$json = json_encode (array ('amount' => array ('value' => $amount_value,
+$contract = array ('amount' => array ('value' => $amount_value,
'fraction' => $amount_fraction,
'currency' => $currency),
'max_fee' => array ('value' => 3,
@@ -110,7 +113,8 @@ $json = json_encode (array ('amount' => array ('value' => $amount_value,
'delivery_date' => "Some Date Format",
'delivery_location' => 'LNAME1')),
'timestamp' => "/Date(" . $now->getTimestamp() . ")/",
- 'pay_url' => "/taler/pay",
+ 'pay_url' => $PAY_URL,
+ 'exec_url' => $EXEC_URL,
'expiry' => "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/",
'refund_deadline' => "/Date(" . $now->add(new DateInterval('P3M'))->getTimestamp() . ")/",
'merchant' => array ('address' => 'LNAME2',
@@ -138,19 +142,22 @@ $json = json_encode (array ('amount' => array ('value' => $amount_value,
'state' => 'Test State',
'region' => 'Test Region',
'province' => 'Test Province',
- 'ZIP code' => 4908))), JSON_PRETTY_PRINT);
+ 'ZIP code' => 4908)));
+$json = json_encode (array ('contract' => $contract, 'exec_url' => $EXEC_URL, 'pay_url' => $PAY_URL), JSON_PRETTY_PRINT);
if ($cli_debug && !$backend_test)
{
echo $json . "\n";
exit;
}
-// Craft the HTTP request, note that the backend
-// could be on an entirely different machine if
-// desired.
-$req = new http\Client\Request ("POST",
- "http://" . $_SERVER["SERVER_NAME"] . "/backend/contract",
- array ("Content-Type" => "application/json"));
+
+$url = (new http\URL("http://".$_SERVER["HTTP_HOST"]))
+ ->mod(array ("path" => "backend/contract"), http\Url::JOIN_PATH);
+
+$req = new http\Client\Request("POST",
+ $url,
+ array ("Content-Type" => "application/json"));
+
$req->getBody()->append ($json);
// Execute the HTTP request
@@ -168,10 +175,11 @@ http_response_code ($status_code);
if ($status_code != 200)
{
echo "Error while generating the contract";
+ echo $resp->body->toString ();
}
else
-{
- // send the contract back to the wallet without touching it
+{ $got_json = json_decode ($resp->body->toString ());
+ $_SESSION['H_contract'] = $got_json->H_contract;
echo $resp->body->toString ();
}
?>
diff --git a/src/frontend/index.html b/src/frontend/index.html
index 8111735f..21ca0d65 100644
--- a/src/frontend/index.html
+++ b/src/frontend/index.html
@@ -1,36 +1,83 @@
<!DOCTYPE html>
<html lang="en">
<head>
- <title>Taler's "Demo" Shop</title>
+ <title>Toy &quot;Store&quot; - Taler Demo</title>
<link rel="stylesheet" type="text/css" href="style.css">
- <script> /* @licstart The following is the entire license notice for the
- JavaScript code in this page.
-
- Copyright (C) 2015 GNUnet e.V.
-
- The JavaScript code in this page is free software: you can
- redistribute it and/or modify it under the terms of the GNU
- Lesser General Public License (GNU LGPL) as published by the Free Software
- Foundation, either version 2.1 of the License, or (at your option)
- any later version. The code is distributed WITHOUT ANY WARRANTY;
- without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU LGPL for more details.
-
- As additional permission under GNU LGPL version 2.1 section 7, you
- may distribute non-source (e.g., minimized or compacted) forms of
- that code without the copy of the GNU LGPL normally required by
- section 4, provided you include this license notice and a URL
- through which recipients can access the Corresponding Source.
-
- @licend The above is the entire license notice
- for the JavaScript code in this page.
- */
- </script>
+ <script type="text/javascript">
+ /* @licstart The following is the entire license notice for the
+ JavaScript code in this page.
+
+ Copyright (C) 2015 GNUnet e.V.
+
+ The JavaScript code in this page is free software: you can
+ redistribute it and/or modify it under the terms of the GNU
+ Lesser General Public License (GNU LGPL) as published by the Free Software
+ Foundation, either version 2.1 of the License, or (at your option)
+ any later version. The code is distributed WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU LGPL for more details.
+
+ As additional permission under GNU LGPL version 2.1 section 7, you
+ may distribute non-source (e.g., minimized or compacted) forms of
+ that code without the copy of the GNU LGPL normally required by
+ section 4, provided you include this license notice and a URL
+ through which recipients can access the Corresponding Source.
+
+ @licend The above is the entire license notice
+ for the JavaScript code in this page.
+ */
+ function handleInstall() {
+ var b = document.getElementById("main");
+ b.classList.add("installed");
+ };
+
+ function handleUninstall() {
+ var b = document.getElementById("main");
+ b.classList.remove("installed");
+ };
+
+ function probeTaler() {
+ var eve = new Event("taler-probe");
+ document.dispatchEvent(eve);
+ }
+
+
+ // Only probe taler once the DOM is ready and
+ // we can manipulate it.
+ window.addEventListener("load", probeTaler, false);
+
+ document.addEventListener("taler-wallet-present", handleInstall, false);
+ document.addEventListener("taler-unload", handleUninstall, false);
+ document.addEventListener("taler-load", handleInstall, false);
+
+ </script>
+ <style>
+ *:not(.installed) .if-installed { display: none }
+ .installed .if-not-installed { display: none }
+ *:not(.installed) .if-not-installed { display: initial }
+ .installed .if-installed { display: initial }
+ </style>
</head>
-<body id="css-zen-garden" onload="signal_me()">
- <div class="supporting" id="welcome" role="main">
- <div class="explanation" id="zen-explanation" role="article">
- <h1>Welcome to the Taler "Demo" Shop</h1>
+
+<body>
+ <header>
+ <div id="logo">
+ <svg height="100" width="100">
+ <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" fill="white" />
+ <text x="19" y="82" font-family="Verdana" font-size="90" fill="darkcyan">S</text>
+ </svg>
+ </div>
+
+ <h1>Toy &quot;Store&quot; - Taler Demo</h1>
+ </header>
+
+ <aside class="sidebar" id="left">
+ </aside>
+
+ <section id="main">
+ <article>
+ <h1>Welcome to the Taler Demo Shop</h1>
+
<p>This "toy" website provides you with the ability to
experience using the
<a href="https://www.taler.net/">GNU Taler</a>
@@ -45,152 +92,93 @@
<tt>mint.demo.taler.net</tt> and
<tt>bank.demo.taler.net</tt>, correspond to a Taler mint
and bank with tight Taler integration respectively.
- <!-- TODO: maybe offer the wallet at 'taler.net/extension' in the
- future, instead of at 'demo.taler.net/'? -->
- </p>
- </div>
- </div>
- <div class="supporting" id="instructions" role="main">
- <div class="explanation" id="installation" role="article">
- <h2>Step 1: Installing the Taler wallet (once)</h2>
- <p>First, you need to install the Taler wallet browser extension.
- It is currently only available for Firefox. If you run
- Firefox, simply click <a href="http://demo.taler.net/extension">here</a>
- to download and install the extension. You will then have to
- click on "allow" and "install" dialogs shown by Firefox.
- After that, the Taler logo should appear on the right side
- of your navigation bar.
- <!-- TODO: insert screenshot highlighting the icon? -->
- </p>
- </div>
- <div class="explanation" id="installation-done" role="article" style="display:none;">
- <h2>Step 1: Installing the Taler wallet (done!)</h2>
- <p>Congratulations, you have installed the Taler wallet correctly.
- You can now proceed with the next steps.
</p>
- </div>
- <div class="explanation" id="wire" role="article" style="display:none;">
- <h2>Step 2: Withdraw coins (occasionally)</h2>
- <p>The next step is to withdraw coins, after all you cannot
- pay with an empty wallet. To be allowed to withdraw
- coins from a mint, you first need to transfer currency to the mint
- using the normal banking system, for example by using a
- wire transfer. If the bank offers a tight integration with Taler, it
- may also support this directly over the home banking online interface.
- <br>
- For the demonstration, we have created a "bank" that
- allows you to "wire" funds (in KUDOS) to the mint simply by
- filling in the desired amount into a form. Naturally, when
- using a real bank with real money, you would have to authenticate
- and authorize the transfer.
- <br>
- Note that you would not do this step for each purchase or each shop.
- Payment with Taler is like paying
- with cash: you withdraw currency at the bank (or an ATM) and then
- pay at many merchants without having to authenticate each time.
- <br>
- So, unless you have already done so, please go ahead and withdraw
- KUDOS at the
- <a href="http://bank.demo.taler.net/" target="_blank">Demo bank</a>
- (opens in a new tab).</p>
- </p>
- </div>
- <div class="explanation" id="payment" role="article" style="display:none;">
- <h2>Step 3: Shop! (as long as you have KUDOS left in the wallet)</h2>
- <p>Now it is time to spend your hard earned KUDOS.
- Note that we cannot really tell if you got any yet,
- as your Taler wallet balance is visible to you, but
- of course is hidden entirely from the shop.</p>
- <p>The form that follows corresponds to the shopping
- cart of a real Web shop; however, we kept it
- very simple for the demonstration.</p>
- <p>So, please choose a project and the amount of KUDOS you
- wish to donate:</p>
- <form name="tform" action="/checkout.php" method="POST">
- <div class="participation" id="fake-shop">
- <br>
- <input type="radio" name="donation_receiver" value="Taler" checked="true">GNU Taler</input>
- <br>
- <input type="radio" name="donation_receiver" value="Tor">Tor</input>
- <br>
- <input type="radio" name="donation_receiver" value="GNUnet">GNUnet</input>
+ </article>
+
+ <section>
+
+ <article>
+ <h2>Step 1: Installing the Taler wallet</h2>
+ <p class="if-not-installed">
+ First, you need to <a href="http://demo.taler.net/">install</a>
+ the Taler wallet browser extension.
+ </p>
+ <p class="if-installed">
+ Congratulations, you have installed the Taler wallet correctly.
+ You can now proceed with the next steps.
+ </p>
+ </article>
+
+ <article class="if-installed">
+ <h2>Step 2: Withdraw coins <sup>(occasionally)</sup></h2>
+
+ <p>The next step is to withdraw coins, after all you cannot
+ pay with an empty wallet. To be allowed to withdraw
+ coins from a mint, you first need to transfer currency to the mint
+ using the normal banking system, for example by using a
+ wire transfer. If the bank offers a tight integration with Taler, it
+ may also support this directly over the home banking online interface.
<br>
- <select id="taler-donation" name="donation_amount">
- <option value="0.1">0.1 KUDOS</option>
- <option value="1.0">1 KUDOS</option>
- <option value="6.0">5 KUDOS (*)</option>
- <option value="10.0">10 KUDOS</option>
- </select>
- <input type="hidden" name="donation_currency" value="KUDOS"/>
- <input type="submit" name="keyName" value="Donate!"/>
+ For the demonstration, we have created a "bank" that
+ allows you to "wire" funds (in KUDOS) to the mint simply by
+ filling in the desired amount into a form. Naturally, when
+ using a real bank with real money, you would have to authenticate
+ and authorize the transfer.
<br>
+ Note that you would not do this step for each purchase or each shop.
+ Payment with Taler is like paying
+ with cash: you withdraw currency at the bank (or an ATM) and then
+ pay at many merchants without having to authenticate each time.
<br>
- </div>
- </form>
- <p>(*) To make it a bit more fun, the 5 KUDOS option
- is deliberately implemented with a fault: the merchant will try to
- make you donate 6 KUDOS instead of the 5 KUDOS you got to see. But do
- not worry, you will be given the opportunity to review the
- final offer from the merchant in a window secured
- by the Taler extension. That way, you can spot the
- error before committing to an incorrect contract.</p>
- </p>
- </div>
- </div>
- <script type="text/javascript">
- /* This function is called if/when a Wallet is installed.
- It should enable the parts of the page that only make
- sense after the Wallet has been loaded.
- */
- function wallet_installed_cb(){
- b = document.getElementById("installation");
- b.style.display = 'none';
- b = document.getElementById("installation-done");
- b.style.display = '';
- b = document.getElementById("wire");
- b.style.display = '';
- b = document.getElementById("payment");
- b.style.display = '';
- };
+ So, unless you have already done so, please go ahead and withdraw
+ KUDOS at the
+ <a href="http://bank.demo.taler.net/" target="_blank">Demo bank</a>
+ (opens in a new tab).</p>
+ </article>
- function wallet_uninstalled_cb(){
- b = document.getElementById("installation");
- b.style.display = '';
- b = document.getElementById("installation-done");
- b.style.display = 'none';
- b = document.getElementById("wire");
- b.style.display = 'none';
- b = document.getElementById("payment");
- b.style.display = 'none';
- };
+ <article class="if-installed">
+ <h2>Step 3: Shop! <sup>(as long as you have KUDOS left)</sup></h2>
- /* The merchant signals its taler-friendlyness to the client */
- function signal_me()
- {
- var eve = new Event('taler-checkout-probe');
- document.body.dispatchEvent(eve);
- //alert("signaling");
- };
+ <p>Now it is time to spend your hard earned KUDOS.
+ Note that we cannot really tell if you got any yet,
+ as your Taler wallet balance is visible to you, but
+ of course is hidden entirely from the shop.</p>
+ <p>The form that follows corresponds to the shopping
+ cart of a real Web shop; however, we kept it
+ very simple for the demonstration.</p>
+ <p>So, please choose a project and the amount of KUDOS you
+ wish to donate:</p>
- function test_without_wallet(){
- wallet_installed_cb();
- }
-
- document.body.addEventListener("taler-unload",
- wallet_uninstalled_cb,
- false, false);
-
- /* Set up a listener to be called whenever a Wallet gets installed
- so that the user is led towards the demo's steps progressively */
- document.body.addEventListener("taler-wallet-present",
- wallet_installed_cb,
- false, false);
-
- /* Setup callback to be called whenever the wallet is loaded/enabled
- while the browser is already on this page */
- document.body.addEventListener("taler-load",
- signal_me,
- false);
- </script>
+ <form name="tform" action="checkout.php" method="POST">
+ <div class="participation" id="fake-shop">
+ <br>
+ <input type="radio" name="donation_receiver" value="Taler" checked="true">GNU Taler</input>
+ <br>
+ <input type="radio" name="donation_receiver" value="Tor">Tor</input>
+ <br>
+ <input type="radio" name="donation_receiver" value="GNUnet">GNUnet</input>
+ <br>
+ <select id="taler-donation" name="donation_amount">
+ <option value="0.1">0.1 KUDOS</option>
+ <option value="1.0">1 KUDOS</option>
+ <option value="6.0">5 KUDOS (*)</option>
+ <option value="10.0">10 KUDOS</option>
+ </select>
+ <input type="hidden" name="donation_currency" value="KUDOS"/>
+ <input type="submit" name="keyName" value="Donate!"/>
+ <br>
+ <br>
+ </div>
+ </form>
+ <p>(*) To make it a bit more fun, the 5 KUDOS option
+ is deliberately implemented with a fault: the merchant will try to
+ make you donate 6 KUDOS instead of the 5 KUDOS you got to see. But do
+ not worry, you will be given the opportunity to review the
+ final offer from the merchant in a window secured
+ by the Taler extension. That way, you can spot the
+ error before committing to an incorrect contract.</p>
+ </article>
+ </section>
+ </section>
</body>
</html>
diff --git a/src/frontend/pay.php b/src/frontend/pay.php
index 97ee5290..bf0be438 100644
--- a/src/frontend/pay.php
+++ b/src/frontend/pay.php
@@ -23,39 +23,39 @@
NOTE: 'max_fee' must be consistent with the same value indicated within
the contract; thus, a "real" merchant must implement such a mapping
-*/
+ */
+
+session_start();
$cli_debug = false;
$backend_test = true;
-if ($_GET['cli_debug'] == 'yes')
+if (isset($_GET['cli_debug']) && $_GET['cli_debug'] == 'yes')
+{
$cli_debug = true;
+}
-if ($_GET['backend_test'] == 'no')
+if (isset($_GET['backend_test']) && $_GET['backend_test'] == 'no')
{
$cli_debug = true;
$backend_test = false;
}
-session_start();
-
-if (!$cli_debug && (! isset($_SESSION['receiver'])))
+if (!isset($_SESSION['H_contract']))
{
- http_response_code(400);
- echo "Please, donate to someone before landing here!";
- exit();
+ echo "No session active.";
+ http_response_code (301);
+ return;
}
-$cli_debug = false;
-$backend_test = true;
-
-if ($_GET['cli_debug'] == 'yes')
- $cli_debug = true;
-
-if ($_GET['backend_test'] == 'no')
+if (isset($_SESSION['payment_ok']) && $_SESSION['payment_ok'] == true)
{
- $cli_debug = true;
- $backend_test = false;
+ $_SESSION['payment_ok'] = true;
+ http_response_code (301);
+ $url = (new http\URL($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']))
+ ->mod(array ("path" => "fulfillment.php"), http\Url::JOIN_PATH);
+ header("Location: $url");
+ die();
}
$post_body = file_get_contents('php://input');
@@ -66,15 +66,15 @@ $edate = array ('edate' =>
$deposit_permission = json_decode ($post_body, true);
-$to_add = array ('max_fee' => array ('value' => 3,
- 'fraction' => 8,
- 'currency' => $_SESSION['currency']),
- 'amount' => array ('value' => $_SESSION['amount_value'],
- 'fraction' => $_SESSION['amount_fraction'],
- 'currency' => $_SESSION['currency']));
+$to_add = array('max_fee' => array('value' => 3,
+ 'fraction' => 8,
+ 'currency' => $_SESSION['currency']),
+ 'amount' => array('value' => $_SESSION['amount_value'],
+ 'fraction' => $_SESSION['amount_fraction'],
+ 'currency' => $_SESSION['currency']));
-$new_deposit_permission = array_merge ($deposit_permission, $to_add);
-$new_deposit_permission_edate = array_merge ($new_deposit_permission, $edate);
+$new_deposit_permission = array_merge($deposit_permission, $to_add);
+$new_deposit_permission_edate = array_merge($new_deposit_permission, $edate);
/* Craft the HTTP request, note that the backend
could be on an entirely different machine if
@@ -85,14 +85,25 @@ if ($cli_debug && !$backend_test)
/* DO NOTE the newline at the end of 'echo's argument */
//echo json_encode ($new_deposit_permission_edate, JSON_PRETTY_PRINT)
- echo json_encode ($new_deposit_permission, JSON_PRETTY_PRINT)
+ echo json_encode($new_deposit_permission, JSON_PRETTY_PRINT)
. "\n";
exit;
}
-$req = new http\Client\Request ("POST",
- "http://" . $_SERVER["SERVER_NAME"] . "/backend/pay",
- array ("Content-Type" => "application/json"));
+
+// Backend is relative to the shop site.
+/**
+ * WARNING: the "shop site" is '"http://".$_SERVER["HTTP_HOST"]'
+ * So do not attach $_SERVER["REQUEST_URI"] before proxying requests
+ * to the backend
+ */
+//$url = (new http\URL("http://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]))
+$url = (new http\URL("http://".$_SERVER["HTTP_HOST"]))
+ ->mod(array ("path" => "backend/pay"), http\Url::JOIN_PATH);
+
+$req = new http\Client\Request("POST",
+ $url,
+ array ("Content-Type" => "application/json"));
$req->getBody()->append (json_encode ($new_deposit_permission));
// Execute the HTTP request
@@ -112,15 +123,19 @@ if ($status_code != 200)
/* error: just forwarding to the wallet what
gotten from the backend (which is forwarding 'as is'
the error gotten from the mint) */
+ echo json_encode ($new_deposit_permission);
+ echo "Error came from the backend, status $status_code\n";
+ echo "\n";
echo $resp->body->toString ();
-
}
else
{
-$_SESSION['payment_ok'] = true;
-http_response_code (301);
-header("Location: http://" . $_SERVER["SERVER_NAME"] . "/fullfillment");
-die();
+ $_SESSION['payment_ok'] = true;
+ http_response_code (301);
+ $url = (new http\URL($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']))
+ ->mod(array ("path" => "fulfillment.php"), http\Url::JOIN_PATH);
+ header("Location: $url");
+ die();
}
?>
diff --git a/src/frontend/style.css b/src/frontend/style.css
index e69de29b..c2cc51ee 100644
--- a/src/frontend/style.css
+++ b/src/frontend/style.css
@@ -0,0 +1,123 @@
+body {
+ background-color: white;
+ margin: 0;
+ padding: 0;
+ font-family: Verdana, sans;
+}
+
+header {
+ width: 100%;
+ height: 100px;
+ margin: 0;
+ padding: 0;
+ border-bottom: 1px solid black;
+}
+
+header h1 {
+ font-size: 200%;
+ margin: 0;
+ padding: 0 0 0 120px;
+ position: relative;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+header #logo {
+ float: left;
+ width: 100px;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+ border-right: 1px solid black;
+}
+
+aside {
+ width: 100px;
+ float: left;
+}
+
+section#main {
+ margin: 0 0 0 100px;
+ padding: 20px;
+ border-left: 1px solid black;
+ height: 100%;
+ max-width: 40em;
+}
+
+section#main h1:first-child {
+ margin-top: 0;
+}
+
+h1 {
+ font-size: 160%;
+}
+
+h2 {
+ font-size: 140%;
+}
+
+h3 {
+ font-size: 120%;
+}
+
+h4, h5, h6 {
+ font-size: 100%;
+}
+
+.loader {
+ font-size: 10px;
+ margin: 50px auto;
+ text-indent: -9999em;
+ width: 11em;
+ height: 11em;
+ border-radius: 50%;
+ background: #ffffff;
+ background: -moz-linear-gradient(left, #000 10%, rgba(255, 255, 255, 0) 42%);
+ background: -webkit-linear-gradient(left, #000 10%, rgba(255, 255, 255, 0) 42%);
+ background: -o-linear-gradient(left, #000 10%, rgba(255, 255, 255, 0) 42%);
+ background: -ms-linear-gradient(left, #000 10%, rgba(255, 255, 255, 0) 42%);
+ position: relative;
+ -webkit-animation: load3 1.4s infinite linear;
+ animation: load3 1.4s infinite linear;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+}
+
+.loader:after {
+ background: #fff;
+ width: 75%;
+ height: 75%;
+ border-radius: 50%;
+ content: '';
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+
+@-webkit-keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+