merchant

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

commit 095639e421333a22cfd118b8c7be8b9b55ce474d
parent 19f94aa343c693b04664c4be86a0388f4bdf3835
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 15 Feb 2016 17:26:56 +0100

Merge branch 'master' of ssh://taler.net/var/git/merchant

Diffstat:
Msrc/backend/merchant.conf | 2+-
Msrc/backend/taler-merchant-httpd_contract.c | 4++--
Msrc/backend/taler-merchant-httpd_pay.c | 12++++++------
Msrc/frontend/checkout.php | 2+-
Asrc/frontend/config.php | 19+++++++++++++++++++
Msrc/frontend/fulfillment.php | 34+++++++++++++++++++++-------------
Msrc/frontend/generate_taler_contract.php | 20++++++++++++++++----
Dsrc/frontend/index.html | 132-------------------------------------------------------------------------------
Asrc/frontend/index.php | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/frontend/pay.php | 43++++++++++++++-----------------------------
Dsrc/frontend_blog/articles/essay-x.html | 19-------------------
Asrc/frontend_blog/articles/fs-essay.html | 390+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/frontend_blog/cc_payment.php | 2+-
Asrc/frontend_blog/essay_cc_pay-fulfillment.php | 22++++++++++++++++++++++
Dsrc/frontend_blog/essay_cc_pay.php | 18------------------
Msrc/frontend_blog/essay_contract.php | 57+++++++++++++++++++++++++++++++++++----------------------
Msrc/frontend_blog/essay_fulfillment.php | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Asrc/frontend_blog/essay_offer.php | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/frontend_blog/essay_pay.php | 78+++++++++++++++++++++++++++++++++++++-----------------------------------------
Dsrc/frontend_blog/execute.js | 33---------------------------------
Dsrc/frontend_blog/execute.php | 56--------------------------------------------------------
Dsrc/frontend_blog/execute.tsx | 41-----------------------------------------
Msrc/frontend_blog/index.html | 13+++++++++----
Dsrc/frontend_blog/teaser.php | 49-------------------------------------------------
Msrc/frontend_lib/merchants.php | 8+++-----
25 files changed, 879 insertions(+), 489 deletions(-)

