Did some things...
This commit is contained in:
@@ -14,11 +14,12 @@ from database import (
|
||||
get_user_by_invoice_id, confirm_reserved_numbers,
|
||||
get_raffle_name, get_raffle,
|
||||
get_remaining_numbers_amount,
|
||||
store_main_message_id, get_main_message_id,
|
||||
get_main_message_id,
|
||||
store_update_message_id, get_update_message_id,
|
||||
get_last_n_other_participants, get_remaining_numbers
|
||||
)
|
||||
from config import BOT_TOKEN, BOT_NAME, WEBHOOK_ID, TYC_DOCUMENT_URL, REVERSE_CHANNELS
|
||||
from config import BOT_TOKEN, BOT_NAME, WEBHOOK_ID, TYC_DOCUMENT_URL, REVERSE_CHANNELS, NEWRELIC_API_KEY, PAYPAL_URL
|
||||
from newrelic_telemetry_sdk import Log, LogClient
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -26,6 +27,33 @@ app = Flask(__name__)
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
|
||||
)
|
||||
|
||||
client = LogClient(license_key=NEWRELIC_API_KEY, host="log-api.eu.newrelic.com")
|
||||
|
||||
# Define a handler that sends records to New Relic
|
||||
class NewRelicHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
try:
|
||||
log = Log(
|
||||
message=self.format(record),
|
||||
level=record.levelname,
|
||||
timestamp_ms=int(record.created * 1000),
|
||||
attributes={
|
||||
"logger": record.name,
|
||||
"app_name": BOT_NAME,
|
||||
"docker_container": "paypal_processor"
|
||||
}
|
||||
)
|
||||
client.send(log)
|
||||
except Exception:
|
||||
self.handleError(record)
|
||||
|
||||
nr_handler = NewRelicHandler()
|
||||
nr_handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.addHandler(nr_handler)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define the Telegram API URL base
|
||||
@@ -135,7 +163,7 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
# send_telegram_message(
|
||||
# user_id,
|
||||
# f"El estado de tu pago para la factura {invoice_id} es '{payment_status}'. "
|
||||
# f"La rifa solo se confirma con pagos 'Completed'. Contacta con un administrador si crees que es un error."
|
||||
# f"El sorteo solo se confirma con pagos 'Completed'. Contacta con un administrador si crees que es un error."
|
||||
# )
|
||||
# return
|
||||
|
||||
@@ -157,7 +185,7 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
logger.error(f"Payment amount mismatch for Invoice ID {invoice_id}. Expected: {expected_amount:.2f}, Received: {payment_amount:.2f}")
|
||||
send_telegram_message(
|
||||
user_id,
|
||||
f"⚠️ La cantidad pagada ({payment_amount:.2f}€) para la factura {invoice_id} no coincide con el total esperado ({expected_amount:.2f}€) para los números {', '.join(numbers)}. "
|
||||
f"⚠️ La cantidad donada ({payment_amount:.2f}€) para la factura {invoice_id} no coincide con el total esperado ({expected_amount:.2f}€) para los números {', '.join(numbers)}. "
|
||||
f"Por favor, contacta con un administrador."
|
||||
)
|
||||
# Do NOT confirm the numbers if amount is wrong
|
||||
@@ -172,8 +200,8 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
# Send confirmation to user
|
||||
send_telegram_message(
|
||||
user_id,
|
||||
f"✅ ¡Pago confirmado para la factura {invoice_id}!\n\n"
|
||||
f"Te has apuntado con éxito a la rifa '{raffle_name}' con las papeletas: {', '.join(numbers)}."
|
||||
f"✅ ¡Donación confirmada para la factura {invoice_id}!\n\n"
|
||||
f"Te has apuntado con éxito al sorteo '{raffle_name}' con las participaciones: {', '.join(numbers)}."
|
||||
# Raffle name can be added here if desired, requires one more DB call or adding it to get_user_by_invoice_id
|
||||
)
|
||||
|
||||
@@ -193,9 +221,10 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
# If it's the last number, update the main message and delete the participate button
|
||||
if remaining_numbers_amount == 0:
|
||||
keyboard = None
|
||||
main_announcement = f"🎯🏆🎯 **Rifa '{raffle_name}' Terminada** 🎯🏆🎯\n\n"
|
||||
main_announcement = f"🎯🏆🎯 **Sorteo '{raffle_name}' terminado** 🎯🏆🎯\n\n"
|
||||
main_announcement += f"{raffle_details['description']}\n\n"
|
||||
main_announcement += f"💵 **Precio por papeleta:** {raffle_details['price']}€\n"
|
||||
main_announcement += f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
main_announcement += f"💵 **Donación mínima:** {raffle_details['price']}€\n"
|
||||
main_announcement += f"📜 Normas y condiciones: {TYC_DOCUMENT_URL}"
|
||||
main_message_id = get_main_message_id(raffle_id)
|
||||
requests.post(f"{TELEGRAM_API_URL}/editMessageCaption", json={
|
||||
@@ -214,10 +243,11 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
]
|
||||
]
|
||||
}
|
||||
main_announcement = f"🏆 Rifa '{raffle_name}' en progreso 🏆\n\n"
|
||||
main_announcement = f"🏆 Sorteo '{raffle_name}' en progreso 🏆\n\n"
|
||||
main_announcement += f"{raffle_details['description']}\n\n"
|
||||
main_announcement += f"💵 **Precio por papeleta:** {raffle_details['price']}€\n"
|
||||
main_announcement += f"🗒️ Quedan {remaining_numbers_amount} papeletas disponibles. ¡Date prisa! 🗒️\n\n"
|
||||
main_announcement += f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
main_announcement += f"💵 **Donación mínima:** {raffle_details['price']}€\n"
|
||||
main_announcement += f"🗒️ Quedan {remaining_numbers_amount} participaciones disponibles. ¡Date prisa! 🗒️\n\n"
|
||||
main_announcement += f"📜 Normas y condiciones: {TYC_DOCUMENT_URL}"
|
||||
main_message_id = get_main_message_id(raffle_id)
|
||||
requests.post(f"{TELEGRAM_API_URL}/editMessageCaption", json={
|
||||
@@ -235,26 +265,26 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
|
||||
numbers_text = ""
|
||||
if len(numbers) > 1:
|
||||
numbers_text = f"con las papeletas: {', '.join(numbers)}"
|
||||
numbers_text = f"con las participaciones: {', '.join(numbers)}"
|
||||
else:
|
||||
numbers_text = f"con la papeleta: {', '.join(numbers)}"
|
||||
numbers_text = f"con la participación: {', '.join(numbers)}"
|
||||
|
||||
new_participant_line = f"🗳️ @{escaped_current_user_name} se ha unido a la rifa {numbers_text}. ¡Mucha suerte! 🗳️"
|
||||
new_participant_line = f"🗳️ @{escaped_current_user_name} se ha unido al sorteo {numbers_text}. ¡Mucha suerte! 🗳️"
|
||||
|
||||
remaining_numbers_text = ""
|
||||
if remaining_numbers_amount > 10:
|
||||
remaining_numbers_text = f"🗒️ Todavía hay {remaining_numbers_amount} papeletas. 🗒️"
|
||||
remaining_numbers_text = f"🗒️ Todavía hay {remaining_numbers_amount} participaciones disponibles. 🗒️"
|
||||
elif remaining_numbers_amount == 1:
|
||||
remaining_numbers = get_remaining_numbers(raffle_id)
|
||||
remaining_numbers_text = f"⏰⏰⏰ ¡Última papeleta! ⏰⏰⏰\n\n"
|
||||
remaining_numbers_text += f"Queda la papeleta: {remaining_numbers[0]}"
|
||||
remaining_numbers_text = f"⏰⏰⏰ ¡Última participación! ⏰⏰⏰\n\n"
|
||||
remaining_numbers_text += f"Queda la participación: {remaining_numbers[0]}"
|
||||
elif remaining_numbers_amount == 0:
|
||||
remaining_numbers_text = "⌛ ¡Ya no hay papeletas! ⌛\n\n"
|
||||
remaining_numbers_text += "¡El resultado de la rifa se dará a conocer a las 21:45h!"
|
||||
remaining_numbers_text = "⌛ ¡Ya no hay participaciones! ⌛\n\n"
|
||||
remaining_numbers_text += "¡El resultado del sorteo se dará a conocer a las 21:45h!"
|
||||
else:
|
||||
remaining_numbers = get_remaining_numbers(raffle_id)
|
||||
remaining_numbers_text = f"🔔🔔🔔 ¡Últimas {remaining_numbers_amount} papeletas disponibles! 🔔🔔🔔\n\n"
|
||||
remaining_numbers_text += f"Quedan las papeletas: {', '.join(remaining_numbers)}"
|
||||
remaining_numbers_text = f"🔔🔔🔔 ¡Últimas {remaining_numbers_amount} participaciones disponibles! 🔔🔔🔔\n\n"
|
||||
remaining_numbers_text += f"Quedan las participaciones: {', '.join(remaining_numbers)}"
|
||||
|
||||
caption = (
|
||||
f"{new_participant_line}\n\n"
|
||||
@@ -262,7 +292,8 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
f"{remaining_numbers_text}\n\n"
|
||||
f"{raffle_description_for_announce}\n\n"
|
||||
f"🔎 Ver detalles: https://t.me/{REVERSE_CHANNELS.get(channel_id_to_announce)}/{get_main_message_id(raffle_id)}\n\n"
|
||||
f"💵 Precio por papeleta: {price_per_number}€\n\n" # Use the specific price
|
||||
f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
f"💵 Donación mínima: {price_per_number}€\n\n"
|
||||
f"📜 Normas y condiciones: {TYC_DOCUMENT_URL} \n\n"
|
||||
)
|
||||
|
||||
@@ -307,7 +338,7 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
store_update_message_id(raffle_id, sent_or_edited_message_id)
|
||||
|
||||
# Send image confirmation to user (price not needed in this caption)
|
||||
user_caption = f"¡Apuntado satisfactoriamente a la rifa '{raffle_name}'! Tus números son: {', '.join(numbers)}"
|
||||
user_caption = f"¡Apuntado satisfactoriamente al sorteo '{raffle_name}'! Tus participaciones son: {', '.join(numbers)}"
|
||||
send_telegram_photo(user_id, image_path, caption=user_caption)
|
||||
|
||||
else:
|
||||
@@ -326,6 +357,15 @@ def receive_paypal_payment(invoice_id, payment_status, payment_amount_str):
|
||||
# admin_chat_id = "YOUR_ADMIN_CHAT_ID"
|
||||
# send_telegram_message(admin_chat_id, f"CRITICAL DB Error: Failed to confirm numbers for invoice {invoice_id}, user {user_id}, raffle {raffle_id}. Payment was valid. Manual check needed.")
|
||||
|
||||
def capture_order(order_id, access_token):
|
||||
url = f"{PAYPAL_URL}/v2/checkout/orders/{order_id}/capture"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {access_token}"
|
||||
}
|
||||
response = requests.post(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
@app.route("/paypal-webhook", methods=["POST"])
|
||||
def paypal_webhook():
|
||||
@@ -343,7 +383,7 @@ def paypal_webhook():
|
||||
|
||||
# 3. Verify signature
|
||||
access_token = get_paypal_access_token()
|
||||
verify_url = "https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature"
|
||||
verify_url = f"{PAYPAL_URL}/v1/notifications/verify-webhook-signature"
|
||||
|
||||
payload = {
|
||||
"auth_algo": headers["paypal-auth-algo"],
|
||||
@@ -367,11 +407,18 @@ def paypal_webhook():
|
||||
logger.info(f"EVENT DATA: {event}")
|
||||
if event_type == "CHECKOUT.ORDER.APPROVED":
|
||||
# process approved order
|
||||
logger.info(f"✅ Order approved: {event['resource']['id']}")
|
||||
logger.info(f"✅ Order approved: {event['resource']['id']}. Capturing payment...")
|
||||
# Capture payment
|
||||
resource = event["resource"]
|
||||
invoice_id = resource.get("id") # capture ID
|
||||
payment_status = resource.get("status") # e.g. COMPLETED
|
||||
payment_amount = resource["purchase_units"][0]["amount"]["value"]
|
||||
capture_order(invoice_id, access_token)
|
||||
elif event_type == "PAYMENT.CAPTURE.COMPLETED":
|
||||
logger.info(f"✅ Payment completed: {event['resource']['id']}")
|
||||
resource = event["resource"]
|
||||
invoice_id = resource["supplementary_data"]["related_ids"]["order_id"]
|
||||
|
||||
payment_status = resource.get("status")
|
||||
payment_amount = resource["amount"]["value"]
|
||||
|
||||
if not all([invoice_id, payment_status, payment_amount]):
|
||||
logger.warning(f"Missing one or more required fields in VERIFIED IPN data: {resource}")
|
||||
@@ -379,9 +426,6 @@ def paypal_webhook():
|
||||
|
||||
# Process the valid payment
|
||||
receive_paypal_payment(invoice_id, payment_status, payment_amount)
|
||||
elif event_type == "PAYMENT.CAPTURE.COMPLETED":
|
||||
logger.info(f"✅ Payment completed: {event['resource']['id']}")
|
||||
# Extract key fields (adjust keys based on your PayPal setup/IPN variables)
|
||||
else:
|
||||
logger.info(f"ℹ️ Received event: {event_type}")
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user