// +---------------------------------------------------------------------- namespace app\controller\api\v1\order; use app\Request; use app\services\pay\PayServices; use app\services\other\ExpressServices; use app\services\product\branch\StoreBranchProductServices; use app\services\user\UserAddressServices; use app\services\user\UserInvoiceServices; use app\services\user\UserServices; use app\services\activity\{collage\UserCollageServices, discounts\StoreDiscountsServices, lottery\LuckLotteryServices, bargain\StoreBargainServices, combination\StorePinkServices }; use app\services\activity\coupon\StoreCouponIssueServices; use crmeb\services\wechat\MiniProgram; use app\services\order\{OtherOrderServices, StoreCartServices, StoreDeliveryOrderServices, StoreOrderCartInfoServices, StoreOrderCommentServices, StoreOrderComputedServices, StoreOrderCreateServices, StoreOrderEconomizeServices, StoreOrderRefundServices, StoreOrderServices, StoreOrderStatusServices, StoreOrderSuccessServices, StoreOrderTakeServices, StoreOrderPromotionsServices, StoreOrderWriteOffServices }; use app\services\pay\OrderPayServices; use app\services\pay\YuePayServices; use app\services\product\product\StoreProductReplyServices; use app\services\product\shipping\ShippingTemplatesServices; use app\services\store\SystemStoreServices; use crmeb\services\CacheService; /** * 订单控制器 * Class StoreOrderController * @package app\controller\api\order */ class StoreOrderController { /** * @var StoreOrderServices */ protected $services; /** * @var int[] */ protected $getChennel = [ 'weixin' => 0, 'routine' => 1, 'weixinh5' => 2, 'pc' => 3, 'app' => 4 ]; /** * 地址信息 * @var string[] */ protected $addressInfo = [ 'id' => 0, 'real_name' => '', 'phone' => '', 'province' => '', 'city' => '', 'district' => '', 'street' => '', 'detail' => '', 'longitude' => '', 'latitude' => '' ]; /** * StoreOrderController constructor. * @param StoreOrderServices $services */ public function __construct(StoreOrderServices $services) { $this->services = $services; } /** * @param Request $request * @return mixed * @throws \Psr\SimpleCache\InvalidArgumentException */ public function checkShipping(Request $request) { [$cartId, $new] = $request->postMore(['cartId', 'new'], true); return app('json')->successful($this->services->checkShipping($request->uid(), $cartId, $new)); } /** * 订单确认 * @param Request $request * @param ShippingTemplatesServices $services * @return mixed * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function confirm(Request $request, ShippingTemplatesServices $services) { if (!$services->get(1, ['id'])) { return app('json')->fail('默认模板未配置,无法下单'); } [$cartId, $new, $addressId, $shippingType, $storeId, $couponId, $luckRecordId, $deliveryType] = $request->postMore([ 'cartId', 'new', ['addressId', 0], ['shipping_type', 1], ['store_id', 0], ['couponId', 0], ['luckRecordId', 0], ['delivery_type', 1], ], true); if (!is_string($cartId) || !$cartId) { return app('json')->fail('请提交购买的商品'); } $user = $request->user()->toArray(); return app('json')->successful($this->services->getOrderConfirmData($user, $cartId, !!$new, (int)$addressId, (int)$shippingType, (int)$storeId, (int)$couponId)); } /** * 计算订单金额 * @param Request $request * @param $key * @return mixed * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function computedOrder(Request $request, StoreOrderComputedServices $computedServices, $key) { if (!$key) return app('json')->fail('参数错误!'); $uid = $request->uid(); if ($checkOrder = $this->services->getOne(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0], 'id,order_id')) return app('json')->status('extend_order', '订单已生成', ['orderId' => $checkOrder['order_id'], 'key' => $key]); [$addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, $newcomerId, $shipping_type, $delivery_type] = $request->postMore([ 'addressId', 'couponId', ['payType', 'yue'], ['useIntegral', 0], 'mark', ['combinationId', 0], ['pinkId', 0], ['seckill_id', 0], ['bargainId', ''], ['newcomerId', 0], ['shipping_type', 1], ['delivery_type', 1], ], true); $payType = strtolower($payType); $cartGroup = $this->services->getCacheOrderInfo($uid, $key); if (!$cartGroup) return app('json')->fail('订单已过期,请刷新当前页面!'); $priceGroup = $computedServices->setParamData([ 'combinationId' => $combinationId, 'pinkId' => $pinkId, 'seckill_id' => $seckill_id, 'bargainId' => $bargainId, 'newcomerId' => $newcomerId ])->computedOrder($request->uid(), $request->user()->toArray(), $cartGroup, (int)$addressId, $payType, !!$useIntegral, (int)$couponId, (int)$shipping_type); if ($priceGroup) return app('json')->status('NONE', 'ok', $priceGroup); else return app('json')->fail('计算失败'); } /** * 订单创建 * @param Request $request * @param StoreOrderCreateServices $createServices * @param $key * @return mixed * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function create(Request $request, StoreOrderCreateServices $createServices, $key) { if (!$key) return app('json')->fail('参数错误!'); $uid = (int)$request->uid(); if ($checkOrder = $this->services->getOne(['unique' => $key, 'uid' => $uid, 'is_del' => 0], 'id,order_id')) return app('json')->status('extend_order', '订单已创建,请点击查看完成支付', ['orderId' => $checkOrder['order_id'], 'key' => $key]); [$addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $collate_code_id, $bargainId, $newcomerId, $from, $shipping_type, $real_name, $phone, $storeId, $news, $invoice_id, $quitUrl, $discountId, $customForm] = $request->postMore([ [['addressId', 'd'], 0], [['couponId', 'd'], 0], ['payType', ''], ['useIntegral', 0], ['mark', ''], [['combinationId', 'd'], 0], [['pinkId', 'd'], 0], [['seckill_id', 'd'], 0], [['collate_code_id', 'd'], 0], //拼单ID 、桌码ID [['bargainId', 'd'], ''], [['newcomerId', 'd'], ''], ['from', 'weixin'], [['shipping_type', 'd'], 1], ['real_name', ''], ['phone', ''], [['store_id', 'd'], 0], ['new', 0], [['invoice_id', 'd'], 0], ['quitUrl', ''], [['discountId', 'd'], 0], ['custom_form', []], ], true); $cartGroup = $this->services->getCacheOrderInfo($uid, $key); if (!$cartGroup) { return app('json')->fail('请勿重复提交或订单已过期 请刷新当前页面!'); } $cartInfo = $cartGroup['cartInfo']; if (!$cartInfo) { return app('json')->fail('订单已过期或提交的商品不在送达区域,请刷新当前页面或重新选择商品下单!'); } $payType = strtolower($payType); if ($shipping_type == 1) { $cartInfo = $cartGroup['cartInfo']; $product_type = $cartInfo[0]['productInfo']['product_type'] ?? 0; //普通商品 验证地址 if ($product_type == 0 && !$addressId) { return app('json')->fail('请选择收货地址!'); } $addressInfo = ($cartGroup['addr'] ?? []) ?: $this->addressInfo; if ($addressId && (!$addressInfo || !isset($addressInfo['id']) || $addressInfo['id'] != $addressId)) { /** @var UserAddressServices $addressServices */ $addressServices = app()->make(UserAddressServices::class); if (!$addressInfo = $addressServices->getOne(['uid' => $uid, 'id' => $addressId, 'is_del' => 0])) return app('json')->fail('地址选择有误!'); $addressInfo = $addressInfo->toArray(); } } elseif ($shipping_type == 4) { $addressInfo = $this->addressInfo; } else { if (!$real_name || !$phone) { return app('json')->fail('请填写姓名和电话'); } $addressInfo = $this->addressInfo; $addressInfo['real_name'] = $real_name; $addressInfo['phone'] = $phone; } //下单前砍价验证 if ($bargainId) { /** @var StoreBargainServices $bargainServices */ $bargainServices = app()->make(StoreBargainServices::class); $bargainServices->checkBargainUser((int)$bargainId, $uid); } //下单前发票验证 if ($invoice_id) { /** @var UserInvoiceServices $userInvoiceServices */ $userInvoiceServices = app()->make(UserInvoiceServices::class); $userInvoiceServices->checkInvoice((int)$invoice_id, $uid); } if ($pinkId) { $pinkId = (int)$pinkId; /** @var StorePinkServices $pinkServices */ $pinkServices = app()->make(StorePinkServices::class); if ($pinkServices->isPink($pinkId, $uid)) return app('json')->status('ORDER_EXIST', '订单生成失败,你已经在该团内不能再参加了', ['orderId' => $this->services->getStoreIdPink($pinkId, $uid)]); if ($this->services->getIsOrderPink($pinkId, $uid)) return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => $this->services->getStoreIdPink($pinkId, $uid)]); if (!CacheService::checkStock(md5($pinkId), 1, 3) || !CacheService::popStock(md5($pinkId), 1, 3)) { return app('json')->fail('该团人员已满'); } } if ($from != 'pc') { if (!$this->services->checkPaytype($payType)) { return app('json')->fail('暂不支持该支付方式,请刷新页面或者联系管理员'); } } $isChannel = $this->getChennel[$from] ?? ($request->isApp() ? 4 : 1); if ($seckill_id || $combinationId || $discountId || $bargainId) { //套餐限量库 if ($discountId) { /** @var StoreDiscountsServices $discountService */ $discountService = app()->make(StoreDiscountsServices::class); $discounts = $discountService->get((int)$discountId); if (!$discounts) { return app('json')->fail('套餐商品未找到!'); } //套餐限量 if ($discounts['is_limit'] && !CacheService::popStock(md5($discountId), 1, 5)) { return app('json')->fail('您购买的套餐不足'); } } foreach ($cartInfo as $item) { if (!isset($item['product_attr_unique']) || !$item['product_attr_unique']) continue; $type = $item['type']; if (in_array($type, [1, 2, 3]) && (!CacheService::checkStock($item['product_attr_unique'], (int)$item['cart_num'], $type) || !CacheService::popStock($item['product_attr_unique'], (int)$item['cart_num'], $type))) { return app('json')->fail('您购买的商品库存已不足' . $item['cart_num'] . $item['productInfo']['unit_name']); } } } try { $msg = ''; $order = $createServices->createOrder($uid, $key, $cartGroup, (int)$addressId, $payType, $addressInfo, $request->user()->toArray(), !!$useIntegral, $couponId, $mark, $pinkId, $isChannel, $shipping_type, $storeId, !!$news, $customForm, (int)$invoice_id, $from, (int)$collate_code_id); } catch (\Throwable $e) { $order = false; $msg = $e->getMessage(); \think\facade\Log::error('订单生成失败,原因:' . $msg . $e->getFile() . $e->getLine()); } if ($order === false) { if ($seckill_id || $combinationId || $discountId || $bargainId) { //回退套餐限量库 if ($discountId) CacheService::setStock(md5($discountId), 1, 5, false); foreach ($cartInfo as $item) { if (!isset($item['product_attr_unique']) || !$item['product_attr_unique']) continue; $type = $item['type']; if (in_array($type, [1, 2, 3])) CacheService::setStock($item['product_attr_unique'], (int)$item['cart_num'], $type, false); } } return app('json')->fail($msg ?: '订单生成失败'); } $orderId = $order['order_id']; if ($orderId) { $orderInfo = $order->toArray(); if (!$orderInfo || !isset($orderInfo['paid'])) { return app('json')->fail('支付订单不存在!'); } $info = compact('orderId', 'key'); switch ($payType) { case PayServices::WEIXIN_PAY: if ($orderInfo['paid']) return app('json')->fail('支付已支付!'); //支付金额为0 if (bcsub((string)$orderInfo['pay_price'], '0', 2) <= 0) { //创建订单jspay支付 /** @var StoreOrderSuccessServices $success */ $success = app()->make(StoreOrderSuccessServices::class); $payPriceStatus = $success->zeroYuanPayment($orderInfo, $uid, PayServices::WEIXIN_PAY); if ($payPriceStatus)//0元支付成功 return app('json')->status('success', '微信支付成功', $info); else return app('json')->status('pay_error'); } else { /** @var OrderPayServices $payServices */ $payServices = app()->make(OrderPayServices::class); if (!$from && $request->isApp()) { $from = 'weixin'; } $info['jsConfig'] = $payServices->orderPay($orderInfo, $from); if ($from == 'weixinh5') { return app('json')->status('wechat_h5_pay', '订单创建成功', $info); } else { return app('json')->status('wechat_pay', '订单创建成功', $info); } } break; case PayServices::YUE_PAY: /** @var YuePayServices $yueServices */ $yueServices = app()->make(YuePayServices::class); $pay = $yueServices->yueOrderPay($orderInfo, $uid); if ($pay['status'] === true) return app('json')->status('success', '余额支付成功', $info); else { if (is_array($pay)) return app('json')->status($pay['status'], $pay['msg'], $info); else return app('json')->status('pay_error', $pay); } break; case PayServices::ALIAPY_PAY: if (!$quitUrl && ($request->isH5() || $request->isWechat())) { return app('json')->status('pay_error', '请传入支付宝支付回调URL', $info); } [$url, $param] = strpos($quitUrl, '?') ? explode('?', $quitUrl) : [$quitUrl, '']; if ($param) { $quitUrl = $quitUrl . '&order_id=' . $orderInfo['order_id']; } else { $quitUrl = $url . '?order_id=' . $orderInfo['order_id']; } //支付金额为0 if (bcsub((string)$orderInfo['pay_price'], '0', 2) <= 0) { //创建订单jspay支付 /** @var StoreOrderSuccessServices $success */ $success = app()->make(StoreOrderSuccessServices::class); $payPriceStatus = $success->zeroYuanPayment($orderInfo, $uid, PayServices::ALIAPY_PAY); if ($payPriceStatus)//0元支付成功 return app('json')->status('success', '支付宝支付成功', $info); else return app('json')->status('pay_error'); } else { /** @var OrderPayServices $payServices */ $payServices = app()->make(OrderPayServices::class); $info['jsConfig'] = $payServices->alipayOrder($orderInfo, $quitUrl, $from == 'routine'); $payKey = md5($orderInfo['order_id']); CacheService::set($payKey, ['order_id' => $orderInfo['order_id'], 'other_pay_type' => false], 300); $info['pay_key'] = $payKey; return app('json')->status(PayServices::ALIAPY_PAY . '_pay', '订单创建成功', $info); } break; default: return app('json')->status('success', '订单创建成功', $info); break; } } else return app('json')->fail('订单生成失败!'); } /** * 订单 再次下单 * @param Request $request * @return mixed */ public function again(Request $request, StoreCartServices $services) { [$uni] = $request->postMore([ ['uni', ''], ], true); if (!$uni) return app('json')->fail('参数错误!'); $order = $this->services->getUserOrderDetail($uni, (int)$request->uid()); if (!$order) return app('json')->fail('订单不存在!'); if (in_array($order['type'], [1, 2, 3, 5])) { $msg = ''; switch ($order['type']) { case 1://秒杀 $msg = '秒杀'; break; case 2://砍价 $msg = '砍价'; break; case 3://拼团 $msg = '拼团'; break; case 5://套餐 $msg = '套餐'; break; } return app('json')->fail($msg . '商品不能再来一单,请在' . $msg . '商品内自行下单!'); } $order = $this->services->tidyOrder($order, true); $cateIds = []; foreach ($order['cartInfo'] as $v) { if ($v['type'] == 0) { [$cartId, $cartNum] = $services->setCart($request->uid(), (int)$v['product_id'], (int)$v['cart_num'], isset($v['productInfo']['attrInfo']['unique']) ? $v['productInfo']['attrInfo']['unique'] : ''); $cateIds[] = $cartId; } } if (!$cateIds) return app('json')->fail('再来一单失败,请重新下单!'); return app('json')->successful('ok', ['cateId' => implode(',', $cateIds)]); } /** * 订单支付 * @param Request $request * @param StorePinkServices $services * @param OrderPayServices $payServices * @param YuePayServices $yuePayServices * @return mixed */ public function pay(Request $request, StorePinkServices $services, OrderPayServices $payServices, YuePayServices $yuePayServices) { [$uni, $paytype, $from, $quitUrl] = $request->postMore([ ['uni', ''], ['paytype', 'weixin'], ['from', 'weixin'], ['quitUrl', ''] ], true); if (!$uni) return app('json')->fail('参数错误!'); $order = $this->services->getUserOrderDetail($uni, (int)$request->uid()); if (!$order) return app('json')->fail('订单不存在!'); if ($order['paid']) return app('json')->fail('该订单已支付!'); if ($order['pink_id'] && $services->isPinkStatus($order['pink_id'])) { return app('json')->fail('该订单已失效!'); } // $isChannel = $this->getChennel[$from] ?? ($request->isApp() ? 4 : 1); //缓存不存在 || 切换另一端支付 // if (!CacheService::get('pay_' . $order['order_id']) || $isChannel != $order['is_channel']) { // mt_srand(); // switch ($from) { // case 'weixin': // if (in_array($order->is_channel, [1, 2, 3, 4])) {//0 // $order['order_id'] = mt_rand(100, 999) . '_' . $order['order_id']; // } // break; // case 'weixinh5': // if (in_array($order->is_channel, [0, 1, 3, 4])) { // $order['order_id'] = mt_rand(100, 999) . '_' . $order['order_id']; // } // break; // case 'routine': // if (in_array($order->is_channel, [0, 2, 3, 4])) { // $order['order_id'] = mt_rand(100, 999) . '_' . $order['order_id']; // } // break; // case 'pc': // case 'aliapy': // $order['order_id'] = mt_rand(100, 999) . '_' . $order['order_id']; // break; // } // } //只要重新支付就更新订单号 if (in_array($paytype, [PayServices::ALIAPY_PAY, PayServices::WEIXIN_PAY])) { mt_srand(); $order['order_id'] = mt_rand(100, 999) . '_' . $order['order_id']; if (sys_config('pay_routine_open', 0)) { /** @var StoreOrderCreateServices $orderCreateServices */ $orderCreateServices = app()->make(StoreOrderCreateServices::class); $order['order_id'] = $orderCreateServices->getNewOrderId(); $this->services->update($order['id'], ['unique' => $order['order_id']], 'id'); } } $order['pay_type'] = $paytype; //重新支付选择支付方式 switch ($order['pay_type']) { case PayServices::WEIXIN_PAY: $jsConfig = $payServices->orderPay($order->toArray(), $from); if ($from == 'weixinh5') { return app('json')->status('wechat_h5_pay', ['jsConfig' => $jsConfig, 'order_id' => $order['order_id']]); } elseif ($from == 'weixin' || $from == 'routine') { return app('json')->status('wechat_pay', ['jsConfig' => $jsConfig, 'order_id' => $order['order_id']]); } elseif ($from == 'pc') { return app('json')->status('wechat_pc_pay', ['jsConfig' => $jsConfig, 'order_id' => $order['order_id']]); } break; case PayServices::ALIAPY_PAY: if (!$quitUrl && $from != 'routine') { return app('json')->fail('请传入支付宝支付回调URL'); } $isCode = $from == 'routine' || $from == 'pc'; $jsConfig = $payServices->alipayOrder($order->toArray(), $quitUrl, $isCode); if ($isCode && !($jsConfig->invalid ?? false)) $jsConfig->invalid = time() + 60; $payKey = md5($order['order_id']); CacheService::set($payKey, ['order_id' => $order['order_id'], 'other_pay_type' => false], 300); return app('json')->status(PayServices::ALIAPY_PAY . '_pay', '订单创建成功', ['jsConfig' => $jsConfig, 'order_id' => $order['order_id'], 'pay_key' => $payKey]); break; case PayServices::YUE_PAY: $pay = $yuePayServices->yueOrderPay($order->toArray(), $request->uid()); if ($pay['status'] === true) return app('json')->status('success', '余额支付成功'); else { if (is_array($pay)) return app('json')->status($pay['status'], $pay['msg']); else return app('json')->status('pay_error', $pay); } break; case PayServices::OFFLINE_PAY: if ($this->services->setOrderTypePayOffline($order['order_id'])) return app('json')->status('success', '订单创建成功'); else return app('json')->status('success', '支付失败'); break; } return app('json')->fail('支付方式错误'); } /** * 支付宝单独支付 * @param OrderPayServices $payServices * @param OtherOrderServices $services * @param string $key * @param string $quitUrl * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function aliPay(OrderPayServices $payServices, OtherOrderServices $services, string $key, string $quitUrl) { if (!$key || !($orderCache = CacheService::get($key))) { return app('json')->fail('该订单无法支付'); } if (!isset($orderCache['order_id'])) { return app('json')->fail('该订单无法支付'); } $order_id = $orderCache['order_id']; if (strpos($orderCache['order_id'], '_')) { $orderArr = explode('_', $orderCache['order_id']); if (count($orderArr) == 2) { $order_id = $orderArr[1] ?? $order_id; } } $payType = isset($orderCache['other_pay_type']) && $orderCache['other_pay_type'] == true; if ($payType) { $orderInfo = $services->getOne(['order_id' => $order_id, 'is_del' => 0, 'paid' => 0]); } else { $orderInfo = $this->services->get(['order_id' => $order_id, 'paid' => 0, 'is_del' => 0]); } if (!$orderInfo) { return app('json')->fail('订单支付状态有误,无法进行支付'); } if (!$quitUrl) { return app('json')->fail('请传入支付宝支付回调URL'); } $payInfo = $payServices->alipayOrder($orderInfo->toArray(), $quitUrl); return app('json')->success(['pay_content' => $payInfo]); } /** * 订单列表 * @param Request $request * @return mixed */ public function lst(Request $request) { $where = $request->getMore([ ['type', '', '', 'status'], ['search', '', '', 'real_name'], ['refund_type', '', '', 'refundTypes'] ]); $where['uid'] = $request->uid(); $where['is_del'] = 0; $where['is_system_del'] = 0; if ($where['status'] === '') { $where['pid'] = 0; } elseif (in_array($where['status'], [-1, -2, -3])) { $where['not_pid'] = 1; } elseif (in_array($where['status'], [0, 1, 2, 3, 4])) { $where['pid'] = 0; } $field = ['id', 'type', 'pid', 'order_id']; $list = $this->services->getOrderApiList($where); return app('json')->successful($list); } /** * 订单详情 * @param Request $request * @param StoreOrderEconomizeServices $services * @param StoreOrderPromotionsServices $storeOrderPromotiosServices * @param $uni * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function detail(Request $request, StoreOrderEconomizeServices $services, StoreOrderPromotionsServices $storeOrderPromotiosServices, $uni) { if (!strlen(trim($uni))) return app('json')->fail('参数错误'); $order = $this->services->getUserOrderDetail($uni, (int)$request->uid(), ['invoice', 'refund' => function ($query) { $query->field('id,store_order_id,refunded_price,refund_explain'); }]); if (!$order) return app('json')->fail('订单不存在'); if ($order['pid'] == -1) return app('json')->make(403, '订单已被拆分为多个订单,请查看订单列表'); $order = $order->toArray(); $order['split'] = []; //门店是否开启 || 门店自提是否开启 if (!sys_config('store_func_status', 1) || !sys_config('store_self_mention')) { //关闭门店自提后 订单隐藏门店信息 $order['shipping_type'] = 1; } if ($order['verify_code']) { $verify_code = $order['verify_code']; $verify[] = substr($verify_code, 0, 4); $verify[] = substr($verify_code, 4, 4); $verify[] = substr($verify_code, 8); $order['_verify_code'] = implode(' ', $verify); } //收银台订单 用户无信息 手机号 if ($order['shipping_type'] == 4 && $order['uid'] && !$order['real_name']) { /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); $userInfo = $userServices->getUserCacheInfo((int)$order['uid']); $order['real_name'] = $userInfo['nickname']; $order['user_phone'] = $userInfo['phone']; } $order['add_time_y'] = date('Y-m-d', $order['add_time']); $order['add_time_h'] = date('H:i:s', $order['add_time']); $order['system_store'] = false; $order['refunded_price'] = $order['refund'][0]['refunded_price'] ?? 0; $order['refund_explain'] = $order['refund'][0]['refund_explain'] ?? ''; unset($order['refund']); if (!$order['store_id'] && $order['shipping_type'] == 2) { $order['store_id'] = $this->services->value(['pid' => $order['id']], 'store_id'); } if ($order['store_id']) { /** @var SystemStoreServices $storeServices */ $storeServices = app()->make(SystemStoreServices::class); $order['system_store'] = $storeServices->getStoreDisposeCache($order['store_id']); } $order['mapKey'] = sys_config('tengxun_map_key'); $order['yue_pay_status'] = (int)sys_config('balance_func_status') && (int)sys_config('yue_pay_status') == 1 ? (int)1 : (int)2;//余额支付 1 开启 2 关闭 $order['pay_weixin_open'] = (int)sys_config('pay_weixin_open') ?? 0;//微信支付 1 开启 0 关闭 $order['ali_pay_status'] = (bool)sys_config('ali_pay_status');//支付包支付 1 开启 0 关闭 $orderData = $this->services->tidyOrder($order, true, true); //核算优惠金额 $vipTruePrice = 0; $refund_num = 0; foreach ($orderData['cartInfo'] ?? [] as $key => &$cart) { $vipTruePrice = bcadd((string)$vipTruePrice, (string)$cart['vip_sum_truePrice'], 2); $refund_num = bcadd((string)$refund_num, (string)$cart['refund_num'], 0); } $orderData['vip_true_price'] = $vipTruePrice; $orderData['total_price'] = floatval(bcsub((string)$orderData['total_price'], (string)$vipTruePrice, 2)); //优惠活动优惠详情 $orderData['promotions_detail'] = $storeOrderPromotiosServices->getOrderPromotionsDetail((int)$order['id']); //同步查询订单商品为查询到 查询缓存信息 if (!$orderData['cartInfo']) { $cartGroup = $this->services->getCacheOrderInfo((int)$order['uid'], $order['unique']); $orderData['cartInfo'] = $cartGroup['cartInfo'] ?? []; } $economize = $services->get(['order_id' => $order['order_id']], ['postage_price', 'member_price']); if ($economize) { $orderData['postage_price'] = $economize['postage_price']; $orderData['member_price'] = $economize['member_price']; } else { $orderData['postage_price'] = 0; $orderData['member_price'] = 0; } $orderData['routine_contact_type'] = sys_config('routine_contact_type', 0); /** @var UserInvoiceServices $userInvoice */ $userInvoice = app()->make(UserInvoiceServices::class); $invoice_func = $userInvoice->invoiceFuncStatus(); $orderData['invoice_func'] = $invoice_func['invoice_func']; $orderData['special_invoice'] = $invoice_func['special_invoice']; $orderData['refund_cartInfo'] = []; $orderData['refund_total_num'] = $orderData['total_num']; $orderData['refund_pay_price'] = $orderData['pay_price']; $orderData['is_apply_refund'] = $orderData['total_num'] > $refund_num; $orderData['is_batch_refund'] = count($orderData['cartInfo']) > 1; $orderData['pinkStatus'] = null; if ($orderData['type'] == 3) { /** @var StorePinkServices $pinkService */ $pinkService = app()->make(StorePinkServices::class); $orderData['pinkStatus'] = $pinkService->value(['order_id' => $orderData['order_id']], 'status'); } /** @var StoreOrderStatusServices $statusServices */ $statusServices = app()->make(StoreOrderStatusServices::class); $log = $statusServices->getColumn(['oid' => $order['id']], 'change_time', 'change_type'); if (isset($log['delivery'])) { $delivery = date('Y-m-d', $log['delivery']); } elseif (isset($log['delivery_goods'])) { $delivery = date('Y-m-d', $log['delivery_goods']); } elseif (isset($log['delivery_fictitious'])) { $delivery = date('Y-m-d', $log['delivery_fictitious']); } else { $delivery = ''; } $orderData['order_log'] = [ 'create' => isset($log['cache_key_create_order']) ? date('Y-m-d', $log['cache_key_create_order']) : '', 'pay' => isset($log['pay_success']) ? date('Y-m-d', $log['pay_success']) : '', 'delivery' => $delivery, 'take' => isset($log['take_delivery']) ? date('Y-m-d', $log['take_delivery']) : '', 'complete' => isset($log['check_order_over']) ? date('Y-m-d', $log['check_order_over']) : '', ]; if ($orderData['give_coupon']) { $couponIds = is_string($orderData['give_coupon']) ? explode(',', $orderData['give_coupon']) : $orderData['give_coupon']; /** @var StoreCouponIssueServices $couponIssueService */ $couponIssueService = app()->make(StoreCouponIssueServices::class); $orderData['give_coupon'] = $couponIssueService->getColumn([['id', 'IN', $couponIds]], 'id,coupon_title'); } $orderData['write_off'] = $orderData['write_times'] = 0; $orderData['write_day'] = ''; $cart = $orderData['cartInfo'][0] ?? []; if ($orderData['product_type'] == 4 && $cart) {//次卡商品 $orderData['write_off'] = $cart['write_off'] ?? max(bcsub((string)$cart['write_times'], (string)$cart['write_surplus_times'], 0), 0); $orderData['write_times'] = $cart['write_times'] ?? 0; $start = $cart['write_start'] ?? 0; $end = $cart['write_end'] ?? 0; if (!$start && !$end) { $orderData['write_day'] = '不限时'; } else { $orderData['write_day'] = ($start ? date('Y-m-d', $start) : '') . '/' . ($end ? date('Y-m-d', $end) : ''); } } // 判断是否开启小程序订单管理 $orderData['order_shipping_open'] = false; if (sys_config('order_shipping_open', 0) && MiniProgram::isManaged() && $order['is_channel'] == 1 && $order['pay_type'] == 'weixin') { // 判断是否存在子未收货子订单 if ($order['pid'] > 0) { if ($this->services->checkSubOrderNotTake((int)$order['pid'], (int)$order['id'])) { $orderData['order_shipping_open'] = true; } } else { $orderData['order_shipping_open'] = true; } } return app('json')->successful('ok', $orderData); } /** * 配送订单详情 * @param Request $request * @param $id * @return mixed */ public function deliveryOrderDetail(Request $request, $id) { if (!strlen(trim($id))) return app('json')->fail('参数错误'); $uid = (int)$request->uid(); $order = $this->services->getOne(['id' => $id, 'uid' => $uid, 'is_del' => 0], 'id,pid,order_id,status,delivery_type,delivery_id,delivery_name', ['deliveryOrder' => function ($query) { $query->field('id,oid,station_type,order_id,user_name,receiver_phone,to_address,delivery_no,finish_code,distance,fee,status'); }]); if (!$order) return app('json')->fail('订单不存在'); $order = $order->toArray(); /** @var StoreOrderStatusServices $statusServices */ $statusServices = app()->make(StoreOrderStatusServices::class); $log = $statusServices->getColumn(['oid' => $order['id']], 'change_time', 'change_type'); /** @var StoreDeliveryOrderServices $deliverOrderSerives */ $deliverOrderSerives = app()->make(StoreDeliveryOrderServices::class); $message = $deliverOrderSerives->getStatusMsg(); $city_delivery = []; foreach ($log as $key => $value) { if (strpos($key, 'city_delivery') !== false) { $key = str_replace('city_delivery_', '', $key); $city_delivery[] = [ 'time' => date('Y-m-d H:i:s', $value), 'label' => $message[$key] ?? '配送中', ]; } } $order['order_log'] = [ 'create' => isset($log['cache_key_create_order']) ? date('Y-m-d', $log['cache_key_create_order']) : '', 'pay' => isset($log['pay_success']) ? date('Y-m-d', $log['pay_success']) : '', 'city_delivery' => $city_delivery, 'take' => isset($log['take_delivery']) ? date('Y-m-d', $log['take_delivery']) : '', 'complete' => isset($log['check_order_over']) ? date('Y-m-d', $log['check_order_over']) : '', ]; return app('json')->successful('ok', $order); } /** * 订单删除 * @param Request $request * @return mixed */ public function del(Request $request) { [$uni] = $request->postMore([ ['uni', ''], ], true); if (!$uni) return app('json')->fail('参数错误!'); $res = $this->services->removeOrder($uni, (int)$request->uid()); if ($res) { return app('json')->successful(); } else { return app('json')->fail('删除失败'); } } /** * 订单收货 * @param Request $request * @return mixed */ public function take(Request $request, StoreOrderTakeServices $services, StoreCouponIssueServices $issueServices) { [$uni] = $request->postMore([ ['uni', ''], ], true); if (!$uni) return app('json')->fail('参数错误!'); $order = $services->takeOrder($uni, (int)$request->uid()); if ($order) { return app('json')->successful('收货成功'); } else return app('json')->fail('收货失败'); } /** * 订单 查看物流 * @param Request $request * @param StoreOrderCartInfoServices $services * @param ExpressServices $expressServices * @param $uni * @param string $type * @return mixed */ public function express(Request $request, StoreOrderCartInfoServices $services, ExpressServices $expressServices, $uni, $type = '') { if ($type == 'refund') { /** @var StoreOrderRefundServices $refundService */ $refundService = app()->make(StoreOrderRefundServices::class); $order = $refundService->refundDetail($uni); $express = $order['refund_express']; $cacheName = $uni . $express; $orderInfo = []; $info = []; $cartNew = []; foreach ($order['cart_info'] as $k => $cart) { $cartNew['cart_num'] = $cart['cart_num']; $cartNew['truePrice'] = $order['type'] == 8 ? 0 : $cart['truePrice']; $cartNew['productInfo']['image'] = $cart['productInfo']['image']; $cartNew['productInfo']['store_name'] = $cart['productInfo']['store_name']; $cartNew['productInfo']['unit_name'] = $cart['productInfo']['unit_name'] ?? ''; array_push($info, $cartNew); unset($cart); } $orderInfo['cartInfo'] = $info; $orderInfo['delivery_id'] = $express; $orderInfo['delivery_name'] = $order['refund_express_name']; $orderInfo['delivery_code'] = ''; $orderInfo['user_address'] = $order['user_address']; $orderInfo['user_mark'] = $order['refund_explain']; } else { if (!$uni || !($order = $this->services->getUserOrderDetail($uni, $request->uid()))) return app('json')->fail('查询订单不存在!'); if ($type != 'refund') { if ($order['delivery_type'] != 'express') return app('json')->fail('该订单不是快递发货,无法查询物流信息'); if (!$order['delivery_id']) return app('json')->fail('该订单不存在快递单号!'); } $express = $type == 'refund' ? $order['refund_express'] : $order['delivery_id']; $cacheName = $uni . $express; $orderInfo = []; $cartInfo = $services->getCartColunm(['oid' => $order['id']], 'cart_info', 'unique'); $info = []; $cartNew = []; foreach ($cartInfo as $k => $cart) { $cart = json_decode($cart, true); $cartNew['cart_num'] = $cart['cart_num']; $cartNew['truePrice'] = $order['type'] == 8 ? 0 : $cart['truePrice']; $cartNew['productInfo']['image'] = $cart['productInfo']['image']; $cartNew['productInfo']['store_name'] = $cart['productInfo']['store_name']; $cartNew['productInfo']['unit_name'] = $cart['productInfo']['unit_name'] ?? ''; array_push($info, $cartNew); unset($cart); } $orderInfo['delivery_id'] = $express; $orderInfo['delivery_name'] = $type == 'refund' ? '用户退回' : $order['delivery_name'];; $orderInfo['delivery_code'] = $type == 'refund' ? '' : $order['delivery_code']; $orderInfo['delivery_type'] = $order['delivery_type']; $orderInfo['user_address'] = $order['user_address']; $orderInfo['user_mark'] = $order['mark']; $orderInfo['cartInfo'] = $info; } return app('json')->successful([ 'order' => $orderInfo, 'express' => [ 'result' => ['list' => $expressServices->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code']) ] ] ]); } /** * 订单评价 * @param Request $request * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function comment(Request $request, StoreOrderCartInfoServices $cartInfoServices, StoreProductReplyServices $replyServices, StoreOrderCommentServices $storeOrderCommentServices, UserCollageServices $collageservices) { $group = $request->postMore([ ['unique', ''], ['comment', ''], ['pics', ''], ['product_score', 5], ['service_score', 5] ]); $unique = $group['unique']; unset($group['unique']); if (!$unique) return app('json')->fail('参数错误!'); $cartInfo = $cartInfoServices->getOne(['unique' => $unique], 'id,oid,uid'); $uid = (int)$request->uid(); if (!$cartInfo || $uid != $cartInfo['uid']) return app('json')->fail('评价商品不存在!'); $oid = (int)$cartInfo['oid']; if ($replyServices->be(['oid' => $oid, 'unique' => $unique])) return app('json')->fail('该商品已评价!'); //保存评价 $storeOrderCommentServices->comment($oid, $uid, $group, $unique); //修改拼单、桌码记录状态 $order = $this->services->get($oid, ['type', 'activity_id']); if (in_array($order['type'], [9, 10])) { $collageservices->update($order['activity_id'], ['status' => 3]); } //缓存抽奖次数 /** @var LuckLotteryServices $luckLotteryServices */ $luckLotteryServices = app()->make(LuckLotteryServices::class); $luckLotteryServices->setCacheLotteryNum($uid, 'comment'); $lottery = $luckLotteryServices->getFactorLottery(4); if (!$lottery) { return app('json')->successful(['to_lottery' => false]); } $lottery = $lottery->toArray(); try { $luckLotteryServices->checkoutUserAuth($uid, (int)$lottery['id'], [], $lottery); $lottery_num = $luckLotteryServices->getLotteryNum($uid, (int)$lottery['id'], [], $lottery); if ($lottery_num > 0) return app('json')->successful(['to_lottery' => true]); } catch (\Exception $e) { return app('json')->successful(['to_lottery' => false]); } } /** * 订单统计数据 * @param Request $request * @return mixed */ public function data(Request $request) { return app('json')->successful($this->services->getOrderData((int)$request->uid())); } /** * 订单退款理由 * @return mixed */ public function refund_reason() { $reason = sys_config('stor_reason') ?: [];//退款理由 $reason = str_replace("\r\n", "\n", $reason);//防止不兼容 $reason = explode("\n", $reason); return app('json')->successful($reason); } /** * 获取退货商品列表 * @param StoreOrderCartInfoServices $services * @param $id * @return mixed */ public function refundCartInfo(Request $request, StoreOrderCartInfoServices $services, $id) { if (!$id) { return app('json')->fail('缺少发货ID'); } [$cart_ids] = $request->postMore([ ['cart_ids', []] ], true); $list = $services->getRefundCartList((int)$id); if ($cart_ids) { foreach ($cart_ids as $cart) { if (!isset($cart['cart_id']) || !$cart['cart_id'] || !isset($cart['cart_num']) || !$cart['cart_num'] || $cart['cart_num'] <= 0) { return app('json')->fail('请重新选择退款商品,或件数'); } } $cart_ids = array_combine(array_column($cart_ids, 'cart_id'), $cart_ids); foreach ($list as &$item) { if (isset($cart_ids[$item['cart_id']]['cart_num'])) $item['cart_num'] = $cart_ids[$item['cart_id']]['cart_num']; } } return app('json')->success($list); } /** * 获取退货商品列表 * @param StoreOrderCartInfoServices $services * @param $id * @return mixed */ public function refundCartInfoList(Request $request) { [$cart_ids, $id] = $request->postMore([ ['cart_ids', []], ['id', 0], ], true); if (!$id) { return app('json')->fail('缺少发货ID'); } return app('json')->success($this->services->refundCartInfoList((array)$cart_ids, (int)$id)); } /** * 用户申请退款 * @param Request $request * @return mixed */ public function applyRefund(Request $request, StoreOrderRefundServices $services, StoreOrderServices $storeOrderServices, $id) { if (!$id) { return app('json')->fail('缺少参数!'); } $data = $request->postMore([ ['text', ''], ['refund_reason_wap_img', ''], ['refund_reason_wap_explain', ''], ['refund_type', 1], ['refund_price', 0.00], ['cart_ids', []] ]); if ($data['text'] == '') return app('json')->fail('参数错误!'); if ($data['cart_ids']) { foreach ($data['cart_ids'] as $cart) { if (!isset($cart['cart_id']) || !$cart['cart_id'] || !isset($cart['cart_num']) || !$cart['cart_num']) { return app('json')->fail('请重新选择退款商品,或件数'); } } } $order = $storeOrderServices->get($id); $uid = (int)$request->uid(); if (!$order || $uid != $order['uid']) { return app('json')->fail('订单不存在!'); } if (!$order['paid']) { return app('json')->fail('请先完成支付!'); } // 开启 ERP 发货后不能申请退货 if (sys_config('erp_open') && $storeOrderServices->getDeliverNum($id, $order)) { return app('json')->fail('订单已发货, 不能申请退货!'); } $refundData = [ 'refund_reason' => $data['text'], 'refund_explain' => $data['refund_reason_wap_explain'], 'refund_img' => json_encode($data['refund_reason_wap_img'] != '' ? explode(',', $data['refund_reason_wap_img']) : []), ]; $res = $services->applyRefund((int)$id, $uid, $order, $data['cart_ids'], (int)$data['refund_type'], (float)$data['refund_price'], $refundData); if ($res) return app('json')->successful('提交申请成功'); else return app('json')->fail('提交失败'); } /** * 用户申请退款 * @param Request $request * @return mixed */ public function refund_verify(Request $request, StoreOrderRefundServices $services) { $data = $request->postMore([ ['text', ''], ['refund_reason_wap_img', ''], ['refund_reason_wap_explain', ''], ['uni', ''], ['refund_type', 1], ['refund_price', 0.00], ['cart_ids', []] ]); $uni = $data['uni']; unset($data['uni']); if (!$uni || $data['text'] == '') return app('json')->fail('参数错误!'); $refundData = [ 'refund_reason' => $data['text'], 'refund_explain' => $data['refund_reason_wap_explain'], 'refund_img' => json_encode($data['refund_reason_wap_img'] != '' ? explode(',', $data['refund_reason_wap_img']) : []), ]; $order = $this->services->getUserOrderDetail($uni, (int)$request->uid()); if (!$order) { return app('json')->fail('订单不存在!'); } if (!$order['paid']) { return app('json')->fail('请先完成支付!'); } $uid = (int)$request->uid(); $res = $services->applyRefund((int)$order['id'], $uid, $order, $data['cart_ids'], (int)$data['refund_type'], (float)$data['refund_price'], $refundData); if ($res) return app('json')->successful('提交申请成功'); else return app('json')->fail('提交失败'); } /** * 用户退货提交快递单号 * @param Request $request * @param StoreOrderRefundServices $services * @return mixed */ public function refund_express(Request $request, StoreOrderRefundServices $services) { $data = $request->postMore([ ['id', ''], ['refund_express', ''], ['refund_phone', ''], ['refund_express_name', ''], ['refund_img', '', '', 'refund_goods_img'], ['refund_explain', '', '', 'refund_goods_explain'], ]); if ($data['id'] == '') return app('json')->fail('参数错误!'); $data['refund_goods_img'] = json_encode($data['refund_goods_img'] != '' ? explode(',', $data['refund_goods_img']) : []); $res = $services->editRefundExpress($data); if ($res) return app('json')->successful('提交成功'); else return app('json')->fail('提交失败'); } /** * 订单取消 未支付的订单回退积分,回退优惠券,回退库存 * @param Request $request * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function cancel(Request $request) { [$id] = $request->postMore([ ['id', 0] ], true); if (!$id) return app('json')->fail('参数错误'); if ($this->services->cancelOrder($id, (int)$request->uid())) return app('json')->successful('取消订单成功'); return app('json')->fail('取消订单失败'); } /** * 订单商品信息 * @param Request $request * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function product(Request $request, StoreOrderCartInfoServices $services) { [$unique] = $request->postMore([ ['unique', ''] ], true); if (!$unique || !($cartInfo = $services->getOne(['unique' => $unique]))) return app('json')->fail('评价商品不存在!'); $cartInfo = $cartInfo->toArray(); $cartProduct = []; $cartProduct['cart_num'] = $cartInfo['cart_info']['cart_num']; $cartProduct['productInfo']['image'] = get_thumb_water($cartInfo['cart_info']['productInfo']['image'] ?? ''); $cartProduct['productInfo']['price'] = $cartInfo['cart_info']['productInfo']['price'] ?? 0; $cartProduct['productInfo']['store_name'] = $cartInfo['cart_info']['productInfo']['store_name'] ?? ''; if (isset($cartInfo['cart_info']['productInfo']['attrInfo'])) { $cartProduct['productInfo']['attrInfo']['product_id'] = $cartInfo['cart_info']['productInfo']['attrInfo']['product_id'] ?? ''; $cartProduct['productInfo']['attrInfo']['suk'] = $cartInfo['cart_info']['productInfo']['attrInfo']['suk'] ?? ''; $cartProduct['productInfo']['attrInfo']['price'] = $cartInfo['cart_info']['productInfo']['attrInfo']['price'] ?? ''; $cartProduct['productInfo']['attrInfo']['image'] = get_thumb_water($cartInfo['cart_info']['productInfo']['attrInfo']['image'] ?? ''); } $cartProduct['product_id'] = $cartInfo['cart_info']['product_id'] ?? 0; $cartProduct['type'] = $cartInfo['cart_info']['type'] ?? 0; $cartProduct['activity_id'] = $cartInfo['cart_info']['activity_id'] ?? 0; $cartProduct['order_id'] = $this->services->value(['id' => $cartInfo['oid']], 'order_id'); return app('json')->successful($cartProduct); } /** * 门店线上支付订单详情 * @param Request $request * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function payCashierOrder(Request $request) { [$store_id] = $request->postMore([ ['store_id', ''] ], true); $uid = $request->uid(); return app('json')->successful($this->services->payCashierOrder((int)$store_id, (int)$uid)); } /**订单核销记录 * @param Request $request * @param StoreOrderWriteOffServices $services * @return \think\Response * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function writeOffRecords(Request $request, StoreOrderWriteOffServices $services, $id) { if (!$id) return app('json')->fail('参数错误'); $uid = $request->uid(); return app('json')->successful($services->userOrderWriteOffRecords(['oid'=>$id, 'uid'=>$uid])); } }