Skip to content

Zjmf 与 TuraIDC 新购/续费单据创建对比

  • 文档性质:对比智简魔方 ZJMF-CBAP 10.4.6 与 turaidc 的新购、续费流程,重点核对“账单 + 订单是否同步创建”,并记录 turaidc 上游对接版本的行为差异。
  • 参照真源:ZJMF-CBAP-10.4.6/10.4.6/app/home/model/CartModel.phpapp/common/model/OrderModel.phpOrderTmpModel.phpzjmf-manger-decoded-main/app/home/controller/CartController.phpapp/common/logic/Renew.phpapp/openapi/controller/HostController.phpdata/route/home.php
  • turaidc 现状依据:backend/app/Services/Finance/CheckoutService.phpbackend/app/Services/Provisioning/ServiceRenewService.phpbackend/app/Services/Finance/PaymentService.phpbackend/app/Services/Order/PaidOrderBusinessFlowDispatcher.phpbackend/plugins/servers/zjmf_finance/lib/ZjmfProvisionService.phpZjmfRenewService.php
  • 当前状态:静态审查完成;未变更任何代码与数据。

概述

三个系统的单据模型不同:

系统主财务单据订单与账单关系账单创建时机
ZJMF-CBAP 10.4.6order + order_item(订单中心)订单为主,shd_invoices 由财务插件补充支付时由财务插件创建,核心包内无账单创建代码
zjmf-manger(turaidc 上游对接架构)invoices + invoice_items(账单中心)orders.invoiceid 关联账单;续费只建账单不建订单新购结算与续费提交时同步创建
turaidcinvoices(账单中心,财务入口)invoices.order_id 关联订单;新购/续费均建 Order下单时与订单在同一事务同步创建

turaidc 对接的 ZJMF 上游接口行为与 zjmf-manger 一致(zjmf_api_login/cart/settle/apply_credit/check_order/host/renew 等路由均存在于 zjmf-manger-decoded-main/data/route/home.php,而 CBAP 10.4.6 的 route/api.php 仅暴露商品接口)。本文同时列出两者作为对照。

1. 新购流程对比

1.1 ZJMF-CBAP 10.4.6:CartModel::settle()

同一事务内依次创建:

  1. ordertype=new,金额为 0 时直接 Paid
  2. host(产品实例,status=Unpaid,关联 order_id
  3. order_item(订单子项,type=host

金额为 0 时直接调用 processPaidOrder() 开通。返回 order_idamounthost_ids不返回账单 ID;账单由财务插件在支付时创建。

1.2 zjmf-manger:CartController::settle()

同一事务内依次创建:

  1. invoicestype=productstatus=Unpaid)→ 获得 invoiceid
  2. ordersstatus=Pendingorders.invoiceid 关联账单)
  3. host(产品实例,orderid 关联订单)
  4. invoice_items(账单子项:setup/host/discount/promo

金额为 0 时账单直接标记 PaidprocessPaidInvoice()。返回 invoiceid(下游场景附 hostid)。

1.3 turaidc:CheckoutService::create()

同一事务内依次创建:

  1. Invoicetype=new_purchasestatus=UNPAID,含报价、优惠券、配置快照)
  2. shadow Ordertype=new,仅内部履约使用,不向用户展示)
  3. 扣减商品库存

支付完成后 PaymentService::handlePaidInvoice()PaidOrderBusinessFlowDispatchernew/renew 同步履约)→ ZjmfProvisionService::provisionOrder() 在上游同步创建:

登录上游 → 清空购物车 → 读取商品配置 → 加入购物车 → POST /cart/settle(上游创建订单 + 账单,解析 invoiceid)→ POST /apply_credit 用供应商余额支付 → 回查 host 详情并落库。

1.4 小结

步骤CBAP 10.4.6zjmf-mangerturaidc
创建账单支付时(财务插件)结算时同步下单时同步
创建订单结算时同步结算时同步下单时同步
账单/订单同事务否(跨插件)
上游同步创建--结算时同步创建订单+账单

2. 续费流程对比

2.1 ZJMF-CBAP 10.4.6

