melodic-marinating-eich.md 6.0 KB

当面付代开通功能实现计划

Context

需要在 xjz-payment-platform 中新增"代商家开通当面付"功能。这是支付宝 ISV 服务商代商家开通当面付收单产品的标准流程,涉及 4 个 API 的顺序调用:

  1. alipay.open.agent.create → 创建事务,获得 batch_no
  2. alipay.open.agent.facetoface.sign → 提交当面付开通申请
  3. alipay.open.agent.confirm → 确认提交事务
  4. alipay.open.agent.order.query → 轮询申请单状态

SDK 验证:所有 Request/Response 类在 alipay-sdk-python-all 中可用。FacetofaceSign 无独立 Model 类,直接在 Request 上设置属性。

实现方案

1. 后端模块 backend/app/plugin/module_payment/facetoface/

完全复用现有 module_payment 的 model/crud/service/controller/schema 模式。

enums.py - 申请单状态枚举

INIT            - 初始化(本地状态,尚未提交)
SUBMITTED       - 已提交到支付宝
MERCHANT_AUDITING - 审核中
MERCHANT_CONFIRM  - 审核通过,等待商家确认
SUCCESS         - 商家已确认,开通成功
CLOSED          - 已关闭(驳回/失败/取消)

model.py - FacetofaceOrderModel

表名 pay_facetoface_order,继承 PaymentModelMixin + TenantMixin

关键字段:

  • batch_no (String64, unique) - 支付宝事务编号
  • order_no (String64) - 支付宝申请单号
  • order_status (String32) - 申请单状态(用枚举)
  • merchant_name (String128) - 商户名称
  • shop_name (String128) - 店铺名称
  • shop_address (String256) - 店铺地址
  • mcc_code (String32) - 商户类别码
  • rate (String16) - 费率
  • business_license_no (String64) - 营业执照号
  • business_license_mobile (String32) - 联系手机号
  • sign_and_auth (Boolean) - 是否同时获取授权
  • confirm_url (Text) - 商家确认链接
  • app_auth_token (String128) - 商家授权 token
  • reject_reason (Text) - 驳回原因
  • remark (Text) - 备注
  • last_query_time (DateTime) - 最后查询时间
  • next_query_time (DateTime) - 下次查询时间
  • query_count (Integer) - 已查询次数

schema.py

  • FacetofaceApplySchema - 申请请求(shop_name, shop_address, mcc_code, rate, business_license_no, business_license_mobile, sign_and_auth 等)
  • FacetofaceOrderOutSchema - 详情响应
  • FacetofaceOrderListOutSchema - 列表响应

crud.py

  • FacetofaceCRUD 继承 CRUDBase
  • get_by_batch_no - 按事务编号查询
  • get_pending_orders - 获取待轮询的申请单

service.py

  • apply_service - 执行三步操作:create → sign → confirm,一次性完成提交
  • query_order_service - 手动查询单个申请单状态
  • poll_pending_orders - 定时任务调用,轮询所有待处理申请单
    • 策略:提交后 5 分钟首查,之后每 4 小时查一次
    • 如果 MERCHANT_AUDITING 超过 1 天,标记需关注

controller.py

  • FacetofaceRouter = APIRouter(prefix="/facetoface", tags=["当面付开通"])
  • POST /facetoface/apply - 提交开通申请
  • GET /facetoface - 查询申请单列表(分页)
  • POST /facetoface/{id}/query - 手动刷新查询状态
  • GET /facetoface/{id} - 查询申请单详情

__init__.py

导出 Router, CRUD, Model, Service 等。

2. 模块注册

backend/app/plugin/module_payment/__init__.py_MODULES 列表加入 "facetoface"

路由自动发现:discover.py 会自动扫描 module_payment/facetoface/controller.py 并注册到 /payment/facetoface

3. 数据库迁移

创建 Alembic migration:backend/app/alembic/versions/c1d2e3f4g5h6_add_facetoface_order.py

4. 定时轮询任务

在应用启动时注册一个 interval 定时任务(通过现有的 APScheduler 系统),每 30 分钟检查一次是否有需要查询状态的申请单。具体轮询间隔由 next_query_time 字段控制:

  • 提交后 5 分钟 → 首查
  • 之后每 4 小时查一次
  • 达到终态(SUCCESS/CLOSED)后停止轮询

5. 前端

frontend/src/api/module_payment/facetoface.ts

API 接口定义 + 状态常量映射。

frontend/src/views/module_payment/facetoface/index.vue

管理页面,包含:

  • 搜索栏:商户名称、店铺名称、状态筛选
  • 数据表格:batch_no、商户名、店铺名、状态、费率、确认链接、创建时间
  • 新增按钮:打开申请表单弹窗
  • 操作列:查询状态、查看详情
  • 申请表单弹窗:填写商户信息后提交

复用现有 CRUD 组件:PageSearch, PageContent, CrudToolbarLeft, CrudToolbarRight, PageModal。

6. 关键文件清单

新建:

  • backend/app/plugin/module_payment/facetoface/__init__.py
  • backend/app/plugin/module_payment/facetoface/enums.py
  • backend/app/plugin/module_payment/facetoface/model.py
  • backend/app/plugin/module_payment/facetoface/schema.py
  • backend/app/plugin/module_payment/facetoface/crud.py
  • backend/app/plugin/module_payment/facetoface/service.py
  • backend/app/plugin/module_payment/facetoface/controller.py
  • backend/app/alembic/versions/c1d2e3f4g5h6_add_facetoface_order.py
  • frontend/src/api/module_payment/facetoface.ts
  • frontend/src/views/module_payment/facetoface/index.vue

修改:

  • backend/app/plugin/module_payment/__init__.py - 注册模块

7. 复用的现有代码

  • AlipayClient.get_client() from app.core.alipay.client
  • PaymentModelMixin, TenantMixin from app.core.base_model
  • CRUDBase from app.core.base_crud
  • CustomException from app.core.exceptions
  • AuthPermission, redis_getter from app.core.dependencies
  • OperationLogRoute from app.core.router_class
  • ResponseSchema, SuccessResponse from app.common.response
  • scheduler from app.core.ap_scheduler (注册轮询任务)
  • 前端: PageSearch, PageContent, CrudToolbarLeft/Right, PageModal 组件

8. 验证

  1. 后端:启动服务,检查 /payment/facetoface 路由是否注册
  2. 数据库:运行 migration 创建表
  3. 前端:访问当面付管理页面,测试列表、搜索、新增申请
  4. 定时任务:检查 APScheduler 日志确认轮询任务注册成功