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 |
|