Mise en veille PayPal, synchro solde OpenRouter et modale de rejet financier
Build and Push Docker Image / build-and-push (push) Successful in 34s

This commit is contained in:
xavier committed 2026-08-23 11:38:37 +02:00
1 parent 2ea18701b5
commit 3e140d7d6f
8 files changed
+380 -293

No files matched your search

+50 -33
View File
@@ -2,49 +2,66 @@ import os
from fasthtml.common import *
def render_paypal_recharge_widget(montant_usd: float = 10.00):
"""
Génère le bouton de paiement PayPal (Smart Button) pour recharger les crédits.
Utilise le Client ID Sandbox défini dans le fichier .env.
"""
client_id = os.getenv("PAYPAL_CLIENT_ID")
if not client_id:
return Div("Clé PayPal (Client ID) manquante dans .env", style="color: red;")
return Div("Clé PayPal manquante dans .env", style="color: red;")
# Le script officiel de PayPal injecte les boutons de paiement
script_paypal = Script(src=f"https://www.paypal.com/sdk/js?client-id={client_id}&currency=USD")
container_id = f"paypal-button-container-{str(montant_usd).replace('.', '')}"
script_logique = Script(f"""
paypal.Buttons({{
createOrder: function(data, actions) {{
return actions.order.create({{
purchase_units: [{{
amount: {{
value: '{montant_usd}'
}}
}}]
}});
}},
onApprove: function(data, actions) {{
return actions.order.capture().then(function(details) {{
alert('Paiement réussi par ' + details.payer.name.given_name + '! Les crédits seront ajoutés.');
// Ici on fera un fetch vers ton backend python pour créditer l'utilisateur
fetch('/api/paypal/success', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/json' }},
body: JSON.stringify({{ orderID: data.orderID }})
}}).then(res => window.location.reload());
}});
function chargerBoutonPayPal() {{
if (typeof paypal !== 'undefined') {{
paypal.Buttons({{
createOrder: function(data, actions) {{
return actions.order.create({{
purchase_units: [{{ amount: {{ value: '{montant_usd}' }} }}]
}});
}},
onApprove: function(data, actions) {{
return actions.order.capture().then(function(details) {{
alert('Paiement Sandbox validé par ' + details.payer.name.given_name + ' ! Vos crédits vont être ajoutés.');
// L'ajout de credentials: 'same-origin' est VITAL pour envoyer le cookie de session !
fetch('/api/paypal/success', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/json' }},
credentials: 'same-origin',
body: JSON.stringify({{ orderID: data.orderID }})
}}).then(res => {{
if(res.ok) {{
document.getElementById('modal-recharge-paypal').style.display = 'none';
window.location.reload();
}} else {{
alert("Erreur lors de la validation serveur.");
}}
}});
}});
}}
}}).render('#{container_id}');
}} else {{
setTimeout(chargerBoutonPayPal, 100);
}}
}}).render('#{container_id}');
}}
chargerBoutonPayPal();
""")
return Div(
# La boîte centrale de paiement
paypal_box = Div(
H3(f"Recharge de {montant_usd}$", style="color: #fff; margin-top: 0; margin-bottom: 15px; font-size: 1.2em; text-align: center;"),
Div(id=container_id, style="min-height: 150px; width: 100%;"),
Button("Fermer", type="button", onclick="document.getElementById('modal-recharge-paypal').style.display='none'", cls="btn-submit", style="background-color: #555; width: 100%; margin-top: 15px; border-radius: 8px; font-size: 0.9em;"),
style="background: #1a1a1a; padding: 25px; border-radius: 12px; border: 2px solid #00e5ff; width: 400px; max-width: 90vw; box-shadow: 0 10px 30px rgba(0,0,0,0.8);"
)
# L'arrière-plan sombre (overlay)
modal_overlay = Div(
script_paypal,
H3(f"Recharge de {montant_usd}$"),
Div(id=container_id),
paypal_box,
script_logique,
style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 1px solid #333; margin-top: 15px; text-align: center; max-width: 300px;"
)
id="modal-recharge-paypal",
style="display: none; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.8); align-items: center; justify-content: center; z-index: 10000;"
)
return modal_overlay