OrderModel::createOrder(type=renew) 分发到续费插件 idcsmart_renew(插件代码不在核心包),插件内部创建续费订单与账单并返回 invoiceid

2.2 zjmf-manger:Renew::renew()/host/renew

  1. 校验产品状态(Active/Suspended)与周期
  2. 计算续费金额(支持换周期、比例续费)
  3. 只创建 invoicestype=renew)+ invoice_items + renew_cycle,不创建订单
  4. 已有未支付续费账单时:删除旧账单重建;存在部分支付时差额退回客户余额
  5. 金额为 0 时直接延长到期时间(不建账单)
  6. 返回 invoiceid + payment

2.3 turaidc:ServiceRenewService

  • createRenewInvoiceForUser() / createRenewOrderForUser():同一事务内创建 Invoicetype=renew)与 shadow Ordertype=renew),双向绑定(invoices.order_id)。
  • 自动续费(BillingAutomationService::createRenewOrders())同样走 createRenewInvoiceForUser()
  • 重复创建保护:已存在同周期未支付账单时复用;金额或优惠变化时先取消旧账单再重建(renew_invoice_replaced)。

支付完成后同步履约 ZjmfRenewService::renewServiceInvoice()

POST /host/renew(上游创建续费账单,解析 invoiceid)→ POST /pay?action=billing&pay=true 用供应商余额支付 → POST /check_order 确认支付完成 → 回写 provision_dataupstream_invoice_idrenew_invoice_idlast_renew_*)。支付失败时支持 recoverRenewInvoiceWithContext() 恢复。

2.4 小结

步骤CBAP 10.4.6zjmf-mangerturaidc
创建续费订单插件创建不创建同步创建
创建续费账单插件创建同步创建同步创建
未支付账单重建-删除重建 + 差额退余额取消重建(renew_invoice_replaced
上游同步创建--提交续费时同步创建账单并余额支付

3. “同步创建账单和订单”验证结论

逐一核对 turaidc 的所有新购/续费入口,账单与订单均在提交时同步创建:

  • [x] 新购:CheckoutService::create() 同事务创建 Invoice + Order
  • [x] 手动续费:createRenewInvoiceForUser() / createRenewOrderForUser() 同事务创建 Invoice + Order 并双向绑定。
  • [x] 自动续费:BillingAutomationServicecreateRenewInvoiceForUser()
  • [x] 支付后同步履约:PaidOrderBusinessFlowDispatcher::SYNCHRONOUS_FULFILLMENT_TYPES = ['new', 'renew'],支付回调内同步调用上游创建订单/账单并余额支付;同步失败回退 provision 队列。
  • [x] 上游新购:/cart/settle 同步创建订单 + 账单,/apply_credit 余额支付。
  • [x] 上游续费:/host/renew 同步创建续费账单,/pay 余额支付,/check_order 确认。
  • [x] 支付路径全覆盖:支付宝回调、主动查询、余额支付、管理员标记已支付均走 handlePaidInvoice() → 同步履约。

结论:turaidc 的新购与续费已实现“账单 + 订单同步创建”(本地同事务),且支付后在上游同步创建订单/账单并完成供应商余额支付。无需新增代码。

4. 差异与注意事项

差异说明处理
CBAP 核心包新购不创建账单账单由财务插件在支付时创建,与 turaidc 的“账单为财务入口”不同turaidc 直接创建 Invoice,符合财务单据生成规则;上游无需改动
上游续费只建账单不建订单zjmf-manger 的 /host/renew 不创建 ordersturaidc 本地独立创建 Order(type=renew),不依赖上游订单
上游结算必须返回 invoiceidturaidc 依赖财务插件版本返回账单 ID,否则拒绝继续(“上游已接受结算,但未返回账单 ID”)已明确对接财务版本;对接纯 CBAP 核心包时无法余额支付上游账单
0 元单处理CBAP 允许 0 元订单直接开通;turaidc CheckoutService 拒绝 amount <= 00 元场景在 turaidc 走人工开通,不属于新购单据流程
上游账单重建语义zjmf-manger 删除旧账单重建并退差额;turaidc 取消旧账单重建行为对齐,均保证同一产品同一周期仅一张有效待支付续费账单

基于 AGPL-3.0-or-later 发布