From 18f994aed94fc7185f20eee93a1b7932445db404 Mon Sep 17 00:00:00 2001 From: hexdev Date: Sun, 31 May 2026 15:17:48 +0700 Subject: [PATCH] fix(pally): use InvId as primary bill identifier instead of custom field --- api/routes/pally.py | 18 ++++++++++++------ tests/send_pally_webhook.py | 17 +++++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/api/routes/pally.py b/api/routes/pally.py index d7dee13..77bb993 100644 --- a/api/routes/pally.py +++ b/api/routes/pally.py @@ -45,7 +45,10 @@ async def pally_callback( bot: Bot = Depends(get_bot), deps: APIDependenciesDTO = Depends(get_deps), ): - oid = custom or "" + # FIXED: Use InvId (which contains the order_id from bill creation) instead of custom field + # The InvId field contains the db_bill.id that was passed as order_id during bill creation + bill_id_str = InvId + logger.info( "Pally webhook received - InvId: %s, OutSum: %s, Commission: %s, TrsId: %s, Status: %s, " "CurrencyIn: %s, custom: %s, SignatureValue: %s", @@ -80,16 +83,19 @@ async def pally_callback( logger.info("Processing successfully paid bill %s", TrsId) - # Validate custom field (order ID) - if not oid or not oid.isdigit(): - logger.critical("Invalid or missing custom field for TrsId %s: '%s'", TrsId, custom) + # Validate bill ID (from InvId field, which contains the order_id from bill creation) + if not bill_id_str or not bill_id_str.isdigit(): + logger.critical( + "Invalid or non-numeric bill ID in InvId field for TrsId %s: '%s'", + TrsId, bill_id_str + ) return "OK" # Find bill in database - bill = await deps.bills_repository.get_bill_by_id(session, int(oid)) + bill = await deps.bills_repository.get_bill_by_id(session, int(bill_id_str)) if not bill: - logger.critical("Bill %s not found in database for TrsId %s", oid, TrsId) + logger.critical("Bill %s not found in database for TrsId %s", bill_id_str, TrsId) return "OK" # Check if already processed diff --git a/tests/send_pally_webhook.py b/tests/send_pally_webhook.py index a9407e5..f5eb949 100644 --- a/tests/send_pally_webhook.py +++ b/tests/send_pally_webhook.py @@ -46,27 +46,28 @@ def main(): pally_token = os.environ["PALLY_TOKEN"] - # Корректные поля согласно документации pally.info - inv_id = f"payment-{args.bill_id}" # InvId - идентификатор платежа - trs_id = f"LXZv3R{args.bill_id}" # TrsId - уникальный идентификатор счета + # ИСПРАВЛЕНО: InvId должен содержать ID счета из БД (это order_id при создании счета) + # Именно InvId используется в webhook handler для поиска счета в БД + inv_id = str(args.bill_id) # InvId = bill ID из нашей БД (order_id при создании) + trs_id = f"LXZv3R{args.bill_id}" # TrsId - уникальный идентификатор счета в Pally currency = "RUB" - custom = str(args.bill_id) # custom field содержит ID счета в нашей БД + custom = None # custom field не используется в production (остается None) commission = "0.00" # Комиссия - # ИСПРАВЛЕНО: используем inv_id вместо payment_id для сигнатуры + # Сигнатура рассчитывается с использованием InvId (который содержит bill ID) signature = calculate_signature( str(args.amount), inv_id, pally_token ) - # ИСПРАВЛЕНО: используем правильные имена полей согласно документации + # Используем правильные имена полей согласно документации pally.info payload = { - "InvId": inv_id, + "InvId": inv_id, # Содержит ID счета из БД "OutSum": str(args.amount), "Commission": commission, "TrsId": trs_id, "Status": args.status, "CurrencyIn": currency, - "custom": custom, + "custom": custom, # None в production "SignatureValue": signature, }