ucloud-pay/ucloud-pay.py

180 lines
6.5 KiB
Python
Raw Normal View History

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)))
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
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 get_token(card_number, cvc, exp_month, exp_year):
stripe_utils = StripeUtils()
token_response = stripe_utils.get_token_from_card(
card_number, cvc, exp_month, exp_year
)
if token_response["response_object"]:
return token_response["response_object"].id
else:
return None
2019-09-13 18:08:48 +00:00
@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"])
token = UserRegisterPayment.get_token(
2019-09-13 19:13:27 +00:00
data["card_number"], data["cvc"], data["expiry_month"],
data["expiry_year"]
)
if token:
2019-09-13 19:13:27 +00:00
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,
2019-09-13 19:13:27 +00:00
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. "
"Contact support@ungleich.ch"
2019-09-13 19:13:27 +00:00
}, 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)
if token:
2019-09-13 19:13:27 +00:00
user_key = "/v1/users/{}/cards/".format(data["email"])
user_value = token
2019-09-13 19:13:27 +00:00
client.put(user_key, user_value, value_in_json=False)
fresh_token = UserRegisterPayment.get_token(
data["card_number"], data["cvc"], data["expiry_month"],
data["expiry_year"]
2019-09-13 19:13:27 +00:00
)
if fresh_token:
resp = stripe_utils.associate_customer_card(
stripe_customer.id, fresh_token
)
if resp["response_object"]:
return {"message":
"Card ending in {} registered as your payment "
"soruce".format(
data['card_number'].strip()[-4:])
}, 200
else:
logging.error("Error obtaining fresh token")
return {"message": "Error with card. Contact support"}, 400
2019-09-13 18:08:48 +00:00
else:
logging.error(
"Unable to associate card "
"{} with customer {}".format(
token["response_object"].card.id,
2019-09-13 19:13:27 +00:00
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)