Files
PolyWeather/web/routers/payments.py
2569718930@qq.com 105713c799 @
支付提交增加 Tx 预校验:提交前链上验签收款地址与金额,防止转错地址;409 错误展示友好中文提示并自动对账恢复

- 新增 validate_intent_tx 方法及 POST /api/payments/intents/{id}/validate 端点,
  在提交前查链上 receipt 对比收款地址和金额,mismatch 直接拦截
- 新增 handleSubmit409 辅助函数,根据后端错误详情分流处理:
  已支付→自动 reconcile,已过期→提示重下单,其他→透传具体原因
- submit/validate 路由透传后端 detail 字段,生产环境也能看到具体错误
- 手动转账面板粘贴 tx hash 后自动触发验证,绿色/红色提示,
  验证不通过时禁用提交按钮

Tested: tsc --noEmit + ruff check . 均通过
@
2026-05-22 04:44:14 +08:00

102 lines
2.8 KiB
Python

"""Payment API routes."""
from fastapi import APIRouter, Request
from web.core import (
ConfirmPaymentTxRequest,
CreatePaymentIntentRequest,
SubmitPaymentTxRequest,
ValidatePaymentTxRequest,
WalletChallengeRequest,
WalletUnbindRequest,
WalletVerifyRequest,
)
from web.services.payment_api import (
confirm_payment_tx as confirm_payment_tx_service,
create_payment_intent as create_payment_intent_service,
create_payment_wallet_challenge,
get_payment_config,
get_payment_intent,
get_payment_runtime,
list_payment_wallets,
reconcile_latest_payment,
submit_payment_tx as submit_payment_tx_service,
unbind_payment_wallet,
validate_payment_tx,
verify_payment_wallet,
)
router = APIRouter(tags=["payments"])
@router.get("/api/payments/config")
async def payment_config(request: Request):
return get_payment_config(request)
@router.get("/api/payments/runtime")
async def payment_runtime(request: Request):
return get_payment_runtime(request)
@router.get("/api/payments/wallets")
async def payment_wallets(request: Request):
return list_payment_wallets(request)
@router.delete("/api/payments/wallets")
async def payment_wallet_unbind(request: Request, body: WalletUnbindRequest):
return unbind_payment_wallet(request, body)
@router.post("/api/payments/wallets/challenge")
async def payment_wallet_challenge(request: Request, body: WalletChallengeRequest):
return create_payment_wallet_challenge(request, body)
@router.post("/api/payments/wallets/verify")
async def payment_wallet_verify(request: Request, body: WalletVerifyRequest):
return verify_payment_wallet(request, body)
@router.post("/api/payments/intents")
async def payment_create_intent(request: Request, body: CreatePaymentIntentRequest):
return create_payment_intent_service(request, body)
@router.get("/api/payments/intents/{intent_id}")
async def payment_get_intent(request: Request, intent_id: str):
return get_payment_intent(request, intent_id)
@router.post("/api/payments/intents/{intent_id}/validate")
async def payment_validate_tx(
request: Request,
intent_id: str,
body: ValidatePaymentTxRequest,
):
return validate_payment_tx(request, intent_id, body)
@router.post("/api/payments/intents/{intent_id}/submit")
async def payment_submit_tx(
request: Request,
intent_id: str,
body: SubmitPaymentTxRequest,
):
return submit_payment_tx_service(request, intent_id, body)
@router.post("/api/payments/intents/{intent_id}/confirm")
async def payment_confirm_tx(
request: Request,
intent_id: str,
body: ConfirmPaymentTxRequest,
):
return confirm_payment_tx_service(request, intent_id, body)
@router.post("/api/payments/reconcile-latest")
async def payment_reconcile_latest(request: Request):
return reconcile_latest_payment(request)