0. 前置条件(必须)

项目说明
服务商资质平台需以服务商身份接入微信支付并开通【分账】权限(微信商户平台-产品中心-分账)。若暂未申请服务商, 也可先用平台自己的直连商户号开通分账(分账给其他商户/个人)。
商户入驻入驻商户需在微信侧成为子商户(特约商户, 由平台服务商发展), 每个商户对应一个子商户号; 或在微信分账接收方中添加商户号/个人openid。
分账标识支付下单时必须传 profit_sharing=true。若一笔订单下单时未带该标识, 微信会拒绝该订单的分账请求(报错如 UNSUPPORTED/该订单不支持分账)。本插件方案一的下单代码已内置该标识。
单笔分账上限微信默认单笔订单对外分账总金额不超过订单金额的 30%, 可申请调高。如需"商户拿80%、平台留20%", 请先在商户平台申请把分账比例上限调到 80% 以上, 再把本插件【分账设置-单笔最大分账比例】同步设置。
API v3 配置商户号(mchid)、AppID、APIv3密钥(32位)、证书序列号、apiclient_key.pem 私钥 — 五样齐全后插件才能调用微信接口。填好保存后可直接点配置页的【一键拉取并保存平台证书】按钮验证配置并自动获取证书。平台证书/平台公钥(pem)用于回调 SHA256withRSA 验签(防伪造回调)与个人openid接收方姓名的加密上传。

1. 方案一: 服务商支付模式(支付流程改造 + 支付即分账)

环节做法
整体链路用户付款 -> 平台(服务商)收单(或子商户收单, 资金进平台/子商户账户) -> 支付回调通知本插件 -> 订单自动标记为可分账 -> 自动/手动调用【请求分账】 -> 按 商户80%/平台20%(示例, 比例可配) 拆账。
下单带分账标识本插件已提供 v3 服务商下单封装(JSAPI/NATIVE/H5), 下单参数含 profit_sharing=true。落地时把站点支付发起脚本由"直连 v2 统一下单"替换为 v3 服务商下单(替换文件与步骤见插件目录 patch/fangan1/)。
回调支付成功后微信把结果回调到 tom_huaidanfenzhang/api/notify.php(可在【分账设置】修改), 该回调验签(可选)+解密后会自动把订单写入【可分账订单】队列; 若开启了"标记后自动分账"且该商户已配置接收方, 会立即分账。
分账结果回写每次发起分账都会随请求携带 分账结果异步回调地址(api/share_notify.php); 微信分账完成/失败后异步通知本插件, 订单自动更新为"已分账成功/失败"(无需人工轮询, 后台也有"查询全部结果"可兜底)。
订单退款-分账回退订单发生退款且货款已分给商户时: 先在【可分账订单】对该"已分账成功"且接收方为商户号(MERCHANT_ID)的订单点【分账回退】(可输入金额, 默认全额), 微信把该笔货款从商户账户退回平台/服务商账户, 资金回到平台后再给买家退款。受理后订单标记"已分账回退", 可点【查询回退】核实微信处理结果。个人openid接收方已分金额不支持API回退, 需联系微信支付处理。
回退闭环保障: 微信分账回退无异步通知, 计划任务会每10分钟自动向微信核实回退单最终结果 —— 回退成功自动累计已回退到账金额(支持对剩余部分点【再次回退】分批回退); 回退失败或未被受理自动把订单重置回"已分账成功", 直接重新点【分账回退】即可重试, 不会卡死在"已回退"状态。
定时兜底(计划任务)插件自带计划任务(默认每10分钟, 可到后台 工具-计划任务 调整): 当开启"标记后自动分账"时自动补跑待分账订单; 同时自动查询并回写"处理中/失败"订单的最终结果 —— 即使分账结果异步回调丢失也能保证最终一致。
子商户号维护每个入驻商户在【分账商户】里维护子商户号/接收方账号; 该账号同时会通过【添加分账接收方】接口同步给微信。
适用于新接入/可改造收单流程的场景, 合规性最好, 微信官方推荐。

2. 方案二: 回调标记 + 通用分账模块(不改收单方式)

环节做法
整体链路沿用现有 tom_pay 收单 -> 在支付回调成功处调用本插件钩子(把每笔商城订单标记为可分账) -> 后台/自动调用微信【请求分账】。
回调改动(核心)找到 source/plugin/tom_pay/wxpayNotify.php(以及微信小程序/公众号支付对应回调), 在支付成功、更新支付单状态后插入一行: include_once DISCUZ_ROOT.'./source/plugin/tom_huaidanfenzhang/paynotify_hook.php';。钩子会自动把该笔订单写入分账队列(如多商户合并支付会自动跳过)。
完整示例见 patch/fangan2/wxpayNotify.addhook.txt。
历史订单开通前已支付的订单, 可用【可分账订单】页"同步商城已支付订单"一次性导入(注意: 只有微信支付的订单才可分账)。
分账接口分账统一走本插件封装的微信 v3 分账接口(添加/删除接收方、请求分账、查询分账、剩余可分成查询)。
适用于不想大改收单流程、先跑通分账的场景。

