From c1f384fb9ab222fe5d12067b82e595c1864ee097 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Sat, 15 Feb 2020 09:38:33 +0100 Subject: [PATCH 1/3] so many notes&hacks! --- README-penguinpay.md | 10 +++++ hack.py | 98 ++++++++++++++++++++++++++++++++++++++++++++ notes.org | 1 + requirements.txt | 3 ++ 4 files changed, 112 insertions(+) create mode 100644 README-penguinpay.md create mode 100644 hack.py create mode 100644 notes.org create mode 100644 requirements.txt diff --git a/README-penguinpay.md b/README-penguinpay.md new file mode 100644 index 0000000..769f183 --- /dev/null +++ b/README-penguinpay.md @@ -0,0 +1,10 @@ +## How to place a order with penguin pay + +### Requirements + +* An ungleich account - can be registered for free on + https://account.ungleich.ch +* httpie installed (provides the http command) + +### Get a membership + * diff --git a/hack.py b/hack.py new file mode 100644 index 0000000..c84f9f6 --- /dev/null +++ b/hack.py @@ -0,0 +1,98 @@ +from flask import Flask, request +from flask_restful import Resource, Api +import etcd3 +import json +import logging +from functools import wraps + +def readable_errors(func): + @wraps(func) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except etcd3.exceptions.ConnectionFailedError as e: + raise UncloudException('Cannot connect to etcd: is etcd running and reachable? {}'.format(e)) + except etcd3.exceptions.ConnectionTimeoutError as e: + raise UncloudException('etcd connection timeout. {}'.format(e)) + + return wrapper + + +class DB(object): + def __init__(self, config, prefix="/"): + self.config = config + + # Root for everything + self.base_prefix= '/nicohack' + + # Can be set from outside + self.prefix = prefix + + self.connect() + + @readable_errors + def connect(self): + self._db_clients = [] + for endpoint in self.config.etcd_hosts: + client = etcd3.client(host=endpoint, **self.config.etcd_args) + self._db_clients.append(client) + + def realkey(self, key): + return "{}{}/{}".format(self.base_prefix, + self.prefix, + key) + + @readable_errors + def get(self, key, as_json=False, **kwargs): + value, _ = self._db_clients[0].get(self.realkey(key), **kwargs) + + if as_json: + value = json.loads(value) + + return value + + + @readable_errors + def set(self, key, value, as_json=False, **kwargs): + if as_json: + value = json.dumps(value) + + # FIXME: iterate over clients in case of failure ? + return self._db_clients[0].put(self.realkey(key), value, **kwargs) + + +class Membership(Resource): + def __init__(self, config): + self.config = config + + def get(self): + data = request.get_json(silent=True) or {} + print("{} {}".format(data, config)) + return {'message': 'Order successful' }, 200 + + +class Order(Resource): + def __init__(self, config): + self.config = config + + @staticmethod + def post(): + print("{} {}".format(data, config)) + data = request.get_json(silent=True) or {} + + + + +if __name__ == '__main__': + app = Flask(__name__) + + config = {} + + config['etcd_url']="https://etcd1.ungleich.ch" + config['ldap_url']="ldaps://ldap1.ungleich.ch" + + api = Api(app) + api.add_resource(Order, '/order', resource_class_args=( config, )) + api.add_resource(Membership, '/membership', resource_class_args=( config, )) + + app.run(host='::', port=5000, debug=True) diff --git a/notes.org b/notes.org new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/notes.org @@ -0,0 +1 @@ +* diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..668fb3f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +flask-restful +ldap3 +etcd3 From aa9548e753bddee41a30517114c79938a1e79873 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Sat, 15 Feb 2020 11:15:26 +0100 Subject: [PATCH 2/3] +gitignore Signed-off-by: Nico Schottelius --- .gitignore | 4 +++- README-penguinpay.md | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 77de841..786a584 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ __pycache__/ pay.conf log.txt -test.py \ No newline at end of file +test.py +STRIPE +venv/ diff --git a/README-penguinpay.md b/README-penguinpay.md index 769f183..89f494a 100644 --- a/README-penguinpay.md +++ b/README-penguinpay.md @@ -7,4 +7,3 @@ * httpie installed (provides the http command) ### Get a membership - * From 074efffaa70ca594457e8dd61b041001ad06706d Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Thu, 20 Feb 2020 09:44:30 +0100 Subject: [PATCH 3/3] ++ hack --- README-penguinpay.md | 35 ++++++++++++++++++++++++++++++++++- config.py | 5 ++++- hack.py | 5 +++++ requirements.txt | 1 + stripe_hack.py | 7 +++++++ stripe_utils.py | 9 +++++---- 6 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 stripe_hack.py diff --git a/README-penguinpay.md b/README-penguinpay.md index 89f494a..3229bc5 100644 --- a/README-penguinpay.md +++ b/README-penguinpay.md @@ -6,4 +6,37 @@ https://account.ungleich.ch * httpie installed (provides the http command) -### Get a membership +## Get a membership + + +## Registering a payment method + +To be able to pay for the membership, you will need to register a +credit card or apply for payment on bill (TO BE IMPLEMENTED). + +### Register credit card + +``` +http POST https://api.ungleich.ch/membership \ + username=nico password=yourpassword \ + cc_number=.. \ + cc_ + +``` + + + +### Request payment via bill + + + + +## Create the membership + + +``` +http POST https://api.ungleich.ch/membership username=nico password=yourpassword + +``` + +## List available products diff --git a/config.py b/config.py index b951830..c3bad9d 100644 --- a/config.py +++ b/config.py @@ -5,7 +5,10 @@ from ldap_manager import LdapManager config = configparser.ConfigParser() config.read('pay.conf') +# Note 2020-02-15: this stuff clearly does not belong here, +# if config.py is used everywhere. + etcd_client = EtcdWrapper(host=config['etcd']['host'], port=config['etcd']['port']) ldap_manager = LdapManager(server=config['ldap']['server'], admin_dn=config['ldap']['admin_dn'], - admin_password=config['ldap']['admin_password']) \ No newline at end of file + admin_password=config['ldap']['admin_password']) diff --git a/hack.py b/hack.py index c84f9f6..cbb9a07 100644 --- a/hack.py +++ b/hack.py @@ -70,6 +70,11 @@ class Membership(Resource): print("{} {}".format(data, config)) return {'message': 'Order successful' }, 200 + def post(self): + data = request.get_json(silent=True) or {} + print("{} {}".format(data, config)) + return {'message': 'Order 2x successful' }, 200 + class Order(Resource): def __init__(self, config): diff --git a/requirements.txt b/requirements.txt index 668fb3f..1fc7b83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ flask-restful ldap3 etcd3 +stripe diff --git a/stripe_hack.py b/stripe_hack.py new file mode 100644 index 0000000..f436c62 --- /dev/null +++ b/stripe_hack.py @@ -0,0 +1,7 @@ +import stripe_utils +import os + + +if __name__ == '__main__': + s = stripe_utils.StripeUtils(os.environ['STRIPE_PRIVATE_KEY']) + print(s.get_stripe_customer_from_email('coder.purple+2002@gmail.com')) diff --git a/stripe_utils.py b/stripe_utils.py index 9474f74..3c68698 100644 --- a/stripe_utils.py +++ b/stripe_utils.py @@ -4,9 +4,9 @@ import stripe import stripe.error import logging -from config import etcd_client as client, config as config - -stripe.api_key = config['stripe']['private_key'] +# FIXME: way too many dependencies in this import +# Most of them are not needed for stripe +#from config import etcd_client as client, config as config def handle_stripe_error(f): @@ -73,8 +73,9 @@ class StripeUtils(object): PLAN_EXISTS_ERROR_MSG = 'Plan {} exists already.\nCreating a local StripePlan now.' PLAN_DOES_NOT_EXIST_ERROR_MSG = 'Plan {} does not exist.' - def __init__(self): + def __init__(self, private_key): self.stripe = stripe + stripe.api_key = private_key @handle_stripe_error def card_exists(self, customer, cc_number, exp_month, exp_year, cvc):