gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-donations] branch master updated: use new API, add d


From: gnunet
Subject: [GNUnet-SVN] [taler-donations] branch master updated: use new API, add donor
Date: Mon, 22 Jan 2018 02:59:50 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository donations.

The following commit(s) were added to refs/heads/master by this push:
     new 73ec94f  use new API, add donor
73ec94f is described below

commit 73ec94f494b2f428d89aab703fd1608634bfd4e9
Author: Florian Dold <address@hidden>
AuthorDate: Mon Jan 22 02:58:20 2018 +0100

    use new API, add donor
---
 talerdonations/donations/donations.py              | 225 +++++++++------------
 talerdonations/donations/templates/backoffice.html |  46 -----
 talerdonations/donations/templates/base.html       |  10 +-
 talerdonations/donations/templates/checkout.html   |   1 +
 .../donations/templates/execute-payment.html       |  12 --
 talerdonations/donations/templates/fallback.html   |  28 ---
 talerdonations/donations/templates/index.html      |  31 ++-
 .../templates/provider-not-supported.html          |   5 +
 talerdonations/helpers.py                          | 101 ---------
 9 files changed, 116 insertions(+), 343 deletions(-)

diff --git a/talerdonations/donations/donations.py 
b/talerdonations/donations/donations.py
index 9b3208a..598cca6 100644
--- a/talerdonations/donations/donations.py
+++ b/talerdonations/donations/donations.py
@@ -20,9 +20,9 @@ import logging
 import os
 import base64
 import random
-from datetime import datetime
 import requests
 import flask
