gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant-frontends] branch master updated: use new w


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant-frontends] branch master updated: use new wallet and merchant backend api
Date: Mon, 13 Feb 2017 03:08:37 +0100

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

dold pushed a commit to branch master
in repository merchant-frontends.

The following commit(s) were added to refs/heads/master by this push:
     new 0e77e34  use new wallet and merchant backend api
0e77e34 is described below

commit 0e77e34c85e060fde08bce25456de9caeef6ba53
Author: Florian Dold <address@hidden>
AuthorDate: Sat Feb 11 17:32:28 2017 +0100

    use new wallet and merchant backend api
---
 talerfrontends/blog/blog.py                        | 224 ++++++---------------
 talerfrontends/blog/content.py                     |   4 +
 talerfrontends/blog/static/web-common              |   2 +-
 talerfrontends/blog/templates/base.html            |   1 -
 talerfrontends/blog/templates/purchase.html        |   4 +-
 talerfrontends/donations/donations.py              | 221 ++++++++------------
 talerfrontends/donations/static/checkout.js        | 103 ----------
 talerfrontends/donations/static/web-common         |   2 +-
 talerfrontends/donations/templates/base.html       |   1 -
 talerfrontends/donations/templates/checkout.html   |  10 +-
 talerfrontends/donations/templates/fallback.html   |  25 +++
 .../donations/templates/fulfillment.html           |   4 +-
 talerfrontends/donations/templates/index.html      |   9 +-
 talerfrontends/helpers.py                          |  51 ++---
 talerfrontends/static/cb.js                        |  20 --
 15 files changed, 210 insertions(+), 471 deletions(-)

diff --git a/talerfrontends/blog/blog.py b/talerfrontends/blog/blog.py
index 0d6a241..ee61f64 100644
--- a/talerfrontends/blog/blog.py
+++ b/talerfrontends/blog/blog.py
@@ -1,5 +1,5 @@
-# tHIS FIle is part of GNU TALER.
-# Copyright (C) 2014-2016 INRIA
+# This file is part of GNU TALER.
+# Copyright (C) 2014-2017 INRIA
 #
 # 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
@@ -15,8 +15,12 @@
 # @author Florian Dold
 # @author Marcello Stanisci
 
-from flask import (Flask, render_template, session, request, jsonify,
-        make_response, redirect, send_file)
+
+"""
+Implement URL handlers and payment logic for the blog merchant.
+"""
+
+import flask
 from urllib.parse import urljoin, urlencode, quote
 import requests
 import logging
@@ -24,19 +28,20 @@ import os
 import base64
 import random
 import time
+import json
 from talerfrontends.common_routes import tracking, history
 from pprint import pprint
 from talerfrontends.talerconfig import TalerConfig
-from talerfrontends.helpers import (make_url, talerdate, frontend_common,
-        sign_contract, expect_parameter, expect_parameter_int, BackendError,
-        MalformedParameterError, join_urlparts, map_in)
+from talerfrontends.helpers import (make_url, frontend_common,
+        expect_parameter, expect_parameter_int, BackendError,
+        MalformedParameterError, join_urlparts)
 from talerfrontends.blog.content import articles, get_article_file, 
get_image_file
 
 logger = logging.getLogger(__name__)
 
 base_dir = os.path.dirname(os.path.abspath(__file__))
 
-app = Flask(__name__, template_folder=base_dir)
+app = flask.Flask(__name__, template_folder=base_dir)
 app.register_blueprint(frontend_common)
 app.debug = True
 app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8')
@@ -53,202 +58,99 @@ app.config.from_object(__name__)
 @app.context_processor
 def utility_processor():
     def url(my_url):
-        return join_urlparts(request.script_root, my_url)
+        return join_urlparts(flask.request.script_root, my_url)
     return dict(url=url)
 
 
 @app.route('/')
 def index():
-    use_js_toggle = request.args.get("use_js", "").lower()
-    if use_js_toggle == "false":
-        session["use_js"] = False
-    elif use_js_toggle == "true":
-        session["use_js"] = True
-    # use JavaScript-free payment API by default
-    use_js = session.setdefault("use_js", False)
-
-    return render_template('templates/index.html', merchant_currency=CURRENCY, 
articles=articles.values(), use_js=use_js)
+    return flask.render_template('templates/index.html', 
merchant_currency=CURRENCY, articles=articles.values())
 
 @app.route('/javascript')
 def javascript_licensing():
