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 new file mode 100644 index 0000000..3229bc5 --- /dev/null +++ b/README-penguinpay.md @@ -0,0 +1,42 @@ +## 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 + + +## 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 new file mode 100644 index 0000000..cbb9a07 --- /dev/null +++ b/hack.py @@ -0,0 +1,103 @@ +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 + + 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): + 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..1fc7b83 --- /dev/null +++ b/requirements.txt @@ -0,0 +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):