+import traceback
 from ..talerconfig import TalerConfig
 from ..helpers import (make_url, \
     expect_parameter, amount_from_float, \
@@ -40,17 +40,64 @@ app.secret_key = 
base64.b64encode(os.urandom(64)).decode('utf-8')
 TC = TalerConfig.from_env()
 BACKEND_URL = TC["frontends"]["backend"].value_string(required=True)
 CURRENCY = TC["taler"]["currency"].value_string(required=True)
-MAX_FEE = dict(value=3, fraction=0, currency=CURRENCY)
 
 app.config.from_object(__name__)
 
 @app.context_processor
 def utility_processor():
-    def url(my_url):
-        return join_urlparts(flask.request.script_root, my_url)
     def env(name, default=None):
         return os.environ.get(name, default)
-    return dict(url=url, env=env)
+    return dict(env=env)
+
+
+def err_abort(abort_status_code, **params):
+    t = flask.render_template("templates/error.html", **params)
+    flask.abort(flask.make_response(t, abort_status_code))
+
+
+def backend_get(endpoint, params):
+    try:
+        resp = requests.get(urljoin(BACKEND_URL, endpoint), params=params)
+    except requests.ConnectionError:
+        err_abort(500, message="Could not establish connection to backend")
+    try:
+        response_json = resp.json()
+    except ValueError:
+        err_abort(500, message="Could not parse response from backend")
+    if resp.status_code != 200:
+        err_abort(500, message="Backend returned error status",
+                  json=response_json, status_code=resp.status_code)
+    return response_json
+
+
+def backend_post(endpoint, json):
+    try:
+        resp = requests.post(urljoin(BACKEND_URL, endpoint), json=json)
+    except requests.ConnectionError:
+        err_abort(500, message="Could not establish connection to backend")
+    try:
+        response_json = resp.json()
+    except ValueError:
+        err_abort(500, message="Could not parse response from backend",
+                  status_code=resp.status_code)
+    if resp.status_code != 200:
+        err_abort(500, message="Backend returned error status",
+                  json=response_json, status_code=resp.status_code)
+    return response_json
+
+
+def expect_parameter(name):
+    val = flask.args.get(name)
+    if not val:
+        return err_abort(400, "parameter '{}' required".format(name))
+    return val
+
+
address@hidden(Exception)
+def internal_error(e):
+    return flask.render_template("templates/error.html",
+                                 message="Internal error",
+                                 stack=traceback.format_exc())
 
 
 @app.route("/")
@@ -64,151 +111,65 @@ def javascript_licensing():
 
 @app.route("/checkout", methods=["GET"])
 def checkout():
-    amount_str = expect_parameter("donation_amount")
+    amount = expect_parameter("donation_amount")
     donation_receiver = expect_parameter("donation_receiver")
-    try:
-        float(amount_str)
-    except ValueError:
-        LOGGER.warning("Invalid amount ('%s')", amount_str)
-        return flask.make_response(
-            flask.jsonify(error="invalid amount"),
-            400)
-    display_alert = flask.request.args.get("display_alert", None)
+    donation_receiver = expect_parameter("donation_donor")
     return flask.render_template(
         "templates/checkout.html",
         donation_amount=amount_str,
         donation_receiver=donation_receiver,
-        merchant_currency=CURRENCY,
-        display_alert=display_alert)
+        donation_donor=donation_donor,
+        merchant_currency=CURRENCY)
 
 
address@hidden("/generate-contract", methods=["GET"])
-def generate_contract():
-    try:
-        donation_receiver = expect_parameter("donation_receiver")
-        donation_amount = expect_parameter("donation_amount")
-    except MissingParameterException as exc:
-        return flask.jsonify(
-            dict(error="Missing parameter '%s'" % exc)), 400
-    amount = amount_from_float(float(donation_amount))
-    order_id = "donation-%s-%X-%s" % \
-               (donation_receiver,
-                random.randint(0, 0xFFFFFFFF),
-                datetime.today().strftime('%H_%M_%S'))
-    order = dict(
-        summary="Donation!",
-        nonce=flask.request.args.get("nonce"),
-        amount=amount,
-        max_fee=dict(value=1, fraction=0, currency=CURRENCY),
-        order_id=order_id,
-        products=[
-            dict(
-                description="Donation to %s" % (donation_receiver,),
-                quantity=1,
-                product_id=0,
-                price=amount,
-            ),
-        ],
-        fulfillment_url=make_url("/fulfillment", ("order_id", order_id)),
-        pay_url=make_url("/pay"),
-        merchant=dict(
-            instance=donation_receiver,
-            address="nowhere",
-            name="Kudos Inc.",
-            jurisdiction="none",
-        ),
-    )
-    resp = requests.post(urljoin(BACKEND_URL, 'proposal'),
-                         json=dict(order=order))
-    if resp.status_code != 200:
-        # It is important to use 'backend_error()', as it handles
-        # the case where the backend gives NO JSON as response.
-        # For example, if it dies, or nginx hijacks somehow the
-        # response.
-        return backend_error(resp)
-    return flask.jsonify(resp.json()), resp.status_code
address@hidden("/provider-not-supported")
+def provider_not_supported():
+    return flask.render_template( "templates/provider-not-supported.html")
+
 
 @app.route("/donate")
 def donate():
     donation_receiver = expect_parameter("donation_receiver")
     donation_amount = expect_parameter("donation_amount")
+    donation_donor = expect_parameter("donation_donor")
     payment_system = expect_parameter("payment_system")
     if payment_system != "taler":
