fix(api): enhance pally webhook with comprehensive error handling and logging
This commit is contained in:
@@ -30,57 +30,100 @@ async def pally_callback(
|
||||
CurrencyIn: str = Form(...),
|
||||
custom: str | None = Form(None),
|
||||
SignatureValue: str = Form(...),
|
||||
# Optional fields for additional information
|
||||
AccountType: str | None = Form(None),
|
||||
AccountNumber: str | None = Form(None),
|
||||
BalanceAmount: str | None = Form(None),
|
||||
BalanceCurrency: str | None = Form(None),
|
||||
PayerPhone: str | None = Form(None),
|
||||
PayerEmail: str | None = Form(None),
|
||||
PayerName: str | None = Form(None),
|
||||
PayerComment: str | None = Form(None),
|
||||
ErrorCode: int | None = Form(None),
|
||||
ErrorMessage: str | None = Form(None),
|
||||
session: AsyncSession = Depends(get_db),
|
||||
bot: Bot = Depends(get_bot),
|
||||
deps: APIDependenciesDTO = Depends(get_deps),
|
||||
):
|
||||
oid = custom or ""
|
||||
logger.info("invid: %s, outsum: %s, commission: %s, TrsId: %s, status: %s, currencyin: %s, custom: %s, sign: %s", InvId, OutSum, Commission, TrsId, Status, CurrencyIn, custom, SignatureValue)
|
||||
logger.info(
|
||||
"Pally webhook received - InvId: %s, OutSum: %s, Commission: %s, TrsId: %s, Status: %s, "
|
||||
"CurrencyIn: %s, custom: %s, SignatureValue: %s",
|
||||
InvId, OutSum, Commission, TrsId, Status, CurrencyIn, custom, SignatureValue
|
||||
)
|
||||
|
||||
# Enhanced logging for failed payments
|
||||
if Status != BillStatus.SUCCESS:
|
||||
logger.warning(
|
||||
"Non-success payment received - Status: %s, ErrorCode: %s, ErrorMessage: %s, TrsId: %s",
|
||||
Status, ErrorCode, ErrorMessage, TrsId
|
||||
)
|
||||
|
||||
# Validate signature
|
||||
raw_string = f"{OutSum}:{InvId}:{settings.pally_token}"
|
||||
expected_signature = hashlib.md5(raw_string.encode("utf-8")).hexdigest().upper()
|
||||
|
||||
logger.debug("Signature validation - Expected: %s, Received: %s, Raw: %s",
|
||||
expected_signature, SignatureValue, raw_string)
|
||||
|
||||
if SignatureValue != expected_signature:
|
||||
logger.critical("Invalid signature for TrsId %s", TrsId)
|
||||
logger.critical(
|
||||
"SECURITY ALERT: Invalid signature for TrsId %s - Expected: %s, Received: %s, Raw: %s",
|
||||
TrsId, expected_signature, SignatureValue, raw_string
|
||||
)
|
||||
raise HTTPException(403, detail="Invalid signature.")
|
||||
|
||||
# Only process successful payments
|
||||
if Status != BillStatus.SUCCESS:
|
||||
logger.info("Bill %s skipped: status=%s", TrsId, Status)
|
||||
return "OK"
|
||||
|
||||
logger.info("Received successfully paid bill %s", TrsId)
|
||||
logger.info("Processing successfully paid bill %s", TrsId)
|
||||
|
||||
if not oid.isdigit():
|
||||
logger.critical("Invalid custom field format for TrsId %s: %s", TrsId, custom)
|
||||
# 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)
|
||||
return "OK"
|
||||
|
||||
# Find bill in database
|
||||
bill = await deps.bills_repository.get_bill_by_id(session, int(oid))
|
||||
|
||||
if not bill:
|
||||
logger.critical("Bill %s is not found in db", TrsId)
|
||||
logger.critical("Bill %s not found in database for TrsId %s", oid, TrsId)
|
||||
return "OK"
|
||||
|
||||
# Check if already processed
|
||||
if bill.status != DepositStatus.PENDING:
|
||||
logger.warning("bill=%s is already paid according to the db", bill.id)
|
||||
logger.warning("Bill %s (TrsId: %s) is already processed with status: %s",
|
||||
bill.id, TrsId, bill.status)
|
||||
return "OK"
|
||||
|
||||
try:
|
||||
amount = int(float(OutSum))
|
||||
|
||||
# Validate payment amount
|
||||
if bill.amount != amount:
|
||||
logger.warning("requested amount for bill=%s is not equal to db entry", bill.id)
|
||||
logger.error(
|
||||
"Amount mismatch for bill %s (TrsId: %s) - Expected: %s, Received: %s",
|
||||
bill.id, TrsId, bill.amount, amount
|
||||
)
|
||||
return "OK"
|
||||
|
||||
logger.info("Processing payment: bill_id=%s, user_id=%s, amount=%s",
|
||||
bill.id, bill.creator_id, amount)
|
||||
|
||||
# Credit user balance
|
||||
await deps.user_repository.increase_user_balance(
|
||||
session,
|
||||
bill.creator_id,
|
||||
amount=amount,
|
||||
tx_type=BalanceTxType.DEPOSIT,
|
||||
description="personal balance deposit via PALLY",
|
||||
description=f"payment via PALLY (TrsId: {TrsId})",
|
||||
)
|
||||
await successful_payment_notification(bot, bill.creator_id, amount)
|
||||
|
||||
# Process referral bonus
|
||||
user = await deps.user_repository.get_user_by_id(session, bill.creator_id)
|
||||
|
||||
referal = user.referal_id if user else None
|
||||
if referal is not None:
|
||||
referal_amount = math.floor(amount * (settings.referal_bonus / 100))
|
||||
@@ -89,19 +132,26 @@ async def pally_callback(
|
||||
referal,
|
||||
referal_amount,
|
||||
tx_type=BalanceTxType.REFERRAL_BONUS,
|
||||
description=f"referal reward for referal_id={bill.creator_id}",
|
||||
description=f"referral reward for user {bill.creator_id} (TrsId: {TrsId})",
|
||||
)
|
||||
await successful_payment_notification(bot, referal, referal_amount)
|
||||
logger.info("Referral bonus processed: referrer_id=%s, amount=%s", referal, referal_amount)
|
||||
|
||||
except Exception:
|
||||
logger.info("Payment processing completed successfully for TrsId %s", TrsId)
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
"Exception caught while processing balances for TrsId %s (Creator: %s)",
|
||||
TrsId,
|
||||
bill.creator_id,
|
||||
"CRITICAL ERROR processing payment for TrsId %s, bill_id %s, user_id %s: %s",
|
||||
TrsId, bill.id, bill.creator_id, str(e)
|
||||
)
|
||||
# Don't return early - still mark as success to prevent retries
|
||||
# The balance operation might have partially succeeded
|
||||
|
||||
# Update bill status to success
|
||||
await deps.bills_repository.update_bill_status(
|
||||
session, int(bill.id), status=DepositStatus.SUCCESS
|
||||
)
|
||||
|
||||
logger.info("Bill %s marked as SUCCESS for TrsId %s", bill.id, TrsId)
|
||||
|
||||
return "OK"
|
||||
|
||||
Reference in New Issue
Block a user