3. 金额计算模型(重要)

项计算
实付金额用户实际支付(微信支付单 amount, 与商城订单一致)。
微信手续费实付金额 × 手续费率(默认 0.6%, 可在设置页/商户级覆盖)。手续费由微信在资金结算时扣走。
可分账基数实付金额 - 微信手续费(即先把手续费扣掉再算分成)。
商户分得基数 × 商户分账比例(默认80%, 可商户级覆盖)。该金额通过微信分账接口划给商户接收方。
平台留成基数 - 商户分得, 保留在平台账户, 无需划转。
上限校验发起分账前校验"商户分得 ≤ 实付金额 × 最大分账比例", 超限订单拦截并提示(需在微信申请提高比例)。
0.01元规则商户分得不足 0.01 元或实付低于起分金额的订单不发起分账(自动跳过)。
重复分账防护发起分账前插件会先向微信查询该订单"剩余可分金额": 仅当微信正常返回且剩余不足以分本次金额时拦截(该情形通常是此前已分账过、本地状态未同步, 避免重复分账造成资损)。列表每行也可点【剩余可分】单笔核实后再操作。
分账动账方式微信商户平台「产品中心-分账」有"冻结资金"与"自动解冻"两种动账方式: 冻结资金订单分账后是否把剩余资金解冻给原收款方, 由【分账设置-冻结资金分账后解冻剩余】控制(选"解冻"); 自动解冻订单请选"不解冻"(此时插件不传 unfreeze_unsplit 参数, 避免微信报参数错误)。

4. 与站内余额/提现的衔接提醒

点微商城(tom_tcmall)原逻辑是"用户支付 -> 平台把货款记入商户站内余额(shop_money) -> 商户站内申请提现(tom_tcshop_money_tixian) -> 平台线下打款"。
使用微信分账后, 商户货款已由微信直接划入商户(子商户号/个人零钱), 平台不再需要从自己的微信账户把货款转给商户。
因此建议:
1) 对已走分账的订单, 关闭/停用商城侧该订单的"佣金结算/余额入账"动作, 避免商户余额被重复入账(可在商城后台将该部分订单不结算, 或按分账单号对账);
2) 商户站内余额仅保留"未走分账订单"的货款与充值等用途;
3) 以本插件的【分账记录】+ 微信商户平台账单为准做财务对账。
若需"分账成功后再给商户站内余额记一笔到账流水(仅记账、不重复提现)", 可后续在本插件里扩展一个回调把分账成功订单写 tom_tcshop_money_log(type=... 仅记账), 注意别与商城原结算重复。

5. 常见错误排查

微信/插件返回原因与处理
该订单不支持分账 / UNSUPPORTED下单时未传 profit_sharing=true。方案一(服务商下单)的订单已自动携带分账标识可直接分账; 方案二沿用直连收单的老订单在支付完成时未声明分账, 微信侧无法对其请求分账(无法事后补标识), 这类历史订单需要联系微信商户平台确认是否可操作, 或走平台手工转账结算。
PARAM_ERROR / 分账金额超限分账总金额超过订单金额×最大分账比例。降低比例或在微信商户平台申请调高上限后, 再对"失败/关闭"订单点【重新待分账】。
接收方未添加 / RECEIVER_NOT_ADDED先到【分账商户】把该接收方"同步到微信"(或到微信商户平台-分账-接收方添加), 再发起分账。
个人openid接收方姓名向个人微信零钱分账需要其真实姓名, 微信要求姓名必须用"微信支付平台证书/平台公钥"做 RSA-OAEP 加密后上传。请在【分账设置】补填平台证书/公钥后, 到【分账商户】对该接收方重新"同步到微信"(以店铺名/备注作为姓名加密); 未配置证书时可先在微信商户平台-分账-接收方中手动添加该 openid 再同步。
商户号/证书签名错误(SIGN_ERROR / 证书序列号不对)核对【分账设置】里 mchid、证书序列号、私钥是否配套(三者必须来自同一商户号的同一套API证书)。
NOT_FOUND / 订单查询不到该订单不是 v3 可查询渠道, 或商户号/子商户号不对。方案二老订单可到微信商户平台查到微信支付单号后在订单备注补录(本插件会优先使用已填的微信单号)。
分账单 NOT_FOUND(未受理)属正常可恢复场景: 请求分账超时导致本地保留单号但微信实际未受理时, 点【查询结果】后插件会自动把订单重置为"待分账", 开启自动分账时由计划任务自动重试, 无需人工干预。
分账请求超时/网络异常(微信可能已受理?)请求分账接口偶发超时时, 插件会保留本次生成的分账单号并把订单置为"分账失败"。请点【查询结果】(或等待计划任务自动查询)向微信核实: 单号真实存在会自动回写"已分账成功/处理中"; 返回订单不存在(未受理)则自动重置为"待分账"重新分账 —— 不会漏分, 也不会重复分(重复分账前"剩余可分不足"检查仍会兜底)。
剩余可分不足(自动拦截)分账前插件会查询微信侧"剩余可分金额", 若不足本次应分金额则拦截并把订单置为"已关闭/跳过"(防止对已分账订单重复分账造成资损, 也避免自动任务反复重试)。请先在【分账记录】核实该订单是否已分账; 若确认未分账, 对该订单点【重新待分账】即可重试。
回调解密失败【分账设置】的 APIv3 密钥与微信商户平台设置不一致。
平台证书到期/验签失败微信支付平台证书约 5 年轮换、平台公钥约每年换发(公钥模式下公钥ID变化)。回到【分账设置】点击【一键拉取并保存平台证书】即可用已保存的 API 凭证重新拉取最新证书并自动保存, 无需手工更换。
OPENID 与 AppID 不匹配接收方为个人 openid 时, 该 openid 必须是在【分账设置-收款AppID】同一公众号/小程序下获取的。