-        return flask.redirect(make_url("checkout",
-                                       ("donation_receiver", 
donation_receiver),
-                                       ("donation_amount", donation_amount),
-                                       ("display_alert", True)))
-    response = 
flask.make_response(flask.render_template('templates/fallback.html'), 402)
-    response.headers["X-Taler-Contract-Url"] = \
-    make_url("/generate-contract",
-             ("donation_receiver", donation_receiver),
-             ("donation_amount", donation_amount))
-    return response
-
-
address@hidden("/fulfillment")
-def fulfillment():
-    order_id = expect_parameter("order_id")
-    payed_order_ids = flask.session.get("payed_order_ids", [])
-    print("order_id:", repr(order_id))
-    print("session:", repr(flask.session))
-    if order_id in payed_order_ids:
-        data = payed_order_ids[order_id]
-        return flask.render_template(
-            "templates/fulfillment.html",
-            donation_receiver=data["donation_receiver"],
-            donation_amount=data["donation_amount"],
-            order_id=order_id,
-            currency=CURRENCY)
-
-    response = 
flask.make_response(flask.render_template("templates/fallback.html"), 402)
-    response.headers["X-Taler-Contract-Query"] = "fulfillment_url"
-    response.headers["X-Taler-Offer-Url"] = make_url("/")
-    return response
+        return flask.redirect(flask.url_for(provider_not_supported))
+    fulfillment_url = flask.url_for(fulfillment, order_id=order_id, 
receiver=donation_receiver, _external=True)
+    order = dict(
+        amount=donation_amount,
+        extra=dict(donor=donation_donor, receiver=donation_receiver),
+        fulfillment_url=fulfillment_url,
+        instance=donation_receiver,
+        summary="Donation to {}".format(donation_receiver),
+    )
+    proposal_resp = backend_post("proposal", dict(order=order))
+    order_id = proposal_resp["order_id"]
+    return flask.redirect(flask.url_for(fulfillment, order_id=order_id))
 
 
address@hidden("/pay", methods=["POST"])
-def pay():
-    deposit_permission = flask.request.get_json()
-    if deposit_permission is None:
-        return flask.jsonify(error="no json in body"), 400
-    resp = requests.post(urljoin(BACKEND_URL, "pay"),
-                         json=deposit_permission)
-    if resp.status_code != 200:
-        return backend_error(resp)
-    proposal_data = resp.json()["contract_terms"]
-    order_id = proposal_data["order_id"]
-    payed_order_ids = flask.session["payed_order_ids"] \
-        = flask.session.get("payed_order_ids", {})
-    payed_order_ids[order_id] = dict(
-        donation_receiver=proposal_data["merchant"]["instance"],
-        donation_amount=amount_to_float(proposal_data["amount"])
address@hidden("/fulfillment/<receiver>/<int:order_id>")
+def fulfillment(order_id):
+    pay_params = dict(
+        instance=INSTANCE,
+        order_id=order_id,
+        resource_url=flask.request.base_url,
+        session_id=session_id,
+        session_sig=session_sig,
     )
-    print("received payment for", order_id)
-    return flask.jsonify(resp.json()), resp.status_code
-
address@hidden("/backoffice")
-def track():
-    response = 
flask.make_response(flask.render_template("templates/backoffice.html"))
-    return response
 
+    pay_status = backend_get("check-payment", pay_params)
 
address@hidden("/history")
-def history():
-    qs = get_query_string().decode("utf-8")
-    url = urljoin(BACKEND_URL, "history")
-    resp = requests.get(url, params=dict(parse_qsl(qs)))
-    if resp.status_code != 200:
-        return backend_error(resp)
-    return flask.jsonify(resp.json()), resp.status_code
+    if pay_status.get("payment_redirect_url"):
+        return flask.redirect(pay_status["payment_redirect_url"])
 
+    if pay_status.get("paid"):
+        return flask.render_template(
+            "templates/fulfillment.html",
+            donation_receiver=data["donation_receiver"],
+            donation_amount=data["donation_amount"],
+            order_id=order_id,
+            currency=CURRENCY)
 
address@hidden("/track/order")
-def track_order():
-    instance = expect_parameter("instance")
-    order_id = expect_parameter("order_id")
-    url = urljoin(BACKEND_URL, "track/transaction")
-    resp = requests.get(url, params=dict(order_id=order_id, instance=instance))
-    if resp.status_code != 200:
-        return backend_error(resp)
-    return flask.jsonify(resp.json()), resp.status_code
+    # no pay_redirect but article not paid, this should never happen!
+    err_abort(500, message="Internal error, invariant failed", json=pay_status)
diff --git a/talerdonations/donations/templates/backoffice.html 
b/talerdonations/donations/templates/backoffice.html
deleted file mode 100644
index 719d4b6..0000000
--- a/talerdonations/donations/templates/backoffice.html
+++ /dev/null
@@ -1,46 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
-  <h1>Backoffice</h1>
-  <p>This page simulates a backoffice facility.  Through it,
-  the user can see the money flow from Taler transactions to
-  wire transfers and viceversa.</p>
-  <table id="history" width="60%" style="visibility: hidden;">
-    <tbody>
-      <tr>
-        <th>Order ID</th>
-        <th>Summary</th>
-        <th>Amount</th>
-        <th>Date</th>
-      </tr>
-    </tbody>
-  </table>
-  <div class="loader"></div>
-  <div id="popup1" class="overlay">
-    <div class="popup">
-      <h2>
-        <a class="close" href="/backoffice">&times;</a>
-      </h2>
-      <div class="track-content">
-        <table>
-          <tbody>
-            <tr>
-              <th>WTID</th>
-              <th>Amount</th>
-              <th>Coin</th>
-              <th>Date</th>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    </div>
-  </div>
-  <a href="#" onclick="get_history(true);" style="margin-left: 90%;">Fake 
scroll</a>
-{% endblock main %}
-
-{% block styles %}
-  <link rel="stylesheet" type="text/css" href="{{ url("/static/popup.css") }}">
-{% endblock styles %}
-
-{% block scripts %}
-  <script src="{{ url('/static/backoffice.js') }}" 
type="application/javascript"></script>
-{% endblock scripts %}
diff --git a/talerdonations/donations/templates/base.html 
b/talerdonations/donations/templates/base.html
index b464752..374e426 100644
--- a/talerdonations/donations/templates/base.html
+++ b/talerdonations/donations/templates/base.html
@@ -18,11 +18,9 @@
 <html data-taler-nojs="true">
 <head>
   <title>Taler Donation Demo</title>
-  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/pure.css') }}" />
-  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/demo.css') }}" />
-  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/taler-fallback.css') }}" id="taler-presence-stylesheet" 
/>
-  <script src="{{ url("/static/web-common/taler-wallet-lib.js") }}" 
type="application/javascript"></script>
-  <script src="{{ url("/static/web-common/lang.js") }}" 
type="application/javascript"></script>
+  <link rel="stylesheet" type="text/css" href="{{ url('static', 
filename='web-common/pure.css') }}" />
+  <link rel="stylesheet" type="text/css" href="{{ url('static', 
filename='web-common/demo.css') }}" />
+  <link rel="stylesheet" type="text/css" href="{{ url('static', 
filename='web-common/taler-fallback.css') }}" id="taler-presence-stylesheet" />
   {% block styles %}{% endblock %}
   {% block scripts %}{% endblock %}
 </head>
