"""充值只信任持久订单;回调与主动查单共用同一到账事务。""" import hashlib import re from decimal import Decimal from sqlalchemy.orm import Session from models_sql import RechargeOrder, Transaction from tip_transaction import lock_wallet_accounts def payment_amount(value): if not isinstance(value, str) or not re.fullmatch(r"[0-9]{1,5}(?:\.[0-9]{1,2})?", value): raise ValueError("invalid payment amount") amount = Decimal(value) if not 1 <= amount <= 10000 or amount != amount.to_integral_value(): raise ValueError("invalid payment amount") return int(amount) def validate_order(row): if (row is None or not isinstance(row.account, str) or not row.account.strip() or type(row.amount) is not int or not 1 <= row.amount <= 10000 or row.status not in {"pending", "paid"}): raise ValueError("invalid recharge order") def validate_ledger(tx, account, amount): if tx is not None and (tx.account != account or tx.tx_type != "RECHARGE" or type(tx.amount) is not int or tx.amount != amount): raise ValueError("invalid recharge ledger") def read_order(db, order_id): if not isinstance(order_id, str) or not re.fullmatch(r"PAY_[0-9a-f]{32}", order_id): return None # 网络查单前的读取不在业务 Session 留下事务或钱包锁。 with Session(bind=db.get_bind(), autoflush=False) as lookup: row = lookup.get(RechargeOrder, order_id) if row is None: return None validate_order(row) tx = lookup.get(Transaction, order_id) validate_ledger(tx, row.account, row.amount) if row.status == "paid" and tx is None: raise ValueError("paid recharge ledger missing") return {"account": row.account, "amount": row.amount, "credited": tx is not None} def persist_order(db, order_id, account, amount): if type(amount) is not int or not 1 <= amount <= 10000 or not isinstance(account, str) or not account.strip(): raise ValueError("invalid recharge request") try: db.add(RechargeOrder(order_id=order_id, account=account, amount=amount, status="pending")) db.commit() except Exception: db.rollback() raise def credit_order(db, order_id, amount): info = read_order(db, order_id) if info is None or type(amount) is not int or amount != info["amount"]: raise ValueError("payment order mismatch") account = info["account"] try: wallet = lock_wallet_accounts(db, (account,), (account,))[account] row = db.query(RechargeOrder).filter(RechargeOrder.order_id == order_id).populate_existing().with_for_update().first() validate_order(row) if row.account != account or row.amount != amount: raise ValueError("payment order changed") tx = db.query(Transaction).filter(Transaction.tx_id == order_id).populate_existing().with_for_update().first() validate_ledger(tx, account, amount) if tx is not None: row.status = "paid" db.commit() return False if row.status != "pending" or type(wallet.balance) is not int: raise ValueError("invalid recharge state") last = db.query(Transaction).filter(Transaction.account == account).order_by( Transaction.created_at.desc(), Transaction.tx_id.desc()).with_for_update().first() previous = last.tx_hash if last else "GENESIS_HASH" digest = hashlib.sha256(f"{order_id}{account}RECHARGE{amount}{previous}".encode()).hexdigest() wallet.balance += amount row.status = "paid" db.add(Transaction(tx_id=order_id, account=account, tx_type="RECHARGE", amount=amount, prev_hash=previous, tx_hash=digest, description="支付宝充值")) db.commit() return True except Exception: db.rollback() raise