'0', // 商品原始总价 'goods_total_price' => '0', // 商品总价 'coupon_discount_fee' => '0', // 优惠券优惠金额 'discount_price' => 0, // 当前订单,总优惠金额(优惠券 + 活动优惠) 'coupon' => null, // 所使用的优惠券 'coupon_goods_ids' => [], 'dispatch_price' => '0', // 运费总价 'score_amount' => 0, // 订单总积分 'order_total_price' => 0, // 订单总费用 'real_price' => 0, // 应支付总金额 (减去优惠之后的) "vip_discount_price"=>0,//会员优惠 "score_fee"=>0,//支付积分 'goods_count'=>0, 'user_id'=>0, 'live_id'=>'', 'live_goods_action_id'=>'' ]; protected $scoreGoodsModel = null; public function __construct($params = []) { $this->user = user_info(); if($this->user){ $this->orderData['user_id'] = $this->user->id; } if($params){ $this->calcParams($params); } } /** * 创建订单 * @param $result * @return mixed */ public function createOrder($result) { $order = $this->createHandle($result); return $order; } /** * 创建订单 * @param $result * @return mixed */ public function createHandle($orderCalculate=[],$orderSource='') { //订单来源 if(!$orderSource){ $orderSource = \app\common\library\Platform::getPlatform(); } // 如果需要支付积分,扣除积分 if ($this->order_type=='score' && $orderCalculate['score_amount']) { //扣积分 $user = \app\common\model\User::getUserInfo($this->user->id); if(!$user || $user['score'] < $orderCalculate['score_amount']){ //抛出异常 积分不足 new \app\common\exception\Exception('当前积分余额不足'); } \app\common\model\User::score((-1 * $orderCalculate['score_amount']),$this->user->id,"积分兑换商品"); } $order = Db::transaction(function () use ($orderCalculate,$orderSource) { $orderData = []; $orderData['order_no'] = orderModel::getSn($this->user->id ?? 0); $orderData['user_id'] = $this->user->id ?? 0; $orderData['need_post'] = 0; $orderData['order_type'] = $this->order_type; $orderData['goods_total_price_marking'] = $this->orderData['goods_total_price_marking']; $orderData['goods_total_price'] = $this->orderData['goods_total_price']; $orderData['dispatch_price'] = $this->orderData['dispatch_price']; $orderData['order_total_price'] = $this->orderData['order_total_price']; $orderData['real_price'] = $this->orderData['real_price']; $orderData['discount_price'] = $this->orderData['discount_price']; $orderData['goods_count'] = $orderCalculate['goods_count']; $orderData['vip_discount_price'] = $this->orderData['vip_discount_price']; $orderData['coupon_discount_fee'] = $this->orderData['coupon_discount_fee'] ?? 0; $orderData['coupon_user_id'] = isset($orderCalculate['coupon']) && $orderCalculate['coupon'] ? $orderCalculate['coupon']['id'] : 0; $orderData['coupon_id'] = isset($orderCalculate['coupon']) && $orderCalculate['coupon']->coupon->id ? $orderCalculate['coupon']->coupon->id : 0; $orderData['status'] = \app\common\constant\order\Status::STATUS_UNPAID; $orderData['buyer_remark'] = $this->remark ?? ''; $orderData['source'] = $orderSource; $orderData['uniacid'] = UNIACID; $orderData['createtime'] = time(); $orderData['live_id'] = $this->orderData['live_id']; $orderData['score_amount'] = $orderCalculate['score_amount']; $orderData['score_fee'] = $orderCalculate['score_amount']; $orderData['is_virtual_pay'] = isset($orderCalculate['is_virtual_pay']) ? intval($orderCalculate['is_virtual_pay']) : 0; if ($orderData['is_virtual_pay'] && $orderData['real_price'] < 1) { $orderData['real_price'] = 1; } $order = orderModel::insertGetId($orderData); // 将优惠券使用掉 if (isset($orderCalculate['coupon']) && $orderCalculate['coupon']) { $orderCalculate['coupon']->use_order_id = $order; $orderCalculate['coupon']->use_time = time(); $orderCalculate['coupon']->allowField(true)->save(); } // 添加 订单 item(使用原始goodsList,不乘汇率) foreach ($this->goodsList as $key => $buyinfo) { $item = []; $item['item_id'] = $buyinfo['item_id']; $item['item_name'] = $buyinfo['item_name']; $item['count'] = $buyinfo['count']; $item['total_price_marking'] = $buyinfo['total_price_marking']; $item['total_price'] = $buyinfo['total_price']; $item['goods_type'] = $buyinfo['goodsType']; $item['unit_price'] = $buyinfo['unit_price']; $item['discount_price'] = $buyinfo['discount_price']; $item['real_price'] = $buyinfo['real_price']; if ($orderData['is_virtual_pay'] && $item['real_price'] < 1) { $item['real_price'] = 1; } $item['snapshoot'] = is_array($buyinfo['snapshoot']) ? json_encode($buyinfo['snapshoot']) : $buyinfo['snapshoot']; $item['vip_discount_price'] = $buyinfo['vip_discount_price']; $item['coupon_discount_fee'] = $buyinfo['coupon_discount_fee']; $item['createtime'] = $orderData['createtime']; $item['send_status'] = $orderData['status']; $item['order_no'] = $orderData['order_no']; $item['user_id'] = $orderData['user_id']; $item['score_amount'] = $orderData['score_amount']; if($this->order_type == 'vipcard' || $this->order_type == 'activity' || $this->order_type == 'live_gift'){ $item['extend_data'] = $buyinfo['extend_data']; } $item['uniacid'] = UNIACID; OrderItem::insert($item); if($item['goods_type'] == 'activity'){ $ticketInfo = json_decode($item['snapshoot'],true); if($ticketInfo['form_user_id'] != $item['user_id']){ throw new \app\common\exception\Exception('报名信息错误,请返回重试'); } } } // 保存订单地址(实物商品) if ($this->order_type == 'physical' && isset($this->orderData['address_id']) && $this->orderData['address_id']) { $this->saveOrderAddress($order, $orderData); } if($orderSource == 'channels' && \app\common\library\Platform::getSystemType() == 'single' && \app\admin\library\project\App::isInstall('channels')){ $hookParams = [ 'params'=>$orderCalculate['channels_params'], 'order'=>$orderData ]; \think\Hook::listen('channels_order_push',$hookParams); } // 重新获取订单 $order = orderModel::where('id', $order)->find(); \app\common\model\order\Log::set($orderData['order_no'],"订单创建完成,等待支付"); \think\Hook::listen('agent',$orderData['order_no']); //同步订单号到直播商品 if($this->orderData['live_goods_action_id']){ $liveGoodsAction = [ 'live_goods_action_id'=>$this->orderData['live_goods_action_id'], 'order_no'=>$orderData['order_no'], 'user_id'=>$orderData['user_id'] ]; \think\Hook::listen('live_goods_order',$liveGoodsAction); } return $order; }); return $order; } /** * 获取请求参数,初始化,并设置默认值 * * @param array $params * @return array */ public function calcParams($params) { $this->order_type = $params['order_type'] ?? 'goods'; if($this->order_type == 'score'){ $this->scoreGoodsModel = new \app\api\model\app\score\Goods; } $this->goodsList = $params['goods_list'] ?? []; $this->coupon_id = $params['coupon_id'] ?? 0; $this->remark = $params['buyer_remark'] ?? ''; $this->money = (isset($params['money']) && $params['money'] > 0) ? $params['money'] : 0; $this->orderData['live_goods_action_id'] = ''; if(isset($params['live_id'])){ $this->orderData['live_id'] = $params['live_id']; } if(isset($params['live_goods_action_id'])){ $this->orderData['live_goods_action_id'] = $params['live_goods_action_id']; } if(isset($params['address_id'])){ $this->orderData['address_id'] = $params['address_id']; } // 获取商品信息 $this->goodsListInit(); } /** * 格式化订单商品 * @return void */ public function goodsListInit() { foreach ($this->goodsList as $key => &$buyinfo) { $buyinfo['extend'] = isset($buyinfo['extend']) ? $buyinfo['extend'] : ''; $detail = Handle::getGoodsDetail($buyinfo['goodsId'],$buyinfo['goodsType'],$buyinfo['count'],$buyinfo['extend']); if (!$detail || $detail['status'] != 1) { throw new Exception('商品不存在或已下架'); } if($buyinfo['goodsType'] == 'vipcard'){ $buyinfo['goodsId'] = explode("_",$buyinfo['goodsId'])[0]; } if($buyinfo['goodsType'] == 'physical'){ $buyinfo['goodsId'] = explode("_",$buyinfo['goodsId'])[0]; } if($this->order_type == 'score'){ $detail['score_goods'] = $this->scoreGoodsModel->where([ 'goods_id'=>$buyinfo['goodsId'] ])->find(); } $buyinfo['coupon_discount_fee'] = 0; $buyinfo['discount_price'] = 0; $buyinfo['detail'] = $detail; // $this->goodsList[] = $buyinfo; // $buyinfo['goods'] = $buyinfo; } } /** * 是否计算促销 * * @return bool */ private function isCalcPromos() { if ($this->order_type == 'score') { return false; // 积分商品不能参与促销 } else { return true; } } /** * 计算订单 * * @return void */ public function calc($calc_type = 'calc') { $this->calc_type = $calc_type; // 检查系统必要条件 // check_env(['bcmath', 'queue']); // 检查是否可下单 $this->calcCheck(); // 计算订单各种费用 $this->calcAmount(); // 计算优惠券费用 if ($this->coupon_id) { $this->calcCoupon(); } foreach ($this->goodsList as $key => $buyinfo) { //单个商品的优惠金额 $this->goodsList[$key]['real_price'] = $this->goodsList[$key]['total_price'] - $this->goodsList[$key]['discount_price']; } // 订单应付金额 $this->orderData['order_total_price'] = bcadd($this->orderData['goods_total_price'], $this->orderData['dispatch_price'], 2); $this->orderData['discount_price'] = bcadd($this->orderData['coupon_discount_fee'], $this->orderData['vip_discount_price'], 2); $this->orderData['real_price'] = bcsub($this->orderData['order_total_price'], $this->orderData['discount_price'], 2); $this->orderData['real_price'] = $this->orderData['real_price'] < 0 ? 0 : $this->orderData['real_price']; return $this->calcReturn(); } /** * 返回订单数据 * @return []|array */ public function calcReturn() { $isVirtualPay = $this->isUseVirtualPay(); $result = [ 'goods_total_price_marking' => $this->orderData['goods_total_price_marking'], 'vip_discount_price'=>$this->orderData['vip_discount_price'], 'goods_total_price' => $this->orderData['goods_total_price'], 'dispatch_price' => $this->orderData['dispatch_price'], 'order_total_price' => $this->orderData['order_total_price'], 'real_price' => $this->orderData['real_price'], 'discount_price' => $this->orderData['discount_price'], 'coupon_discount_fee' => $this->orderData['coupon_discount_fee'] ]; // 处理小数点保留两位小数 foreach ($result as $key => $amount) { $result[$key] = number_format($amount, 2, '.', ''); } $orderGoodsList = $this->goodsList; if ($isVirtualPay) { $result = $this->convertVirtualPayResultPrices($result); $orderGoodsList = $this->convertVirtualPayGoodsPrices($orderGoodsList); } // 合并不需要处理小数点的 $result = array_merge($result, [ 'score_amount' => $this->orderData['score_amount'], 'goods_count' => $this->orderData['goods_count'], 'is_virtual_pay' => $isVirtualPay, 'orderGoodsList' => $orderGoodsList ]); // 如果是下单,合并 优惠券, 收货地址 if ($this->calc_type == 'create') { $result = array_merge($result, [ "coupon" => $this->orderData['coupon'] ]); } else { $result = array_merge($result, ['msg' => $this->msg]); } return $result; } /** * 转换订单金额字段为代币展示金额。 * @param array $result * @return array */ protected function convertVirtualPayResultPrices($result) { return \app\common\library\pay\VirtualPayService::convertPriceFields($result, [ 'goods_total_price_marking', 'vip_discount_price', 'goods_total_price', 'dispatch_price', 'order_total_price', 'real_price', 'discount_price', 'coupon_discount_fee' ]); } /** * 转换订单商品金额字段为代币展示金额。 * @param array $goodsList * @return array */ protected function convertVirtualPayGoodsPrices($goodsList) { foreach ($goodsList as &$buyinfo) { $buyinfo = \app\common\library\pay\VirtualPayService::convertPriceFields($buyinfo, [ 'coupon_discount_fee', 'discount_price', 'real_price', 'total_price_marking', 'total_price', 'unit_price', 'vip_discount_price' ]); if (isset($buyinfo['detail'])) { $detail = $buyinfo['detail']; if (!is_array($detail)) { $detail = $detail instanceof \think\Model ? $detail->toArray() : (array)$detail; } $detail = \app\common\library\pay\VirtualPayService::convertPriceFields($detail, [ 'price', 'price_marking', 'pay_price', 'min_price' ]); $buyinfo['detail'] = $detail; $buyinfo['snapshoot'] = json_encode($detail); } } unset($buyinfo); return $goodsList; } /** * 根据订单内商品实际类型判断是否使用微信虚拟支付。 * @return int */ protected function isUseVirtualPay() { foreach ($this->goodsList as $buyinfo) { $goodsType = isset($buyinfo['detail']['type']) ? $buyinfo['detail']['type'] : ($buyinfo['goodsType'] ?? ''); if (!$goodsType) { continue; } if (\app\common\library\pay\VirtualPayService::isUseVirtualPay($goodsType)) { return 1; } } return 0; } /** * 计算优惠券的优惠 * * @return void */ public function calcCoupon() { // 获取优惠券 $this->getCoupon($this->coupon_id); if ($this->orderData['coupon']) { $this->orderData['coupon']->coupon_money = $this->orderData['coupon']->coupon_money > $this->orderData['goods_total_price'] ? $this->orderData['goods_total_price'] : $this->orderData['coupon']->coupon_money; $this->orderData['coupon_discount_fee'] = $this->orderData['coupon']->coupon_money; // 获取优惠券时计算的金额 $this->orderData['coupon_goods_ids'] = $this->orderData['coupon']->goods_ids; // 获取优惠券时参与的商品 // 将当前优惠券优惠金额平分到使用优惠券的商品上 foreach ($this->goodsList as &$buyInfo) { if (in_array($buyInfo['goodsId'], $this->orderData['coupon_goods_ids'])) { $avgDiscountPrice = bcdiv($this->orderData['coupon_discount_fee'], $this->orderData['goods_total_price'], 6); $buyInfo['coupon_discount_fee'] = bcmul($buyInfo['total_price'], $avgDiscountPrice, 6); $buyInfo['coupon_discount_fee'] = round($buyInfo['coupon_discount_fee'], 2); $buyInfo['discount_price'] += $buyInfo['coupon_discount_fee']; } } } else { $this->exception('优惠券不可用'); } } /** * 计算订单各种费用 * * @return array */ public function calcAmount() { // 计算商品金额 foreach ($this->goodsList as $key => $buyinfo) { $detail = $buyinfo['detail']; $this->orderData['goods_count'] += $buyinfo['count']; // 当前商品原始总价 $current_goods_total_price_marking = ($detail['price_marking'] * $buyinfo['count']); $this->orderData['goods_total_price_marking'] += $current_goods_total_price_marking; // 当前商品现在总价 // 当前商品所需积分 $current_score_amount = 0; //会员折扣金额 $current_vip_discount_price = 0; $current_goods_total_price = 0; switch ($this->order_type){ case 'score': // 积分商城规格 $current_score_amount = ($detail['score_goods']['score'] * $buyinfo['count']); $this->orderData['score_amount'] += $current_score_amount; $current_goods_total_price = 0; break; case 'activity': // 线下活动 $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; $this->goodsList[$key]['extend_data'] = \fast\Random::numeric(14); break; case 'exercises': // 题库练习 $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; break; case 'live_gift': // 直播礼物 $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; $this->goodsList[$key]['extend_data'] = $buyinfo['extend']['course_id'].'_'.$buyinfo['extend']['message_topic']; break; case 'goods': $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; //获取付费VIP折扣 if($this->user){ $vipUserGoodsDiscount = \app\common\model\app\vip\CardPrivilege::getPrivilegeGoodsDiscount($this->user->id,$detail['id']); if($vipUserGoodsDiscount){ //会员折扣金额 $current_vip_discount_price += number_format(($current_goods_total_price * (10 - $vipUserGoodsDiscount) / 10), 2, '.', '');; } } break; case 'physical': //购买实物商品的订单 规格格式为商品价格_商品数量 $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; $this->goodsList[$key]['extend_data'] = $detail['price'].'_'.$buyinfo['count']; // 检查库存是否满足购买数量 $goodsId = $detail['id'] ?? 0; $specType = $detail['spec_type'] ?? 'single'; $buyCount = $buyinfo['count'] ?? 1; $skuPriceQuery = \app\admin\model\app\physical\SkuPrice::where('goods_id', $goodsId) ->where('uniacid', UNIACID); if ($specType == 'single') { $skuPrice = $skuPriceQuery->order('id', 'asc')->find(); } else { $skuText = $detail['sku_text'] ?? ''; $skuPrice = $skuPriceQuery->where('goods_sku_text', $skuText)->find(); } if (!$skuPrice) { throw new Exception('商品规格不存在'); } if ($skuPrice['stock'] < $buyCount) { throw new Exception('商品库存不足'); } // 检查限购 $goods = \app\admin\model\app\physical\Goods::where('id', $goodsId) ->where('uniacid', UNIACID) ->find(); if ($goods) { $singleLimit = $goods['single_limit'] ?? 0; $lifetimeLimit = $goods['lifetime_limit'] ?? 0; // 检查单次限购 if ($singleLimit > 0 && $buyCount > $singleLimit) { throw new Exception('单次限购' . $singleLimit . '件'); } // 检查终身限购 if ($lifetimeLimit > 0 && $this->user) { $purchasedCount = \app\common\model\order\Item::where('user_id', $this->user->id) ->where('item_id', $goodsId) ->where('goods_type', 'physical') ->where('refund_status', '<>', 3) ->sum('count'); if (($purchasedCount + $buyCount) > $lifetimeLimit) { throw new Exception('终身限购' . $lifetimeLimit . '件,已购买' . $purchasedCount . '件'); } } } break; case 'composite': if (!\app\admin\library\project\App::isInstall('composite')) { throw new \app\common\exception\Exception('组合商品未安装'); } // 组合商品:extend_data 存储规格ID和规格价格的组合 $this->goodsList[$key]['extend_data'] = $detail['spec_id'].'_'.$detail['price']; $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; // 组合原价(划线价) if (isset($detail['price_marking'])) { $current_goods_total_price_marking = ($detail['price_marking'] * $buyinfo['count']); } break; case 'vipcard': //购买会员卡的订单 规格格式为会员卡价格_又下时间 $this->goodsList[$key]['extend_data'] = $detail['price'].'_'.$detail['time']; //判断会员卡配置 换购,状态 $cardConfig = \app\common\model\app\Config::getConfig('vip'); if($cardConfig['status'] != 1){ throw new Exception('会员卡购买通道暂时关闭'); } //付费会员卡逻辑 $userVipInfo = \app\common\model\app\vip\CardUser::getUserVipInfo($this->user->id); //判断会员卡换购状态 if($cardConfig['exchange'] != 1){ if($userVipInfo && $userVipInfo['card_id'] != $detail['id']){ throw new Exception('暂不支持会员卡换购'); } } //限购 if($detail['limit'] != 0){ $orderCount = OrderItem::with(['order'=>function($query){ $query->where([ 'status'=>\app\common\constant\order\Status::STATUS_SUCCESS ]); }])->where([ 'extend_data'=>$this->goodsList[$key]['extend_data'], 'item_id'=>$detail['id'], 'user_id'=>$this->user->id ])->count(); if($orderCount >= $detail['limit']){ throw new Exception("该会员卡规格限购{$detail['limit']}次,当前已购{$orderCount}次"); } } $current_goods_total_price = ($detail['price'] * $buyinfo['count']); $this->orderData['goods_total_price'] += $current_goods_total_price; break; } //会员折扣金额 $this->goodsList[$key]['vip_discount_price'] = $current_vip_discount_price; $this->goodsList[$key]['discount_price'] += $current_vip_discount_price; $this->orderData['vip_discount_price'] += $current_vip_discount_price; //商品划线价格 $this->goodsList[$key]['total_price_marking'] = $current_goods_total_price_marking; //商品总价 $this->goodsList[$key]['total_price'] = $current_goods_total_price; //商品单价 $this->goodsList[$key]['unit_price'] = $detail['price']; $this->goodsList[$key]['item_id'] = $detail['id']; $this->goodsList[$key]['item_name'] = $detail['name']; //积分支付数 $this->goodsList[$key]['score_amount'] = $current_score_amount; $this->goodsList[$key]['snapshoot'] = json_encode($detail); } } /** * 下单前检测,商品状态,秒杀,拼团活动状态,必要的选择项(比如下单收货地址),收货地址等 * * @param array $params,请求参数 * @return array */ public function calcCheck() { if (!count($this->goodsList)) { $this->exception('请选择要购买的商品'); } if ($this->order_type == 'score' && count($this->goodsList) > 1) { $this->exception('积分商品必须单独购买'); } // 购买课程前表单校验 if (\app\admin\library\project\App::isInstall('form')) { foreach ($this->goodsList as $goodsItem) { $goodsId = $goodsItem['goodsId'] ?? 0; if (!$goodsId) continue; // 通过 content_id 匹配,不按 content_type(课程类商品 order 的 goodsType 是 course, // 而 bind 表存储的实际类型如 column/video 等,直接匹配会查不到) $bindForms = \app\admin\model\app\form\Bind::alias('bind') ->join('app_form f', 'bind.form_id = f.id') ->where('bind.content_id', $goodsId) ->where('f.bind_type', 'before_buy') ->where('f.status', 1) ->field('bind.form_id, f.name') ->select(); if (!empty($bindForms)) { foreach ($bindForms as $bindForm) { $submitted = \app\admin\model\app\form\Log::where([ 'form_id' => $bindForm['form_id'], 'user_id' => $this->orderData['user_id'] ])->count(); if (!$submitted) { $this->exception("请先完成购买前表单:{$bindForm['name']}"); } } } } } } /** * 检测用户优惠券是否可用 * * @param array|object $coupon * @param string $type * @return array|object */ private function checkCoupon($coupon) { $can_use = true; $cannot_use_msg = ''; // (积分或者活动 并且 优惠券不支持优惠叠加) if($this->order_type == 'score'){ $can_use = false; $cannot_use_msg = '积分商品不可使用优惠券'; return compact('can_use', 'cannot_use_msg'); } if ($this->orderData['vip_discount_price'] > 0 && $coupon->coupon->double_discount_status == 2) { $can_use = false; $cannot_use_msg = '该优惠券不可与会员叠加使用'; return compact('can_use', 'cannot_use_msg'); } if($coupon->coupon->status == 3){ $can_use = false; $cannot_use_msg = '该优惠券已作废'; return compact('can_use', 'cannot_use_msg'); } $goods_total_price = 0; $goodsIds = []; // 符合优惠券规则的 商品 ids $goods_bind_ids = json_encode($coupon->goods_bind_ids); $goods_bind_ids = str_replace("column","course",$goods_bind_ids); $goods_bind_ids = str_replace("video","course",$goods_bind_ids); $goods_bind_ids = str_replace("article","course",$goods_bind_ids); $goods_bind_ids = str_replace("audio","course",$goods_bind_ids); $goods_bind_ids = str_replace("live","course",$goods_bind_ids); $goods_bind_ids = json_decode($goods_bind_ids,true); if ($coupon->use_scope == 'all_use') { // 计算商品总金额 foreach ($this->goodsList as $buyInfo) { $buyInfo['goods_total_price'] = $buyInfo['detail']['price'] * $buyInfo['count']; $goods_total_price = bcadd($goods_total_price, $buyInfo['total_price'], 2); $goodsIds[] = $buyInfo['goodsId']; } } elseif ($coupon->use_scope == 'goods') { // 计算指定商品的总金额是否满足 foreach ($this->goodsList as $buyInfo) { if($buyInfo['goodsType'] == 'activity'){ $buyInfo['goodsId'] = $buyInfo['detail']['id']; } if (in_array($buyInfo['goodsId']."_".$buyInfo['goodsType'], $goods_bind_ids)) { $goods_total_price = bcadd($goods_total_price, $buyInfo['total_price'], 2); $goodsIds[] = $buyInfo['goodsId']; } } } elseif ($coupon->use_scope == 'disabled_goods') { // 计算非指定的商品的总金额是否满足 foreach ($this->goodsList as $buyInfo) { if($buyInfo['goodsType'] == 'activity'){ $buyInfo['goodsId'] = $buyInfo['detail']['id']; } if (!in_array($buyInfo['goodsId']."_".$buyInfo['goodsType'], $goods_bind_ids)) { $goods_total_price = bcadd($goods_total_price, $buyInfo['total_price'], 2); $goodsIds[] = $buyInfo['goodsId']; } } } if($goods_total_price == 0){ $can_use = false; $cannot_use_msg = '优惠券不支持该商品'; return compact('can_use', 'cannot_use_msg'); } if (floatval($coupon->enough) <= $goods_total_price) { $coupon->coupon_money = $coupon->amount; $coupon->goods_total_price = $goods_total_price; // 参与优惠券的商品的总金额 $coupon->goods_ids = $goodsIds; if ($coupon->type == 'discount') { $scale = bcmul($coupon->coupon->discount, 0.1, 3); $scale = $scale > 1 ? 1 : ($scale < 0 ? 0 : $scale); $coupon_money = bcmul(bcsub(1, $scale, 3), $goods_total_price, 2); // 优惠金额最大为 coupon->max_amount; $coupon['coupon_money'] = floatval($coupon->max_amount) && $coupon_money > $coupon->max_amount ? $coupon->max_amount : $coupon_money; } $this->orderData['coupon'] = $coupon; } else { $can_use = false; if ($goods_total_price > 0) { $cannot_use_msg = '商品金额不满足优惠券门槛'; } else { $cannot_use_msg = '优惠券不支持该商品'; } } return compact('can_use', 'cannot_use_msg'); } /** * 获取用户的优惠券列表,可用和不可用的做区分 * @return array */ public function getCoupons($calc_type = 'coupons') { $user = user_info(); $this->calc_type = $calc_type; // 检查是否可下单 $this->calcCheck(); // 计算订单各种费用 $this->calcAmount(); // 用户可用优惠券列表 $coupons = \app\admin\model\app\coupon\CouponUser::with('coupon')->where('user_id', $user->id)->canUse()->select(); $cannot_use = []; $can_use = []; foreach ($coupons as $key => $coupon) { $result = $this->checkCoupon($coupon); if (isset($result['can_use']) && $result['can_use']) { $can_use[] = $coupon; } else { $coupon->cannot_use_msg = $result['cannot_use_msg']; $cannot_use[] = $coupon; } } return compact('can_use', 'cannot_use'); } public function getCoupon($coupon_id) { $user = user_info(); // 选用的优惠券 $coupon = \app\admin\model\app\coupon\CouponUser::with('coupon')->where('user_id', $user->id)->canUse()->find($coupon_id); if ($coupon) { $result = $this->checkCoupon($coupon); return (isset($result['can_use']) && $result['can_use']) ? $coupon : null; } return null; } /** * 判断并处理异常 * * @param string $msg 处理结果 * @param boolean $force 是否强制抛出异常 * @return boolean */ private function exception($msg, $force = false) { if ($this->calc_type == 'create' || $force) { // 如果是创建订单,或者强制抛出异常 throw new \app\common\exception\Exception($msg); } else { // 预下单,记录第一条错误信息 if (!$this->msg) { $this->msg = $msg; } } return false; } /** * 保存订单地址 * * @param int $orderId 订单ID * @param array $orderData 订单数据 * @return void */ private function saveOrderAddress($orderId, $orderData) { $addressId = $this->orderData['address_id']; // 获取用户地址 $address = \think\Db::name('user_address') ->where('id', $addressId) ->where('user_id', $this->user->id) ->where('uniacid', UNIACID) ->find(); if (!$address) { throw new \app\common\exception\Exception('收货地址不存在'); } // 转换为数组 $address = is_object($address) ? $address->toArray() : $address; // 保存订单地址 $orderAddressData = [ 'order_id' => $orderId, 'user_id' => $this->user->id, 'consignee' => $address['name'], 'mobile' => $address['mobile'], 'province_name' => $address['province'], 'city_name' => $address['city'], 'district_name' => $address['district'], 'address' => $address['address'], 'province_id' => $address['province_id'] ?? 0, 'city_id' => $address['city_id'] ?? 0, 'district_id' => $address['district_id'] ?? 0, 'uniacid' => UNIACID, 'createtime' => time(), 'updatetime' => time() ]; \think\Db::name('app_physical_order_address')->insert($orderAddressData); } }