summaryrefslogtreecommitdiff
path: root/python/example/example.py
blob: 505144c3b7d99e6c49b52abf80dbb93f43bbe89c (plain)
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