-    return render_template('templates/javascript.html')
-
-def make_contract(article_name, tid, timestamp):
-    """
-    Make (or rather restore) a contract.
-    Always produces the same output for the same inputs.
-    """
-    logger.info("making contract for %s", repr((article_name, tid, timestamp)))
-    fulfillment_url = make_url(
-            "/essay/" + quote(article_name),
-            ("uuid", "${H_contract}"),
-            ("timestamp", timestamp),
-            ("tid", tid))
-    contract = dict(
-           summary="Article %s" % article_name,
-            amount=ARTICLE_AMOUNT,
-            max_fee=dict(value=3, fraction=0, currency=CURRENCY),
-            transaction_id=tid,
-            products=[
-                dict(
-                    description="Essay: " + article_name.replace("_", " "),
-                    quantity=1,
-                    product_id=0,
-                    price=ARTICLE_AMOUNT,
-                ),
-            ],
-            timestamp=talerdate(timestamp),
-            pay_deadline=talerdate(timestamp + 60*60*24*100),
-            # refund deadline now, as it allows the aggregator to work ASAP
-            refund_deadline=talerdate(timestamp),
-            fulfillment_url=fulfillment_url,
-            merchant=dict(
-                instance=INSTANCE,
-                address="nowhere",
-                name="Kudos Inc.",
-                jurisdiction="none",
-                ),
-            locations={},
-            )
-    return contract
+    return flask.render_template('templates/javascript.html')
+
 
 @app.route('/generate-contract', methods=["GET"])
 def generate_contract():
-    now = int(time.time())
-    tid = random.randint(1, 2**50)
     article_name = expect_parameter("article_name")
-    contract = make_contract(article_name=article_name, tid=tid, timestamp=now)
-    contract_resp = sign_contract(contract)
-    logger.info("generated contract: %s" % str(contract_resp))
-    return jsonify(**contract_resp)
+    order = dict(
+        amount=ARTICLE_AMOUNT,
+        max_fee=dict(value=1, fraction=0, currency=CURRENCY),
+        products=[
+            dict(
+                description="Essay: " + article_name.replace("_", " "),
+                quantity=1,
+                product_id=0,
+                price=ARTICLE_AMOUNT,
+            ),
+        ],
+        fulfillment_url=make_url("/essay/" + quote(article_name)),
+        merchant=dict(
+            instance=INSTANCE,
+            address="nowhere",
+            name="Kudos Inc.",
+            jurisdiction="none",
+        ),
+        extra=dict(article_name=article_name),
+    )
+    r = requests.post(urljoin(BACKEND_URL, 'proposal'), json=dict(order=order))
+    if r.status_code != 200:
+        logger.error("failed to POST to '%s'", url)
+        raise BackendError(r.status_code, r.text)
+    proposal_resp = r.json()
+    return flask.jsonify(**proposal_resp)
+
 
 
 @app.route("/cc-payment/<name>")
 def cc_payment(name):
-    return render_template('templates/cc-payment.html', article_name=name)
-
+    return flask.render_template('templates/cc-payment.html', 
article_name=name)
 
-def offer_js():
-    pass
 
 
 @app.route("/essay/<name>")
 @app.route("/essay/<name>/data/<data>")
 def article(name, data=None):
     logger.info("processing %s" % name)
-    payed_articles = session.get("payed_articles", [])
-    # #4456:
-    # Check if 'name' is in payed article *and* if 'data'
-    # belongs to 'name's related data. If yes, send data back
-    # Note that the second check is made at parsing time.
+    payed_articles = flask.session.get("payed_articles", [])
     if name in payed_articles:
         article = articles[name]
         if article is None:
             flask.abort(500)
         if data is not None:
-            logger.info("extra data for %s: %s" % (name, data))
             if data in article.extra_files:
-                logger.info("you have the right to get this image")
-                logger.info("article extra files are: " + 
str(article.extra_files))
-                return send_file(get_image_file(data))
+                return flask.send_file(get_image_file(data))
             else:
-                logger.info("you have NO right to get this image")
-                return "", 400
-        return send_file(get_article_file(article))
-
-    use_js = session.get("use_js", True)
-
-    hc = request.args.get("uuid")
-    tid_str = request.args.get("tid")
-    timestamp_str = request.args.get("timestamp")
-    if hc is None or tid_str is None or timestamp_str is None:
-        contract_url = make_url("/generate-contract", ("article_name",name))
-        if use_js:
-            return render_template(
-                    'templates/purchase.html',
-                    article_name=name,
-                    no_contract=1,
-                    contract_url=quote(contract_url),
-                    data_attribute="data-taler-contractoffer=" + contract_url)
-        else:
-            response = 
make_response(render_template('templates/fallback.html'), 402)
-            response.headers["X-Taler-Contract-Url"] = contract_url
-            return response
-    try:
-        tid = int(tid_str)
-    except ValueError:
-        raise MalformedParameterError("tid")
-    try:
-        timestamp = int(timestamp_str)
-    except ValueError:
-        raise MalformedParameterError("timestamp")
-
-    restored_contract = make_contract(article_name=name, tid=tid, 
timestamp=timestamp)
-    contract_resp = sign_contract(restored_contract)
-    logger.info("restored contract: %s" % str(contract_resp))
-
-    if contract_resp["H_contract"] != hc:
-        # FIXME: should just redirect to checkout ...
-        e = jsonify(error="contract mismatch", was=hc, 
expected=contract_resp["H_contract"])
-        return e, 400
+                return "permission denied", 400
+        return flask.send_file(get_article_file(article))
 
