230 lines
7.9 KiB
Python
230 lines
7.9 KiB
Python
import json
|
|
import os
|
|
import dotenv
|
|
|
|
dotenv.load_dotenv()
|
|
|
|
from models import Clinics
|
|
import uuid
|
|
from fastapi import Request
|
|
from datetime import datetime
|
|
from models import PaymentLogs
|
|
from enums.enums import ClinicStatus
|
|
|
|
from database import get_db
|
|
from sqlalchemy.orm import Session
|
|
import stripe
|
|
from loguru import logger
|
|
|
|
|
|
class StripeServices:
|
|
def __init__(self):
|
|
self.db: Session = next(get_db())
|
|
self.logger = logger
|
|
self.webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET")
|
|
|
|
async def create_customer(self, user_id: int, email: str, name: str):
|
|
try:
|
|
customer = stripe.Customer.create(
|
|
email=email, name=name, metadata={"user_id": user_id}
|
|
)
|
|
return customer
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error creating customer: {e}")
|
|
raise
|
|
|
|
async def delete_customer(self, customer_id: str):
|
|
try:
|
|
stripe.Customer.delete(customer_id)
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error deleting customer: {e}")
|
|
raise
|
|
|
|
async def create_account(self, user_id: int, email: str, name: str, phone: str):
|
|
try:
|
|
account = stripe.Account.create(
|
|
type="express",
|
|
country="AU",
|
|
capabilities={
|
|
"card_payments": {"requested": True},
|
|
"transfers": {"requested": True},
|
|
},
|
|
business_type="individual",
|
|
individual={"first_name": name, "email": email},
|
|
metadata={"user_id": user_id},
|
|
)
|
|
return account
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error creating account: {e}")
|
|
raise
|
|
|
|
async def delete_account(self, account_id: str):
|
|
try:
|
|
stripe.Account.delete(account_id)
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error deleting account: {e}")
|
|
raise
|
|
|
|
async def create_checkout_session(self, user_id: int):
|
|
try:
|
|
checkout_session = stripe.checkout.Session.create(
|
|
payment_method_types=["card"],
|
|
line_items=[
|
|
{
|
|
"price_data": {
|
|
"currency": "aud",
|
|
"product_data": {
|
|
"name": "Willio Voice Subscription",
|
|
},
|
|
"unit_amount": 5000,
|
|
},
|
|
"quantity": 1,
|
|
}
|
|
],
|
|
expand=["payment_intent"],
|
|
mode="payment",
|
|
payment_intent_data={"metadata": {"order_id": "1"}},
|
|
success_url="http://54.79.156.66/",
|
|
cancel_url="http://54.79.156.66/",
|
|
metadata={"user_id": user_id},
|
|
)
|
|
return checkout_session
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error creating checkout session: {e}")
|
|
raise
|
|
|
|
async def create_setup_fees(self, customer_id: str, amount: int):
|
|
try:
|
|
setup_intent = stripe.InvoiceItem.create(
|
|
customer=customer_id,
|
|
amount=amount,
|
|
currency="aud",
|
|
description="Setup Fees",
|
|
)
|
|
return setup_intent
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error creating setup intent: {e}")
|
|
raise
|
|
|
|
async def create_subscription_checkout(self, fees_to_be: dict, clinic_id: int, account_id: str, customer_id: str):
|
|
try:
|
|
|
|
unique_id = str(uuid.uuid4())
|
|
unique_clinic_id = f"clinic_{clinic_id}_{unique_id}"
|
|
|
|
line_items = [{
|
|
'price_data': {
|
|
'currency': 'aud',
|
|
'product_data': {
|
|
'name': 'Monthly Subscription',
|
|
},
|
|
'unit_amount': fees_to_be["subscription_fees"],
|
|
'recurring': {
|
|
'interval': 'year',
|
|
},
|
|
},
|
|
'quantity': 1,
|
|
}]
|
|
|
|
line_items.append({
|
|
'price_data': {
|
|
'currency': 'aud',
|
|
'product_data': {
|
|
'name': 'Per Call',
|
|
},
|
|
'unit_amount': fees_to_be["per_call_charges"],
|
|
},
|
|
'quantity': 1,
|
|
})
|
|
|
|
line_items.append({
|
|
'price_data': {
|
|
'currency': 'aud',
|
|
'product_data': {
|
|
'name': 'Setup Fee',
|
|
},
|
|
'unit_amount': fees_to_be["setup_fees"],
|
|
},
|
|
'quantity': 1,
|
|
})
|
|
|
|
metadata = {
|
|
"clinic_id": clinic_id,
|
|
"unique_clinic_id": unique_clinic_id,
|
|
"account_id": account_id,
|
|
"customer_id": customer_id
|
|
}
|
|
|
|
session_data = {
|
|
'customer': customer_id,
|
|
'payment_method_types': ['card'],
|
|
'mode': 'subscription',
|
|
'line_items': line_items,
|
|
'success_url': 'http://54.79.156.66/',
|
|
'cancel_url': 'http://54.79.156.66/',
|
|
'metadata': metadata,
|
|
'subscription_data': {
|
|
'metadata': metadata
|
|
}
|
|
}
|
|
|
|
session = stripe.checkout.Session.create(**session_data)
|
|
|
|
payment_log = PaymentLogs(
|
|
customer_id=customer_id,
|
|
account_id=account_id,
|
|
amount=fees_to_be["total"],
|
|
clinic_id=clinic_id,
|
|
unique_clinic_id=unique_clinic_id,
|
|
payment_status="pending",
|
|
metadata_logs=json.dumps(metadata)
|
|
)
|
|
self.db.add(payment_log)
|
|
self.db.commit()
|
|
|
|
return session
|
|
except stripe.error.StripeError as e:
|
|
self.logger.error(f"Error creating checkout session: {e}")
|
|
raise
|
|
|
|
|
|
async def handle_webhook(self, request: Request):
|
|
try:
|
|
payload = await request.body()
|
|
event = stripe.Webhook.construct_event(
|
|
payload, request.headers.get("Stripe-Signature"), self.webhook_secret
|
|
)
|
|
self.logger.info(f"Stripe webhook event type: {event['type']}")
|
|
|
|
if event["type"] == "invoice.payment_succeeded":
|
|
pass
|
|
|
|
# if event["type"] == "payment_intent.succeeded":
|
|
# await self.update_payment_log(event["data"]["object"]["metadata"]["unique_clinic_id"])
|
|
|
|
elif event["type"] == "checkout.session.completed":
|
|
await self.update_payment_log(event["data"]["object"]["metadata"]["unique_clinic_id"], event["data"]["object"]["metadata"]["clinic_id"])
|
|
|
|
return event
|
|
except ValueError as e:
|
|
self.logger.error(f"Invalid payload: {e}")
|
|
raise
|
|
except stripe.error.SignatureVerificationError as e:
|
|
self.logger.error(f"Invalid signature: {e}")
|
|
raise
|
|
|
|
async def update_payment_log(self, unique_clinic_id:str, clinic_id:int):
|
|
try:
|
|
payment_log = self.db.query(PaymentLogs).filter(PaymentLogs.unique_clinic_id == unique_clinic_id).first()
|
|
if payment_log:
|
|
payment_log.payment_status = "success"
|
|
self.db.commit()
|
|
|
|
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
|
if clinic:
|
|
clinic.status = ClinicStatus.UNDER_REVIEW
|
|
self.db.commit()
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error updating payment log: {e}")
|
|
raise |