文件
xionggeshop/addons/shopro/tests/split_commission_verify.sql
2026-09-29 11:44:50 +08:00

369 行
15 KiB
SQL

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

-- =============================================================================
-- 分账开关 & 已分账订单佣金去向 · 线上只读核验脚本
-- =============================================================================
-- 用途:
-- 1) 判断当前是否走支付通道分账(微信分账 / 汇付延时分账)
-- 2) 核对已分账订单:网关分账明细 vs 业务佣金/钱包入账是否一致、有无重复发放风险
--
-- 用法:
-- mysql -u用户名 -p 数据库名 < split_commission_verify.sql
-- 或在客户端中分段执行(建议先跑「一、全局配置」)
--
-- 表前缀默认 fa_,若不同请全局替换 fa_
-- 本脚本仅 SELECT,不修改数据
-- =============================================================================
SET NAMES utf8mb4;
-- =============================================================================
-- 一、全局配置:是否开启分账、走哪条通道
-- =============================================================================
SELECT '=== 1. 分账总配置 shopro_split_config ===' AS section;
SELECT name, value, description
FROM fa_shopro_split_config
WHERE name IN (
'split_enable', 'split_mode', 'split_provider', 'split_timing',
'split_amount_source', 'split_max_rate', 'delay_acct_enable',
'platform_receiver_account', 'platform_receiver_name',
'platform_huifu_id', 'platform_acct_id'
)
ORDER BY name;
SELECT '=== 2. 汇付支付配置 shopro_huifu_config(关键项)===' AS section;
SELECT name, value
FROM fa_shopro_huifu_config
WHERE name IN (
'status', 'env', 'huifu_id', 'upper_huifu_id',
'miniprogram_channel', 'delay_acct_enable', 'onboard_required'
)
ORDER BY name;
SELECT '=== 3. 分销/区域代理结算事件(与分账时机对比)===' AS section;
SELECT 'commission' AS cfg, name, value
FROM fa_shopro_commission_config
WHERE name IN ('commission_event', 'level', 'self_buy')
UNION ALL
SELECT 'regional_agent', name, value
FROM fa_shopro_regional_agent_config
WHERE name IN ('commission_event', 'status');
-- 人工解读(见下方说明):
-- split_enable=1 且 split_mode 非 wallet → 会尝试支付通道分账
-- miniprogram_channel=huifu + split 开启 + pay_type=huifu_wechat → 汇付延时分账
-- split_timing 默认 payed;commission_event 默认 confirm → 可能出现「先分账、后入账钱包」
SELECT '=== 4. 配置结论(自动推断,供对照)===' AS section;
SELECT
sc_enable.value AS split_enable,
sc_mode.value AS split_mode,
sc_provider.value AS split_provider,
sc_timing.value AS split_timing,
sc_delay.value AS split_delay_acct_enable,
hf_channel.value AS miniprogram_channel,
hf_status.value AS huifu_plugin_status,
CASE
WHEN IFNULL(sc_enable.value, '0') <> '1' THEN '未走支付分账(总开关关闭)'
WHEN sc_mode.value = 'wallet' THEN '未走支付分账(仅钱包模式)'
WHEN hf_channel.value = 'huifu' AND IFNULL(hf_status.value, '0') = '1'
AND sc_mode.value IN ('huifu', 'both')
THEN '走汇付延时分账(huifu_wechat 订单)'
WHEN hf_channel.value = 'huifu' AND IFNULL(hf_status.value, '0') = '1'
AND IFNULL(sc_provider.value, 'auto') IN ('auto', 'huifu')
THEN '走汇付延时分账(auto/huifu 提供方 + 小程序汇付通道)'
WHEN sc_mode.value IN ('wechat', 'both') THEN '走微信分账(pay_type=wechat 订单)'
ELSE '分账已开但通道需结合 pay_type 人工确认'
END AS inferred_split_path
FROM (SELECT value FROM fa_shopro_split_config WHERE name = 'split_enable' LIMIT 1) sc_enable
CROSS JOIN (SELECT IFNULL(value, 'wechat') AS value FROM fa_shopro_split_config WHERE name = 'split_mode' LIMIT 1) sc_mode
CROSS JOIN (SELECT IFNULL(value, 'auto') AS value FROM fa_shopro_split_config WHERE name = 'split_provider' LIMIT 1) sc_provider
CROSS JOIN (SELECT IFNULL(value, 'payed') AS value FROM fa_shopro_split_config WHERE name = 'split_timing' LIMIT 1) sc_timing
CROSS JOIN (SELECT IFNULL(value, '0') AS value FROM fa_shopro_split_config WHERE name = 'delay_acct_enable' LIMIT 1) sc_delay
CROSS JOIN (SELECT IFNULL(value, 'yansongda') AS value FROM fa_shopro_huifu_config WHERE name = 'miniprogram_channel' LIMIT 1) hf_channel
CROSS JOIN (SELECT IFNULL(value, '0') AS value FROM fa_shopro_huifu_config WHERE name = 'status' LIMIT 1) hf_status;
-- =============================================================================
-- 二、分账订单统计(近 90 天,可改 INTERVAL)
-- =============================================================================
SELECT '=== 5. 分账订单按状态/通道汇总(近90天)===' AS section;
SELECT
so.channel,
so.status,
CASE so.status
WHEN 0 THEN '待分账'
WHEN 1 THEN '分账中'
WHEN 2 THEN '成功'
WHEN 3 THEN '部分成功'
WHEN 4 THEN '失败'
ELSE CONCAT('未知(', so.status, ')')
END AS status_label,
COUNT(*) AS cnt,
ROUND(SUM(so.split_amount), 2) AS sum_split_amount,
ROUND(SUM(so.total_amount), 2) AS sum_order_pay
FROM fa_shopro_split_order so
INNER JOIN fa_shopro_order o ON o.id = so.order_id
WHERE o.paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
GROUP BY so.channel, so.status
ORDER BY so.channel, so.status;
SELECT '=== 6. 已支付订单 pay_type 分布(近90天)===' AS section;
SELECT
pay_type,
COUNT(*) AS order_cnt,
ROUND(SUM(pay_fee), 2) AS sum_pay_fee
FROM fa_shopro_order
WHERE status >= 1
AND paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
GROUP BY pay_type;
-- =============================================================================
-- 三、已分账订单:佣金去了哪里(网关 vs 钱包)
-- =============================================================================
-- 网关分账:fa_shopro_split_order_receiver + receiver 表(汇付 huifu_id / 微信 openid)
-- 业务佣金:fa_shopro_commission_reward / fa_shopro_regional_agent_reward
-- 钱包入账:fa_shopro_user_wallet_log type=commission_income / regional_agent_income
-- 代码说明:shouldSkipWallet() 尚未接入 Reward,分账开启时仍可能同时入账钱包(需重点核对)
SELECT '=== 7. 分账成功订单明细(最近 30 笔)===' AS section;
SELECT
so.id AS split_order_id,
so.order_id,
so.order_sn,
so.channel,
so.status,
so.total_amount AS order_pay_fee,
so.split_amount AS split_to_receivers,
ROUND(so.total_amount - so.split_amount, 2) AS implied_platform_remain,
FROM_UNIXTIME(so.createtime) AS split_at,
so.confirm_hf_seq_id,
o.pay_type
FROM fa_shopro_split_order so
INNER JOIN fa_shopro_order o ON o.id = so.order_id
WHERE so.status IN (2, 3)
ORDER BY so.id DESC
LIMIT 30;
SELECT '=== 8. 上述成功分账的接收方明细(最近 30 单)===' AS section;
SELECT
so.order_sn,
sor.role_type,
sor.amount,
sor.description,
sor.status AS line_status,
sr.receiver_account,
sr.receiver_type,
sr.channel AS receiver_channel,
sr.receiver_name
FROM fa_shopro_split_order so
INNER JOIN fa_shopro_split_order_receiver sor ON sor.split_order_id = so.id
LEFT JOIN fa_shopro_split_receiver sr ON sr.id = sor.receiver_id
WHERE so.status IN (2, 3)
AND so.id IN (
SELECT id FROM (
SELECT so2.id
FROM fa_shopro_split_order so2
WHERE so2.status IN (2, 3)
ORDER BY so2.id DESC
LIMIT 30
) t
)
ORDER BY so.order_sn DESC, sor.id;
SELECT '=== 9. 分账成功订单 · 业务佣金与钱包对照 ===' AS section;
SELECT
so.order_sn,
so.channel,
so.split_amount AS gateway_split_sum,
IFNULL(cr.dist_commission, 0) AS dist_reward_sum,
IFNULL(cr.dist_accounted, 0) AS dist_wallet_settled_cnt,
IFNULL(rr.reg_commission, 0) AS regional_reward_sum,
IFNULL(rr.reg_accounted, 0) AS regional_wallet_settled_cnt,
IFNULL(wl.wallet_commission, 0) AS wallet_commission_income,
IFNULL(wl.wallet_regional, 0) AS wallet_regional_income,
CASE
WHEN IFNULL(wl.wallet_commission, 0) + IFNULL(wl.wallet_regional, 0) > 0
AND so.split_amount > 0
THEN '⚠ 网关已分账且钱包也有佣金流水(可能双重发放,需业务确认)'
WHEN so.split_amount > 0
AND IFNULL(wl.wallet_commission, 0) + IFNULL(wl.wallet_regional, 0) = 0
AND IFNULL(cr.dist_accounted, 0) + IFNULL(rr.reg_accounted, 0) = 0
THEN '✓ 佣金主要在支付通道(未入钱包或尚未结算)'
WHEN so.split_amount = 0 THEN '分账金额为0(检查接收方/规则)'
ELSE '请人工核对'
END AS check_hint
FROM fa_shopro_split_order so
INNER JOIN fa_shopro_order o ON o.id = so.order_id
LEFT JOIN (
SELECT order_id,
SUM(commission) AS dist_commission,
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS dist_accounted
FROM fa_shopro_commission_reward
WHERE status >= 0
GROUP BY order_id
) cr ON cr.order_id = so.order_id
LEFT JOIN (
SELECT order_id,
SUM(commission) AS reg_commission,
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS reg_accounted
FROM fa_shopro_regional_agent_reward
WHERE status >= 0
GROUP BY order_id
) rr ON rr.order_id = so.order_id
LEFT JOIN (
SELECT order_id,
SUM(wallet_commission) AS wallet_commission,
SUM(wallet_regional) AS wallet_regional
FROM (
SELECT cr.order_id,
SUM(CASE WHEN wl.type = 'commission_income' THEN wl.wallet ELSE 0 END) AS wallet_commission,
0 AS wallet_regional
FROM fa_shopro_commission_reward cr
INNER JOIN fa_shopro_user_wallet_log wl
ON wl.item_id = cr.id AND wl.type = 'commission_income' AND wl.wallet_type = 'money'
WHERE cr.status = 1
GROUP BY cr.order_id
UNION ALL
SELECT rr.order_id, 0,
SUM(CASE WHEN wl.type = 'regional_agent_income' THEN wl.wallet ELSE 0 END)
FROM fa_shopro_regional_agent_reward rr
INNER JOIN fa_shopro_user_wallet_log wl
ON wl.item_id = rr.id AND wl.type = 'regional_agent_income' AND wl.wallet_type = 'money'
WHERE rr.status = 1
GROUP BY rr.order_id
) wsum
GROUP BY order_id
) wl ON wl.order_id = so.order_id
WHERE so.status IN (2, 3)
ORDER BY so.id DESC
LIMIT 50;
-- =============================================================================
-- 四、异常检测(应排查项)
-- =============================================================================
SELECT '=== 10. 有佣金记录但分账失败/缺失(汇付单,近90天)===' AS section;
SELECT
o.id AS order_id,
o.order_sn,
o.pay_type,
o.pay_fee,
IFNULL(so.status, -99) AS split_status,
LEFT(so.wx_result, 120) AS split_fail_msg,
IFNULL(cr.reward_cnt, 0) + IFNULL(rr.reward_cnt, 0) AS reward_cnt,
IFNULL(cr.reward_sum, 0) + IFNULL(rr.reward_sum, 0) AS reward_sum
FROM fa_shopro_order o
LEFT JOIN (
SELECT order_id, COUNT(*) AS reward_cnt, SUM(commission) AS reward_sum
FROM fa_shopro_commission_reward WHERE status >= 0 GROUP BY order_id
) cr ON cr.order_id = o.id
LEFT JOIN (
SELECT order_id, COUNT(*) AS reward_cnt, SUM(commission) AS reward_sum
FROM fa_shopro_regional_agent_reward WHERE status >= 0 GROUP BY order_id
) rr ON rr.order_id = o.id
LEFT JOIN fa_shopro_split_order so ON so.order_id = o.id AND so.channel = 'huifu'
WHERE o.pay_type = 'huifu_wechat'
AND o.paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
AND (IFNULL(cr.reward_cnt, 0) + IFNULL(rr.reward_cnt, 0)) > 0
AND (so.id IS NULL OR so.status IN (0, 4))
ORDER BY o.id DESC
LIMIT 50;
SELECT '=== 11. 分账失败记录(status=4,最近 20 条)===' AS section;
SELECT
so.order_id,
so.order_sn,
so.channel,
so.split_amount,
so.retry_count,
FROM_UNIXTIME(so.next_retry_time) AS next_retry,
LEFT(so.wx_result, 200) AS fail_reason
FROM fa_shopro_split_order so
WHERE so.status = 4
ORDER BY so.id DESC
LIMIT 20;
SELECT '=== 12. 有推广/区域佣金但缺少汇付接收方(导致无法分账)===' AS section;
SELECT DISTINCT
r.order_id,
o.order_sn,
'commission' AS reward_source,
a.user_id AS beneficiary_user_id,
u.mobile,
ho.huifu_id AS onboard_huifu_id,
sr.id AS split_receiver_id
FROM fa_shopro_commission_reward r
INNER JOIN fa_shopro_order o ON o.id = r.order_id
INNER JOIN fa_shopro_commission_agent a ON a.id = r.agent_id
INNER JOIN fa_user u ON u.id = a.user_id
LEFT JOIN fa_shopro_huifu_onboard ho ON ho.user_id = a.user_id AND ho.status = 'approved'
LEFT JOIN fa_shopro_split_receiver sr ON sr.role_type = 'promoter'
AND sr.role_id = a.user_id AND sr.channel = 'huifu' AND sr.status = 'normal'
WHERE r.status >= 0
AND o.pay_type = 'huifu_wechat'
AND o.paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
AND sr.id IS NULL
LIMIT 30;
SELECT '=== 13. 延时分账标记:支付扩展 delay_acct(近90天汇付单抽样)===' AS section;
SELECT
pe.order_id,
o.order_sn,
pe.delay_acct_flag,
pe.confirm_status,
pe.confirm_hf_seq_id,
so.status AS split_order_status
FROM fa_shopro_huifu_pay_ext pe
INNER JOIN fa_shopro_order o ON o.id = pe.order_id
LEFT JOIN fa_shopro_split_order so ON so.order_id = pe.order_id AND so.channel = 'huifu'
WHERE o.pay_type = 'huifu_wechat'
AND o.paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
ORDER BY pe.order_id DESC
LIMIT 30;
SELECT '=== 14. 分账接收方台账(汇付/微信)===' AS section;
SELECT channel, role_type, COUNT(*) AS cnt,
SUM(CASE WHEN status = 'normal' THEN 1 ELSE 0 END) AS normal_cnt
FROM fa_shopro_split_receiver
GROUP BY channel, role_type;
-- =============================================================================
-- 五、单笔订单深度核验(把 @order_sn 改成实际订单号后执行)
-- =============================================================================
/*
SET @order_sn = '2025010100000001';
SELECT o.* FROM fa_shopro_order o WHERE o.order_sn = @order_sn;
SELECT * FROM fa_shopro_split_order WHERE order_sn = @order_sn;
SELECT sor.*, sr.receiver_account, sr.channel
FROM fa_shopro_split_order_receiver sor
LEFT JOIN fa_shopro_split_receiver sr ON sr.id = sor.receiver_id
WHERE sor.split_order_id IN (SELECT id FROM fa_shopro_split_order WHERE order_sn = @order_sn);
SELECT * FROM fa_shopro_commission_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
SELECT * FROM fa_shopro_regional_agent_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
SELECT wl.*
FROM fa_shopro_user_wallet_log wl
WHERE wl.wallet_type = 'money'
AND wl.type IN ('commission_income', 'regional_agent_income', 'commission_back', 'regional_agent_back')
AND (
wl.item_id IN (SELECT id FROM fa_shopro_commission_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1))
OR wl.item_id IN (SELECT id FROM fa_shopro_regional_agent_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1))
);
SELECT * FROM fa_shopro_huifu_pay_ext WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
*/