-    session[hc] = si = session.get(hc, {})
-    si['article_name'] = name
-    si['plain_contract'] = contract_resp["contract"]
-    session.modified = True
-
-    pay_url = make_url("/pay")
-    offering_url = make_url("/article/%s" % (quote(name),))
-    if use_js:
-        return render_template(
-                'templates/purchase.html',
-                hc=hc,
-                pay_url=quote(pay_url),
-                offering_url=quote(offering_url),
-                article_name=name,
-                no_contract=0,
-                data_attribute="data-taler-executecontract=%s,%s,%s" % (hc, 
pay_url, offering_url))
-    else:
-        response = make_response(render_template('templates/fallback.html'), 
402)
-        response.headers["X-Taler-Contract-Hash"] = hc
-        response.headers["X-Taler-Pay-Url"] = pay_url
-        response.headers["X-Taler-Offer-Url"] = offering_url
-        return response
+    contract_url = make_url("/generate-contract", ("article_name",name))
+    response = 
flask.make_response(flask.render_template('templates/fallback.html'), 402)
+    response.headers["X-Taler-Contract-Url"] = contract_url
+    response.headers["X-Taler-Contract-Query"] = "fulfillment_url"
+    response.headers["X-Taler-Pay-Url"] = make_url("/pay")
+    response.headers["X-Taler-Offer-Url"] = make_url("/essay/" + name)
+    return response
 
 
 @app.route('/pay', methods=["POST"])
 def pay():
-    deposit_permission = request.get_json()
+    deposit_permission = flask.request.get_json()
     if deposit_permission is None:
-        e = jsonify(error="no json in body")
-        return e, 400
-
-    hc = deposit_permission.get("H_contract")
-
-    if hc is None:
-        e = jsonify(error="malformed deposit permission", hint="H_contract 
missing")
+        e = flask.jsonify(error="no json in body")
         return e, 400
-    logger.info("deposit permission: %s" % str(deposit_permission))
-
-    si = session.get(hc)
-    if si is None:
-        e = jsonify(error="no session for contract")
-        return e, 400 
 
     r = requests.post(urljoin(BACKEND_URL, 'pay'), json=deposit_permission)
     if 200 != r.status_code:
         raise BackendError(r.status_code, r.text)
-    r = map_in(si['plain_contract'], hc)
-    article = si["article_name"]
-    logging.info("added payment for article %s", article)
-
-    payed_articles = session["payed_articles"] = session.get("payed_articles", 
[])
-    if article not in payed_articles:
-        payed_articles.append(article)
 
-    session.permanent = True
+    proposal_data = r.json()['proposal_data']
+    article_name = proposal_data['extra']['article_name']
+    payed_articles = flask.session["payed_articles"] = 
flask.session.get("payed_articles", [])
+    if article_name not in payed_articles:
+        payed_articles.append(article_name)
 
-    logger.info("Successful payment: %s" % r.text)
     return r.text, 200
 
 app.add_url_rule('/history', 'history', history)
diff --git a/talerfrontends/blog/content.py b/talerfrontends/blog/content.py
index 8b079a2..48010b8 100644
--- a/talerfrontends/blog/content.py
+++ b/talerfrontends/blog/content.py
@@ -14,6 +14,10 @@
 #
 # @author Florian Dold
 
+"""
+Define content and associated metadata that is served on the blog.
+"""
+
 from collections import OrderedDict
 from bs4 import BeautifulSoup
 from pkg_resources import resource_stream, resource_filename
diff --git a/talerfrontends/blog/static/web-common 
b/talerfrontends/blog/static/web-common
index dc9d5ab..9701ed4 160000
--- a/talerfrontends/blog/static/web-common
+++ b/talerfrontends/blog/static/web-common
@@ -1 +1 @@
-Subproject commit dc9d5ab2308fef7cdd1e8c95fbf4fdd51bed7bfb
+Subproject commit 9701ed4caa1cb541c1f645b05bfe190975b3e42b
diff --git a/talerfrontends/blog/templates/base.html 
b/talerfrontends/blog/templates/base.html
index 7e3111a..533626c 100644
--- a/talerfrontends/blog/templates/base.html
+++ b/talerfrontends/blog/templates/base.html
@@ -21,7 +21,6 @@
   <link rel="stylesheet" type="text/css" href="{{ 
url("/static/web-common/lang.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-common/cb.js") }}" 
type="application/javascript"></script>
   <script src="{{ url("/static/web-common/lang.js") }}" 
