فهرست منبع

1. 完成顺丰平台订单取消实现
2. 统一各平台取消订单的返回数据(都要有:deductionFee 字段)

shizhongqi 8 ماه پیش
والد
کامیت
ab657b5e0f

+ 10 - 1
app-ghs/controllers/DeliveryController.php

@@ -466,13 +466,22 @@ class DeliveryController extends BaseController
             }
             $cancelCostCent = $res['data']['actual_cancel_cost_cent']; //取消实际需金额(单位:分)
         }
+        if($platform='shunfeng') {
+            //请求订单预取消接口,获取是否可取消。如果运单状态不允许取消,则直接返回
+            $cancelParams = ['order_id'=>$orderId, 'order_cancel_code'=>$post['order_cancel_code']];
+            $res = $ds->getAdapter()->preCancelOrder($cancelParams);
+            if($res['code'] != 0){
+                util::fail('运单状态不允许取消');
+            }
+            $post['order_type'] = 1; //查询订单ID类型	 1、顺丰订单号 2、商家订单号
+        }
 
         $post['order_cancel_role'] = 1; //1:商户取消, 2:用户取消
         $ret = $ds->cancelOrder($orderId, $post);
         if($ret['code'] == 0) {
             // 更新跑腿订单与批发订单状态
             $gdo->orderStatus = -1;
-            $gdo->cancelCost = $cancelCostCent;
+            $gdo->cancelCost = $ret['platform'] !== 'fengniao' ? $ret['data']['deductionFee'] : $cancelCostCent; // 由于蜂鸟平台返回的扣费不一样造成
             if(!$gdo->save()) {
                 Yii::error('保存配送订单失败: ' . json_encode($gdo->errors));
                 util::fail('保存配送订单失败');

+ 2 - 0
common/components/delivery/platform/shunfeng/Shunfeng.php

@@ -3,6 +3,8 @@
 
 namespace common\components\delivery\platform\shunfeng;
 
+use common\components\delivery\helpers\HttpClient;
+
 /**
  * Class Shunfeng  核心类,保存顺风同城平台的开发者信息
  * @package common\components\delivery\platform\shunfeng

+ 3 - 0
common/components/delivery/services/adapter/FengniaoAdapter.php

@@ -828,6 +828,7 @@ class FengniaoAdapter extends Fengniao implements Adapter
                 Yii::error("[FengniaoAdapter] Failed to parse business_data: " . $resp['business_data']);
                 return [
                     'code' => -1,
+                    'platform' => 'fengniao',
                     'msg' => 'Failed to parse response data',
                     'data' => null
                 ];
@@ -835,6 +836,7 @@ class FengniaoAdapter extends Fengniao implements Adapter
 
             return [
                 'code' => 0,
+                'platform' => 'fengniao',
                 'data' => [
                     'result' => (bool)($respData['result'] ?? false),
                     'reverse_order_ok' => (bool)($respData['reverse_order_ok'] ?? false),
@@ -844,6 +846,7 @@ class FengniaoAdapter extends Fengniao implements Adapter
 
         return [
             'code' => (int)($resp['code'] ?? -1),
+            'platform' => 'fengniao',
             'msg' => $resp['msg'] ?? 'Unknown error',
             'data' => null
         ];

+ 2 - 1
common/components/delivery/services/adapter/HuolalaAdapter.php

@@ -429,7 +429,7 @@ class HuolalaAdapter implements Adapter
         );
 
         // 发送请求
-        $resp = HttpClient::post($this->baseUrl, $payload);
+        $resp = HttpClient::post($this->baseUrl, $payload, ['Content-type'=>'application/json']);
 
         // 处理响应
         if (isset($resp['ret']) && $resp['ret'] == 0 && isset($resp['data'])) {
@@ -488,6 +488,7 @@ class HuolalaAdapter implements Adapter
                 'code' => 0,
                 'platform' => 'huolala',
                 'data' => [
+                    'deductionFee' => 0, //取消收费金额(单位:分)
                     'order_status' => $respData['order_status']
                 ]
             ];

+ 5 - 1
common/components/delivery/services/adapter/ShansongAdapter.php

@@ -274,7 +274,11 @@ class ShansongAdapter extends Shansong implements Adapter
             return [
                 'code' => 0,
                 'platform' => 'shansong',
-                'data' => $respData
+                'data' => [
+                    'deductionFee' => $respData['deductAmount'], //取消收费金额(单位:分)
+                    'abortType' => $respData['abortType'],
+                    'abortReason' => $respData['abortReason']
+                ]
             ];
         }
 

+ 147 - 1
common/components/delivery/services/adapter/ShunfengAdapter.php

@@ -3,7 +3,6 @@ namespace common\components\delivery\services\adapter;
 
 
 use bizGhs\order\classes\OrderItemClass;
-use common\components\delivery\helpers\HttpClient;
 use common\components\delivery\platform\shunfeng\Shunfeng;
 use Yii;
 
@@ -165,6 +164,153 @@ class ShunfengAdapter extends Shunfeng implements Adapter
         ];
     }
 
+    /**
+     * 取消订单
+     * 
+     * 当商家处发生异常需要取消配送时,调用此接口对订单进行取消操作。
+     * @param array $data 预取消查询参数,结构参考:
+     *   [
+     *       // ========== 必填参数(二选一)==========
+     *       'order_id' => '订单ID',
+     *       'partner_order_code' => '外部订单号',
+     *       // 注意:order_id 和 partner_order_code 必填一个
+     *
+     *       // ========== 必填参数 ==========
+     *       'order_cancel_code' => '取消原因code(从可用取消原因列表接口返回结果选择)',
+     *   ]
+     * @param string $orderId 顺丰订单号(SF订单号或商家订单号)
+     * @param array $reason 取消原因信息
+     *        [
+     *            'cancel_code' => int,    // 可选:取消原因代码(默认313=其他)
+     *            'cancel_reason' => string, // 可选:其他取消原因说明
+     *            'order_type' => int      // 可选:1-顺丰订单号,2-商家订单号(默认1)
+     *        ]
+     * @return array 取消结果
+     */
+    public function cancelOrder($orderId, $data)
+    {
+        // 构建请求参数
+        $payload = [
+            'order_id' => $orderId,
+            'push_time' => time(), // 取消时间戳(秒级)
+        ];
+
+        $payload['cancel_code'] = $data['order_cancel_code'];
+        if(isset($data['order_cancel_reason'])){
+            $payload['cancel_reason'] = $data['order_cancel_reason'];
+        }
+
+        if (isset($data['order_type'])) {
+            $payload['order_type'] = $data['order_type'];
+        }
+
+        // 调用API
+        $resp = $this->httpRequest('cancelorder', $payload);
+
+        // 处理响应
+        if (isset($resp['error_code']) && $resp['error_code'] == 0 && isset($resp['result'])) {
+            $result = $resp['result'];
+            return [
+                'code' => 0,
+                'platform' => 'shunfeng',
+                'data' => [
+                    'deductionFee' => $result['deduction_detail']['deduction_fee'], //取消收费金额(单位:分)
+                    'sf_order_id' => $result['sf_order_id'],
+                    'shop_order_id' => $result['shop_order_id'],
+                    'shop_cancel_times' => $result['deduction_detail']['shop_cancel_times'],
+                    'free_cancel_times' => $result['deduction_detail']['free_cancel_times'],
+                    'push_time' => $result['push_time'],
+                ]
+            ];
+        }
+
+        return [
+            'code' => (int)($resp['error_code'] ?? -1),
+            'platform' => 'shunfeng',
+            'msg' => $resp['error_msg'] ?? 'Cancel order failed',
+            'data' => null
+        ];
+    }
+
+    /**
+     * 预取消订单
+     *
+     * 并非真正取消订单,用来验证是否可以取消订单并返回计价等信息。
+     *
+     * @param array $data 预取消订单参数
+     *        [
+     *            'order_id' => string,    // 必须:订单ID(顺丰订单号或商家订单号)
+     *            'cancel_reason' => string, // 可选:取消原因
+     *            'shop_id' => string,     // 可选:店铺ID
+     *            'shop_type' => int       // 可选:店铺类型(1-顺丰,2-接入方)
+     *        ]
+     * @return array 预取消结果(包含是否可以取消、计费信息等)
+     */
+    public function preCancelOrder($data)
+    {
+        // 验证必填参数
+        if (empty($data['order_id'])) {
+            return [
+                'code' => -1,
+                'msg' => 'order_id is required',
+                'data' => null
+            ];
+        }
+
+        // 构建请求参数
+        $payload = [
+            'order_id' => $data['order_id'],
+            'push_time' => time(), // 取消时间戳(秒级)
+        ];
+
+        // 添加可选参数
+        if (isset($data['cancel_reason']) && !empty($data['cancel_reason'])) {
+            $payload['cancel_reason'] = $data['cancel_reason'];
+        }
+
+        if (isset($data['shop_id']) && !empty($data['shop_id'])) {
+            $payload['shop_id'] = $data['shop_id'];
+        }
+
+        if (isset($data['shop_type'])) {
+            $payload['shop_type'] = $data['shop_type'];
+        }
+
+        // 调用API
+        $resp = $this->httpRequest('precancelorder', $payload);
+
+        // 处理响应
+        if (isset($resp['error_code']) && $resp['error_code'] == 0 && isset($resp['result'])) {
+            $result = $resp['result'];
+            return [
+                'code' => 0,
+                'platform' => 'shunfeng',
+                'data' => [
+                    'order_type' => $result['order_type'],
+                    'could_cancel' => $result['could_cancel'],
+                    'promise_delivery_time' => $result['promise_delivery_time'], // 承诺配送时长(分)
+                    'delivery_type' => $result['delivery_type'], // 订单类型(0-预约送达,1-立即单,2-预约上门)
+                    'is_cancel_charge_price_rule' => $result['is_cancel_charge_price_rule'],
+                    'is_over_free_cancel_times' => $result['is_over_free_cancel_times'], // 是否超出免费取消次数
+                    'is_deduction_fee' => $result['is_deduction_fee'], // 是否有取消收费
+                    'deduction_fee' => $result['deduction_fee'], // 取消收费(单位:分)
+                    'cancel_charge_price_rule' => $result['cancel_charge_price_rule'],
+                    'shop_cancel_times' => $result['shop_cancel_times'],
+                    'free_cancel_times' => $result['free_cancel_times'],
+                    'sf_order_id' => $result['sf_order_id'],
+                    'shop_order_id' => $result['shop_order_id'],
+                    'push_time' => $result['push_time'],
+                ]
+            ];
+        }
+
+        return [
+            'code' => (int)($resp['error_code'] ?? -1),
+            'msg' => $resp['error_msg'] ?? 'Pre-cancel order failed',
+            'data' => null
+        ];
+    }
+
     public function getPrice($data)
     {
 //        $requestData = [