Files
uniprop-manual/prop-acc/一次性收费/场景-异常-微信支付回调延迟.md
2026-05-25 13:54:35 +08:00

6.8 KiB

title, tags, audience, status, last_reviewed, code_version
title tags audience status last_reviewed code_version
场景 - 异常 - 微信支付回调延迟
prop-acc
一次性收费
业务场景
异常故障
业户
业务人员
stable 2026-05-25 2026-05-22

场景:微信支付回调延迟

业户在微信里付款成功,但系统订单还停在 Pending 状态。等几分钟才更新,业户和业务人员都可能误以为出问题了。

典型情境

[!example] 真实情境 周日晚上李太太在小程序下单充电桩电费 ¥200,微信支付成功 —— 微信弹窗"已付款"、扣款记录里也看到了。

但她切回小程序"我的订单",订单状态还是"待付款"。等了 1 分钟没变化,她以为没成功,又点了一次"立即支付"

微信弹"您已支付过该订单,无需重复支付",这才放心。3 分钟后小程序终于刷新为"已完成"。

为什么会延迟?

[!info] 微信回调链路 业户支付 → 微信服务器 → 物业服务器 webhook → 系统更新订单状态。

任何一步网络慢、服务器忙、回调队列堆积,都可能让"系统知道你付款了"晚几秒到几分钟。99% 的回调在 10 秒内到达,1% 可能要 30 秒~5 分钟,极少数(0.01%)完全丢失

业户视角

您可能看到的几种状态

时间 微信侧 小程序订单状态 您的感觉
0-3 秒 支付完成 仍然显示"待付款" 正常,刷新一下
3-30 秒 支付完成 已变"已完成" 完美
30 秒-5 分钟 支付完成 仍然"待付款" 怀疑没成功
> 5 分钟 支付完成 一直"待付款" 真的有问题

您应该怎么办

[!warning] 不要重复支付! 微信有重复支付防护(同一订单只能付一次),但万一系统出问题,重复支付的钱可能很难退

正确步骤:

  1. 看微信"账单 / 钱包"里是否有这笔扣款记录

    • 有 → 钱已经付了,不要再付
    • 无 → 钱没出去,可以放心重新支付
  2. 钱已付但小程序不更新:

    • 等 5 分钟
    • 下拉刷新小程序订单页
    • 还不更新 → 联系物业前台
  3. 联系物业前台:

    • 告诉他们订单号 + 微信扣款截图
    • 物业能在 Filament 后台手动核实并标记完成

别担心,钱不会丢

[!success] 双向保障

  • 微信侧:确认扣款,有微信账单为证
  • 物业侧:即使回调彻底丢失,微信商户后台能看到这笔交易,物业人工核对后手动入账

业务人员视角

业户来问"我付了但显示没付"怎么处理?

1. 让业户出示微信扣款记录(截图 / 商家订单号)

2. Filament 后台搜业户订单号(CO-xxx)
   ├── 状态显示 Pending  → 回调真的没到
   └── 状态已是 Completed → 回调刚到,提示业户刷新页面

3. 状态 Pending 且业户确认已付:
   ├── 在微信商户后台查这笔交易
   │   └── 找到 transaction_id (微信侧订单号)
   ├── 与系统 CO-xxx 的 order_no 核对
   └── 如确认是同一笔:手动标记完成

手动标记完成

[!warning] 当前 UI 没有直接的"标记完成"按钮 当前只能通过 MarkAdHocEventPaidAction 业务方法调用。临时方案:

  • 走 Tinker:app(MarkAdHocEventPaidAction::class)->handle($event, [...])
  • 或者在 Filament 后台为业户重新建一笔(走 A 流即收即付),把原 Pending 单走作废

长期方案:给 ViewAdHocEvent 加一个"手动标记已付款"Action,挂 TODO。

后台技术细节

sequenceDiagram
    participant 业户
    participant 微信
    participant 微信服务器
    participant 物业 webhook
    participant 系统
    participant 业务人员

    业户->>微信: 付款 ¥200
    微信->>业户: 弹窗"已付款"
    微信->>微信服务器: 入账

    Note over 微信服务器: 网络/服务器繁忙

    微信服务器-->>物业 webhook: ⏳ 延迟 30s ~ 5min ⏳

    Note over 业户: 业户看小程序仍显示待付款

    业户->>业务人员: 询问"我付了为什么还是待付款"
    业务人员->>微信商户后台: 查 transaction_id
    业务人员->>系统: 手动 MarkAsPaid
    系统->>系统: CollectionOrder + AdHocEvent → Completed
    系统-->>业户: 推通知"已付款"

    Note over 微信服务器: 几分钟后,延迟回调终于到了
    微信服务器->>物业 webhook: 现在才到
    物业 webhook->>系统: 检查订单已 Completed → 跳过 (幂等)

几个关键设计决策

1. 回调幂等

[!info] 系统设计 webhook 处理时先查订单状态:

  • 若是 Pending → 走 MarkAdHocEventPaidAction 完成流程
  • 若已是 Completed → 直接返回成功,不做任何事
  • 若是 Voided → 退回退款流程(钱原路退回业户)

这样不论回调到达多少次,系统都保持一致状态。

2. 业户重复支付的处理

如果业户没看到状态更新而重复点了"立即支付":

  • 微信端会拦截(同一订单只能付一次)
  • 系统侧不会收到第二笔扣款

但万一某些渠道允许重复支付(罕见):

  • 系统会收到两笔 transaction_id 不同的回调
  • 第一笔正常处理 → 翻 Completed
  • 第二笔到达时 → 系统发现订单已 Completed,直接对第二笔发起原路退款

3. 超时 vs 回调延迟的竞争

[!warning] 一个微妙的边界情况 业户付款的瞬间正好是订单 expires_at,超时 job 同时跑:

  • 超时 job 拿到锁先把订单 → Voided
  • 微信回调晚 1 秒到 → 看到 Voided,触发原路退款(钱退回业户)

业户此时看到"扣款 + 几小时后退款"。这是正常容错行为,不是 bug。

常见问题

[!question] 业户已经离开了,但延迟回调到了,会怎样? 系统正常翻 Completed,生成 Receipt。业户下次打开小程序就能看到状态更新和收据。无需联系物业。

[!question] 5 分钟还没到回调,但业户急着要 IC 卡怎么办? 走业务人员的"手动标记完成"路径(见上)。信任微信侧扣款记录优先

[!question] 同一笔订单回调收到 2 次怎么办? 幂等设计 → 第二次直接返回成功。详见上述设计决策 1。

[!question] 物业怎么知道是不是真的"回调丢了"? 监控 + 报警:

  • 每天对账微信商户后台 vs 系统订单总数
  • 差额 > 阈值(比如 5 笔)发警报
  • 人工补单(查商户后台 → 手动标记)

相关概念

异常分支

  • 业户付了款但物业拒绝处理 → 走 场景-已收款作废 退款给业户
  • 回调收到但金额对不上 → 数据问题,技术介入