type="application/javascript"></script>
   <meta http-equiv="content-type" content="text/html;CHARSET=utf-8">
   {% block scripts %}{% endblock %}
diff --git a/talerfrontends/blog/templates/purchase.html 
b/talerfrontends/blog/templates/purchase.html
index f605ace..d1baf38 100644
--- a/talerfrontends/blog/templates/purchase.html
+++ b/talerfrontends/blog/templates/purchase.html
@@ -33,9 +33,9 @@
 {% endblock main %}
 
 {% block body_prelude %}
-<script src="/static/body-prelude.js" type="application/javascript"></script>
+  <script src="{{ url('/static/body-prelude.js') }}" 
type="application/javascript"></script>
 {% endblock body_prelude %}
 
 {% block scripts %}
-<script src="/static/purchase.js" type="application/javascript"></script>
+  <script src="{{ url('/static/purchase.js') }}" 
type="application/javascript"></script>
 {% endblock scripts %}
diff --git a/talerfrontends/donations/donations.py 
b/talerfrontends/donations/donations.py
index 4657337..c7b52f3 100644
--- a/talerfrontends/donations/donations.py
+++ b/talerfrontends/donations/donations.py
@@ -15,7 +15,7 @@
 # @author Florian Dold
 # @author Marcello Stanisci
 
-from flask import Flask, render_template, session, request, jsonify, 
make_response, redirect, abort
+import flask
 from urllib.parse import urljoin, urlencode, quote
 import requests
 import logging
@@ -23,21 +23,20 @@ import os
 import base64
 import random
 import time
+from datetime import datetime
 import jinja2
 from talerfrontends.common_routes import tracking, history
 from talerfrontends.talerconfig import TalerConfig
-from talerfrontends.helpers import (make_url, talerdate, frontend_common,
-        expect_parameter, expect_parameter_int, BackendError,
-        MissingParameterError, sign_contract, track_transaction,
-        track_transfer, talerdate_to_obj, amount_to_string, get_history,
-        NoSessionActiveError, join_urlparts, map_in)
+from talerfrontends.helpers import (make_url, frontend_common,
+        expect_parameter, BackendError, amount_to_string, amount_from_float,
+        amount_to_float, join_urlparts)
 from talerfrontends.common_routes import tracking
 
 logger = logging.getLogger(__name__)
 
 base_dir = os.path.dirname(os.path.abspath(__file__))
 
-app = Flask(__name__, template_folder=base_dir)
+app = flask.Flask(__name__, template_folder=base_dir)
 app.register_blueprint(frontend_common)
 app.debug = True
 app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8')
@@ -55,170 +54,122 @@ print(app.config)
 @app.context_processor
 def utility_processor():
     def url(my_url):
-        return join_urlparts(request.script_root, my_url)
+        return join_urlparts(flask.request.script_root, my_url)
     return dict(url=url)
 
 
 @app.route('/')
 def index():
-    return render_template('templates/index.html', merchant_currency=CURRENCY)
+    return flask.render_template('templates/index.html', 
merchant_currency=CURRENCY)
+
 
 @app.route('/javascript')
 def javascript_licensing():
-    return render_template('templates/javascript.html')
+    return flask.render_template('templates/javascript.html')
+
 
 @app.route('/checkout', methods=["GET"])
 def checkout():
-    print(request.form)
     amount_str = expect_parameter("donation_amount")
+    donation_receiver = expect_parameter("donation_receiver")
     try:
         amount = float(amount_str)
     except ValueError:
         logger.warn("Invalid amount ('%s')", amount_str)
-        e = jsonify(error="invalid amount")
-        return make_response(e, 400)
-    session["amount"] = amount
-    session["instance"] = expect_parameter("instance")
-    return render_template('templates/checkout.html', 
merchant_currency=CURRENCY)
-
-
-def make_contract(instance, tid, aval, afrac, timestamp):
-    """
-    Make (or rather restore) a contract.
-    Always produces the same output for the same inputs.
-    """
-    amount = dict(value=aval, fraction=afrac, currency=CURRENCY)
-    fulfillment_url = make_url(
-            "fulfillment",
-            ("uuid", "${H_contract}"),
-            ("instance", instance),
-            ("aval", aval),
-            ("timestamp", timestamp),
-            ("tid", tid),
-            ("afrac", afrac),
-            ("acurr", CURRENCY))
-    contract = dict(
-           summary="Donation to %s" % instance,
-            amount=amount,
-            max_fee=MAX_FEE,
-            transaction_id=tid,
-            products=[
-                dict(
-                    description="Donation to %s" % (instance,),
-                    quantity=1,
-                    product_id=0,
-                    price=amount
-                ),
-                ],
-            timestamp=talerdate(timestamp),
-            pay_deadline=talerdate(timestamp + 60*60*24*100),
-            # instantaneous refund, as it allows debugging the aggregator 
faster
-            refund_deadline=talerdate(timestamp),
-            fulfillment_url=fulfillment_url,
-            merchant=dict(
-                instance=instance,
-                address="nowhere",
-                name="Kudos Inc.",
-                jurisdiction="none",
-                ),
-            locations={},
-            )
-    return contract
+        e = flask.jsonify(error="invalid amount")
+        return flask.make_response(e, 400)
+    return flask.render_template('templates/checkout.html',
+            donation_amount=amount_str,
+            donation_receiver=donation_receiver,
+            merchant_currency=CURRENCY)
 
 
 @app.route('/generate-contract', methods=["GET"])
 def generate_contract():
