feat(pay): 微信服务商分账+资金托管改造——OPC个人/商户双绑定收款、验收95/5分账、回调确认、escrow资金托管字段扩展
- profitsharing.py:服务商分账客户端(添加接收方/发起分账/查分账/退款/回调验签) - payment_bindings + settlement_logs:OPC 收款绑定(personal openid / merchant 子商户号)与分账流水镜像 - settlement_service.release_escrow:验收后优先发起微信分账(95%接单者/5%平台),未配置时降级台账结算(channel=manual) - handle_split_notify:分账回调确认 escrow released(幂等) - 路由:分账回调 + 绑定创建/列表/停用 - 迁移:alembic 0039(新表 + escrows 幂等加列)+ 兜底迁移脚本 + 冒烟测试
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""幂等迁移:为 ``escrows`` 表补充微信服务商分账扩展列(非运行态)。
|
||||
|
||||
用法:uv run python scripts/db/migrate_escrow_columns.py
|
||||
|
||||
- 通过 SQLAlchemy Inspector 检查缺失列,对缺失列执行 ``ALTER TABLE ... ADD COLUMN``;
|
||||
- 幂等:已存在列自动跳过,可重复执行;兼容 SQLite(默认)与 MySQL(生产)。
|
||||
- 新增表 ``payment_bindings`` / ``settlement_logs`` 由应用启动时 ``create_all`` 幂等创建,
|
||||
无需在此处理(本脚本只负责对既有表加列)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from sqlalchemy import create_engine, inspect # noqa: E402
|
||||
|
||||
from app.infrastructure.db import sync_database_url # noqa: E402
|
||||
|
||||
# escrows 需补充的扩展列(列名, 方言通用 DDL)
|
||||
ESCROW_COLUMNS = [
|
||||
("channel", "VARCHAR(32) NOT NULL DEFAULT 'wx_split'"),
|
||||
("transaction_id", "VARCHAR(64) NOT NULL DEFAULT ''"),
|
||||
("share_order_no", "VARCHAR(64) NOT NULL DEFAULT ''"),
|
||||
("share_status", "VARCHAR(32) NOT NULL DEFAULT 'pending'"),
|
||||
("receiver_binding_id", "VARCHAR(64) NOT NULL DEFAULT ''"),
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
url = sync_database_url()
|
||||
engine = create_engine(url)
|
||||
insp = inspect(engine)
|
||||
if "escrows" not in insp.get_table_names():
|
||||
print("escrows 表不存在(未建库),无需迁移")
|
||||
return
|
||||
existing = {c["name"] for c in insp.get_columns("escrows")}
|
||||
added, skipped = [], []
|
||||
for name, ddl in ESCROW_COLUMNS:
|
||||
if name in existing:
|
||||
skipped.append(name)
|
||||
continue
|
||||
with engine.begin() as conn:
|
||||
conn.exec_driver_sql(f"ALTER TABLE escrows ADD COLUMN {name} {ddl}")
|
||||
added.append(name)
|
||||
print(f"新增列: {added or '无'}")
|
||||
print(f"已存在跳过: {skipped or '无'}")
|
||||
engine.dispose()
|
||||
if added:
|
||||
print("迁移完成。")
|
||||
else:
|
||||
print("无新增列,escrows 已是最新。")
|
||||
print("注:新表 payment_bindings / settlement_logs 由应用启动时 create_all 幂等创建。")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user