servii-backend/finances.py
Charles Le Maux 15059a7063 [+] Added payments.
Created a subscription system, and added different permission levels to the users depending on their subscription
2024-09-27 10:23:32 +02:00

138 lines
4.6 KiB
Python

import stripe
from flask import request, jsonify, Blueprint
from stripe import StripeClient
import firebase_manager
from firebase_manager import log_exception_to_firestore
payment_api = Blueprint('payment_api_bp', 'bp_payment_api')
stripe_api_key: str = ("sk_live_51PyIYTP3VLLeb9GlKRfsTMh4olzrJxkT1PwXGlW2G"
"HPUeFZmTFHe5ITI0L2tZPBnJd2lHarQifIV5TMh505KFuL300mkItQuBo")
endpoint_secret: str = "whsec_2a1cadb771f7acfdeaac6720fdd56d3353cca5d38bdc2ed88336932968531457"
stripe.api_key = stripe_api_key
client: StripeClient = StripeClient(api_key=stripe_api_key)
products: [str] = ["",
"price_1Q3Ji5P3VLLeb9GlMOZuafV9", "price_1Q3Ji3P3VLLeb9GlqNStquBo", "price_1Q3Ji1P3VLLeb9Gl5uqH23js"]
@payment_api.route('/get-checkout-session', methods=['GET'])
def create_checkout_session():
try:
permission: int = int(request.headers.get('permission'))
email: str = request.headers.get('email')
except ValueError as err:
print(err)
permission: None = None
email: None = None
if not permission:
return jsonify(message="No product query provided."), 404
if not email:
return jsonify(message="No customer email provided."), 404
try:
session = stripe.checkout.Session.create(
ui_mode = 'embedded',
line_items=[
{
'price': products[permission],
'quantity': 1,
},
],
allow_promotion_codes=True,
mode='subscription',
customer_email= email,
return_url= "https://app.servii.fr" + '/return?session_id={CHECKOUT_SESSION_ID}',
automatic_tax={'enabled': True},
)
except Exception as err:
firebase_manager.log_exception_to_firestore(exception=err, user_id="Stripe")
return jsonify(message="Unable to get associated product."), 500
return jsonify(clientSecret=session.client_secret), 200
@payment_api.route('/get-session-status', methods=['GET'])
def session_status():
try:
session = stripe.checkout.Session.retrieve(request.args.get('session_id'))
return jsonify(status=session.status, customer_email=session.customer_details.email), 200
except Exception as err:
firebase_manager.log_exception_to_firestore(exception=err, user_id="Stripe")
return jsonify(message="Unable to retrieve payment session status."), 500
@payment_api.route('/finances', methods=['POST'])
def webhook():
payload = request.get_data(as_text=True)
sig_header = request.headers.get('Stripe-Signature')
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as err:
print(f"Invalid payload: {err}")
return jsonify({'message': 'Invalid payload'}), 400
except stripe.error.SignatureVerificationError as err:
print(f"Invalid signature: {err}")
return jsonify({'message': 'Invalid signature'}), 400
try:
match event['type']:
case 'customer.subscription.created' | 'customer.subscription.updated':
firestore_metadata: int = extract_firestore_data(event)
user_id: str = extract_user_id(event)
firebase_manager.update_firestore(user_id=user_id, data={"subscription": firestore_metadata})
case 'customer.subscription.deleted':
user_id: str = extract_user_id(event)
firebase_manager.update_firestore(user_id=user_id, data={"subscription": 0})
return jsonify({'status': 'success'}), 200
except Exception as err:
log_exception_to_firestore(exception=err, user_id="Stripe")
return jsonify({'status': 'error'}), 500
def extract_firestore_data(event):
try:
firestore_metadata = (
event.get('data', {})
.get('object', {})
.get('items', {})
.get('data', [{}])[0]
.get('price', {})
.get('metadata', {})
.get('firestore', 0)
)
return int(firestore_metadata)
except (IndexError, KeyError, ValueError) as e:
return None
def extract_user_id(event):
try:
customer_id = event.get('data', {}).get('object', {}).get('customer', None)
customer = client.customers.retrieve(customer_id)
mail: str = customer.get("email", None)
user_id: str = firebase_manager.get_user_from_mail(mail)
return user_id
except (IndexError, KeyError) as e:
return None
except Exception as err:
log_exception_to_firestore(exception=err, user_id="Stripe")
return None
if __name__ == "__main__":
pass