-    if "instance" not in session or "amount" not in session:
-        raise NoSessionActiveError()
-    instance = session["instance"]
-    amount = float(session["amount"])
-
-    amount_value = int(amount)
-    amount_fraction = int((amount - amount_value) * FRACTION)
-    now = int(time.time())
-    tid = random.randint(1, 2**50)
+    donation_receiver = expect_parameter("donation_receiver")
+    donation_amount = expect_parameter("donation_amount")
+    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(
+        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)),
+        merchant=dict(
+            instance=donation_receiver,
+            address="nowhere",
+            name="Kudos Inc.",
+            jurisdiction="none",
+        ),
+    )
+    print("order: ", order)
+    r = requests.post(urljoin(BACKEND_URL, 'proposal'), json=dict(order=order))
+    if r.status_code != 200:
+        logger.error("failed to POST to '%s'", url)
+        raise BackendError(r.status_code, r.text)
+    proposal_resp = r.json()
+    return flask.jsonify(**proposal_resp)
 
-    contract = make_contract(instance=instance, tid=tid, aval=amount_value, 
afrac=amount_fraction, timestamp=now)
-    contract_resp = sign_contract(contract)
-    logger.info("generated contract: %s" % str(contract_resp))
-    return jsonify(**contract_resp)
address@hidden('/donate')
+def donate():
+    donation_receiver = expect_parameter("donation_receiver")
+    donation_amount = expect_parameter("donation_amount")
+    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
 
 
 @app.route('/fulfillment')
 def fulfillment():
-    uuid = expect_parameter("uuid")
-    instance = expect_parameter("instance")
-    afrac = expect_parameter_int("afrac")
-    aval = expect_parameter_int("aval")
-    timestamp = expect_parameter_int("timestamp")
-    tid = expect_parameter_int("tid")
-    amount_str = str(int(aval) + float(afrac) / FRACTION)
-    if uuid not in session or not session[uuid].get("is_payed"):
-        restored_contract = make_contract(instance=instance, tid=tid, 
aval=aval, afrac=afrac, timestamp=timestamp)
-        contract_resp = sign_contract(restored_contract)
-        logger.info("restored contract: %s" % str(contract_resp))
-
-        if contract_resp["H_contract"] != uuid:
-            # FIXME: should just redirect to checkout ...
-            e = jsonify(error="contract mismatch")
-            return e, 400
-
-        session[uuid] = si = session.get(uuid, {})
-        si['instance'] = instance
-        si['amount'] = "%s %s" % (aval + float(afrac / FRACTION), CURRENCY)
-        si['plain_contract'] = contract_resp['contract']
-
-        pay_url = make_url("pay")
-        offering_url = make_url("checkout",
-                                ("instance", instance),
-                                ("donation_currency", CURRENCY),
-                                ("donation_amount", amount_str))
-        return render_template(
-                'templates/execute-payment.html',
-                hc=uuid,
-                pay_url=quote(pay_url),
-                offering_url=quote(offering_url))
-
-    real_instance = session[uuid]['instance']
-    real_amount = session[uuid]['amount']
-    # everything is payed, so show final page
-    return render_template('templates/fulfillment.html', 
instance=real_instance, amount=real_amount)
+    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-Pay-Url"] = make_url("/pay")
+    response.headers["X-Taler-Offer-Url"] = make_url("/")
+    return response
 
 
 @app.route('/pay', methods=["POST"])
 def pay():
