[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [taler-merchant-frontends] branch master updated: use new wallet and merchant backend api,
gnunet <=