☰
聊天显示“已送达”,钱到账了吗?IM 转账状态机避坑笔记
2026/10/4 1:24:38 网站建设 项目流程

对方在聊天里回了一句“转过去了”,消息显示已送达。你去看余额,没变。

做过 IM 内转账的工程师,多半处理过这种工单:聊天里是一个状态,账本里是另一个。这种错位可以叫它“幽灵状态”。

核心结论:IM 转账中,消息的 DELIVERED 只代表内容送达设备,转账是否完成以账本的 SETTLED 为准。两者应建成两套独立状态机,通过 transfer_id 关联,由账本事件驱动聊天卡片更新。

MPChat 的转账入口在会话里,资金动作由 MPChat Pay 处理。把消息的 DELIVERED 渲染成“对方已收款”,就是拿通信层的信号回答资金层的问题。

说明:下文为通用架构模型,用于技术讨论,不代表 MPChat 现网接口、字段或内部实现。

消息状态和转账状态有什么区别?

消息状态: CREATED → SENT → DELIVERED → READ 转账状态: CREATED → AUTH_PENDING → PROCESSING → SETTLED └──────→ FAILED
消息状态机转账状态机
回答的问题内容送到了没有钱记到账上了没有
终态READSETTLED / FAILED
依据消息服务账本

对方在聊天里打出“我已转账”,也只是一条消息。

数据模型怎么拆?

表关键字段作用
chat_messagemessage_id, conversation_id, msg_status, transfer_id(可空)记录消息投递
transfertransfer_id, sender_account, recipient_account, amount, status记录转账进度
ledger_entryentry_id, transfer_id, account_id, direction, amount记录借贷分录

message_id 可以关联 transfer_id,但不能代替它。聊天窗口负责展示,账本是资金状态的 Source of Truth。

为什么不能先推“成功”卡片再记账?

先推卡片、再异步写账本,账本一旦写入失败或回滚,收款方看到了成功提示,交易记录里却没有这笔钱。

约束很简单:转账满足账本确认条件后,才生成“已完成”事件;聊天卡片只消费这个事件。

结算和通知怎么分离?

function settleTransfer(transferId): begin transaction transfer = lockTransfer(transferId) if transfer.status == SETTLED: return assert transfer.status == PROCESSING writeDebitEntry(transferId, transfer.senderAccount, transfer.amount) writeCreditEntry(transferId, transfer.recipientAccount, transfer.amount) updateTransferStatus(transferId, SETTLED) writeOutboxEvent(eventKey = "transfer.settled:" + transferId, transferId) commit function onTransferSettled(event): if alreadyConsumed(event.eventKey): return updateChatPaymentCard(event.transferId, displayStatus = "completed") markConsumed(event.eventKey)

这里有两处幂等:

  • 账本侧:锁单后检查状态,结算重试不会重复记账。

  • 聊天侧:按 eventKey 去重,事件重投不会生成两张“已完成”卡片。

记账和写 Outbox 事件在同一事务里提交。通知失败只重试通知,不重做资金转移。

“对方说转了,我没收到”怎么排查?

按 transfer_id 查三层:

  1. 指令层:转账是否创建,收款账户和金额是否正确。

  2. 账本层:是否到达最终状态,借贷记录是否完整。

  3. 展示层:收款侧能否查到记录,聊天卡片和交易详情是否一致。

现象问题出在哪先查什么
账已记完,聊天仍显示“处理中”展示投影没跟上修展示投影
聊天显示“已完成”,账本缺记录状态发布早于记账发布顺序、事务边界、补偿任务

状态不同步的单子,别靠重新发起一笔转账来补。再发一笔,账上多了一次真实转移,原来那条记录还在。

FAQ

消息显示 DELIVERED,能说明对方收到钱了吗?不能。DELIVERED 只说明消息到达接收端设备,资金状态要看转账记录是否为 SETTLED。

聊天里的转账卡片该由谁来更新?由结算完成后发出的事件驱动,聊天卡片只负责展示。

通知发送失败怎么办?重试通知即可。已结算的转账不需要重新转一次。


转账入口离对话越近,越需要在系统里把消息证据和资金证据分开。用户在意的是这笔交易查得到、对得上,聊天里看到的和账单写的是同一个结论。

你们团队的支付卡片,是订阅账本事件,还是由业务服务直接推送?评论区聊聊。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询