-    deposit_permission = request.get_json()
-    hc = deposit_permission.get("H_contract")
-    if hc is None:
-        e = jsonify(error="malformed deposit permission", hint="H_contract 
missing")
-        return e, 400
-
-    si = session.get(hc)
-    if si is None:
-        e = jsonify(error="no session for contract")
-        return e, 400
-
+    deposit_permission = flask.request.get_json()
     if deposit_permission is None:
-        e = jsonify(error="no json in body")
+        e = flask.jsonify(error="no json in body")
         return e, 400
 
-    # this 'instance' fields is needed by the exchange to know which
-    # merchant instance will finally get money by wire transfer
-    deposit_permission['instance'] = si['instance']
-    logger.info("deposit permission: %s" % str(deposit_permission))
-
-    # The backend will verify that the information in the deposit permission
-    # (except for the instance, which we added/verified ourselves) is correct.
     r = requests.post(urljoin(BACKEND_URL, 'pay'), json=deposit_permission)
-    if r.status_code != 200:
+    if 200 != r.status_code:
         raise BackendError(r.status_code, r.text)
 
-    r = map_in(si['plain_contract'], hc)
-    si['is_payed'] = True
-    session.modified = True
-    session.permanent = True
+    proposal_data = r.json()['proposal_data']
+    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'])
+    )
+
+    print("received payment for", order_id)
 
-    logger.info("Successful payment: %s" % r.text)
     return r.text, 200
 
 app.add_url_rule('/history', 'history', history)
diff --git a/talerfrontends/donations/static/checkout.js 
b/talerfrontends/donations/static/checkout.js
deleted file mode 100644
index 0105547..0000000
--- a/talerfrontends/donations/static/checkout.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-  @licstart  The following is the entire license notice for the
-  JavaScript code in this page.
-
-  Copyright (C) 2015, 2016 INRIA
-
-  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.
-
-  @author Marcello Stanisci
-  @author Florian Dold
-*/
-"use strict";
-
-/* This function is called from "taler_pay" after
-   we downloaded the JSON contract from the merchant.
-   We now need to pass it to the extension. */
-function handle_contract(contract_wrapper) {
-  var cEvent = new CustomEvent('taler-confirm-contract', {
-    detail: {
-      contract_wrapper: contract_wrapper
-    }
-  });
-  document.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();
-
-  /* Note that the URL we give here is specific to the Demo-shop
-     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'. */
-  contract_request.open("GET", "generate-contract", 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 extension) alert (contract_request.responseText); */
-        console.log("response text:", contract_request.responseText);
-        var contract_wrapper = JSON.parse(contract_request.responseText);
-        if (!contract_wrapper) {
-          console.error("response text is invalid JSON");
-          return;
-        }
-        handle_contract(contract_wrapper);
-      } else {
-        /* There was an error obtaining the contract from the merchant,
-           obviously this should not happen. To keep it simple, we just
-           alert the user to the error. */
-        alert("Failure to download contract from merchant " +
-              "(" + contract_request.status + "):\n" +
-              contract_request.responseText);
-      }
-    }
-  };
-  contract_request.onerror = function (e) {
-    /* There was an error obtaining the contract from the merchant,
-       obviously this should not happen. To keep it simple, we just
-       alert the user to the error. */
-    alert("Failure requesting the contract:\n" + contract_request.statusText);
-  };
-  contract_request.send();
-}
-
-
-/* This function is called when the user presses the
-   'Ok' button.  We are now supposed to trigger the
-   "correct" payment system logic. For this demo, we
-   only handle "taler". */
-function pay() {
-  var form = document.forms[0];
-  var choice = form.elements["payment_system"].value;
-  if (choice == "taler") {
-    taler_pay(form);
-  } else {
-    alert("You selected '" + choice + "', but we do not support this payment 
system in the demo.");
-  }
-};
-
-function init(){
-  document.getElementById("select-payment-method").onclick = pay;
-}
-
-document.addEventListener("DOMContentLoaded", init);
diff --git a/talerfrontends/donations/static/web-common 
b/talerfrontends/donations/static/web-common
index dc9d5ab..9701ed4 160000
--- a/talerfrontends/donations/static/web-common
+++ b/talerfrontends/donations/static/web-common
@@ -1 +1 @@
-Subproject commit dc9d5ab2308fef7cdd1e8c95fbf4fdd51bed7bfb
+Subproject commit 9701ed4caa1cb541c1f645b05bfe190975b3e42b
diff --git a/talerfrontends/donations/templates/base.html 
b/talerfrontends/donations/templates/base.html
index 11030c7..32dbad7 100644
--- a/talerfrontends/donations/templates/base.html
+++ b/talerfrontends/donations/templates/base.html
@@ -21,7 +21,6 @@
   <link rel="stylesheet" type="text/css" href="{{ 
url("/static/web-common/style.css") }}">
   <link rel="stylesheet" type="text/css" href="{{ 
url("/static/web-common/lang.css") }}">
   <script src="{{ url("/static/web-common/taler-wallet-lib.js") }}" 
type="application/javascript"></script>
-  <script src="{{ url("/static-common/cb.js") }}"></script>
   <script src="{{ url("/static/web-common/lang.js") }}" 
