diff --git a/application/admin/controller/shopro/order/Aftersale.php b/application/admin/controller/shopro/order/Aftersale.php index 6ac6b1b..6a085e5 100644 --- a/application/admin/controller/shopro/order/Aftersale.php +++ b/application/admin/controller/shopro/order/Aftersale.php @@ -297,32 +297,36 @@ class Aftersale extends Backend $this->error('订单商品已退款,不能重复退款'); } - Db::transaction(function () use ($aftersale, $order, $orderItem, $refund_money, $refund_surplus_money) { - $data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem]; - \think\Hook::listen('aftersale_finish_before', $data); + try { + Db::transaction(function () use ($aftersale, $order, $orderItem, $refund_money, $refund_surplus_money) { + $data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem]; + \think\Hook::listen('aftersale_finish_before', $data); - $aftersale->aftersale_status = \app\admin\model\shopro\order\Aftersale::AFTERSALE_STATUS_OK; // 售后同意 - $aftersale->refund_status = \app\admin\model\shopro\order\Aftersale::REFUND_STATUS_FINISH; // 售后同意退款 - $aftersale->refund_fee = bcadd($refund_money, $aftersale->refund_fee, 2); // 已退款金额 - $aftersale->save(); + $aftersale->aftersale_status = \app\admin\model\shopro\order\Aftersale::AFTERSALE_STATUS_OK; // 售后同意 + $aftersale->refund_status = \app\admin\model\shopro\order\Aftersale::REFUND_STATUS_FINISH; // 售后同意退款 + $aftersale->refund_fee = bcadd($refund_money, $aftersale->refund_fee, 2); // 已退款金额 + $aftersale->save(); - // 增加售后单变动记录 - OrderAftersaleLog::operAdd($order, $aftersale, $this->auth->getUserInfo(), 'admin', [ - 'reason' => '卖家同意退款', - 'content' => '售后订单已退款', - 'images' => [] - ]); + // 增加售后单变动记录 + OrderAftersaleLog::operAdd($order, $aftersale, $this->auth->getUserInfo(), 'admin', [ + 'reason' => '卖家同意退款', + 'content' => '售后订单已退款', + 'images' => [] + ]); - $orderItem->aftersale_status = OrderItem::AFTERSALE_STATUS_OK; - $orderItem->save(); - \addons\shopro\model\OrderAction::operAdd($order, $orderItem, $this->auth->getUserInfo(), 'admin', '管理员同意售后退款'); + $orderItem->aftersale_status = OrderItem::AFTERSALE_STATUS_OK; + $orderItem->save(); + \addons\shopro\model\OrderAction::operAdd($order, $orderItem, $this->auth->getUserInfo(), 'admin', '管理员同意售后退款'); - // 退款 - \app\admin\model\shopro\order\Order::startRefund($order, $orderItem, $refund_money, $this->auth->getUserInfo(), '管理员同意售后退款'); + // 退款 + \app\admin\model\shopro\order\Order::startRefund($order, $orderItem, $refund_money, $this->auth->getUserInfo(), '管理员同意售后退款'); - $data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem]; - \think\Hook::listen('aftersale_finish_after', $data); - }); + $data = ['aftersale' => $aftersale, 'order' => $order, 'item' => $orderItem]; + \think\Hook::listen('aftersale_finish_after', $data); + }); + } catch (\Throwable $e) { + $this->error($e->getMessage()); + } return $this->success('操作成功'); } diff --git a/application/admin/controller/shopro/order/Order.php b/application/admin/controller/shopro/order/Order.php index 0f6eb79..e00a05f 100644 --- a/application/admin/controller/shopro/order/Order.php +++ b/application/admin/controller/shopro/order/Order.php @@ -1034,40 +1034,44 @@ class Order extends Base } } - Db::transaction(function () use ($order, $items, $item_id, $refund_money, $refund_surplus_money) { - if ($item_id) { - // 单个商品退款 - $item = $items[$item_id]; - \app\admin\model\shopro\order\Order::startRefund($order, $item, $refund_money, $this->auth->getUserInfo(), '管理员操作退款'); - } else { - // 全部退款 - // 未退款 item 商品总金额 - $goods_total_amount = 0; - foreach ($items as $ke => $it) { - $goods_total_amount += ($it['goods_price'] * $it['goods_num']); - } - - $current_refunded_money = 0; - for ($i = 0; $i < count($items); $i++) { - if ($i == (count($items) - 1)) { - // 最后一条,全部退完 - $current_refund_money = $refund_money - $current_refunded_money; - } else { - // 按比例计算当前 item 应退金额 - $current_refund_money = round($refund_money * (($items[$i]['goods_price'] * $it['goods_num']) / $goods_total_amount), 2); - } - if (($current_refunded_money + $current_refund_money) > $refund_money) { - $current_refund_money = $refund_money - $current_refunded_money; + try { + Db::transaction(function () use ($order, $items, $item_id, $refund_money, $refund_surplus_money) { + if ($item_id) { + // 单个商品退款 + $item = $items[$item_id]; + \app\admin\model\shopro\order\Order::startRefund($order, $item, $refund_money, $this->auth->getUserInfo(), '管理员操作退款'); + } else { + // 全部退款 + // 未退款 item 商品总金额 + $goods_total_amount = 0; + foreach ($items as $ke => $it) { + $goods_total_amount += ($it['goods_price'] * $it['goods_num']); } - if ($current_refund_money >= 0) { // 支付金额或者退款金额 为 0 也能退 - $current_refunded_money += $current_refund_money; + $current_refunded_money = 0; + for ($i = 0; $i < count($items); $i++) { + if ($i == (count($items) - 1)) { + // 最后一条,全部退完 + $current_refund_money = $refund_money - $current_refunded_money; + } else { + // 按比例计算当前 item 应退金额 + $current_refund_money = round($refund_money * (($items[$i]['goods_price'] * $it['goods_num']) / $goods_total_amount), 2); + } + if (($current_refunded_money + $current_refund_money) > $refund_money) { + $current_refund_money = $refund_money - $current_refunded_money; + } - \app\admin\model\shopro\order\Order::startRefund($order, $items[$i], $current_refund_money, $this->auth->getUserInfo(), '管理员操作退款'); + if ($current_refund_money >= 0) { // 支付金额或者退款金额 为 0 也能退 + $current_refunded_money += $current_refund_money; + + \app\admin\model\shopro\order\Order::startRefund($order, $items[$i], $current_refund_money, $this->auth->getUserInfo(), '管理员操作退款'); + } } } - } - }); + }); + } catch (\Throwable $e) { + $this->error($e->getMessage()); + } $item_list = \app\admin\model\shopro\order\OrderItem::where(['order_id' => $id])->select(); return $this->success('操作成功', null, $item_list); diff --git a/tests/OrderRefundExceptionCatchTest.php b/tests/OrderRefundExceptionCatchTest.php new file mode 100644 index 0000000..f8d45ea --- /dev/null +++ b/tests/OrderRefundExceptionCatchTest.php @@ -0,0 +1,78 @@ +testAftersaleRefundCatchesThrowable(); + $this->testOrderRefundCatchesThrowable(); + + echo "\n测试结果: {$this->passed} 通过, {$this->failed} 失败\n"; + if ($this->failed > 0) { + exit(1); + } + } + + private function assert($condition, $message) + { + if ($condition) { + echo " [PASS] {$message}\n"; + $this->passed++; + } else { + echo " [FAIL] {$message}\n"; + $this->failed++; + } + } + + /** + * 测试 Aftersale 控制器 refund 方法是否具备 try catch (\Throwable $e) 与 $this->error($e->getMessage()) + */ + public function testAftersaleRefundCatchesThrowable() + { + $filePath = __DIR__ . '/../application/admin/controller/shopro/order/Aftersale.php'; + $this->assert(is_file($filePath), "Aftersale.php 控制器必须存在"); + + $content = file_get_contents($filePath); + + // 提取 refund 方法体 + $startPos = strpos($content, 'function refund('); + $this->assert($startPos !== false, "Aftersale.php 必须包含 refund 方法"); + + $nextFuncPos = strpos($content, 'public function ', $startPos + 20); + $methodBody = substr($content, $startPos, $nextFuncPos - $startPos); + + $hasTryCatch = preg_match('/try\s*\{\s*Db::transaction\(.+?\}\s*catch\s*\(\\\\?Throwable\s+\$e\)\s*\{\s*\$this->error\(\$e->getMessage\(\)\);\s*\}/s', $methodBody); + $this->assert((bool)$hasTryCatch, "Aftersale.php 的 refund 方法必须使用 try...catch(\\Throwable \$e) 包裹 Db::transaction 并在失败时调用 \$this->error(\$e->getMessage())"); + } + + /** + * 测试 Order 控制器 refund 方法是否具备 try catch (\Throwable $e) 与 $this->error($e->getMessage()) + */ + public function testOrderRefundCatchesThrowable() + { + $filePath = __DIR__ . '/../application/admin/controller/shopro/order/Order.php'; + $this->assert(is_file($filePath), "Order.php 控制器必须存在"); + + $content = file_get_contents($filePath); + + // 提取 refund 方法体 + $startPos = strpos($content, 'function refund('); + $this->assert($startPos !== false, "Order.php 必须包含 refund 方法"); + + $nextFuncPos = strpos($content, 'public function ', $startPos + 20); + $methodBody = substr($content, $startPos, $nextFuncPos - $startPos); + + $hasTryCatch = preg_match('/try\s*\{\s*Db::transaction\(.+?\}\s*catch\s*\(\\\\?Throwable\s+\$e\)\s*\{\s*\$this->error\(\$e->getMessage\(\)\);\s*\}/s', $methodBody); + $this->assert((bool)$hasTryCatch, "Order.php 的 refund 方法必须使用 try...catch(\\Throwable \$e) 包裹 Db::transaction 并在失败时调用 \$this->error(\$e->getMessage())"); + } +} + +$test = new OrderRefundExceptionCatchTest(); +$test->run();