1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
import flask
import requests
from urllib.parse import urljoin, urlencode
import taler.util.amount
import base64
import os
import logging
import json
from random import randint
from datetime import datetime
app = flask.Flask(__name__)
app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8')
logger = logging.getLogger(__name__)
CURRENCY = "TESTKUDOS"
BACKEND_URL = "http://backend.test.taler.net/"
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", "}")
@app.route("/")
def index():
return flask.render_template("index.html")
@app.route("/donate")
def donate():
response = flask.Response(status=402)
response.headers["X-Taler-Contract-Url"] = "/generate-proposal"
return response
@app.route("/generate-proposal")
def generate_proposal():
DONATION = amount.string_to_amount("0.1:%s" % CURRENCY)
MAX_FEE = amount.string_to_amount("0.05:%s" % CURRENCY)
ORDER_ID = "tutorial-%X-%s" % (randint(0, 0xFFFFFFFF), datetime.today().strftime("%H_%M_%S"))
order = dict(
order_id=ORDER_ID,
nonce=flask.request.args.get("nonce"),
amount=DONATION,
max_fee=MAX_FEE,
products=[
dict(
description="Donation",
quantity=1,
product_id=0,
price=DONATION,
),
],
fulfillment_url=make_url("/fulfillment", ("order_id", ORDER_ID)),
pay_url=make_url("/pay"),
merchant=dict(
instance="tutorial",
address="nowhere",
name="Donation tutorial",
jurisdiction="none",
),
)
url = urljoin(BACKEND_URL, "proposal")
r = requests.post(url, json=dict(order=order))
if r.status_code != 200:
logger.error("failed to POST to '%s'", url)
return r.text, r.status_code
proposal_resp = r.json()
return flask.jsonify(**proposal_resp)
@app.route("/fulfillment")
def fulfillment():
paid = flask.session.get("paid", False)
if paid:
return "Thank you! Your order id is: <b>%s</b>." % flask.session["order_id"]
response = flask.Response(status=402)
response.headers["X-Taler-Contract-Url"] = make_url("/generate-contract")
response.headers["X-Taler-Contract-Query"] = "fulfillment_url"
response.headers["X-Taler-Offer-Url"] = make_url("/donate")
return response
@app.route("/pay", methods=["POST"])
def pay():
deposit_permission = flask.request.get_json()
if deposit_permission is None:
e = flask.jsonify(error="no json in body")
return e, 400
r = requests.post(urljoin(BACKEND_URL, 'pay'), json=deposit_permission)
if 200 != r.status_code:
logger.error("Backend said, status code: %d, object: %s" % (r.status_code, r.text))
return r.text, r.status_code
contract_terms = r.json()["contract_terms"]
flask.session["paid"] = True
flask.session["order_id"] = contract_terms["order_id"]
return flask.jsonify(r.json()), 200
|