type="application/javascript"></script>
   {% block scripts %}{% endblock %}
 </head>
diff --git a/talerfrontends/donations/templates/checkout.html 
b/talerfrontends/donations/templates/checkout.html
index bace390..4a8e891 100644
--- a/talerfrontends/donations/templates/checkout.html
+++ b/talerfrontends/donations/templates/checkout.html
@@ -28,8 +28,10 @@
     two steps to keep each step as simple as possible.
   </p>
 
-  <form name="tform" action="" method="POST">
+  <form name="tform" action="{{ url('/donate') }}" method="get">
     <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="radio" name="payment_system" value="lisa"
              id="lisa-radio-button-id">Lisa</input>
       <br/>
@@ -41,14 +43,10 @@
              checked
              id="taler-radio-button-id" 
class="taler-installed-enable">Taler</input>
       <br/>
-      <input id="select-payment-method" type="button" value="Ok"></input>
+      <input id="select-payment-method" type="submit" value="Ok"></input>
     </div>
   </form>
 
 </article>
 
 {% endblock main %}
-
-{% block scripts %}
-<script src="/static/checkout.js" type="application/javascript"></script>
-{% endblock scripts %}
diff --git a/talerfrontends/donations/templates/fallback.html 
b/talerfrontends/donations/templates/fallback.html
new file mode 100644
index 0000000..ecf22ae
--- /dev/null
+++ b/talerfrontends/donations/templates/fallback.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+  <body>
+   <div id="ccfakeform" class="fade">
+     <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"></input><br>
+       Family name<br> <input type="text"></input><br>
+       Age<br> <input type="text"></input><br>
+       Nationality<br> <input type="text"></input><br>
+       Gender<br> <input type="radio" name"gender">Male</input>
+       CC number<br> <input type="text"></input><br>
+       <input type="radio" name="gender">Female</input><br>
+     </form>
+     <form method="get" action="/cc-payment/{{ article_name }}">
+       <input type="submit"></input>
+     </form>
+   </div>
+  </body>
+</html>
diff --git a/talerfrontends/donations/templates/fulfillment.html 
b/talerfrontends/donations/templates/fulfillment.html
index 4a50947..67e56ff 100644
--- a/talerfrontends/donations/templates/fulfillment.html
+++ b/talerfrontends/donations/templates/fulfillment.html
@@ -1,5 +1,7 @@
 {% extends "templates/base.html" %}
 
 {% block main %}
-Thanks for donating {{ amount }} to {{ instance }}.
+<p> Thanks for donating <strong>{{ donation_amount }} {{ currency }}</strong> 
to <strong>{{ donation_receiver }}</strong>.</p>
+
+<p>Please keep the order identifier <strong>{{ order_id }}</strong> as a 
receipt for your donation.</p>
 {% endblock main %}
diff --git a/talerfrontends/donations/templates/index.html 
b/talerfrontends/donations/templates/index.html
index 23f5a13..4c835c8 100644
--- a/talerfrontends/donations/templates/index.html
+++ b/talerfrontends/donations/templates/index.html
@@ -2,12 +2,11 @@
 
 {% block scripts %}
 <meta name="merchant_currency" value="{{ merchant_currency }}">
-<script src="/static/index.js" type="application/javascript"></script>
+<script src="{{ url('/static/index.js') }}" 
type="application/javascript"></script>
 {% endblock %}
 
 {% block main %}
   <h1 lang="en">Welcome to the Taler Donation "Shop" Demo</h1>
-  <h1 lang="it">Benvenuti nel negozio dimostrativo di Taler</h1>
 
   <p>This "toy" website provides you with the ability to
     experience using the
@@ -53,11 +52,11 @@
   <form name="tform" action="checkout" method="GET">
     <div class="participation" id="fake-shop">
       <br>
-      <input type="radio" name="instance" value="Taler" checked="true">GNU 
Taler</input>
+      <input type="radio" name="donation_receiver" value="Taler" 
checked="true">GNU Taler</input>
       <br>
-      <input type="radio" name="instance" value="Tor">Tor</input>
+      <input type="radio" name="donation_receiver" value="Tor">Tor</input>
       <br>
-      <input type="radio" name="instance" value="GNUnet">GNUnet</input>
+      <input type="radio" name="donation_receiver" 
value="GNUnet">GNUnet</input>
       <br>
       <select id="taler-donation" name="donation_amount">
         <!-- options are added dynamically -->
diff --git a/talerfrontends/helpers.py b/talerfrontends/helpers.py
index ab61754..d17c249 100644
--- a/talerfrontends/helpers.py
+++ b/talerfrontends/helpers.py
@@ -31,23 +31,25 @@ TRACK_TRANSACTION_CONFLICT = 2308
 tc = TalerConfig.from_env()
 BACKEND_URL = tc["frontends"]["backend"].value_string(required=True)
 NDIGITS = tc["frontends"]["NDIGITS"].value_int()
