Update routes/subscription.py
Browse files- routes/subscription.py +32 -33
routes/subscription.py
CHANGED
|
@@ -796,15 +796,12 @@ async def stripe_webhook(request: Request):
|
|
| 796 |
return {"status": "error", "message": str(e)}
|
| 797 |
|
| 798 |
@router.post("/create_price")
|
| 799 |
-
async def create_price(
|
| 800 |
-
data: CreatePriceRequest,
|
| 801 |
-
user_token: str = Header(None, alias="User-key")
|
| 802 |
-
):
|
| 803 |
try:
|
| 804 |
if not user_token:
|
| 805 |
raise HTTPException(status_code=401, detail="Missing User-key header")
|
| 806 |
|
| 807 |
-
#
|
| 808 |
user_id = verify_token(user_token)
|
| 809 |
logger.info(f"🔹 User verified. user_id: {user_id}")
|
| 810 |
|
|
@@ -812,13 +809,13 @@ async def create_price(
|
|
| 812 |
emergency_price = data.emergency_price
|
| 813 |
consultations = data.consultations
|
| 814 |
|
| 815 |
-
#
|
| 816 |
if not (500 <= amount <= 99900):
|
| 817 |
raise HTTPException(status_code=400, detail="Amount must be between $5 and $999")
|
| 818 |
if not (500 <= emergency_price <= 99900):
|
| 819 |
raise HTTPException(status_code=400, detail="Emergency price must be between $5 and $999")
|
| 820 |
|
| 821 |
-
#
|
| 822 |
if consultations is None:
|
| 823 |
consultations = 0
|
| 824 |
elif consultations < 0:
|
|
@@ -826,10 +823,10 @@ async def create_price(
|
|
| 826 |
|
| 827 |
logger.info(f"🔹 Validated amounts: amount = {amount}, emergency_price = {emergency_price}, consultations = {consultations}")
|
| 828 |
|
| 829 |
-
#
|
| 830 |
supabase_url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}"
|
| 831 |
headers = {
|
| 832 |
-
"Authorization": f"Bearer {user_token}",
|
| 833 |
**SUPABASE_HEADERS
|
| 834 |
}
|
| 835 |
response = requests.get(supabase_url, headers=headers)
|
|
@@ -844,10 +841,10 @@ async def create_price(
|
|
| 844 |
|
| 845 |
user = user_data[0]
|
| 846 |
existing_price_id = user.get("price_id")
|
| 847 |
-
user_full_name = user.get("name", "Unknown User")
|
| 848 |
-
user_avatar = user.get("avatar", None)
|
| 849 |
|
| 850 |
-
#
|
| 851 |
name_parts = user_full_name.split()
|
| 852 |
if len(name_parts) > 1:
|
| 853 |
abbreviated_name = f"{name_parts[0]} {name_parts[1][0]}."
|
|
@@ -858,60 +855,62 @@ async def create_price(
|
|
| 858 |
|
| 859 |
logger.info(f"🔹 Existing price_id: {existing_price_id}, user_name: {abbreviated_name}")
|
| 860 |
|
| 861 |
-
#
|
| 862 |
product_data = {
|
| 863 |
-
"name": product_name,
|
| 864 |
}
|
| 865 |
|
| 866 |
-
if user_avatar:
|
| 867 |
product_data["images"] = [user_avatar]
|
| 868 |
|
| 869 |
product = stripe.Product.create(**product_data)
|
| 870 |
product_id = product.id
|
| 871 |
logger.info(f"✅ New product created: {product_id}")
|
| 872 |
|
| 873 |
-
#
|
| 874 |
price = stripe.Price.create(
|
| 875 |
unit_amount=amount,
|
| 876 |
currency="brl",
|
| 877 |
recurring={"interval": "month"},
|
| 878 |
-
product=product_id
|
| 879 |
)
|
| 880 |
new_price_id = price.id
|
| 881 |
logger.info(f"✅ New price created: {new_price_id}")
|
| 882 |
|
| 883 |
-
#
|
| 884 |
if existing_price_id:
|
| 885 |
subscriptions = stripe.Subscription.list(status="active")
|
| 886 |
for sub in subscriptions.auto_paging_iter():
|
| 887 |
if sub["items"]["data"][0]["price"]["id"] == existing_price_id:
|
| 888 |
-
#
|
| 889 |
-
stripe.Subscription.modify(sub.id,
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 893 |
logger.info(f"🔹 Subscription {sub.id} set to cancel at period end and updated with new price {new_price_id}.")
|
| 894 |
|
| 895 |
-
#
|
| 896 |
update_data = {
|
| 897 |
-
"price_id": new_price_id,
|
| 898 |
-
"price": amount,
|
| 899 |
-
"emergency_price": emergency_price,
|
| 900 |
-
"consultations": consultations
|
| 901 |
}
|
| 902 |
|
| 903 |
-
# Aqui estamos incluindo o cabeçalho de autenticação com o token JWT correto
|
| 904 |
update_headers = {
|
| 905 |
-
"Authorization": f"Bearer {user_token}",
|
| 906 |
"apikey": SUPABASE_KEY,
|
| 907 |
"Content-Type": "application/json"
|
| 908 |
}
|
| 909 |
|
| 910 |
update_response = requests.patch(supabase_url, headers=update_headers, json=update_data)
|
| 911 |
|
| 912 |
-
# Log detalhado para verificar a resposta
|
| 913 |
-
logger.info(f"🔹 Supabase PATCH response: {update_response.status_code} - {update_response.text}")
|
| 914 |
-
|
| 915 |
if update_response.status_code not in [200, 204]:
|
| 916 |
raise HTTPException(status_code=500, detail=f"Failed to update Supabase: {update_response.text}")
|
| 917 |
|
|
|
|
| 796 |
return {"status": "error", "message": str(e)}
|
| 797 |
|
| 798 |
@router.post("/create_price")
|
| 799 |
+
async def create_price(data: CreatePriceRequest, user_token: str = Header(None, alias="User-key")):
|
|
|
|
|
|
|
|
|
|
| 800 |
try:
|
| 801 |
if not user_token:
|
| 802 |
raise HTTPException(status_code=401, detail="Missing User-key header")
|
| 803 |
|
| 804 |
+
# 1. Validar o token e obter user_id
|
| 805 |
user_id = verify_token(user_token)
|
| 806 |
logger.info(f"🔹 User verified. user_id: {user_id}")
|
| 807 |
|
|
|
|
| 809 |
emergency_price = data.emergency_price
|
| 810 |
consultations = data.consultations
|
| 811 |
|
| 812 |
+
# 2. Verificar se os valores estão dentro dos limites permitidos
|
| 813 |
if not (500 <= amount <= 99900):
|
| 814 |
raise HTTPException(status_code=400, detail="Amount must be between $5 and $999")
|
| 815 |
if not (500 <= emergency_price <= 99900):
|
| 816 |
raise HTTPException(status_code=400, detail="Emergency price must be between $5 and $999")
|
| 817 |
|
| 818 |
+
# 3. Consultations precisa ser 0 obrigatoriamente se não for definido
|
| 819 |
if consultations is None:
|
| 820 |
consultations = 0
|
| 821 |
elif consultations < 0:
|
|
|
|
| 823 |
|
| 824 |
logger.info(f"🔹 Validated amounts: amount = {amount}, emergency_price = {emergency_price}, consultations = {consultations}")
|
| 825 |
|
| 826 |
+
# 4. Buscar price_id, name, avatar e bio do usuário no Supabase
|
| 827 |
supabase_url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}"
|
| 828 |
headers = {
|
| 829 |
+
"Authorization": f"Bearer {user_token}",
|
| 830 |
**SUPABASE_HEADERS
|
| 831 |
}
|
| 832 |
response = requests.get(supabase_url, headers=headers)
|
|
|
|
| 841 |
|
| 842 |
user = user_data[0]
|
| 843 |
existing_price_id = user.get("price_id")
|
| 844 |
+
user_full_name = user.get("name", "Unknown User")
|
| 845 |
+
user_avatar = user.get("avatar", None)
|
| 846 |
|
| 847 |
+
# Criar nome abreviado do usuário
|
| 848 |
name_parts = user_full_name.split()
|
| 849 |
if len(name_parts) > 1:
|
| 850 |
abbreviated_name = f"{name_parts[0]} {name_parts[1][0]}."
|
|
|
|
| 855 |
|
| 856 |
logger.info(f"🔹 Existing price_id: {existing_price_id}, user_name: {abbreviated_name}")
|
| 857 |
|
| 858 |
+
# 5. Criar produto no Stripe
|
| 859 |
product_data = {
|
| 860 |
+
"name": product_name,
|
| 861 |
}
|
| 862 |
|
| 863 |
+
if user_avatar:
|
| 864 |
product_data["images"] = [user_avatar]
|
| 865 |
|
| 866 |
product = stripe.Product.create(**product_data)
|
| 867 |
product_id = product.id
|
| 868 |
logger.info(f"✅ New product created: {product_id}")
|
| 869 |
|
| 870 |
+
# 6. Criar novo preço no Stripe
|
| 871 |
price = stripe.Price.create(
|
| 872 |
unit_amount=amount,
|
| 873 |
currency="brl",
|
| 874 |
recurring={"interval": "month"},
|
| 875 |
+
product=product_id
|
| 876 |
)
|
| 877 |
new_price_id = price.id
|
| 878 |
logger.info(f"✅ New price created: {new_price_id}")
|
| 879 |
|
| 880 |
+
# 7. Cancelar as assinaturas existentes e aplicar o novo price_id sem descontos
|
| 881 |
if existing_price_id:
|
| 882 |
subscriptions = stripe.Subscription.list(status="active")
|
| 883 |
for sub in subscriptions.auto_paging_iter():
|
| 884 |
if sub["items"]["data"][0]["price"]["id"] == existing_price_id:
|
| 885 |
+
# Cancelar assinatura no final do período
|
| 886 |
+
stripe.Subscription.modify(sub.id, cancel_at_period_end=True)
|
| 887 |
+
# Aplicar o novo preço na próxima fatura
|
| 888 |
+
stripe.Subscription.modify(
|
| 889 |
+
sub.id,
|
| 890 |
+
items=[{
|
| 891 |
+
"id": sub["items"]["data"][0]["id"],
|
| 892 |
+
"price": new_price_id
|
| 893 |
+
}],
|
| 894 |
+
proration_behavior="none" # Garantir que não haja prorrogação ou descontos
|
| 895 |
+
)
|
| 896 |
logger.info(f"🔹 Subscription {sub.id} set to cancel at period end and updated with new price {new_price_id}.")
|
| 897 |
|
| 898 |
+
# 8. Atualizar Supabase com o novo price_id
|
| 899 |
update_data = {
|
| 900 |
+
"price_id": new_price_id,
|
| 901 |
+
"price": amount,
|
| 902 |
+
"emergency_price": emergency_price,
|
| 903 |
+
"consultations": consultations
|
| 904 |
}
|
| 905 |
|
|
|
|
| 906 |
update_headers = {
|
| 907 |
+
"Authorization": f"Bearer {user_token}",
|
| 908 |
"apikey": SUPABASE_KEY,
|
| 909 |
"Content-Type": "application/json"
|
| 910 |
}
|
| 911 |
|
| 912 |
update_response = requests.patch(supabase_url, headers=update_headers, json=update_data)
|
| 913 |
|
|
|
|
|
|
|
|
|
|
| 914 |
if update_response.status_code not in [200, 204]:
|
| 915 |
raise HTTPException(status_code=500, detail=f"Failed to update Supabase: {update_response.text}")
|
| 916 |
|