request->get('id', 0); $order = OrderClass::getOrderById($id); if (empty($order)) { util::fail('没有找到订单'); } $this->assertOrderOwner($order); $orderPrice = (float)($order['orderPrice'] ?? 0); $tkPrice = (float)($order['tkPrice'] ?? 0); $couldRefundPrice = round(max(0, $orderPrice - $tkPrice), 2); $apply = MallRefundApplyClass::getLatestByOrderId($id); if (!empty($apply) && is_array($apply)) { $apply['statusText'] = MallRefundApplyClass::statusText($apply['status'] ?? 0); if (!empty($apply['product']) && is_string($apply['product'])) { $apply['productList'] = json_decode($apply['product'], true) ?: []; } } // 分销售后截止提示(仅提示,真正拦截在提交时) $refundDeadlineTip = ''; $distOrder = DistributionOrderClass::getByCondition(['orderId' => $id]); if (!empty($distOrder)) { $finishTime = $distOrder['finishTime'] ?? ''; if (!empty($finishTime) && $finishTime !== '0000-00-00 00:00:00') { $rule = \bizHd\distribution\classes\DistributionRuleClass::getRule( (int)($order['shopId'] ?? 0), (int)($order['mainId'] ?? $this->mainId) ); $settleDays = max(0, (int)($rule['settleDays'] ?? 0)); $deadline = date('Y-m-d H:i', strtotime($finishTime) + $settleDays * 86400); $refundDeadlineTip = "分销订单完成后{$settleDays}天内可申请售后,截止:{$deadline}"; } } util::success([ 'orderInfo' => $order, 'goodsInfoList' => $order['goodsInfoList'] ?? [], 'itemInfoList' => $order['itemList'] ?? [], 'couldRefundPrice' => $couldRefundPrice, 'apply' => $apply, 'refundDeadlineTip' => $refundDeadlineTip, 'canApply' => $this->canApplyRefund($order, $apply), ]); } /** * 顾客提交售后申请(仅落待审核记录) */ public function actionCreateOrder() { $post = Yii::$app->request->post(); $id = (int)($post['id'] ?? 0); util::checkRepeatCommit('mall_refund_' . $id, 5); $order = HdOrderClass::getById($id, true); if (empty($order)) { util::fail('没有找到订单'); } $this->assertOrderOwner($order); if ((int)$order->payStatus !== 1) { util::fail('订单未付款,无法申请售后'); } if ((int)$order->status === HdOrderClass::ORDER_STATUS_UN_PAY) { util::fail('待付款订单无法申请售后'); } if ((int)$order->status === HdOrderClass::ORDER_STATUS_CANCEL) { util::fail('已取消订单无法申请售后'); } // 前端 ORDER_STATUS 含已退款=6,全额退完后可能落此状态 if ((int)$order->status === 6) { util::fail('已退款订单无法申请售后'); } if ((int)($order->forward ?? 0) === 1) { util::fail('售后收入单无法申请售后'); } if (MallRefundApplyClass::hasPendingByOrderId($id)) { util::fail('已有待审核的售后申请,请勿重复提交'); } // 分销关联订单:完成后超过 settleDays 不可再申请 DistributionOrderClass::assertRefundNotExpired( $id, (int)$order->shopId, (int)($order->mainId ?? $this->mainId) ); $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { $extra = [ 'userId' => (int)$this->userId, 'hdId' => (int)$this->hdId, 'customId' => (int)$this->customId, 'shopId' => (int)$order->shopId, 'mainId' => (int)($order->mainId ?? $this->mainId), ]; $apply = MallRefundApplyService::createApply($post, $order, $extra); $transaction->commit(); util::success([ 'id' => (int)$apply->id, 'status' => (int)$apply->status, 'statusText' => MallRefundApplyClass::statusText($apply->status), ], '提交成功,请等待商家审核'); } catch (\Exception $e) { $transaction->rollBack(); Yii::info('商城售后申请失败:' . $e->getMessage()); // util::fail 已输出时不会走到这里;其它异常统一提示 if (strpos($e->getMessage(), '操作失败') === false) { util::fail($e->getMessage() ?: '申请失败'); } util::fail('申请失败'); } } /** * 顾客售后申请列表 */ public function actionList() { $where = ['customId' => (int)$this->customId]; $status = Yii::$app->request->get('status', ''); if ($status !== '' && $status !== null) { $where['status'] = (int)$status; } $list = MallRefundApplyClass::getCustomApplyList($where); if (!empty($list['list'])) { foreach ($list['list'] as &$row) { $row['statusText'] = MallRefundApplyClass::statusText($row['status'] ?? 0); } unset($row); } util::success($list); } /** * 顾客售后申请详情 */ public function actionDetail() { $id = (int)Yii::$app->request->get('id', 0); $apply = MallRefundApplyClass::getById($id, true); MallRefundApplyClass::validByCustom($apply, (int)$this->customId); $data = $apply->toArray(); $data['statusText'] = MallRefundApplyClass::statusText($apply->status); if (!empty($data['product'])) { $data['productList'] = json_decode($data['product'], true) ?: []; } util::success($data); } /** * 顾客撤销待审核申请 */ public function actionCancelOrder() { $post = Yii::$app->request->post(); $id = (int)($post['id'] ?? 0); $apply = MallRefundApplyClass::getById($id, true); MallRefundApplyClass::validByCustom($apply, (int)$this->customId); $connection = Yii::$app->db; $transaction = $connection->beginTransaction(); try { MallRefundApplyService::cancel($apply); $transaction->commit(); util::complete('已撤销申请'); } catch (\Exception $e) { $transaction->rollBack(); Yii::info('撤销售后申请失败:' . $e->getMessage()); util::fail($e->getMessage() ?: '撤销失败'); } } /** * 校验订单归属当前登录顾客 * @param array|object $order */ protected function assertOrderOwner($order) { $customId = is_object($order) ? (int)($order->customId ?? 0) : (int)($order['customId'] ?? 0); $userId = is_object($order) ? (int)($order->userId ?? 0) : (int)($order['userId'] ?? 0); if ($customId > 0 && (int)$this->customId > 0 && $customId === (int)$this->customId) { return; } // 兼容早期仅绑 userId 的订单 if ($userId > 0 && $userId === (int)$this->userId) { return; } util::fail('不是你的订单,无法操作'); } /** * 是否允许新开售后申请 * @param array $order * @param array|null $apply * @return int 1可申请 0不可 */ protected function canApplyRefund($order, $apply) { if ((int)($order['payStatus'] ?? 0) !== 1) { return 0; } $status = (int)($order['status'] ?? 0); if (in_array($status, [HdOrderClass::ORDER_STATUS_UN_PAY, HdOrderClass::ORDER_STATUS_CANCEL, 6], true)) { return 0; } if ((int)($order['forward'] ?? 0) === 1) { return 0; } if (!empty($apply) && (int)($apply['status'] ?? -1) === MallRefundApplyClass::STATUS_PENDING) { return 0; } $could = bcsub((string)($order['orderPrice'] ?? 0), (string)($order['tkPrice'] ?? 0), 2); if (bccomp($could, '0', 2) <= 0) { return 0; } return 1; } }