| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <?php
- /**
- * 用途:商城顾客售后申请接口
- * 谁用:mallApp 订单详情「申请售后」页
- * 解决:顾客提交/查看/撤销售后申请;真正退款由商家在 hdApp 审核通过后执行
- */
- namespace mall\controllers;
- use bizHd\distribution\classes\DistributionOrderClass;
- use bizHd\order\classes\OrderClass as HdOrderClass;
- use bizHd\refund\classes\MallRefundApplyClass;
- use bizHd\refund\services\MallRefundApplyService;
- use bizMall\order\classes\OrderClass;
- use common\components\util;
- use Yii;
- class RefundController extends BaseController
- {
- /**
- * 申请页初始化数据:订单商品 + 可退金额 + 已有申请进度
- */
- public function actionGetRefundData()
- {
- $id = (int)Yii::$app->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;
- }
- }
|