#!/bin/bash set -e cd /home/def/otb_billing/backend || exit 1 STAMP="$(date +%Y%m%d-%H%M%S)" cp app.py "app.py.pending-payment-logic.${STAMP}.bak" python3 <<'PY' from pathlib import Path p = Path("app.py") text = p.read_text() old_block_1 = """ payment_id = (request.args.get("payment_id") or "").strip() if not payment_id and pending_crypto_payment: payment_id = str(pending_crypto_payment.get("id") or "").strip() if payment_id.isdigit(): """ new_block_1 = """ payment_id = (request.args.get("payment_id") or "").strip() if not payment_id and pending_crypto_payment: stale_pending_without_tx = False try: created_dt = pending_crypto_payment.get("created_at") if created_dt and created_dt.tzinfo is None: created_dt = created_dt.replace(tzinfo=timezone.utc) stale_pending_without_tx = ( str(pending_crypto_payment.get("payment_status") or "").lower() == "pending" and not pending_crypto_payment.get("txid") and created_dt is not None and datetime.now(timezone.utc) >= (created_dt + timedelta(minutes=2)) ) except Exception: stale_pending_without_tx = False if stale_pending_without_tx: try: cursor.execute(\"\"\" UPDATE payments SET payment_status = 'failed' WHERE id = %s AND payment_status = 'pending' AND (txid IS NULL OR txid = '') \"\"\", (pending_crypto_payment["id"],)) conn.commit() except Exception: pass pending_crypto_payment = None else: payment_id = str(pending_crypto_payment.get("id") or "").strip() if payment_id.isdigit(): """ if old_block_1 not in text: raise SystemExit("FAILED: block 1 not found") text = text.replace(old_block_1, new_block_1, 1) old_block_2 = """ else: pending_crypto_payment["created_at_local"] = "" pending_crypto_payment["lock_expires_at_local"] = "" pending_crypto_payment["lock_expires_at_iso"] = "" pending_crypto_payment["lock_expired"] = True received_dt = pending_crypto_payment.get("received_at") """ new_block_2 = """ else: pending_crypto_payment["created_at_local"] = "" pending_crypto_payment["lock_expires_at_local"] = "" pending_crypto_payment["lock_expires_at_iso"] = "" pending_crypto_payment["lock_expired"] = True if ( str(pending_crypto_payment.get("payment_status") or "").lower() == "pending" and not pending_crypto_payment.get("txid") and pending_crypto_payment.get("lock_expired") ): try: cursor.execute(\"\"\" UPDATE payments SET payment_status = 'failed' WHERE id = %s AND payment_status = 'pending' AND (txid IS NULL OR txid = '') \"\"\", (pending_crypto_payment["id"],)) conn.commit() except Exception: pass pending_crypto_payment = None payment_id = "" received_dt = pending_crypto_payment.get("received_at") if pending_crypto_payment else None """ if old_block_2 not in text: raise SystemExit("FAILED: block 2 not found") text = text.replace(old_block_2, new_block_2, 1) p.write_text(text) print("OK: pending payment logic patched") PY python3 -m py_compile app.py echo "PY_COMPILE_OK" sudo systemctl restart otb_billing sudo systemctl status otb_billing --no-pager -l echo echo "===== verify patched area =====" sed -n '5220,5325p' app.py