diff --git a/src/backend/merchant.conf b/src/backend/merchant.conf @@ -25,7 +25,7 @@ EDATE = 3 week DB = postgres [mint-taler] -URI = http://mint.demo.taler.net/ +URI = http://mint.test.taler.net/ MASTER_KEY = Q1WVGRGC1F4W7RYC6M23AEGFEXQEHQ730K3GG0B67VPHQSRR75H0 # Auditors must be in sections "auditor-", the rest of the section diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c @@ -61,7 +61,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, uint64_t transaction_id; struct TMH_PARSE_FieldSpecification spec[] = { TMH_PARSE_member_amount ("amount", &total), - TMH_PARSE_member_amount ("max_fee", &total), + TMH_PARSE_member_amount ("max_fee", &max_fee), TMH_PARSE_member_uint64 ("transaction_id", &transaction_id), TMH_PARSE_MEMBER_END }; @@ -130,7 +130,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:O, s:O, s:O}", "contract", jcontract, - "sig", TALER_json_from_data (&contract_sig, + "merchant_sig", TALER_json_from_data (&contract_sig, sizeof (contract_sig)), "H_contract", TALER_json_from_data (&contract.h_contract, sizeof (contract.h_contract))); diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c @@ -641,15 +641,15 @@ MH_handler_pay (struct TMH_RequestHandler *rh, struct TALER_MerchantSignatureP merchant_sig; struct TALER_ContractPS cp; struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_array ("coins", &coins), - TMH_PARSE_member_string ("mint", &pc->chosen_mint), - TMH_PARSE_member_uint64 ("transaction_id", &pc->transaction_id), - TMH_PARSE_member_amount ("max_fee", &pc->max_fee), TMH_PARSE_member_amount ("amount", &pc->amount), - TMH_PARSE_member_time_abs ("timestamp", &pc->timestamp), - TMH_PARSE_member_time_abs ("refund_deadline", &pc->refund_deadline), + TMH_PARSE_member_array ("coins", &coins), TMH_PARSE_member_fixed ("H_contract", &pc->h_contract), + TMH_PARSE_member_amount ("max_fee", &pc->max_fee), TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig), + TMH_PARSE_member_string ("mint", &pc->chosen_mint), + TMH_PARSE_member_time_abs ("refund_deadline", &pc->refund_deadline), + TMH_PARSE_member_time_abs ("timestamp", &pc->timestamp), + TMH_PARSE_member_uint64 ("transaction_id", &pc->transaction_id), TMH_PARSE_MEMBER_END }; diff --git a/src/frontend/checkout.php b/src/frontend/checkout.php @@ -142,7 +142,7 @@ function taler_pay(form) { var contract_request = new XMLHttpRequest(); /* Note that the URL we give here is specific to the Demo-shop - and not required by the protocol: each web shop can + and not dictated by the protocol: each web shop can 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'. */ diff --git a/src/frontend/config.php b/src/frontend/config.php @@ -0,0 +1,19 @@ +<?php + +$host = $_SERVER["HTTP_HOST"]; + +switch ($host) { +case "shop.demo.taler.net": + $SHOP_CURRENCY = "KUDOS"; + break; +case "shop.test.taler.net": + $SHOP_CURRENCY = "PUDOS"; + break; +default: + http_response_code ($status_code); + echo "<p>Configuration error: No currency for domain $host</p>\n"; + die(); + break; +} + +?> diff --git a/src/frontend/fulfillment.php b/src/frontend/fulfillment.php @@ -5,10 +5,11 @@ <link rel="stylesheet" type="text/css" href="style.css"> <script type="application/javascript" src="taler-presence.js"></script> <script type="application/javascript"> - function executePayment(H_contract, pay_url) { + function executePayment(H_contract, pay_url, offering_url) { var detail = { H_contract: H_contract, - pay_url: pay_url + pay_url: pay_url, + offering_url: offering_url }; var eve = new CustomEvent('taler-execute-payment', {detail: detail}); document.dispatchEvent(eve); @@ -52,14 +53,6 @@ include '../frontend_lib/util.php'; -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; -} - $hc = get($_GET["uuid"]); if (empty($hc)) @@ -74,23 +67,31 @@ session_start(); $payments = get($_SESSION['payments'], array()); $my_payment = get($payments[$hc]); +// This will keep the query parameters. +$pay_url = url_rel("pay.php"); + +$offering_url = url_rel("checkout.php", true); + if (null === $my_payment) { echo "<p>you do not have the session state for this contract: " . $hc . "</p>"; + echo "<p>Asking the wallet to re-execute it ... </p>"; + echo "<script>executePayment('$hc', '$pay_url', '$offering_url');</script>"; return; } if (true !== get($my_payment["is_payed"], false)) { - $pay_url = url_rel("pay.php"); echo "<p>you have not payed for this contract: " . $hc . "</p>"; echo "<p>Asking the wallet to re-execute it ... </p>"; echo "<script>executePayment('$hc', '$pay_url');</script>"; return; } +$receiver = $my_payment["receiver"]; + $news = false; -switch ($_SESSION['receiver']) +switch ($receiver) { case "Taler": $news = "https://taler.net/news"; @@ -102,7 +103,14 @@ switch ($_SESSION['receiver']) $news = "https://www.torproject.org/press/press.html.en"; break; } -echo generate_msg($news); + +$msg = "<p>Thanks for donating to " . $receiver . ".</p>"; +if ($news) +{ + $msg .= "<p>Check our latest <a href=\"" . $news . "\">news!</a></p>"; +} + +echo $msg; ?> </article> diff --git a/src/frontend/generate_taler_contract.php b/src/frontend/generate_taler_contract.php @@ -51,16 +51,28 @@ $teatax = array('value' => 1, // Take a timestamp $now = new DateTime('now'); + +// Include all information so we can +// restore the contract without storing it +$fulfillment_url = url_rel("fulfillment.php") + . '?uuid=${H_contract}' + . '&receiver=' . urlencode($receiver) + . '&aval=' . urlencode($amount_value) + . '&afrac=' . urlencode($amount_fraction) + . '&acurr=' . urlencode($currency) + . '&tid=' . $transaction_id; + // pack the JSON for the contract $contract = array( - 'fulfillment_url' => (url_rel("fulfillment.php") . '?uuid=${H_contract}'), + 'fulfillment_url' => $fulfillment_url, 'amount' => array( 'value' => $amount_value, 'fraction' => $amount_fraction, 'currency' => $currency), - 'max_fee' => array('value' => 3, - 'fraction' => 01010, - 'currency' => $currency), + 'max_fee' => array( + 'value' => 3, + 'fraction' => 01010, + 'currency' => $currency), 'transaction_id' => $transaction_id, 'products' => array( array( diff --git a/src/frontend/index.html b/src/frontend/index.html @@ -1,132 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <title>Toy &quot;Store&quot; - Taler Demo</title> - <link rel="stylesheet" type="text/css" href="style.css"> - <script src="taler-presence.js" type="text/javascript"> - </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 &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> - payment system without using - valuable currency. Instead, for the demonstrator we - will be using a "toy" currency, KUDOS. However, please remember that - Taler is designed to work with ordinary currencies, such - as Dollars or Euros, not just toy currencies. - <br> - This page, <tt>shop.demo.taler.net</tt> models the behavior of a - typical Web shop supporting Taler. The other pages of the demo, - <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. - </p> - </article> - - <section> - - <article> - <h2>Step 1: Installing the Taler wallet</h2> - <p class="taler-installed-hide"> - First, you need to <a href="http://demo.taler.net/">install</a> - the Taler wallet browser extension. - </p> - <p class="taler-installed-show"> - Congratulations, you have installed the Taler wallet correctly. - You can now proceed with the next steps. - </p> - </article> - - <article class="taler-installed-show"> - <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> - 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> - </article> - - <article class="taler-installed-show"> - <h2>Step 3: Shop! <sup>(as long as you have KUDOS left)</sup></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> - <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/index.php b/src/frontend/index.php @@ -0,0 +1,156 @@ +<!DOCTYPE html> +<?php +require_once "config.php"; +?> +<html lang="en"> +<head> + <title>Toy &quot;Store&quot; - Taler Demo</title> + <link rel="stylesheet" type="text/css" href="style.css"> + <script src="taler-presence.js" type="text/javascript"></script> +<script type="text/javascript"> +<?php +echo "\tvar shop_currency = '$SHOP_CURRENCY';\n"; +?> + + function addOption(value, label) { + var s = document.getElementById("taler-donation"); + let e = document.createElement("option"); + e.textContent = label ? label : ("".concat(value, " ", shop_currency)); + e.value = value; + s.appendChild(e); + } + + function init() { + let e = document.getElementById("currency-input"); + e.value = shop_currency; + addOption("0.1"); + addOption("1.0"); + addOption("6.0", "".concat(5, " ", shop_currency)); + addOption("10"); + } + + document.addEventListener("DOMContentLoaded", init); + +</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 &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> + payment system without using + valuable currency. Instead, for the demonstrator we + will be using a "toy" currency, KUDOS. However, please remember that + Taler is designed to work with ordinary currencies, such + as Dollars or Euros, not just toy currencies. + <br> + This page, <tt>shop.demo.taler.net</tt> models the behavior of a + typical Web shop supporting Taler. The other pages of the demo, + <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. + </p> + </article> + + <section> + + <article> + <h2>Step 1: Installing the Taler wallet</h2> + <p class="taler-installed-hide"> + First, you need to <a href="http://demo.taler.net/">install</a> + the Taler wallet browser extension. + </p> + <p class="taler-installed-show"> + Congratulations, you have installed the Taler wallet correctly. + You can now proceed with the next steps. + </p> + </article> + + <article class="taler-installed-show"> + <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> + 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> + </article> + + <article class="taler-installed-show"> + <h2>Step 3: Shop! <sup>(as long as you have KUDOS left)</sup></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> + <br> + <select id="taler-donation" name="donation_amount"> + <!-- options will be added dynamically --> + </select> + <input id="currency-input" type="hidden" name="donation_currency"/> + <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 @@ -19,7 +19,6 @@ include '../frontend_lib/util.php'; $hc = get($_GET["uuid"]); - if (empty($hc)) { http_response_code(400); @@ -30,42 +29,22 @@ if (empty($hc)) return; } -session_start(); - -$payments = &pull($_SESSION, 'payments', array()); - -if (!isset($payments[$hc])) +// TODO: check if contract body matches URL parameters, +// so we won't generate a response for the wrong receiver. +$receiver = get($_GET["receiver"]); +if (empty($receiver)) { http_response_code(400); echo json_encode(array( - "error" => "no session active", + "error" => "missing parameter", + "parameter" => "receiver" )); return; } -$my_payment = &$payments[$hc]; - $post_body = file_get_contents('php://input'); - -$now = new DateTime('now'); -$edate = array ( - 'edate' => - "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/"); - $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'])); - -$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 desired. */ @@ -76,7 +55,7 @@ $url = url_rel("backend/pay"); $req = new http\Client\Request("POST", $url, array("Content-Type" => "application/json")); -$req->getBody()->append (json_encode ($new_deposit_permission)); +$req->getBody()->append (json_encode ($deposit_permission)); // Execute the HTTP request $client = new http\Client; @@ -101,6 +80,12 @@ if ($status_code != 200) die(); } -$my_payment["is_payed"] = true; +session_start(); + +$payments = &pull($_SESSION, "payments", array()); +$payments[$hc] = array( + 'receiver' => $receiver, + 'is_payed' => true +); ?> diff --git a/src/frontend_blog/articles/essay-x.html b/src/frontend_blog/articles/essay-x.html @@ -1,19 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <title>Blog site demonstration</title> - <link rel="stylesheet" type="text/css" href="style.css"> -</head> -<body> - <div id="teaser"> - <p> - The x essay is - </p> - </div> - <div id="full-article"> - <p> - about something - </p> - </div> -</body> -</html> diff --git a/src/frontend_blog/articles/fs-essay.html b/src/frontend_blog/articles/fs-essay.html @@ -0,0 +1,390 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <title>Blog site demonstration</title> + <link rel="stylesheet" type="text/css" href="style.css"> +</head> +<body> + <div id="teaser"> + + <p> + What is Free Software + </p> + </div> + <div id="full-article"> + <h2>What is free software?</h2> + + <h3>The Free Software Definition</h3> + + <blockquote> + <p> + The free software definition presents the criteria for whether a + particular software program qualifies as free software. From time to + time we revise this definition, to clarify it or to resolve questions + about subtle issues. See the <a href="#History">History section</a> + below for a list of changes that affect the definition of free + software. + </p> + </blockquote> + + <p> + &ldquo;Free software&rdquo; means software that respects users' + freedom and community. Roughly, it means that <b>the users have the + freedom to run, copy, distribute, study, change and improve the + software</b>. Thus, &ldquo;free software&rdquo; is a matter of + liberty, not price. To understand the concept, you should think of + &ldquo;free&rdquo; as in &ldquo;free speech,&rdquo; not as in + &ldquo;free beer&rdquo;. We sometimes call it &ldquo;libre + software&rdquo; to show we do not mean it is gratis. + </p> + + <p> + We campaign for these freedoms because everyone deserves them. With + these freedoms, the users (both individually and collectively) control + the program and what it does for them. When users don't control the + program, we call it a &ldquo;nonfree&rdquo; or + &ldquo;proprietary&rdquo; program. The nonfree program controls the + users, and the developer controls the program; this makes the + program <a href="/philosophy/free-software-even-more-important.html"> + an instrument of unjust power</a>. + </p> + + <p> + A program is free software if the program's users have the + four essential freedoms: + </p> + + <ul> + <li>The freedom to run the program as you wish, + for any purpose (freedom 0).</li> + <li>The freedom to study how the program works, and change it so it + does your computing as you wish (freedom 1). Access to the source + code is a precondition for this. + </li> + <li>The freedom to redistribute copies so you can help your neighbor + (freedom 2). + </li> + <li>The freedom to distribute copies of your modified versions + to others (freedom 3). By doing this you can give the whole + community a chance to benefit from your changes. + Access to the source code is a precondition for this. + </li> + </ul> + + <p> + A program is free software if it gives users adequately all of these + freedoms. Otherwise, it is nonfree. While we can distinguish various + nonfree distribution schemes in terms of how far they fall short of + being free, we consider them all equally unethical.</p> + + <p>In any given scenario, these freedoms must apply to whatever code + we plan to make use of, or lead others to make use of. For instance, + consider a program A which automatically launches a program B to + handle some cases. If we plan to distribute A as it stands, that + implies users will need B, so we need to judge whether both A and B + are free. However, if we plan to modify A so that it doesn't use B, + only A needs to be free; we can ignore B.</p> + + <p>The rest of this page clarifies certain points about what makes + specific freedoms adequate or not.</p> + + <p>Freedom to distribute (freedoms 2 and 3) means you are free to + redistribute copies, either with or without modifications, either + gratis or charging a fee for distribution, to + <a href="#exportcontrol">anyone anywhere</a>. Being free to do these + things means (among other things) that you do not have to ask or pay + for permission to do so. + </p> + + <p> + You should also have the freedom to make modifications and use them + privately in your own work or play, without even mentioning that they + exist. If you do publish your changes, you should not be required to + notify anyone in particular, or in any particular way. + </p> + + <p> + The freedom to run the program means the freedom for any kind of person + or organization to use it on any kind of computer system, for any kind of + overall job and purpose, without being required to communicate about it + with the developer or any other specific entity. In this freedom, it is + the <em>user's</em> purpose that matters, not the <em>developer's</em> + purpose; you as a user are free to run the program for your purposes, + and if you distribute it to someone else, she is then free to run it + for her purposes, but you are not entitled to impose your purposes on her. + </p> + + <p> + The freedom to run the program as you wish means that you are not + forbidden or stopped from doing so. It has nothing to do with what + functionality the program has, or whether it is useful for what you + want to do.</p> + + <p> + The freedom to redistribute copies must include binary or executable + forms of the program, as well as source code, for both modified and + unmodified versions. (Distributing programs in runnable form is necessary + for conveniently installable free operating systems.) It is OK if there + is no way to produce a binary or executable form for a certain program + (since some languages don't support that feature), but you must have the + freedom to redistribute such forms should you find or develop a way to + make them. + </p> + + <p> + In order for freedoms 1 and 3 (the freedom to make changes and the + freedom to publish the changed versions) to be meaningful, you must have + access to the source code of the program. Therefore, accessibility of + source code is a necessary condition for free software. Obfuscated + &ldquo;source code&rdquo; is not real source code and does not count + as source code. + </p> + + <p> + Freedom 1 includes the freedom to use your changed version in place of + the original. If the program is delivered in a product designed to + run someone else's modified versions but refuse to run yours &mdash; a + practice known as &ldquo;tivoization&rdquo; or &ldquo;lockdown&rdquo;, + or (in its practitioners' perverse terminology) as &ldquo;secure + boot&rdquo; &mdash; freedom 1 becomes an empty pretense rather than a + practical reality. These binaries are not free + software even if the source code they are compiled from is free. + </p> + + <p> + One important way to modify a program is by merging in available free + subroutines and modules. If the program's license says that you + cannot merge in a suitably licensed existing module &mdash; for instance, if it + requires you to be the copyright holder of any code you add &mdash; then the + license is too restrictive to qualify as free. + </p> + + <p> + Freedom 3 includes the freedom to release your modified versions + as free software. A free license may also permit other ways of + releasing them; in other words, it does not have to be + a <a href="/copyleft/copyleft.html">copyleft</a> license. However, a + license that requires modified versions to be nonfree does not qualify + as a free license. + </p> + + <p> + In order for these freedoms to be real, they must be permanent and + irrevocable as long as you do nothing wrong; if the developer of the + software has the power to revoke the license, or retroactively add + restrictions to its terms, without your doing anything wrong to give + cause, the software is not free. + </p> + + <p> + However, certain kinds of rules about the manner of distributing free + software are acceptable, when they don't conflict with the central + freedoms. For example, <a href="/copyleft/copyleft.html">copyleft</a> + (very simply stated) is the rule that when redistributing the program, + you cannot add restrictions to deny other people the central freedoms. + This rule does not conflict with the central freedoms; rather it + protects them. + </p> + + <p> + In the GNU project, we use copyleft to protect the four freedoms + legally for everyone. We believe there are important reasons why + <a href="/philosophy/pragmatic.html">it is better to use + copyleft</a>. However, + <a href="/philosophy/categories.html#Non-CopyleftedFreeSoftware"> + noncopylefted free software</a> is ethical + too. See <a href="/philosophy/categories.html">Categories of Free + Software</a> for a description of how &ldquo;free software,&rdquo; + &ldquo;copylefted software&rdquo; and other categories of software + relate to each other. + </p> + + <p> + &ldquo;Free software&rdquo; does not mean &ldquo;noncommercial&rdquo;. A free + program must be available for commercial use, commercial development, + and commercial distribution. Commercial development of free software + is no longer unusual; such free commercial software is very important. + You may have paid money to get copies of free software, or you may have + obtained copies at no charge. But regardless of how you got your copies, + you always have the freedom to copy and change the software, even to + <a href="/philosophy/selling.html">sell copies</a>. + </p> + + <p> + Whether a change constitutes an improvement is a subjective matter. + If your right to modify a program is limited, in substance, to changes that + someone else considers an improvement, that program is not free. + </p> + + <p> + However, rules about how to package a modified version are acceptable, + if they don't substantively limit your freedom to release modified + versions, or your freedom to make and use modified versions privately. + Thus, it is acceptable for the license to require that you change the + name of the modified version, remove a logo, or identify your + modifications as yours. As long as these requirements are not so + burdensome that they effectively hamper you from releasing your + changes, they are acceptable; you're already making other changes to + the program, so you won't have trouble making a few more. + </p> + + <p> + Rules that &ldquo;if you make your version available in this way, you + must make it available in that way also&rdquo; can be acceptable too, + on the same condition. An example of such an acceptable rule is one + saying that if you have distributed a + modified version and a previous developer asks for a copy of it, you + must send one. (Note that such a rule still leaves you the choice of + whether to distribute your version at all.) Rules that require release + of source code to the users for versions that you put into public use + are also acceptable. + </p> + + <p> + A special issue arises when a license requires changing the name by + which the program will be invoked from other programs. That + effectively hampers you from releasing your changed version so that it + can replace the original when invoked by those other programs. This + sort of requirement is acceptable only if there's a suitable aliasing + facility that allows you to specify the original program's name as an + alias for the modified version.</p> + + <p> + Sometimes government <a id="exportcontrol">export control regulations</a> + and trade sanctions can constrain your freedom to distribute copies of + programs internationally. Software developers do not have the power to + eliminate or override these restrictions, but what they can and must do + is refuse to impose them as conditions of use of the program. In this + way, the restrictions will not affect activities and people outside the + jurisdictions of these governments. Thus, free software licenses + must not require obedience to any nontrivial export regulations as a + condition of exercising any of the essential freedoms. + </p> + + <p> + Merely mentioning the existence of export regulations, without making + them a condition of the license itself, is acceptable since it does + not restrict users. If an export regulation is actually trivial for + free software, then requiring it as a condition is not an actual + problem; however, it is a potential problem, since a later change in + export law could make the requirement nontrivial and thus render the + software nonfree. + </p> + + <p> + A free license may not require compliance with the license of a + nonfree program. Thus, for instance, if a license requires you to + comply with the licenses of &ldquo;all the programs you use&rdquo;, in + the case of a user that runs nonfree programs this would require + compliance with the licenses of those nonfree programs; that makes the + license nonfree. + </p> + + <p> + It is acceptable for a free license to specify which jurisdiction's + law applies, or where litigation must be done, or both. + </p> + + <p> + Most free software licenses are based on copyright, and there are limits + on what kinds of requirements can be imposed through copyright. If a + copyright-based license respects freedom in the ways described above, it + is unlikely to have some other sort of problem that we never anticipated + (though this does happen occasionally). However, some free software + licenses are based on contracts, and contracts can impose a much larger + range of possible restrictions. That means there are many possible ways + such a license could be unacceptably restrictive and nonfree. + </p> + + <p> + We can't possibly list all the ways that might happen. If a + contract-based license restricts the user in an unusual way that + copyright-based licenses cannot, and which isn't mentioned here as + legitimate, we will have to think about it, and we will probably conclude + it is nonfree. + </p> + + <p> + When talking about free software, it is best to avoid using terms + like &ldquo;give away&rdquo; or &ldquo;for free,&rdquo; because those terms imply that + the issue is about price, not freedom. Some common terms such + as &ldquo;piracy&rdquo; embody opinions we hope you won't endorse. See + <a href="/philosophy/words-to-avoid.html">Confusing Words and Phrases that + are Worth Avoiding</a> for a discussion of these terms. We also have + a list of proper <a href="/philosophy/fs-translations.html">translations of + &ldquo;free software&rdquo;</a> into various languages. + </p> + + <p> + Finally, note that criteria such as those stated in this free software + definition require careful thought for their interpretation. To decide + whether a specific software license qualifies as a free software license, + we judge it based on these criteria to determine whether it fits their + spirit as well as the precise words. If a license includes unconscionable + restrictions, we reject it, even if we did not anticipate the issue + in these criteria. Sometimes a license requirement raises an issue + that calls for extensive thought, including discussions with a lawyer, + before we can decide if the requirement is acceptable. When we reach + a conclusion about a new issue, we often update these criteria to make + it easier to see why certain licenses do or don't qualify. + </p> + + <p> + If you are interested in whether a specific license qualifies as a free + software license, see our <a href="/licenses/license-list.html">list + of licenses</a>. If the license you are concerned with is not + listed there, you can ask us about it by sending us email at + <a href="mailto:licensing@gnu.org">&lt;licensing@gnu.org&gt;</a>. + </p> + + <p> + If you are contemplating writing a new license, please contact the + Free Software Foundation first by writing to that address. The + proliferation of different free software licenses means increased work + for users in understanding the licenses; we may be able to help you + find an existing free software license that meets your needs. + </p> + + <p> + If that isn't possible, if you really need a new license, with our + help you can ensure that the license really is a free software license + and avoid various practical problems. + </p> + + <h3 id="beyond-software">Beyond Software</h3> + + <p> + <a href="/philosophy/free-doc.html">Software manuals must be free</a>, + for the same reasons that software must be free, and because the + manuals are in effect part of the software. + </p> + + <p> + The same arguments also make sense for other kinds of works of + practical use &mdash; that is to say, works that embody useful knowledge, + such as educational works and reference + works. <a href="http://wikipedia.org">Wikipedia</a> is the best-known + example. + </p> + + <p> + Any kind of work <em>can</em> be free, and the definition of free software + has been extended to a definition of <a href="http://freedomdefined.org/"> + free cultural works</a> applicable to any kind of works. + </p> + + <h3 id="open-source">Open Source?</h3> + + <p> + Another group uses the term &ldquo;open source&rdquo; to mean + something close (but not identical) to &ldquo;free software&rdquo;. We + prefer the term &ldquo;free software&rdquo; because, once you have heard that + it refers to freedom rather than price, it calls to mind freedom. The + word &ldquo;open&rdquo; <a href="/philosophy/open-source-misses-the-point.html"> + never refers to freedom</a>. + </p> + + + </div> +</body> +</html> diff --git a/src/frontend_blog/cc_payment.php b/src/frontend_blog/cc_payment.php @@ -44,7 +44,7 @@ <input type="radio" name="gender">Female</input><br> </form> <?php - echo "<form method=\"post\" action=\"essay_cc_pay.php?article=$article\"><input type=\"submit\"></input></form>"; + echo "<form method=\"post\" action=\"essay_cc_pay-fulfillment.php?article=$article\"><input type=\"submit\"></input></form>"; ?> </article> </section> diff --git a/src/frontend_blog/essay_cc_pay-fulfillment.php b/src/frontend_blog/essay_cc_pay-fulfillment.php @@ -0,0 +1,22 @@ +<?php + +include '../frontend_lib/util.php'; +include './blog_lib.php'; + +session_start(); +if (!$_SESSION['cc_payment']) +{ + echo "No session active"; + die(); +} +$article = get($_GET['article']); +if (null == $article) +{ + http_response_code(400); + echo "Bad request (no article specified)"; + return; +} +$article_doc = get_article($article); +echo $article_doc->saveHTML(); + +?> diff --git a/src/frontend_blog/essay_cc_pay.php b/src/frontend_blog/essay_cc_pay.php @@ -1,18 +0,0 @@ -<?php -session_start(); -if (!$_SESSION['cc_payment']) -{ - echo "No session active"; - die(); -} -$article = $_GET['article']; -$_SESSION['payment_ok'] = true; -if (!isset($_SESSION['allowed_articles'])) - $_SESSION['allowed_articles'] = array ($article => true); -else $_SESSION['allowed_articles'] = array_merge($_SESSION['allowed_articles'], array ($article => true)); -http_response_code (301); -$url = 'http://' . $_SERVER['HTTP_HOST'] . "/essay_fulfillment.php?article=$article"; -header("Location: " . $url); -echo $url; -die(); -?> diff --git a/src/frontend_blog/essay_contract.php b/src/frontend_blog/essay_contract.php @@ -24,36 +24,42 @@ * */ include("../frontend_lib/merchants.php"); +include("../frontend_lib/util.php"); include("./blog_lib.php"); session_start(); -if (!isset($_GET['article'])){ +$article = get($_GET['article']); +if (null == $article){ echo "Please land here just to buy articles"; die(); } -$article = $_GET['article']; -$_SESSION['article'] = $article; -// 2 to-do // send contract $transaction_id = rand(0, 1001); $p_id = hexdec(substr(sha1($article), -5)); -$teatax = array ('value' => 1, - 'fraction' => 0, - 'currency' => "KUDOS"); + $now = new DateTime('now'); $teaser = get_teaser($article); -$pay_url = "essay_pay.php"; -$exec_url = "execute.php"; -$contract_json = generate_contract(1, - 0, - "KUDOS", +$amount_value = 0; +$amount_fraction = 50000; +$currency = "EUR"; +$teatax = array ('value' => 1, + 'fraction' => 0, + 'currency' => $currency); +$transaction_id = rand(0, 1001); +// Include all information so we can +// restore the contract without storing it +$fulfillment_url = url_rel("essay_fulfillment.php") + . '&uuid=${H_contract}'; //<= super weird: that should be a '?', not '&', but works +//file_put_contents("/tmp/debg1", $fulfillment_url); +$contract_json = generate_contract($amount_value, + $amount_fraction, + $currency, $transaction_id, trim($teaser->nodeValue), $p_id, $teatax, $now, - $pay_url, - $exec_url); + $fulfillment_url); $resp = give_to_backend($_SERVER["HTTP_HOST"], "backend/contract", $contract_json); @@ -65,15 +71,22 @@ http_response_code ($status_code); // Now generate our body if ($status_code != 200) { - echo "Error while generating the contract"; - echo $resp->body->toString (); + echo json_encode(array( + 'error' => "internal error", + 'hint' => "backend indicated error", + 'detail' => $resp->body->toString() + ), JSON_PRETTY_PRINT); } else -{ $got_json = json_decode ($resp->body->toString ()); - $_SESSION['H_contract'] = $got_json->H_contract; - $_SESSION['article_value'] = 1; - $_SESSION['article_fraction'] = 0; - $_SESSION['article_currency'] = "KUDOS"; - echo $resp->body->toString (); +{ + $got_json = json_decode($resp->body->toString(), true); + $hc = $got_json["H_contract"]; + + $payments = &pull($_SESSION, "payments", array()); + $payments[$hc] = array( + 'article' => $article, + ); + + echo json_encode ($got_json, JSON_PRETTY_PRINT); } ?> diff --git a/src/frontend_blog/essay_fulfillment.php b/src/frontend_blog/essay_fulfillment.php @@ -1,20 +1,101 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <title>Taler's "Demo" Shop</title> + <link rel="stylesheet" type="text/css" href="style.css"> + <script type="application/javascript" src="taler-presence.js"></script> + <script type="application/javascript"> + function executePayment(H_contract, pay_url, offering_url) { + var detail = { + H_contract: H_contract, + pay_url: pay_url, + offering_url: offering_url + }; + var eve = new CustomEvent('taler-execute-payment', {detail: detail}); + document.dispatchEvent(eve); + } + </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 - Product Page</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. -include("./blog_lib.php"); -session_start(); -if (!isset($_GET['article'])){ + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along with + TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> + */ + +include '../frontend_lib/util.php'; +include './blog_lib.php'; + +$hc = get($_GET["uuid"]); + +if (empty($hc)) +{ + http_response_code(400); + echo "<p>Bad request (UUID missing)</p>"; + return; +} + +$article = get($_GET["article"]); +if (null == $article){ http_response_code(400); - echo "No article specified"; - die(); + echo "<p>Bad request (article missing)</p>"; + return; } -$article = $_GET['article']; -/* check if the client is allowed to get the wanted article */ -if(!isset($_SESSION['allowed_articles'][$article])){ - http_response_code(401); // unauthorized - echo "Not allowed to read this article"; - die(); + +session_start(); + +$payments = get($_SESSION['payments'], array()); +$my_payment = get($payments[$hc]); + +// This will keep the query parameters. +$pay_url = url_rel("essay_pay.php"); +$offering_url = url_rel("essay_offer.php"); +$offering_url .= "?article=" . $_GET["article"]; + +if (true !== get($my_payment["is_payed"], false) || null === $my_payment) +{ + echo "<p>Paying ... at $pay_url </p>"; + echo "<script>executePayment('$hc', '$pay_url', '$offering_url');</script>"; + return; } -// get the article + +// control here == article payed + +$article = $my_payment["article"]; + $article_doc = get_article($article); echo $article_doc->saveHTML(); + ?> + </article> + </section> +</body> +</html> diff --git a/src/frontend_blog/essay_offer.php b/src/frontend_blog/essay_offer.php @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<head> +<script type="text/javascript"> + + function handle_contract(json_contract) { + var cEvent = new CustomEvent('taler-contract', + {detail: json_contract}); + document.dispatchEvent(cEvent); + }; + function get_contract(article) { + var contract_request = new XMLHttpRequest(); + + contract_request.open("GET", + "essay_contract.php?article=" + article, + true); + contract_request.onload = function (e) { + if (contract_request.readyState == 4) { + if (contract_request.status == 200) { + console.log("response text:", + contract_request.responseText); + handle_contract(contract_request.responseText); + } else { + alert("Failure to download contract from merchant " + + "(" + contract_request.status + "):\n" + + contract_request.responseText); + } + } + }; + contract_request.onerror = function (e) { + alert("Failure requesting the contract:\n" + + contract_request.statusText); + }; + contract_request.send(); +} +</script> +</head> +<body> +<?php + + include("../frontend_lib/merchants.php"); + include("../frontend_lib/util.php"); + include("./blog_lib.php"); + session_start(); + $article = get($_GET['article']); + if (null == $article){ + echo "Please land here just to buy articles"; + die(); + } + echo "<script>get_contract('$article');</script>" +?> +</body> +</html> diff --git a/src/frontend_blog/essay_pay.php b/src/frontend_blog/essay_pay.php @@ -26,62 +26,58 @@ include("../frontend_lib/util.php"); include("./blog_lib.php"); session_start(); -if (!isset($_SESSION['H_contract'])) + +$hc = get($_GET["uuid"]); +if (empty($hc)) { - echo "No session active."; - http_response_code (301); + http_response_code(400); + echo json_encode(array( + "error" => "missing parameter", + "parameter" => "uuid" + )); return; } -if (isset($_SESSION['payment_ok']) && $_SESSION['payment_ok'] == true) +// TODO: check if contract body matches URL parameters, +// so we won't generate a response for the wrong receiver. +$article = get($_GET["article"]); +if (empty($article)) { - $_SESSION['payment_ok'] = true; - http_response_code (301); - $url = (new http\URL($_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) - ->mod(array ("path" => "essay_fulfillment.php?article=".$_SESSION['article']), http\Url::JOIN_PATH); - header("Location: $url"); - die(); + http_response_code(400); + echo json_encode(array( + "error" => "missing parameter", + "parameter" => "article" + )); + return; } -$article = $_SESSION['article']; -$post_body = file_get_contents('php://input'); -$deposit_permission = json_decode ($post_body, true); -$to_add = array('max_fee' => array('value' => 3, - 'fraction' => 8, - 'currency' => $_SESSION['article_currency']), - 'amount' => array('value' => $_SESSION['article_value'], - 'fraction' => $_SESSION['article_fraction'], - 'currency' => $_SESSION['article_currency'])); -$complete_deposit_permission = array_merge($deposit_permission, $to_add); - +$deposit_permission = file_get_contents('php://input'); +file_put_contents('/tmp/pay.dbg', 'about to pay\n', FILE_APPEND); $resp = give_to_backend($_SERVER['HTTP_HOST'], "backend/pay", - json_encode($complete_deposit_permission, JSON_PRETTY_PRINT)); + $deposit_permission); +file_put_contents('/tmp/pay.dbg', 'backend respd\n', FILE_APPEND); $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) { - /* 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, payment undone. Status $status_code\n"; - echo "\n"; - echo $resp->body->toString (); -} -else -{ - $_SESSION['payment_ok'] = true; - if (!isset($_SESSION['allowed_articles'])) - $_SESSION['allowed_articles'] = array ($article => true); - else $_SESSION['allowed_articles'] = array_merge($_SESSION['allowed_articles'], array ($article => true)); - http_response_code (301); - $url = (new http\URL($_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) - ->mod(array ("path" => "essay_fulfillment.php?article=$article"), http\Url::JOIN_PATH); - header("Location: $url"); + $json = json_encode( + array( + "error" => "backend error", + "status" => $status_code, + "detail" => $resp->body->toString())); + echo $json; die(); } + +session_start(); + +$payments = &pull($_SESSION, "payments", array()); +$payments[$hc] = array( + 'article' => $article, + 'is_payed' => true +); +?> diff --git a/src/frontend_blog/execute.js b/src/frontend_blog/execute.js @@ -1,33 +0,0 @@ -"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_blog/execute.php b/src/frontend_blog/execute.php @@ -1,56 +0,0 @@ -<!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_blog/execute.tsx b/src/frontend_blog/execute.tsx @@ -1,41 +0,0 @@ -"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_blog/index.html b/src/frontend_blog/index.html @@ -40,10 +40,15 @@ <article class="articles"> <ul style="list-style-type:none"> <li> - <a href="/cc_payment.php?article=essay-x" class="read-more" id="essay-x"> + <a href="/cc_payment.php?article=fs-essay" class="read-more" id="fs-essay"> <div class="teasers_item"> - <h3>Essay x</h3> - <p>In essay x, we will ...</p> + <h3>What is Free Software</h3> + <p> + The free software definition presents the criteria for whether a + particular software program qualifies as free software. From time to + time we revise this definition, to clarify it or to resolve questions + about subtle issues. + </p> </div> </a> </li> @@ -139,7 +144,7 @@ function has_taler_wallet_cb(aEvent) var articles_links = document.getElementsByClassName("read-more"); for(var i=0; i < articles_links.length; i++) //console.log(link); - articles_links[i].setAttribute("href", "javascript:taler_pay(\"" + articles_links[i].id + "\")"); + articles_links[i].setAttribute("href", "/essay_offer.php?article=" + articles_links[i].id); }; /* Function called when the Taler extension was unloaded; diff --git a/src/frontend_blog/teaser.php b/src/frontend_blog/teaser.php @@ -1,49 +0,0 @@ -<html> -<?php -/* - This file is part of GNU TALER. - Copyright (C) 2014, 2015 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software - Foundation; either version 2.1, 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License along with - TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/> -*/ - -/** - * This file should: - * - * 1. fetch the article teaser and attach a 'read more' link to it - * - */ -$article = (isset($_GET['article']) ? $_GET['article'] : "No article"); -$content = file_get_contents("articles/$article.html"); -$doc = new DOMDocument(); -$doc->loadHTML($content); -$teaser = $doc->getElementById("teaser"); -?> -<head> - <title> - <?php echo $article ?> - </title> -</head> -<body onload="signal_taler_wallet_onload();"> -<?php if ($article == "No article") - echo "Please select some article"; - else { - session_start(); - $_SESSION['article'] = $article; - echo $teaser->nodeValue; - } -?> - <br><a href="cc_payment.html" id="read-more">read more</a> - -</body> - -</html> diff --git a/src/frontend_lib/merchants.php b/src/frontend_lib/merchants.php @@ -13,8 +13,7 @@ function generate_contract($amount_value, $p_id, $teatax, $now, - $pay_url, - $exec_url){ + $fulfillment_url){ $contract = array ('amount' => array ('value' => $amount_value, 'fraction' => $amount_fraction, 'currency' => $currency), @@ -33,8 +32,7 @@ function generate_contract($amount_value, 'delivery_date' => "Some Date Format", 'delivery_location' => 'LNAME1')), 'timestamp' => "/Date(" . $now->getTimestamp() . ")/", - 'pay_url' => $pay_url, - 'exec_url' => $exec_url, + 'fulfillment_url' => $fulfillment_url, 'expiry' => "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/", 'refund_deadline' => "/Date(" . $now->add(new DateInterval('P3M'))->getTimestamp() . ")/", 'merchant' => array ('address' => 'LNAME2', @@ -63,7 +61,7 @@ function generate_contract($amount_value, 'region' => 'Test Region', 'province' => 'Test Province', 'ZIP code' => 4908))); - $json = json_encode (array ('contract' => $contract, 'exec_url' => $exec_url, 'pay_url' => $pay_url), JSON_PRETTY_PRINT); + $json = json_encode (array ('contract' => $contract, JSON_PRETTY_PRINT)); return $json; }