6. 插件文件结构

source/plugin/tom_huaidanfenzhang/
├── discuz_plugin_tom_huaidanfenzhang_SC_UTF8.xml   安装包(XML, 后台导入)
├── install.php / uninstall.php                      建表/删表
├── class/function.core.php                          业务核心(配置/算钱/导入/分账/接收方)
├── class/wechatv3.class.php                         微信支付 APIv3 客户端(签名/下单/分账)
├── table/                                           数据表操作类
├── admin.inc.php + admin/*                          后台管理
├── api/_bootstrap.inc.php                           独立回调公共引导(加载Discuz+验签工具)
├── api/notify.php                                   方案一: v3 支付结果回调
├── api/share_notify.php                             微信分账结果异步回调(自动回写状态)
├── paynotify_hook.php                               方案二: tom_pay 回调钩子(被引入)
├── tom_huaidanfenzhang.inc.php                      前台入口(收银台JSON接口, 可选)
└── patch/                                           两套方案的改造补丁与说明

7. 同城到家(tom_tcdaojia)接入分账(服务商货款实时分账)

项说明
业务范围只纳入"真实服务交易"(到家订单 type=1 上门服务 / 2 拉货搬家 / 3 帮忙跑腿 / 4 陪诊代办等 且 servicer_id>0)的微信支付订单; 置顶/入驻/等级/保证金等平台收入单(type=5+)不会进入分账队列。【可分账订单】页切换到"只看到家"可核对。
货款归属到家订单的资金归属方 = 接单服务商(即到家后台"服务商管理"记录), 等价于商城的"店铺"。到【分账商户/接收方】切到"到家服务商(tom_tcdaojia)"页签, 为服务商新增接收方并"同步到微信"即可开始分账。
分账时机支付成功即分(与商城一致)。两条入队通道: ① 若已按方案二在 tom_pay 支付回调引入 paynotify_hook.php, 到家支付回调会即时把订单写入队列并自动分账; ② 插件计划任务(每10分钟)与【可分账订单】页"同步已支付订单(商城+到家)"会把遗漏的已支付到家订单补导入 —— 未配置接收方时保持"待分账", 配好后下一轮自动补分。
比例口径服务商分得比例建议按"100-平台抽佣比例"在该服务商的接收方上单独填(例如平台抽佣15%则填85, 字段说明见接收方编辑页)。金额模型与商城一致: 分账基数=实付-微信手续费, 服务商所得=基数×比例, 平台留成=基数-服务商所得。
退款安全(自动回退)到家后台对订单执行原路退款前会自动检测该单是否已被微信分账: 已分账且接收方为商户号(MERCHANT_ID) → 自动调用微信"分账回退"把已分货款退回平台后放行退款; 已分账但接收方为个人openid(不支持API回退) → 拦截并提示先在【可分账订单】人工处理; 分账处理中/失败的订单也会先拦截, 处理完队列后重试退款即可。该联动已内置, 无需再改动到家插件任何退款/结算逻辑。
与站内钱包结算衔接分账货款由微信直接划入服务商账户/零钱; 到家插件原有的钱包余额/结算/提现是否同步记账由站点自行决定(推荐"只记账、不重复打款", 财务以本插件【分账记录】+微信商户平台账单为准对账)。本插件不写到家侧任何资金流水。
商城(tom_tcmall)退款联动同一套退款门卫也已接入商城后台"退款管理"(admin/refund.php): 执行退款前若该单货款已被微信分账给店铺, 会自动先回退分账(MERCHANT_ID)或拦截提示人工(PERSONAL_OPENID), 行为与到家一致, 防止商城场景重复打款。
老库升级方式覆盖上传新版后, 首次访问本插件任意后台页/计划任务/支付回调会自动补齐 biz 表结构与索引; 也提供手工脚本 source/plugin/tom_huaidanfenzhang/patch/upgrade_1.3_biz.sql(把表前缀换成站点实际前缀后执行)。


点微同城扩展插件坏蛋分账 1.0.0 - 图1点微同城扩展插件坏蛋分账 1.0.0 - 图2点微同城扩展插件坏蛋分账 1.0.0 - 图3点微同城扩展插件坏蛋分账 1.0.0 - 图4点微同城扩展插件坏蛋分账 1.0.0 - 图5