简介
本开发文档面向 DouPHP 小程序钱包管理系统,围绕余额查询、充值套餐、交易流水、工作端扣款、提现申请与处理、订单余额支付与退款等核心能力进行系统化说明。重点解释资金安全机制(行锁、事务、幂等)、账户模型(余额、冻结、可用余额)、以及用户体验优化(实时余额、通知、操作历史)。
项目结构
钱包相关代码按“前端控制器 + 业务服务 + 核心钱包”分层组织:
- API 层:小程序侧的余额查询、充值入口、会员明细、工作端核销等接口。
- 前台服务层:充值套餐构建、流水展示、工作端扣款、付款码刷新等。
- 核心钱包层:统一的余额/积分写入、快照更新、事件入账。
- 后台管理:余额流水审计、提现审核与打款、参数初始化。
graph TB
subgraph "小程序API"
A["api/controller/money/MoneyController"]
B["api/controller/money/UserController"]
C["api/controller/money/WorkController"]
end
subgraph "前台服务"
D["front/service/money/MoneyService"]
E["front/service/withdraw/WithdrawService"]
end
subgraph "核心钱包"
F["core/service/wallet/WalletService"]
G["core/service/payment/PaymentService"]
end
subgraph "后台管理"
H["admin/service/money/MoneyService"]
I["admin/controller/withdraw/WithdrawController"]
end
A --> D
B --> D
C --> D
D --> F
E --> F
G --> F
H --> F
I --> E
核心组件
- 余额查询与充值入口:提供充值套餐列表、当前余额、标题等基础信息。
- 会员余额明细:分页返回用户余额流水,包含动作、金额、累计余额、时间等。
- 工作端扣款:支持手机号或付款码查找目标用户并扣减余额,用于线下收款场景。
- 提现申请:创建提现单并冻结/扣减对应金额,记录流水。
- 订单余额支付:在订单支付流程中通过钱包通道完成扣款与支付记录。
- 后台流水与提现管理:余额流水审计、批量删除;提现审核、打款标记、卡号解锁。
架构总览
系统采用“控制器 -> 服务 -> 钱包/统计”的分层架构,关键路径如下:
- 小程序余额查询:API 控制器调用前台 MoneyService,再经 UserStatsService 汇总余额。
- 充值套餐:API 控制器调用前台 MoneyService 获取套餐列表与默认项。
- 工作端扣款:API 控制器校验权限后,调用前台 MoneyService 解析用户并扣款。
- 提现申请:前台 WithdrawService 创建提现单并通过 WalletService 写入负向流水。
- 订单余额支付:PaymentService 在事务内调用 WalletService 扣款并落库支付记录。
sequenceDiagram
participant App as "小程序"
participant API as "MoneyController"
participant Svc as "前台MoneyService"
participant Stats as "UserStatsService"
participant W as "WalletService"
App->>API : 请求余额/充值页面
API->>Svc : 构建套餐/明细数据
Svc->>Stats : 查询用户总余额
Stats-->>Svc : 返回total
Svc-->>API : 返回套餐/明细/total
API-->>App : JSON响应
详细组件分析
余额查询与充值入口
- 功能要点
- 返回充值页标题、套餐列表、默认选中项、当前余额。
- 套餐数据来自模型排序查询,金额格式化输出。
- 关键实现
- 控制器暴露 index/recharge 两个接口。
- 前台服务负责组装套餐与余额。
flowchart TD
Start(["进入充值页"]) --> List["获取套餐列表"]
List --> Default["选择默认套餐"]
Default --> Total["读取用户总余额"]
Total --> Render["渲染页面数据"]
Render --> End(["返回JSON"])
会员余额明细与付款码
- 功能要点
- 分页返回用户余额流水,包含动作、金额、累计余额、时间。
- 支持刷新付款码,供工作端扫码扣款。
- 关键实现
- 控制器 index/payCode 分别处理明细与付款码刷新。
- 前台服务封装分页查询与付款码生成。
sequenceDiagram
participant App as "小程序"
participant UC as "UserController"
participant MS as "前台MoneyService"
App->>UC : 请求余额明细
UC->>MS : buildMoneyListData(userId, page)
MS-->>UC : 返回log_list/pager
UC-->>App : JSON响应
App->>UC : 请求刷新付款码
UC->>MS : refreshUserPayCode(userId)
MS-->>UC : 返回新付款码
UC-->>App : JSON响应
工作端扣款(线下收款)
- 功能要点
- 支持按手机号或付款码定位目标用户。
- 校验权限与金额合法性后扣减余额。
- 关键实现
- WorkController 校验权限与参数,调用前台服务解析用户并扣款。
- 前台服务根据配置决定使用手机号或付款码模式。
sequenceDiagram
participant WK as "WorkController"
participant MS as "前台MoneyService"
participant WS as "WalletService"
WK->>WK : 检查工作端权限
WK->>MS : findWorkCustomerUserIdByPayMode(模式, number)
MS-->>WK : 返回customerUserId
WK->>MS : deductCustomerMoneyByWork(customerUserId, money, workerId)
MS->>WS : createMoney(user_id, 'work', workerId, 'pay', -money)
WS-->>MS : 成功
MS-->>WK : 成功
WK-->>WK : 返回结果
提现申请与处理
- 功能要点
- 用户提交提现申请,系统创建提现单并扣减余额(冻结/扣减),记录流水。
- 后台可标记已打款、批量删除、解锁卡号。
- 关键实现
- 前台 WithdrawService 创建提现记录并调用 WalletService 写入负向流水。
- 后台 WithdrawController 提供打款、批量操作、解锁等能力。
sequenceDiagram
participant U as "用户"
participant VS as "前台WithdrawService"
participant W as "WalletService"
participant AC as "后台WithdrawController"
U->>VS : 提交提现申请
VS->>W : createMoney(userId, 'user', userId, 'withdraw', -amount)
W-->>VS : 写入流水并更新快照
VS-->>U : 返回申请结果
AC->>AC : 后台标记已打款/批量删除/解锁
订单余额支付与退款
- 功能要点
- 订单支付时若选择钱包通道,则在事务内扣款并写入支付记录,最终尝试完成订单。
- 售后退款时若原支付方式为钱包,则回退余额并更新退款状态。
- 关键实现
- PaymentService 在 order.paid 场景中调用 WalletService 扣款,并插入 order_payment。
- 退款分支对 wallet 通道执行反向入账与状态更新。
sequenceDiagram
participant O as "订单系统"
participant P as "PaymentService"
participant W as "WalletService"
O->>P : 发起余额支付(order_sn, amount)
P->>W : createMoney(userId, 'user', userId, 'order_pay', -amount)
W-->>P : 写入流水并更新快照
P->>P : 插入order_payment记录
P->>O : 尝试完成订单
Note over P,O : 退款时同理反向入账
余额支付插件(网页端)
- 功能要点
- 展示当前余额、应付金额、支付后剩余,并提供立即支付按钮。
- 提交到回调地址完成支付确认。
- 关键实现
- work.plugin.php 输出余额支付表单与提示。
flowchart TD
A["加载余额支付页面"] --> B["计算余额与应付"]
B --> C{"余额是否充足?"}
C -- 否 --> D["引导前往充值"]
C -- 是 --> E["生成token并输出表单"]
E --> F["提交到notify_url完成支付"]
依赖关系分析
- 控制器依赖前台服务:MoneyController/UserController/WorkController 均依赖前台 MoneyService。
- 前台服务依赖核心钱包:所有余额变动统一通过 WalletService 写入,保证一致性与幂等。
- 订单支付依赖钱包:PaymentService 在支付/退款流程中调用 WalletService。
- 后台管理依赖前台服务:后台 MoneyService 主要用于流水查询与审计。
graph LR
MC["MoneyController"] --> FM["前台MoneyService"]
UC["UserController"] --> FM
WC["WorkController"] --> FM
FM --> WS["WalletService"]
PS["PaymentService"] --> WS
AMS["后台MoneyService"] --> WS
VC["WithdrawController"] --> VS["前台WithdrawService"]
VS --> WS
性能与一致性
- 并发安全
- 余额写入使用行级锁(FOR UPDATE)确保并发安全,避免超扣。
- 订单支付/退款使用数据库事务包裹多表写入,保证原子性。
- 幂等与防重
- 充值包入账基于订单号防重,避免重复入账。
- 支付记录使用唯一流水号,防止重复落库。
- 快照与可读性
- user_wallet 作为视图聚合缓存,快速读取余额/积分等字段,减少复杂聚合查询。
- 建议
- 高并发场景下,优先读 user_wallet 快照,写路径保持短事务。
- 对关键路径增加监控与告警(如扣款失败、退款异常)。
故障排查指南
- 余额不足
- 现象:工作端扣款或订单支付失败。
- 排查:检查用户 totalMoney、最近流水、是否存在并发扣款竞争。
- 充值未到账
- 现象:购买充值包后余额未增加。
- 排查:检查订单是否已支付、充值包入账逻辑是否触发、是否因订单号重复被跳过。
- 提现未生效
- 现象:提交提现后余额未扣减。
- 排查:检查提现单是否创建成功、WalletService 是否写入负向流水、后台是否已打款。
- 支付失败日志
- 现象:订单支付异常。
- 排查:查看 PaymentService 错误日志,核对钱包扣款与支付记录写入是否完整。
结论
DouPHP 钱包管理系统以 WalletService 为核心,统一处理余额与积分的写入与快照更新,结合前台服务与后台管理,形成完整的余额查询、充值、工作端扣款、提现与订单支付闭环。通过行锁、事务与幂等设计保障资金安全,配合快照提升查询性能。建议在上线前完善监控与审计,确保异常可追踪、可恢复。
附录:接口与数据模型
主要接口概览
- 余额查询与充值
- 充值入口:返回套餐列表、默认项、当前余额。
- 余额明细:分页返回用户流水与累计余额。
- 付款码:刷新用户付款码,供工作端扫码扣款。
- 工作端扣款
- 搜索用户:按手机号或付款码查找用户并展示流水。
- 扣款:校验权限与金额后扣减余额。
- 提现
- 申请:创建提现单并扣减余额。
- 后台:标记已打款、批量删除、解锁卡号。
- 订单支付
- 余额支付:在订单支付流程中通过钱包通道扣款并落库。
数据模型与业务逻辑
- 余额流水(dou_money)
- 关键字段:user_id、operator_type、action、money、total、from、source_type、source_id、created_at。
- 行为:每次变动写入一行,total 为累计余额,用于审计与对账。
- 钱包快照(dou_user_wallet)
- 关键字段:id、money_balance、money_freeze、point_balance、point_freeze、total_consumption、total_promote。
- 行为:由 WalletService 在写入流水后 upsert 更新,提供快速读取。
- 提现单(withdraw)
- 关键字段:withdraw_sn、user_id、money、card_number、card_bank、card_name、card_status、created_at。
- 行为:创建提现单并写入负向余额流水,后台可标记打款。
- 支付记录(order_payment)
- 关键字段:payment_sn、order_id、order_sn、gateway、amount、status、paid_at。
- 行为:钱包支付时插入记录,状态随支付/退款变化。