merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 69bbbd9a4d9dd7bc2bd15cea190743f5c5276636
parent 7e253f1d8b8d93348d8bd1b1144eaee446061dd0
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 18 Aug 2015 22:56:03 +0200

clean up logic, more comments, etc.

Diffstat:
Dsrc/frontend/cert.php | 83-------------------------------------------------------------------------------
Msrc/frontend/checkout.php | 165++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Asrc/frontend/generate_taler_contract.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/frontend/index.html | 8++++----
4 files changed, 199 insertions(+), 155 deletions(-)

diff --git a/src/frontend/cert.php b/src/frontend/cert.php @@ -1,83 +0,0 @@ -<!DOCTYPE html> -<?php -/* - This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> -*/ - -/* - - Here goes all the Taler paying logic. The steps are - - 1. recover the session - 2. generate the JSON to forward to the backend - 3. route back to the wallet the certificate just gotten -*/ - - -// recover the session -session_start(); -if(!isset($_SESSION['maydonate'])){ - http_response_code(404); - echo "Please try to donate before getting to this page :)"; -} -else{ - // fake product id - $p_id = rand(0,1001); - // generate a transaction/certificate id. In production context, it's wishable to - // record this value - $trans_cert_id = rand(0, 1001); - // fake a human readable description of this deal - $desc = "donation aimed to stop the ants' massacre on hicking paths"; - // fake the price's integer (actually, the system is testishly suited for just 10 EUR coins) - $value = 10; - // fake the price's fractional - $fraction = 0; - // hardcode the currency - $currency = "EUR"; - - // pack the JSON - $json = json_encode (array ('desc' => $desc, 'product' => $p_id, 'cid' => $trans_cert_id, - 'price' => array ('value' => $value, - 'fraction' => $fraction, - 'currency' => $currency))); - // test - // echo $json; - // echo phpinfo (); - - // crafting the request - $req = new http\Client\Request ("POST", - "http://" . $_SERVER["SERVER_NAME"] . "/backend" . "/contract", - //"http://localhost:9898/", - array ("Content-Type" => "application/json")); - $req->getBody()->append ($json); - - $client = new http\Client; - $client->enqueue($req)->send (); - $resp = $client->getResponse (); - $status_code = $resp->getResponseCode (); - http_response_code ($status_code); - - - if ($status_code != 200){ - echo "Error while generating the certificate, response code : " . $status_code; - } - // send the contract back to the wallet without touching it - else{ - echo $resp->body->toString (); - } -} - - -?> diff --git a/src/frontend/checkout.php b/src/frontend/checkout.php @@ -34,109 +34,138 @@ payments methods and actually implementing just Taler; technically the steps are: - 1. retrieve the name of who will receive this donation - 2. show a menu with all the required payments means - 3. create a session - 4. (JavaScript) implement the "checkout" button for the sole Taler way. - Actually, this button's duty is to notice this web portal that the customer - wants to see a certificate, and optionally to pay. - - --> + 1. retrieve the information about the donation from the + form and remember it in a PHP session + 2. show a menu with all the required payments system options, + only showing "Taler" if the wallet is present + 3. (JavaScript) implement the "checkout" button for Taler, + for the demo we ignore the other payment options. +--> <?php - -// getting the donation receiver's name -$got_donation = $_POST['group0']; -// create session -session_start(); -$_SESSION['maydonate'] = true; + // get the donation information from form + $donation_receiver = $_POST['donation_receiver']; + $donation_amount = $_POST['donation_amount']; + + // create PHP session and store donation information in session + session_start(); + $_SESSION['receiver'] = $donation_receiver; + $_SESSION['amount'] = $donation_amount; ?> <form name="tform" action="" method="POST"> -<div id="opt-form" align="left"><br> -<input type="radio" name="group1" value="Lisa">Lisa<br> -<input type="radio" name="group1" value="You Card" checked>You Card<br> -<input type="radio" name="group1" value="Card Me">Card Me<br> -<input id="t-button-id" type="radio" name="group1" value="Taler" disabled="true">Taler<br> -<input type="button" onclick="ok(this.form)" value="Ok"> -</div> + <div id="opt-form" align="left"><br> + <input type="radio" name="payment_system" value="lisa" checked>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> <script type="text/javascript"> -// trigger certificate generation on the server, and signal certificate -// arrival "here" in the client. - -function ok(form){ - for(var cnt=0; cnt < form.group1.length; cnt++){ - var choice = form.group1[cnt]; - if(choice.checked){ - if(choice.value == "Taler"){ - var cert = new XMLHttpRequest(); - /* request certificate */ - cert.open("POST", "/cert.php", true); - cert.onload = function (e) { - if (cert.readyState == 4) { - if (cert.status == 200){ - /* display certificate (i.e. it sends the JSON string - to the (XUL) extension) */ - sendContract(cert.responseText); - } - else alert("No certificate gotten, status " + cert.status); - } - }; - - cert.onerror = function (e){ - alert(cert.statusText); - }; - - cert.send(null); - } - else alert(choice.value + ": NOT available "); - } - } +/* We got a JSON contract from the merchant, + pass it to the extension */ +function handle_contract(json_contract) +{ + var cevent = new CustomEvent('taler-contract', { 'detail' : jsonContract }); + document.body.dispatchEvent(cevent); }; +/* Trigger Taler contract generation on the server, and pass the + contract to the extension once we got it. */ +function taler_pay(form) +{ + var contract_request = new XMLHttpRequest(); + contract_request.open("POST", "/generate_taler_contract.php", true); + contract_request.onload = function (e) + { + if (contract_request.readyState == 4) + { + if (contract_request.status == 200) + { + /* display contract_requestificate (i.e. it sends the JSON string + to the (XUL) extension) */ + handle_contract(contract_request.responseText); + } + else + { + alert("Failed to receive contract from server. Status was " + contract_request.status); + } + } + }; + contract_request.onerror = function (e) + { + alert(contract_request.statusText); + }; + contract_request.send(null); +} + + +/* This function is called when the user presses the + 'Ok' button. We are now supposed to trigger the + "corret" payment system logic. For this demo, we + only handle "taler". */ +function pay(form) +{ + for (var cnt=0; cnt < form.payment_system.length; cnt++) + { + var choice = form.payment_system[cnt]; + + if (choice.checked) + { + if (choice.value == "taler") + { + taler_pay(form); + } + else + { + alert(choice.value + ": NOT available in this demo!"); + } + } + } +}; -/* the following event gets fired whenever a customer has a Taler +/* The following event gets fired whenever a customer has a Taler wallet installed in his browser. In that case, the webmaster can decide whether or not displaying Taler as a payment option */ - -function has_taler_wallet_cb(aEvent){ +function has_taler_wallet_cb(event) +{ // event awaited by the wallet to change its button's color var eve = new Event('taler-currency'); document.body.dispatchEvent(eve); // enable the Taler payment option from the form - var tbutton = document.getElementById("t-button-id"); + var tbutton = document.getElementById("taler-radio-button-id"); tbutton.removeAttribute("disabled"); }; -// The Taler extension was unloaded, disable the option -function taler_wallet_unload_cb(aEvent){ - var tbutton = document.getElementById("t-button-id"); +/* Function called when the Taler extension was unloaded, + here we disable the option */ +function taler_wallet_unload_cb(event) +{ + var tbutton = document.getElementById("taler-radio-button-id"); tbutton.addAttribute("disabled"); }; - -function sendContract(jsonContract){ - - var cevent = new CustomEvent('taler-contract', { 'detail' : jsonContract }); - document.body.dispatchEvent(cevent); -}; /* FIXME: these triggers do not work when I enable/disable the extension... */ -// to be triggered by the wallet +// Register event to be triggered by the wallet (when present) document.body.addEventListener("taler-wallet", has_taler_wallet_cb, false); -// to be triggered by the wallet when it is unloaded +// Register event to be triggered by the wallet when it is unloaded document.body.addEventListener("taler-unload", taler_wallet_unload_cb, false); - </script> </body> </html> diff --git a/src/frontend/generate_taler_contract.php b/src/frontend/generate_taler_contract.php @@ -0,0 +1,98 @@ +<?php +/* + This file is part of TALER + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> +*/ + +/* + This code generates a Taler contract in JSON format. Key steps are: + + 1. recover the PHP session with the contract information + 2. generate the JSON to forward to the backend + 3. forward the response with the contract from the backend to + to the wallet +*/ + + +// 1) recover the session information +session_start(); +if ( (! isset($_SESSION['receiver'])) || + (! isset($_SESSION['amount'])) +{ + http_response_code (404); + echo "Please select a contract before getting to this page..."; + exit (0); +} + +/* Obtain session state */ +$receiver = $_SESSION['receiver']; +$amount = intval ($_SESSION['amount']); + +/* Fill in variables for simple JSON contract */ +// fake product id +// --- FIXME: base on receiver for more realism! +$p_id = rand(0,1001); +// generate a front-end transaction id. +// In production context, we might want to +// record this value somewhere together +// with the rest of the contract data. +$transaction_id = rand(0, 1001); +// Human-readable description of this deal +$desc = "Donation to " . $receiver; +// Add the value +$value = $amount; +// We don't have a fraction. +$fraction = 0; +// This is our 'toy' currency +$currency = "KUDOS"; + +// pack the JSON for the contract +// --- FIXME: exact format needs review! +$json = json_encode (array ('desc' => $desc, + 'product' => $p_id, + 'cid' => $transaction_id, + 'price' => array ('value' => $value, + 'fraction' => $fraction, + 'currency' => $currency))); + +// Craft the HTTP request, note that the backend +// could be on an entirely different machine if +// desired. +$req = new http\Client\Request ("POST", + "/backend/contract", + array ("Content-Type" => "application/json")); +$req->getBody()->append ($json); + +// Execute the HTTP request +$client = new http\Client; +$client->enqueue($req)->send (); + +// Fetch the response +$resp = $client->getResponse (); +$status_code = $resp->getResponseCode (); + +// Our response code is the same we got from the backend: +http_response_code ($status_code); + +// Now generate our body +if ($status_code != 200) +{ + echo "Error while generating the contract, response code: " . $status_code; +} +else +{ + // send the contract back to the wallet without touching it + echo $resp->body->toString (); +} +?> diff --git a/src/frontend/index.html b/src/frontend/index.html @@ -108,13 +108,13 @@ <form name="tform" action="/checkout.php" method="POST"> <div class="participation" id="fake-shop"> <br> - <input type="radio" name="group0" value="Taler" checked="true">Taler</input> + <input type="radio" name="donation_receiver" value="Taler" checked="true">Taler</input> <br> - <input type="radio" name="group0" value="Tor">Tor</input> + <input type="radio" name="donation_receiver" value="Tor">Tor</input> <br> - <input type="radio" name="group0" value="GNUnet">GNUnet</input> + <input type="radio" name="donation_receiver" value="GNUnet">GNUnet</input> <br> - <select id="taler-donation" name="kudos-donation"> + <select id="taler-donation" name="donation_amount"> <option value="1">1 KUDOS</option> <option value="6">5 KUDOS (*)</option> <option value="10">10 KUDOS</option>