From 87ce558c076dbf77da0d1efbfad5262aac4d9a89 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: Fri, 9 Oct 2026 12:57:40 +0800 Subject: [PATCH] =?UTF-8?q?```=20feat(shopro=5Fwechat=5Ftrade):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BE=AE=E4=BF=A1=E5=8F=91=E8=B4=A7=E4=B8=80?= =?UTF-8?q?=E5=BE=8B=E8=87=AA=E6=8F=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 shipping_force_self_pickup 配置项,默认开启,用于控制 upload_shipping_info 时固定使用 logistics_type=4(用户自提) - 修改 WxShippingPayload 类,新增 resolveLogisticsType 和 shouldUseExpressTracking 方法处理自提逻辑 - 更新配置页面添加自提开关组件及说明 - 修改数据库操作逻辑,支持配置项不存在时的插入操作 - 在 README.md 中补充相关命令行工具使用说明和配置说明 - 更新安装脚本添加默认配置值 ``` --- addons/shopro_wechat_trade/README.md | 19 +++++++++++++++ .../controller/shopro_wechat_trade/Config.php | 15 +++++++++++- .../shopro_wechat_trade/config/index.html | 6 +++++ addons/shopro_wechat_trade/install.sql | 3 ++- .../library/WxShippingPayload.php | 24 ++++++++++++++++--- .../library/WxTradeConfig.php | 8 +++++++ .../js/backend/shopro_wechat_trade/config.js | 1 + .../controller/shopro_wechat_trade/Config.php | 15 +++++++++++- .../shopro_wechat_trade/config/index.html | 6 +++++ .../js/backend/shopro_wechat_trade/config.js | 1 + 10 files changed, 92 insertions(+), 6 deletions(-) diff --git a/addons/shopro_wechat_trade/README.md b/addons/shopro_wechat_trade/README.md index b6f0b14..46544a0 100644 --- a/addons/shopro_wechat_trade/README.md +++ b/addons/shopro_wechat_trade/README.md @@ -60,6 +60,25 @@ php think shopro_wechat_trade:retry-failed php think shopro_wechat_trade:confirm-orders --sn=202608500438103091004500,202606584688620091002100 # 商城已是「已收货」、只补微信: php think shopro_wechat_trade:confirm-orders --sn=订单号 --skip-mall +# 自提/到店:未发货会自动先触发自提发货(logistics_type=4),再商城确认+微信同步 +php think shopro_wechat_trade:confirm-orders --sn=202606584688620091002100 +``` + +## 微信发货一律按自提 + +后台 **微信交易合规 → 微信发货一律自提**(`shipping_force_self_pickup`,默认开启): + +- 调用 `upload_shipping_info` 时固定 **`logistics_type = 4`(用户自提)** +- 不再要求快递单号/快递公司,用订单号作 `tracking_no` +- **不改变**商城订单的配送方式(快递单仍可在后台照常发货) + +已同步过「快递」的旧单若需按自提重传,在同步日志里对该单重新触发发货同步,或 `php think shopro_wechat_trade:retry-failed`。 + +已有库可执行: + +```sql +INSERT IGNORE INTO fa_shopro_wechat_trade_config (`name`, `value`, `group`, `description`) VALUES +('shipping_force_self_pickup', '1', 'basic', '微信 upload_shipping_info 一律按用户自提(logistics_type=4)'); ``` ## 触发点 diff --git a/addons/shopro_wechat_trade/application/admin/controller/shopro_wechat_trade/Config.php b/addons/shopro_wechat_trade/application/admin/controller/shopro_wechat_trade/Config.php index 59dfb28..1f7707a 100644 --- a/addons/shopro_wechat_trade/application/admin/controller/shopro_wechat_trade/Config.php +++ b/addons/shopro_wechat_trade/application/admin/controller/shopro_wechat_trade/Config.php @@ -32,7 +32,20 @@ class Config extends Backend $this->error('参数错误'); } foreach ($params as $name => $value) { - Db::name('shopro_wechat_trade_config')->where('name', $name)->update(['value' => $value]); + if ($name === 'mini_program_app_id') { + continue; + } + $exists = Db::name('shopro_wechat_trade_config')->where('name', $name)->find(); + if ($exists) { + Db::name('shopro_wechat_trade_config')->where('name', $name)->update(['value' => $value]); + } else { + Db::name('shopro_wechat_trade_config')->insert([ + 'name' => $name, + 'value' => $value, + 'group' => 'basic', + 'description' => '', + ]); + } } WxTradeConfig::reload(); $this->success('保存成功'); diff --git a/addons/shopro_wechat_trade/application/admin/view/shopro_wechat_trade/config/index.html b/addons/shopro_wechat_trade/application/admin/view/shopro_wechat_trade/config/index.html index eba6af5..92c708f 100644 --- a/addons/shopro_wechat_trade/application/admin/view/shopro_wechat_trade/config/index.html +++ b/addons/shopro_wechat_trade/application/admin/view/shopro_wechat_trade/config/index.html @@ -14,6 +14,12 @@ + + + + 开启后 upload_shipping_info 固定 logistics_type=4(用户自提),不再传快递单号;商城配送方式不变。 + + diff --git a/addons/shopro_wechat_trade/install.sql b/addons/shopro_wechat_trade/install.sql index ef0a4b1..83756c0 100644 --- a/addons/shopro_wechat_trade/install.sql +++ b/addons/shopro_wechat_trade/install.sql @@ -36,4 +36,5 @@ INSERT IGNORE INTO `__PREFIX__shopro_wechat_trade_config` (`name`, `value`, `gro ('wechat_trade_enable', '1', 'basic', '微信交易合规总开关'), ('order_detail_path', 'pages/order/detail?id=${商品订单号}', 'basic', '购物订单跳转路径'), ('max_retry', '5', 'basic', '失败最大重试次数'), -('retry_interval', '300', 'basic', '重试间隔秒'); +('retry_interval', '300', 'basic', '重试间隔秒'), +('shipping_force_self_pickup', '1', 'basic', '微信 upload_shipping_info 一律按用户自提(logistics_type=4)'); diff --git a/addons/shopro_wechat_trade/library/WxShippingPayload.php b/addons/shopro_wechat_trade/library/WxShippingPayload.php index 9e92246..2dbb3bc 100644 --- a/addons/shopro_wechat_trade/library/WxShippingPayload.php +++ b/addons/shopro_wechat_trade/library/WxShippingPayload.php @@ -18,6 +18,24 @@ class WxShippingPayload return self::$logisticsMap[$dispatchType] ?? 1; } + /** 同步微信发货时使用的 logistics_type(1 快递 2 同城 3 虚拟 4 自提) */ + public static function resolveLogisticsType($dispatchType) + { + if (WxTradeConfig::getInstance()->shippingForceSelfPickup()) { + return 4; + } + return self::mapLogisticsType($dispatchType); + } + + public static function shouldUseExpressTracking(array $item) + { + if (WxTradeConfig::getInstance()->shippingForceSelfPickup()) { + return false; + } + $dispatchType = $item['dispatch_type'] ?? 'express'; + return in_array($dispatchType, ['express', 'store'], true); + } + public static function buildUploadPayload($order, array $items, $triggerItem = null) { $transactionId = WxOrderContext::resolveTransactionId($order); @@ -37,7 +55,8 @@ class WxShippingPayload $allItems = self::filterAllActiveItems($items); $deliveryMode = count($shippableItems) >= count($allItems) ? 1 : 2; - $logisticsType = self::mapLogisticsType($triggerItem['dispatch_type'] ?? ($shippableItems[0]['dispatch_type'] ?? 'express')); + $dispatchHint = $triggerItem['dispatch_type'] ?? ($shippableItems[0]['dispatch_type'] ?? 'express'); + $logisticsType = self::resolveLogisticsType($dispatchHint); $shippingList = []; foreach ($shippableItems as $item) { $shippingList[] = self::buildShippingListItem($item, $order); @@ -93,11 +112,10 @@ class WxShippingPayload protected static function buildShippingListItem(array $item, $order) { - $dispatchType = $item['dispatch_type'] ?? 'express'; $desc = mb_substr($item['goods_title'] ?? '商城商品', 0, 120); $entry = ['item_desc' => $desc]; - if (in_array($dispatchType, ['express', 'store'], true)) { + if (self::shouldUseExpressTracking($item)) { $trackingNo = trim((string) ($item['express_no'] ?? '')); $expressCode = WxExpressMapper::toWechatCode($item['express_code'] ?? ''); if ($trackingNo === '') { diff --git a/addons/shopro_wechat_trade/library/WxTradeConfig.php b/addons/shopro_wechat_trade/library/WxTradeConfig.php index 6c9f1cd..a87301b 100644 --- a/addons/shopro_wechat_trade/library/WxTradeConfig.php +++ b/addons/shopro_wechat_trade/library/WxTradeConfig.php @@ -65,4 +65,12 @@ class WxTradeConfig $v = intval($this->get('retry_interval', 300)); return $v > 0 ? $v : 300; } + + /** + * upload_shipping_info 是否一律按「用户自提」(logistics_type=4),与商城 dispatch_type 无关 + */ + public function shippingForceSelfPickup() + { + return $this->get('shipping_force_self_pickup', '1') === '1'; + } } diff --git a/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/config.js b/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/config.js index 9ab358d..def5ddd 100644 --- a/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/config.js +++ b/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/config.js @@ -9,6 +9,7 @@ define(['jquery', 'bootstrap', 'backend', 'form'], function ($, undefined, Backe order_detail_path: 'pages/order/detail?id=${商品订单号}', max_retry: '5', retry_interval: '300', + shipping_force_self_pickup: '1', mini_program_app_id: '' }, checkResult: '' diff --git a/application/admin/controller/shopro_wechat_trade/Config.php b/application/admin/controller/shopro_wechat_trade/Config.php index 5f37355..9f523f9 100644 --- a/application/admin/controller/shopro_wechat_trade/Config.php +++ b/application/admin/controller/shopro_wechat_trade/Config.php @@ -32,7 +32,20 @@ class Config extends Backend $this->error('参数错误'); } foreach ($params as $name => $value) { - Db::name('shopro_wechat_trade_config')->where('name', $name)->update(['value' => $value]); + if ($name === 'mini_program_app_id') { + continue; + } + $exists = Db::name('shopro_wechat_trade_config')->where('name', $name)->find(); + if ($exists) { + Db::name('shopro_wechat_trade_config')->where('name', $name)->update(['value' => $value]); + } else { + Db::name('shopro_wechat_trade_config')->insert([ + 'name' => $name, + 'value' => $value, + 'group' => 'basic', + 'description' => '', + ]); + } } WxTradeConfig::reload(); $this->success('保存成功'); diff --git a/application/admin/view/shopro_wechat_trade/config/index.html b/application/admin/view/shopro_wechat_trade/config/index.html index ed66834..596e7ea 100644 --- a/application/admin/view/shopro_wechat_trade/config/index.html +++ b/application/admin/view/shopro_wechat_trade/config/index.html @@ -14,6 +14,12 @@ + + + + 开启后 upload_shipping_info 固定 logistics_type=4(用户自提),不再传快递单号;商城配送方式不变。 + + diff --git a/public/assets/js/backend/shopro_wechat_trade/config.js b/public/assets/js/backend/shopro_wechat_trade/config.js index 75e1016..f9bb6b3 100644 --- a/public/assets/js/backend/shopro_wechat_trade/config.js +++ b/public/assets/js/backend/shopro_wechat_trade/config.js @@ -9,6 +9,7 @@ define(['jquery', 'bootstrap', 'backend', 'form'], function ($, undefined, Backe order_detail_path: 'pages/order/detail?order_sn=${商品订单号}', max_retry: '5', retry_interval: '300', + shipping_force_self_pickup: '1', mini_program_app_id: '' }, checkResult: ''