-FRACTION = tc["frontends"]["FRACTION"].value_int()
 CURRENCY = tc["taler"]["CURRENCY"].value_string()
 
+FRACTION_BASE = 1e8
+
 if not NDIGITS:
     NDIGITS = 2
 
-def floatify(amount_dict):
-    return amount_dict['value'] + (float(amount_dict['fraction']) / 
float(FRACTION))
+def amount_to_float(amount):
+    return amount['value'] + (float(amount['fraction']) / float(FRACTION_BASE))
 
-# Cut fractional part to NDIGITS digits.
-def stringify_amount(amount_float):
+def amount_to_string(amount):
+    f = amount_to_float(amount)
     o = "".join(["%.", "%sf" % NDIGITS])
-    return o % amount_float
+    return o % f
 
-def amount_to_string(amount):
-    f = floatify(amount)
-    return stringify_amount(f) + " " + amount['currency']
+def amount_from_float(x):
+    value = int(x)
+    fraction = int((x - value) * FRACTION_BASE)
+    return dict(currency=CURRENCY, value=value, fraction=fraction)
 
 
 def join_urlparts(*parts):
@@ -63,6 +65,7 @@ def join_urlparts(*parts):
         s += n
     return s
 
+
 def amount_sum(a, b):
     assert(a["currency"] == b["currency"])
     fractions = a["fraction"] + b["fraction"]
@@ -71,6 +74,7 @@ def amount_sum(a, b):
            "currency": a["currency"]}
     return ret
 
+
 # Give a - b.  Mostly needed by backoffice
 def amount_sub(a, b):
     assert(a["currency"] == b["currency"])
@@ -97,9 +101,11 @@ def amount_sub(a, b):
 
     return ret
 
+
 def amount_get_zero():
     return {"value": 0, "fraction": 0, "currency": CURRENCY}
 
+
 def make_url(page, *query_params):
     """
     Return a URL to a page in the current Flask application with the given
@@ -137,17 +143,6 @@ frontend_common = Blueprint("talerfrontends-common",
                 static_url_path="/static-common")
 
 
-# Issue a HTTP POST to /map/in to the backend.
-def map_in(contract, h_contract):
-    r = requests.post(urljoin(BACKEND_URL, 'map/in'),
-                      json=dict(contract=contract,
-                                h_contract=h_contract))
-    if 422 == r.status_code:
-        raise MalformedParameterError("h_contract")
-    if 200 != r.status_code:
-        raise BackendError(r.status_code, r.text)
-    return r
-
 # This class is used when the wallet detects any error
 # and it calls the onError handler installed by the merchant
 class CustomError(Exception):
@@ -296,16 +291,6 @@ def track_transaction(tid, instance):
     return track
 
 
-def sign_contract(contract):
-    url = urljoin(current_app.config["BACKEND_URL"], 'contract')
-    r = requests.post(url, json=dict(contract=contract))
-    if r.status_code != 200:
-        logger.error("failed to POST to '%s'", url)
-        raise BackendError(r.status_code, r.text)
-    contract_resp = r.json()
-    return contract_resp
-
-
 def make_400(ret):
     return make_response(ret, 400)
 
@@ -348,12 +333,10 @@ def handle_malformed_parameter_error(error):
 
 @frontend_common.app_errorhandler(BackendError)
 def handle_backend_error(error):
-    jerror = json.loads(error.response)
-    error_msg = jerror.get("error", error.response)
-    logger.warn("Backend error, status %s, body %s" % (error.status, 
error_msg))
+    logger.warn("Backend error, status %s, body %s", error.status, 
repr(error.response))
     return make_response(render_template("error.html",
                                          error="backend error",
-                                         details=error_msg),
+                                         details=error.response),
                          error.status)
 
 @frontend_common.app_errorhandler(CustomError)
diff --git a/talerfrontends/static/cb.js b/talerfrontends/static/cb.js
deleted file mode 100644
index 75cbf7d..0000000
--- a/talerfrontends/static/cb.js
+++ /dev/null
@@ -1,20 +0,0 @@
-"use strict";
-var on_error = function(error, detail){
-  var response = detail.response || '{"error": "Not given"}';
-  var hint = detail.hint || "Not given";
-  var status_code = detail.status || 400;
-  var body = {
-    code: error,
-    hint: hint,
-    status: status_code};
-  var schema = window.location.href.split("//")[0];
-  var enc = btoa(JSON.stringify(body));
-  var url = schema
-            + "//"
-            + window.location.hostname
-            + ":" + window.location.port
-            + "/error?enc="
-            + encodeURIComponent(enc);
-  window.location = url;
-  };
-taler.onError(on_error);

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



reply via email to

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