From 48cde5f8918c72f3cf57794189d6a22c449a57d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=AF=E4=B9=90=E5=8A=A0=E5=86=B0?= <11869599+addie66@user.noreply.gitee.com> Date: Thu, 8 Oct 2026 14:02:12 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(shopro=5Fhuifu):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=B1=87=E4=BB=98=E4=B8=AA=E4=BA=BA=E8=BF=9B=E4=BB=B6?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=8F=90=E4=BA=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增以下命令: - php think shopro_huifu:onboard-auto-submit(每 5-10 分钟自动提交) - php think shopro_huifu:onboard-poll(每 10 分钟轮询审核状态) - php think shopro_huifu:diagnose-freeze-flow(冻结/解冻链路诊断) 完善了汇付插件的 README 文档,包含新功能说明和安装验证步骤。 ``` --- addons/shopro_huifu/README.md | 20 +++++++++++++++++++ addons/shopro_wechat_trade/README.md | 4 +++- .../library/SyncLogger.php | 9 +++++++++ .../library/WxShippingPayload.php | 19 ++++++++++++------ .../library/WxShippingService.php | 4 ++++ 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/addons/shopro_huifu/README.md b/addons/shopro_huifu/README.md index 09eb68a..98040d8 100644 --- a/addons/shopro_huifu/README.md +++ b/addons/shopro_huifu/README.md @@ -53,6 +53,19 @@ php think shopro_huifu:compensate php think shopro_huifu:compensate --order_sn=2026111111220944091001100 php think shopro_huifu:split-retry + +# 每 5-10 分钟:汇付个人进件自动提交(业务已通过且从未提交→立即;失败满 24h→重提) +php think shopro_huifu:onboard-auto-submit + +# 每 10 分钟:轮询进件审核中状态 +php think shopro_huifu:onboard-poll +``` + +已有站点若后台无「自动提交进件」开关,执行 SQL:`addons/shopro_huifu/upgrade_huifu_onboard_auto.sql`(替换表前缀)。 + +```bash +# 试跑(不调用汇付) +php think shopro_huifu:onboard-auto-submit --dry-run ``` ## 安装验证 @@ -121,6 +134,13 @@ php think shopro_huifu:import-bank-branch --file=addons/shopro_huifu/data/cnaps. 支付成功通知会优先落库微信 `transaction_id`(`wx_response.transaction_id` / `out_trans_id`),供 `shopro_wechat_trade` 插件调用 `upload_shipping_info`。汇付流水仍保存在 `shopro_huifu_pay_ext.hf_seq_id`。 +冻结/解冻链路只读诊断(服务器有 `.env` 时): + +```bash +php think shopro_huifu:diagnose-freeze-flow +# 或 mysql < addons/shopro_huifu/docs/diagnose-freeze-flow.sql +``` + ## 支付故障排查 | 报错 | 处理 | diff --git a/addons/shopro_wechat_trade/README.md b/addons/shopro_wechat_trade/README.md index 81fe0ea..f07b99e 100644 --- a/addons/shopro_wechat_trade/README.md +++ b/addons/shopro_wechat_trade/README.md @@ -60,7 +60,9 @@ php think shopro_wechat_trade:retry-failed ## 触发点 - `order_send_after` → 异步 `upload_shipping_info` -- `order_confirm_after`(全部 item 已收货)→ `notify_confirm_receive` +- `order_confirm_after`(全部 item 已收货)→ `notify_confirm_receive`(须已有 shipping 同步成功;`received_time` 为秒级时间戳) + +微信错误 **47001 data format error** 多为确认收货 JSON 格式不符(勿用 RFC3339 字符串作为 `received_time`)。 ## 小程序跳转 diff --git a/addons/shopro_wechat_trade/library/SyncLogger.php b/addons/shopro_wechat_trade/library/SyncLogger.php index 634eaf8..6d2165e 100644 --- a/addons/shopro_wechat_trade/library/SyncLogger.php +++ b/addons/shopro_wechat_trade/library/SyncLogger.php @@ -70,4 +70,13 @@ class SyncLogger ->where('status', 'success') ->find(); } + + public static function hasSuccessfulShipping($orderId) + { + return (bool) Db::name('shopro_wechat_trade_sync') + ->where('order_id', $orderId) + ->where('sync_type', 'shipping') + ->where('status', 'success') + ->find(); + } } diff --git a/addons/shopro_wechat_trade/library/WxShippingPayload.php b/addons/shopro_wechat_trade/library/WxShippingPayload.php index b610f74..9e92246 100644 --- a/addons/shopro_wechat_trade/library/WxShippingPayload.php +++ b/addons/shopro_wechat_trade/library/WxShippingPayload.php @@ -75,13 +75,20 @@ class WxShippingPayload $confirmTime = intval($ext['confirm_time']); } - return [ - 'order_key' => [ - 'order_number_type' => 2, - 'transaction_id' => $transactionId, - ], - 'received_time' => self::formatUploadTime($confirmTime), + // 官方 POST /wxa/sec/order/notify_confirm_receive:received_time 为秒级时间戳(number),非 RFC3339 + $payload = [ + 'transaction_id' => $transactionId, + 'received_time' => intval($confirmTime), ]; + $mchid = WxOrderContext::resolveMchid($order); + if ($mchid !== '') { + $payload['merchant_id'] = $mchid; + } + $orderSn = trim((string) ($order['order_sn'] ?? '')); + if ($orderSn !== '') { + $payload['merchant_trade_no'] = $orderSn; + } + return $payload; } protected static function buildShippingListItem(array $item, $order) diff --git a/addons/shopro_wechat_trade/library/WxShippingService.php b/addons/shopro_wechat_trade/library/WxShippingService.php index 5dddcd4..934e8b6 100644 --- a/addons/shopro_wechat_trade/library/WxShippingService.php +++ b/addons/shopro_wechat_trade/library/WxShippingService.php @@ -72,6 +72,10 @@ class WxShippingService return true; } + if (!SyncLogger::hasSuccessfulShipping($orderId)) { + throw new \RuntimeException('须先成功 upload_shipping_info 再同步确认收货(notify_confirm_receive)'); + } + $order = Order::with('item')->where('id', $orderId)->find(); if (!$order || !Bridge::shouldHandleOrder($order)) { return false;