@@ -43,7 +41,7 @@
   </div>
 
   <section id="main" class="content">
-    <a href="{{ url("/") }}">
+    <a href="{{ url_for('index') }}">
       <div id="logo">
         <svg height="100" width="100">
           <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" 
fill="white" />
diff --git a/talerdonations/donations/templates/checkout.html 
b/talerdonations/donations/templates/checkout.html
index a7d009c..2785af8 100644
--- a/talerdonations/donations/templates/checkout.html
+++ b/talerdonations/donations/templates/checkout.html
@@ -36,6 +36,7 @@
     <div id="opt-form" align="left"><br>
       <input type="hidden" name="donation_receiver" value="{{ 
donation_receiver }}"></input>
       <input type="hidden" name="donation_amount" value="{{ donation_amount 
}}"></input>
+      <input type="hidden" name="donation_donor" value="{{ donation_donor 
}}"></input>
       <input type="radio" name="payment_system" value="lisa"
              id="lisa-radio-button-id">Lisa</input>
       <br/>
diff --git a/talerdonations/donations/templates/execute-payment.html 
b/talerdonations/donations/templates/execute-payment.html
deleted file mode 100644
index e1283ce..0000000
--- a/talerdonations/donations/templates/execute-payment.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "templates/base.html" %}
-
-{% block scripts %}
-<meta name="contract-hash" value="{{ hc }}">
-<meta name="pay-url" value="{{ pay_url|safe }}">
-<meta name="offering-url" value="{{ offering_url|safe }}">
-<script src="static/execute-payment.js" type="application/javascript"></script>
-{% endblock scripts %}
-
-{% block main %}
-<div id="msg">Executing payment <span id="action-indicator"></span></div>
-{% endblock main %}
diff --git a/talerdonations/donations/templates/fallback.html 
b/talerdonations/donations/templates/fallback.html
deleted file mode 100644
index 8dc426b..0000000
--- a/talerdonations/donations/templates/fallback.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
-
-<p class="taler-installed-show">
-Payment is being processed.  If nothing happens, please <a href="{{ 
request.path }}">click here</a>.
-</p>
-  
-<div id="ccfakeform" class="taler-installed-hide">
-  <p>
-    Oops, it looks like you don't have a Taler wallet installed.  Why don't 
you enter
-    all your credit card details before reading the article? <em>You can also
-    use GNU Taler to complete the purchase at any time.</em>
-  </p>
-
-  <form>
-    First name<br> <input type="text"><br>
-    Family name<br> <input type="text"><br>
-    Age<br> <input type="text"><br>
-    Nationality<br> <input type="text"><br>
-    Gender<br> <input type="radio" name"gender">Male</input>
-    CC number<br> <input type="text"><br>
-    <input type="radio" name="gender">Female<br>
-  </form>
-  <form method="get" action="/cc-payment/{{ article_name }}">
-   <input type="submit"></input>
-  </form>
-</div>
-{% endblock main %}
diff --git a/talerdonations/donations/templates/index.html 
b/talerdonations/donations/templates/index.html
index 097c781..3ba9638 100644
--- a/talerdonations/donations/templates/index.html
+++ b/talerdonations/donations/templates/index.html
@@ -32,31 +32,26 @@ You are paying with an imaginary currency ({{ 
merchant_currency }}).
         <option value="GNUnet">GNUnet</option>
         <option value="Taler">GNU Taler</option>
         <option value="Tor">Tor</option>
