From 455755737e6dcb7f938f7e6f9672bfc3e38f0a73 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:01:43 +0200 Subject: yapf style file --- talerdonations/donations/donations.py | 76 +++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 31 deletions(-) (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index f0f97c5..5655734 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -53,6 +53,7 @@ app.config.from_object(__name__) def utility_processor(): def env(name, default=None): return os.environ.get(name, default) + return dict(env=env) @@ -76,7 +77,9 @@ def err_abort(abort_status_code, **params): def backend_get(endpoint, params): headers = {"Authorization": "ApiKey " + APIKEY} try: - resp = requests.get(urljoin(BACKEND_URL, endpoint), params=params, headers=headers) + resp = requests.get(urljoin(BACKEND_URL, endpoint), + params=params, + headers=headers) except requests.ConnectionError: err_abort(500, message="Could not establish connection to backend") try: @@ -84,8 +87,10 @@ def backend_get(endpoint, params): 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) + err_abort(500, + message="Backend returned error status", + json=response_json, + status_code=resp.status_code) return response_json @@ -100,21 +105,25 @@ def backend_get(endpoint, params): def backend_post(endpoint, json): headers = {"Authorization": "ApiKey " + APIKEY} try: - resp = requests.post(urljoin(BACKEND_URL, endpoint), json=json, headers=headers) + resp = requests.post(urljoin(BACKEND_URL, endpoint), + json=json, + headers=headers) 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", + 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) + err_abort(500, + message="Backend returned error status", + json=response_json, + status_code=resp.status_code) return response_json - ## # Inspect GET arguments in the look for a parameter. # @@ -126,6 +135,7 @@ def expect_parameter(name): return err_abort(400, message="parameter '{}' required".format(name)) return val + ## # "Fallback" exception handler to capture all the unmanaged errors. # @@ -138,13 +148,16 @@ def internal_error(e): message="Internal error", stack=traceback.format_exc()) + ## # Serve the main index page. # # @return response object of the index page. @app.route("/") def index(): - return flask.render_template("templates/index.html", merchant_currency=CURRENCY) + return flask.render_template("templates/index.html", + merchant_currency=CURRENCY) + ## # Serve the "/javascript" page. @@ -155,7 +168,6 @@ def javascript_licensing(): return flask.render_template("templates/javascript.html") - ## # Serve the "/checkout" page. This page lets the # user pick the payment method they want to use, @@ -167,12 +179,11 @@ def checkout(): amount = expect_parameter("donation_amount") donation_receiver = expect_parameter("donation_receiver") donation_donor = expect_parameter("donation_donor") - return flask.render_template( - "templates/checkout.html", - donation_amount=amount, - donation_receiver=donation_receiver, - donation_donor=donation_donor, - merchant_currency=CURRENCY) + return flask.render_template("templates/checkout.html", + donation_amount=amount, + donation_receiver=donation_receiver, + donation_donor=donation_donor, + merchant_currency=CURRENCY) ## @@ -182,8 +193,7 @@ def checkout(): # @return response object about the mentioned impossibility. @app.route("/provider-not-supported") def provider_not_supported(): - return flask.render_template( "templates/provider-not-supported.html") - + return flask.render_template("templates/provider-not-supported.html") ## @@ -201,18 +211,24 @@ def donate(): payment_system = expect_parameter("payment_system") if payment_system != "taler": return flask.redirect(flask.url_for("provider_not_supported")) - fulfillment_url = flask.url_for("fulfillment", receiver=donation_receiver, _external=True) + fulfillment_url = flask.url_for("fulfillment", + receiver=donation_receiver, + _external=True) order = dict( amount=donation_amount, - extra=dict(donor=donation_donor, receiver=donation_receiver, amount=donation_amount), + extra=dict(donor=donation_donor, + receiver=donation_receiver, + amount=donation_amount), fulfillment_url=fulfillment_url, instance=donation_receiver, summary="Donation to {}".format(donation_receiver), ) order_resp = backend_post("order", dict(order=order)) order_id = order_resp["order_id"] - return flask.redirect(flask.url_for("fulfillment", receiver=donation_receiver, order_id=order_id)) - + return flask.redirect( + flask.url_for("fulfillment", + receiver=donation_receiver, + order_id=order_id)) ## @@ -226,8 +242,7 @@ def donate(): @app.route("/donation/") def fulfillment(receiver): order_id = expect_parameter("order_id") - pay_params = dict(instance=receiver, - order_id=order_id) + pay_params = dict(instance=receiver, order_id=order_id) pay_status = backend_get("check-payment", pay_params) if pay_status.get("payment_redirect_url"): @@ -235,13 +250,12 @@ def fulfillment(receiver): if pay_status.get("paid"): extra = pay_status["contract_terms"]["extra"] - return flask.render_template( - "templates/fulfillment.html", - donation_receiver=extra["receiver"], - donation_amount=extra["amount"], - donation_donor=extra["donor"], - order_id=order_id, - currency=CURRENCY) + return flask.render_template("templates/fulfillment.html", + donation_receiver=extra["receiver"], + donation_amount=extra["amount"], + donation_donor=extra["donor"], + order_id=order_id, + currency=CURRENCY) # no pay_redirect but article not paid, this should never happen! err_abort(500, message="Internal error, invariant failed", json=pay_status) -- cgit v1.2.3 From 9c282aa69a4d25f186e591a075b0f2830b5ec45a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:02:31 +0200 Subject: make pretty --- setup.py | 51 +++++++++-------- talerdonations/donations/donations.py | 100 ++++++++++++++++++++-------------- talerdonations/talerconfig.py | 95 ++++++++++++++++++-------------- 3 files changed, 136 insertions(+), 110 deletions(-) (limited to 'talerdonations/donations/donations.py') diff --git a/setup.py b/setup.py index 71526a9..906567c 100755 --- a/setup.py +++ b/setup.py @@ -1,28 +1,27 @@ from setuptools import setup, find_packages -setup(name='talerdonations', - version='0.6.0pre1', - description='Example donations site for GNU Taler', - url='git://taler.net/donations', - author=['Marcello Stanisci', 'Florian Dold'], - author_email=['stanisci.m@gmail.com', 'dold@taler.net'], - license='GPL', - packages=find_packages(), - install_requires=["Flask>=0.10", - "requests", - "uwsgi", - "jsmin"], - tests_require=["mock", "nose"], - test_suite="nose.collector", - package_data={ - '':[ - "donations/templates/*.html", - "donations/static/*.svg", - "donations/static/*.css", - "donations/static/web-common/*.png", - "donations/static/web-common/*.css", - "donations/static/web-common/*.html", - ] - }, - scripts=['./bin/taler-merchant-donations'], - zip_safe=False) +setup( + name='talerdonations', + version='0.6.0pre1', + description='Example donations site for GNU Taler', + url='git://taler.net/donations', + author=['Marcello Stanisci', 'Florian Dold'], + author_email=['stanisci.m@gmail.com', 'dold@taler.net'], + license='GPL', + packages=find_packages(), + install_requires=["Flask>=0.10", "requests", "uwsgi", "jsmin"], + tests_require=["mock", "nose"], + test_suite="nose.collector", + package_data={ + '': [ + "donations/templates/*.html", + "donations/static/*.svg", + "donations/static/*.css", + "donations/static/web-common/*.png", + "donations/static/web-common/*.css", + "donations/static/web-common/*.html", + ] + }, + scripts=['./bin/taler-merchant-donations'], + zip_safe=False +) diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index 5655734..220fbb7 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -77,9 +77,9 @@ def err_abort(abort_status_code, **params): def backend_get(endpoint, params): headers = {"Authorization": "ApiKey " + APIKEY} try: - resp = requests.get(urljoin(BACKEND_URL, endpoint), - params=params, - headers=headers) + resp = requests.get( + urljoin(BACKEND_URL, endpoint), params=params, headers=headers + ) except requests.ConnectionError: err_abort(500, message="Could not establish connection to backend") try: @@ -87,10 +87,12 @@ def backend_get(endpoint, params): 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) + err_abort( + 500, + message="Backend returned error status", + json=response_json, + status_code=resp.status_code + ) return response_json @@ -105,22 +107,26 @@ def backend_get(endpoint, params): def backend_post(endpoint, json): headers = {"Authorization": "ApiKey " + APIKEY} try: - resp = requests.post(urljoin(BACKEND_URL, endpoint), - json=json, - headers=headers) + resp = requests.post( + urljoin(BACKEND_URL, endpoint), json=json, headers=headers + ) 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) + 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) + err_abort( + 500, + message="Backend returned error status", + json=response_json, + status_code=resp.status_code + ) return response_json @@ -144,9 +150,11 @@ def expect_parameter(name): # (and execution stack!). @app.errorhandler(Exception) def internal_error(e): - return flask.render_template("templates/error.html", - message="Internal error", - stack=traceback.format_exc()) + return flask.render_template( + "templates/error.html", + message="Internal error", + stack=traceback.format_exc() + ) ## @@ -155,8 +163,9 @@ def internal_error(e): # @return response object of the index page. @app.route("/") def index(): - return flask.render_template("templates/index.html", - merchant_currency=CURRENCY) + return flask.render_template( + "templates/index.html", merchant_currency=CURRENCY + ) ## @@ -179,11 +188,13 @@ def checkout(): amount = expect_parameter("donation_amount") donation_receiver = expect_parameter("donation_receiver") donation_donor = expect_parameter("donation_donor") - return flask.render_template("templates/checkout.html", - donation_amount=amount, - donation_receiver=donation_receiver, - donation_donor=donation_donor, - merchant_currency=CURRENCY) + return flask.render_template( + "templates/checkout.html", + donation_amount=amount, + donation_receiver=donation_receiver, + donation_donor=donation_donor, + merchant_currency=CURRENCY + ) ## @@ -211,14 +222,16 @@ def donate(): payment_system = expect_parameter("payment_system") if payment_system != "taler": return flask.redirect(flask.url_for("provider_not_supported")) - fulfillment_url = flask.url_for("fulfillment", - receiver=donation_receiver, - _external=True) + fulfillment_url = flask.url_for( + "fulfillment", receiver=donation_receiver, _external=True + ) order = dict( amount=donation_amount, - extra=dict(donor=donation_donor, - receiver=donation_receiver, - amount=donation_amount), + extra=dict( + donor=donation_donor, + receiver=donation_receiver, + amount=donation_amount + ), fulfillment_url=fulfillment_url, instance=donation_receiver, summary="Donation to {}".format(donation_receiver), @@ -226,9 +239,10 @@ def donate(): order_resp = backend_post("order", dict(order=order)) order_id = order_resp["order_id"] return flask.redirect( - flask.url_for("fulfillment", - receiver=donation_receiver, - order_id=order_id)) + flask.url_for( + "fulfillment", receiver=donation_receiver, order_id=order_id + ) + ) ## @@ -250,12 +264,14 @@ def fulfillment(receiver): if pay_status.get("paid"): extra = pay_status["contract_terms"]["extra"] - return flask.render_template("templates/fulfillment.html", - donation_receiver=extra["receiver"], - donation_amount=extra["amount"], - donation_donor=extra["donor"], - order_id=order_id, - currency=CURRENCY) + return flask.render_template( + "templates/fulfillment.html", + donation_receiver=extra["receiver"], + donation_amount=extra["amount"], + donation_donor=extra["donor"], + order_id=order_id, + currency=CURRENCY + ) # 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/talerconfig.py b/talerdonations/talerconfig.py index 7959ec2..1a33294 100644 --- a/talerdonations/talerconfig.py +++ b/talerdonations/talerconfig.py @@ -171,11 +171,13 @@ class Entry: LOGGER.warning( "Configuration is missing option '%s' in section '%s',\ falling back to '%s'", self.option, - self.section, default) + self.section, default + ) else: LOGGER.warning( "Configuration ** is missing option '%s' in section '%s'", - self.option.upper(), self.section.upper()) + self.option.upper(), self.section.upper() + ) return default return self.value @@ -373,7 +375,8 @@ class TalerConfig: # a error occurs). def value_string(self, section, option, **kwargs) -> str: return self.sections[section][option].value_string( - kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")) + kwargs.get("default"), kwargs.get("required"), kwargs.get("warn") + ) ## # Get a value from the config that should be a filename. @@ -388,7 +391,8 @@ class TalerConfig: # a error occurs). def value_filename(self, section, option, **kwargs) -> str: return self.sections[section][option].value_filename( - kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")) + kwargs.get("default"), kwargs.get("required"), kwargs.get("warn") + ) ## # Get a integer value from the config. @@ -402,7 +406,8 @@ class TalerConfig: # a error occurs). def value_int(self, section, option, **kwargs) -> int: return self.sections[section][option].value_int( - kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")) + kwargs.get("default"), kwargs.get("required"), kwargs.get("warn") + ) ## # Load default values from canonical locations. @@ -477,48 +482,58 @@ class TalerConfig: pair = line.split() if 2 != len(pair): LOGGER.error( - "invalid inlined config filename given ('%s')" - % line) + "invalid inlined config filename given ('%s')" % + line + ) continue if pair[1].startswith("/"): self.load_file(pair[1]) else: self.load_file( - os.path.join(os.path.dirname(filename), - pair[1])) + os.path.join( + os.path.dirname(filename), pair[1] + ) + ) continue if line.startswith("["): if not line.endswith("]"): LOGGER.error( - "invalid section header in line %s: %s", - lineno, repr(line)) + "invalid section header in line %s: %s", lineno, + repr(line) + ) section_name = line.strip("[]").strip().strip('"') current_section = section_name continue if current_section is None: LOGGER.error( "option outside of section in line %s: %s", lineno, - repr(line)) + repr(line) + ) continue pair = line.split("=", 1) if len(pair) != 2: - LOGGER.error("invalid option in line %s: %s", lineno, - repr(line)) + LOGGER.error( + "invalid option in line %s: %s", lineno, repr(line) + ) key = pair[0].strip() value = pair[1].strip() if value.startswith('"'): value = value[1:] if not value.endswith('"'): - LOGGER.error("mismatched quotes in line %s: %s", - lineno, repr(line)) + LOGGER.error( + "mismatched quotes in line %s: %s", lineno, + repr(line) + ) else: value = value[:-1] - entry = Entry(self.sections, - current_section, - key, - value=value, - filename=filename, - lineno=lineno) + entry = Entry( + self.sections, + current_section, + key, + value=value, + filename=filename, + lineno=lineno + ) sections[current_section][key] = entry except FileNotFoundError: # not logging here, as this interests the final user mostly. @@ -561,26 +576,22 @@ if __name__ == "__main__": import argparse PARSER = argparse.ArgumentParser() - PARSER.add_argument("--section", - "-s", - dest="section", - default=None, - metavar="SECTION") - PARSER.add_argument("--option", - "-o", - dest="option", - default=None, - metavar="OPTION") - PARSER.add_argument("--config", - "-c", - dest="config", - default=None, - metavar="FILE") - PARSER.add_argument("--filename", - "-f", - dest="expand_filename", - default=False, - action='store_true') + PARSER.add_argument( + "--section", "-s", dest="section", default=None, metavar="SECTION" + ) + PARSER.add_argument( + "--option", "-o", dest="option", default=None, metavar="OPTION" + ) + PARSER.add_argument( + "--config", "-c", dest="config", default=None, metavar="FILE" + ) + PARSER.add_argument( + "--filename", + "-f", + dest="expand_filename", + default=False, + action='store_true' + ) ARGS = PARSER.parse_args() TC = TalerConfig.from_file(ARGS.config) -- cgit v1.2.3 From e7c20a11fac21ab485b17feec81d0887be4cf5eb Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:09:02 +0200 Subject: url-based payments --- talerdonations/donations/donations.py | 26 +++++++- .../donations/templates/request_payment.html | 69 ++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 talerdonations/donations/templates/request_payment.html (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index 220fbb7..06c6617 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -245,6 +245,16 @@ def donate(): ) +## +# This endpoint is used by the payment request page +# to check if the payment has been completed via the QR code. +@app.route("/check-status/") +def check_status(order_id, session_id): + pay_params = dict( instance=INSTANCE, order_id=order_id) + pay_status = backend_get("check-payment", pay_params) + return flask.jsonify(paid=pay_status["paid"]) + + ## # Serve the fulfillment page. # @@ -260,7 +270,21 @@ def fulfillment(receiver): pay_status = backend_get("check-payment", pay_params) if pay_status.get("payment_redirect_url"): - return flask.redirect(pay_status["payment_redirect_url"]) + taler_pay_uri = pay_status["taler_pay_uri"] + qrcode_svg = get_qrcode_svg(taler_pay_uri) + check_status_url_enc = urllib.parse.quote( + flask.url_for("check_status", order_id=order_id) + ) + content = flask.render_template( + "templates/request_payment.html", + article_name=article_name, + taler_pay_uri=taler_pay_uri, + qrcode_svg=qrcode_svg, + check_status_url_enc=check_status_url_enc + ) + headers = {"Taler": taler_pay_uri} + resp = flask.Response(content, status=402, headers=headers) + return resp if pay_status.get("paid"): extra = pay_status["contract_terms"]["extra"] diff --git a/talerdonations/donations/templates/request_payment.html b/talerdonations/donations/templates/request_payment.html new file mode 100644 index 0000000..6e050d0 --- /dev/null +++ b/talerdonations/donations/templates/request_payment.html @@ -0,0 +1,69 @@ +{% extends "templates/base.html" %} + + +{% block meta %} + +{% endblock meta %} + + +{% block scripts %} + +{% endblock scripts %} + + +{% block main %} + +

Payment Required

+ +
+

+ Looks like your browser doesn't support GNU Taler payments. You can try + installing a wallet browser extension. +

+
+ +
+ +

+ You can use this QR code to pay with your mobile wallet: +

+ + {{ qrcode_svg | safe }} + +

+ Click this link to open your system's Taler wallet if it exists. +

+ +
+ +{% endblock main %} -- cgit v1.2.3 From 31a05eaab426a6121a93945f1f2e08a686987560 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:10:43 +0200 Subject: make pretty --- talerdonations/donations/donations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index 06c6617..886705f 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -250,7 +250,7 @@ def donate(): # to check if the payment has been completed via the QR code. @app.route("/check-status/") def check_status(order_id, session_id): - pay_params = dict( instance=INSTANCE, order_id=order_id) + pay_params = dict(instance=INSTANCE, order_id=order_id) pay_status = backend_get("check-payment", pay_params) return flask.jsonify(paid=pay_status["paid"]) -- cgit v1.2.3 From 06bf80ca7326e9e1c72b27cb4734f9eefc20f68e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:13:16 +0200 Subject: no more redirect URL --- talerdonations/donations/donations.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index 886705f..d4dd36d 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -269,7 +269,18 @@ def fulfillment(receiver): pay_params = dict(instance=receiver, order_id=order_id) pay_status = backend_get("check-payment", pay_params) - if pay_status.get("payment_redirect_url"): + + if pay_status.get("paid"): + extra = pay_status["contract_terms"]["extra"] + return flask.render_template( + "templates/fulfillment.html", + donation_receiver=extra["receiver"], + donation_amount=extra["amount"], + donation_donor=extra["donor"], + order_id=order_id, + currency=CURRENCY + ) + else: taler_pay_uri = pay_status["taler_pay_uri"] qrcode_svg = get_qrcode_svg(taler_pay_uri) check_status_url_enc = urllib.parse.quote( @@ -286,16 +297,5 @@ def fulfillment(receiver): resp = flask.Response(content, status=402, headers=headers) return resp - if pay_status.get("paid"): - extra = pay_status["contract_terms"]["extra"] - return flask.render_template( - "templates/fulfillment.html", - donation_receiver=extra["receiver"], - donation_amount=extra["amount"], - donation_donor=extra["donor"], - order_id=order_id, - currency=CURRENCY - ) - # no pay_redirect but article not paid, this should never happen! err_abort(500, message="Internal error, invariant failed", json=pay_status) -- cgit v1.2.3 From 8ef2843d05d57c07115dba494cc913efc3f19014 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:15:09 +0200 Subject: qrcode --- setup.py | 2 +- talerdonations/donations/donations.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'talerdonations/donations/donations.py') diff --git a/setup.py b/setup.py index 906567c..042635f 100755 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( author_email=['stanisci.m@gmail.com', 'dold@taler.net'], license='GPL', packages=find_packages(), - install_requires=["Flask>=0.10", "requests", "uwsgi", "jsmin"], + install_requires=["Flask>=0.10", "requests", "uwsgi", "jsmin", "qrcode", "lxml"], tests_require=["mock", "nose"], test_suite="nose.collector", package_data={ diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index d4dd36d..c00844b 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -26,6 +26,9 @@ import random import requests import flask import traceback +import qrcode +import qrcode.image.svg +import lxml.etree from ..talerconfig import TalerConfig LOGGER = logging.getLogger(__name__) @@ -255,6 +258,12 @@ def check_status(order_id, session_id): return flask.jsonify(paid=pay_status["paid"]) +def get_qrcode_svg(data): + factory = qrcode.image.svg.SvgImage + img = qrcode.make(data, image_factory=factory) + return lxml.etree.tostring(img.get_image()).decode("utf-8") + + ## # Serve the fulfillment page. # -- cgit v1.2.3 From cdd70817d77265a897e4efb1fed22e66e2c99ce9 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:15:58 +0200 Subject: urllib --- talerdonations/donations/donations.py | 1 + 1 file changed, 1 insertion(+) (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index c00844b..21eb76a 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -26,6 +26,7 @@ import random import requests import flask import traceback +import urllib import qrcode import qrcode.image.svg import lxml.etree -- cgit v1.2.3 From b38365fa582a52592d00f36e8dee2ee9bfca9ee6 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 29 Aug 2019 19:16:45 +0200 Subject: I want static typing --- talerdonations/donations/donations.py | 1 - 1 file changed, 1 deletion(-) (limited to 'talerdonations/donations/donations.py') diff --git a/talerdonations/donations/donations.py b/talerdonations/donations/donations.py index 21eb76a..d85c9a9 100644 --- a/talerdonations/donations/donations.py +++ b/talerdonations/donations/donations.py @@ -298,7 +298,6 @@ def fulfillment(receiver): ) content = flask.render_template( "templates/request_payment.html", - article_name=article_name, taler_pay_uri=taler_pay_uri, qrcode_svg=qrcode_svg, check_status_url_enc=check_status_url_enc -- cgit v1.2.3