2019-09-13 18:08:48 +00:00
|
|
|
import binascii
|
2019-09-13 05:02:23 +00:00
|
|
|
import json
|
2019-09-13 18:08:48 +00:00
|
|
|
|
|
|
|
import requests
|
|
|
|
from decouple import config
|
2019-09-13 05:02:23 +00:00
|
|
|
from flask import Flask, request
|
|
|
|
from flask_restful import Resource, Api
|
2019-09-13 18:08:48 +00:00
|
|
|
from pyotp import TOTP
|
|
|
|
|
2019-09-13 06:37:53 +00:00
|
|
|
from config import etcd_client as client, logging, APP_PORT
|
2019-09-13 18:08:48 +00:00
|
|
|
from stripe_utils import StripeUtils
|
2019-09-13 05:02:23 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
api = Api(app)
|
|
|
|
|
|
|
|
|
2019-09-13 18:08:48 +00:00
|
|
|
def check_otp(name, realm, token):
|
|
|
|
try:
|
|
|
|
data = {
|
|
|
|
"auth_name": config("AUTH_NAME", ""),
|
|
|
|
"auth_token": TOTP(config("AUTH_SEED", "")).now(),
|
|
|
|
"auth_realm": config("AUTH_REALM", ""),
|
|
|
|
"name": name,
|
|
|
|
"realm": realm,
|
|
|
|
"token": token,
|
|
|
|
}
|
|
|
|
except binascii.Error:
|
|
|
|
return 400
|
|
|
|
|
|
|
|
response = requests.post(
|
|
|
|
"{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format(
|
|
|
|
OTP_SERVER=config("OTP_SERVER", ""),
|
|
|
|
OTP_VERIFY_ENDPOINT=config("OTP_VERIFY_ENDPOINT", "verify/"),
|
|
|
|
),
|
|
|
|
data=data,
|
|
|
|
)
|
|
|
|
return response.status_code
|
|
|
|
|
|
|
|
|
2019-09-13 05:02:23 +00:00
|
|
|
class ListProducts(Resource):
|
|
|
|
@staticmethod
|
|
|
|
def get():
|
|
|
|
products = client.get_prefix("/v1/products/", value_in_json=False)
|
|
|
|
prod_dict = {}
|
|
|
|
for p in products:
|
|
|
|
prod_dict[p.key] = json.loads(p.value)
|
2019-09-13 18:08:48 +00:00
|
|
|
logging.debug("Products = {}".format(prod_dict))
|
2019-09-13 05:02:23 +00:00
|
|
|
return prod_dict, 200
|
|
|
|
|
2019-09-13 18:08:48 +00:00
|
|
|
|
2019-09-13 05:02:23 +00:00
|
|
|
class AddProduct(Resource):
|
|
|
|
@staticmethod
|
|
|
|
def post():
|
|
|
|
data = request.json
|
2019-09-13 18:08:48 +00:00
|
|
|
logging.debug("Got data: {}".format(str(data)))
|
2019-09-13 19:18:30 +00:00
|
|
|
otp_response = check_otp(data["name"], data["realm"],
|
|
|
|
data["token"])
|
|
|
|
if otp_response != 200:
|
|
|
|
return {"message": "Wrong Credentials"}, 403
|
2019-09-13 05:02:23 +00:00
|
|
|
|
2019-09-13 19:18:30 +00:00
|
|
|
try:
|
|
|
|
product_key = "/v1/products/"
|
|
|
|
product_value = {
|
|
|
|
"name": data["product_name"],
|
|
|
|
"description": data["product_description"],
|
|
|
|
"type": data["product_type"],
|
|
|
|
"price": data["product_price"],
|
|
|
|
"recurring_duration": data["product_recurring_duration"],
|
|
|
|
"recurring_duration_units":
|
|
|
|
data["product_recurring_duration_units"]
|
|
|
|
}
|
|
|
|
logging.debug("Adding product data: {}".format(str(product_value)))
|
|
|
|
client.put(product_key, product_value, value_in_json=True)
|
|
|
|
return {"message":
|
|
|
|
"Product {} created".format(data['product_name'])}, 200
|
|
|
|
except KeyError as ke:
|
|
|
|
logging.error("KeyError occurred. details = {}".format(str(ke)))
|
|
|
|
return {"message":
|
|
|
|
"Missing or wrong parameters"}, 400
|
2019-09-13 18:08:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
class UserRegisterPayment(Resource):
|
|
|
|
@staticmethod
|
|
|
|
def post():
|
|
|
|
try:
|
|
|
|
data = request.json
|
|
|
|
logging.debug("Got data: {}".format(str(data)))
|
|
|
|
otp_response = check_otp(data["name"], data["realm"],
|
|
|
|
data["token"])
|
|
|
|
if otp_response != 200:
|
|
|
|
return {"message": "Wrong Credentials"}, 403
|
|
|
|
|
|
|
|
stripe_utils = StripeUtils()
|
|
|
|
stripe_customer = stripe_utils.get_stripe_customer_from_email(
|
|
|
|
data["email"])
|
2019-09-13 19:13:27 +00:00
|
|
|
token_response = stripe_utils.get_token_from_card(
|
|
|
|
data["card_number"], data["cvc"], data["expiry_month"],
|
|
|
|
data["expiry_year"]
|
|
|
|
)
|
|
|
|
logging.debug("token type = {} {} ".format(type(token_response),
|
|
|
|
token_response))
|
|
|
|
if token_response["response_object"]:
|
|
|
|
if stripe_customer is None:
|
2019-09-13 18:08:48 +00:00
|
|
|
stripe_customer_resp = stripe_utils.create_customer(
|
2019-09-13 19:13:27 +00:00
|
|
|
name=data["card_holder_name"],
|
|
|
|
token=token_response["response_object"].id,
|
|
|
|
email=data["email"]
|
2019-09-13 18:08:48 +00:00
|
|
|
)
|
|
|
|
if stripe_customer_resp:
|
2019-09-13 19:13:27 +00:00
|
|
|
stripe_customer = stripe_customer_resp[
|
|
|
|
"response_object"]
|
2019-09-13 18:08:48 +00:00
|
|
|
else:
|
|
|
|
logging.error("Could not get/create stripe_customer "
|
|
|
|
"for {}".format(data["email"]))
|
|
|
|
return {"message":
|
|
|
|
"Error with card. Contact support"}, 400
|
2019-09-13 19:13:27 +00:00
|
|
|
else:
|
|
|
|
logging.error("Could not get token for the card")
|
|
|
|
return {"message": "Error with card. Details: {}. "
|
|
|
|
"Contact support@ungleich.ch".format(
|
|
|
|
token_response["error"])
|
|
|
|
}, 400
|
2019-09-13 18:08:48 +00:00
|
|
|
|
|
|
|
user_key = "/v1/users/{}/stripe_customer/".format(data["email"])
|
|
|
|
user_value = stripe_customer.id
|
|
|
|
client.put(user_key, user_value, value_in_json=False)
|
|
|
|
|
2019-09-13 19:13:27 +00:00
|
|
|
if token_response:
|
|
|
|
user_key = "/v1/users/{}/cards/".format(data["email"])
|
|
|
|
user_value = token_response["response_object"].card.id
|
|
|
|
client.put(user_key, user_value, value_in_json=False)
|
|
|
|
resp = stripe_utils.associate_customer_card(
|
|
|
|
stripe_customer.id, token_response["response_object"].id
|
|
|
|
)
|
|
|
|
if resp["response_object"]:
|
|
|
|
return {"message":
|
|
|
|
"Card ending in {} registered as your payment "
|
|
|
|
"soruce".format(
|
|
|
|
data['card_number'].strip()[-4:])
|
|
|
|
}, 200
|
2019-09-13 18:08:48 +00:00
|
|
|
else:
|
|
|
|
logging.error(
|
|
|
|
"Unable to associate card "
|
|
|
|
"{} with customer {}".format(
|
2019-09-13 19:13:27 +00:00
|
|
|
token_response["response_object"].card.id,
|
|
|
|
data["email"]
|
2019-09-13 18:08:48 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
return {"message": "Error with card. Contact support"}, 400
|
|
|
|
|
|
|
|
except KeyError as key_error:
|
2019-09-13 19:13:27 +00:00
|
|
|
logging.error("Key error occurred")
|
2019-09-13 18:08:48 +00:00
|
|
|
logging.error(str(key_error))
|
2019-09-13 19:13:27 +00:00
|
|
|
return {"message": "Missing or wrong parameters"}, 400
|
2019-09-13 18:08:48 +00:00
|
|
|
|
2019-09-13 05:02:23 +00:00
|
|
|
|
|
|
|
api.add_resource(ListProducts, "/product/list")
|
|
|
|
api.add_resource(AddProduct, "/product/add")
|
2019-09-13 19:13:27 +00:00
|
|
|
api.add_resource(UserRegisterPayment, "/user/register_payment")
|
2019-09-13 05:02:23 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2019-09-13 06:37:53 +00:00
|
|
|
app.run(host="::", port=APP_PORT, debug=True)
|