-        <!-- options are added dynamically -->
       </select>
       <select id="taler-donation" name="donation_amount">
-        <option value="0.1">0.1 {{ merchant_currency }}</option>
-        <option value="1">1 {{ merchant_currency }}</option>
-        <option value="6">5 {{ merchant_currency }}</option>
-        <option value="10">10 {{ merchant_currency }}</option>
+        <option value="{{ merchant_currency }}:0.1">0.1 {{ merchant_currency 
}}</option>
+        <option value="{{ merchant_currency }}:1">1 {{ merchant_currency 
}}</option>
+        <option value="{{ merchant_currency }}:6">5 {{ merchant_currency 
}}</option>
+        <option value="{{ merchant_currency }}:10">10 {{ merchant_currency 
}}</option>
       </select>
-      <input type="submit" class="pure-button pure-button-primary" 
value="Donate!"/>
+      <input type="text" name="donation_donor" value="Anonymous" />
+      <input type="submit" class="pure-button pure-button-primary" 
value="Donate!" />
     </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.
+    (*) To make it a bit more fun, the 5 {{ merchant_currency }} option is
+    deliberately implemented with a fault: the merchant will try to make you
+    donate 6 {{ merchant_currency} instead of the 5 {{ merchant_currency }} 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>
 </div>
 
-<!-- <h2>Back-office interface</h2> -->
-<!--p>Try the <a href="backoffice">back-office</a>, in order to track
-orders and corresponding deposits.
-</p Depends on #4992 -->
-
 {% endblock %}
diff --git a/talerdonations/donations/templates/provider-not-supported.html 
b/talerdonations/donations/templates/provider-not-supported.html
new file mode 100644
index 0000000..e10d66a
--- /dev/null
+++ b/talerdonations/donations/templates/provider-not-supported.html
@@ -0,0 +1,5 @@
+{% extends "templates/base.html" %}
+
+{% block main %}
+Unfortunately the selected payment provider is not supported in this demo.
+{% endblock main %}
diff --git a/talerdonations/helpers.py b/talerdonations/helpers.py
deleted file mode 100644
index 614e463..0000000
--- a/talerdonations/helpers.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#  This file is part of TALER
-#  (C) 2016 INRIA
-#
-#  TALER is free software; you can redistribute it and/or modify it under the
-#  terms of the GNU Affero 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, see <http://www.gnu.org/licenses/>
-#
-#  @author Florian Dold
-#  @author Marcello Stanisci
-
-from urllib.parse import urljoin, urlencode
-import logging
-import json
-import flask
-from .talerconfig import TalerConfig
-
-LOGGER = logging.getLogger(__name__)
-
-TC = TalerConfig.from_env()
-BACKEND_URL = TC["frontends"]["backend"].value_string(required=True)
-NDIGITS = TC["frontends"]["NDIGITS"].value_int()
-CURRENCY = TC["taler"]["CURRENCY"].value_string()
-
-FRACTION_BASE = 1e8
-
-if not NDIGITS:
-    NDIGITS = 2
-
-class MissingParameterException(Exception):
-    def __init__(self, param):
-        self.param = param
-        super().__init__()
-
-def amount_to_float(amount):
-    return amount['value'] + (float(amount['fraction']) / float(FRACTION_BASE))
-
-
-def amount_from_float(floatx):
-    value = int(floatx)
-    fraction = int((floatx - value) * FRACTION_BASE)
-    return dict(currency=CURRENCY, value=value, fraction=fraction)
-
-
-def join_urlparts(*parts):
-    ret = ""
-    part = 0
-    while part < len(parts):
-        buf = parts[part]
-        part += 1
-        if ret.endswith("/"):
-            buf = buf.lstrip("/")
-        elif ret and not buf.startswith("/"):
-            buf = "/" + buf
-        ret += buf
-    return ret
-
-
-def make_url(page, *query_params):
-    """
-    Return a URL to a page in the current Flask application with the given
-    query parameters (sequence of key/value pairs).
-    """
-    query = urlencode(query_params)
-    if page.startswith("/"):
-        root = flask.request.url_root
-        page = page.lstrip("/")
-    else:
-        root = flask.request.base_url
-    url = urljoin(root, "%s?%s" % (page, query))
-    # urlencode is overly eager with quoting, the wallet right now
-    # needs some characters unquoted.
-    return url.replace("%24", "$").replace("%7B", "{").replace("%7D", "}")
-
-
-def expect_parameter(name, alt=None):
-    value = flask.request.args.get(name, None)
-    if value is None and alt is None:
-        LOGGER.error("Missing parameter '%s' from '%s'." % (name, 
flask.request.args))
-        raise MissingParameterException(name)
-    return value if value else alt
-
-
-def get_query_string():
-    return flask.request.query_string
-
-def backend_error(requests_response):
-    LOGGER.error("Backend error: status code: "
-                 + str(requests_response.status_code))
-    try:
-        return flask.jsonify(requests_response.json()), 
requests_response.status_code
-    except json.decoder.JSONDecodeError:
-        LOGGER.error("Backend error (NO JSON returned): status code: "
-                     + str(requests_response.status_code))
-        return flask.jsonify(dict(error="Backend died, no JSON got from it")), 
502

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]