// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\service\order; use app\api\model\card\UserRiceCard as UserRiceCardModel; use app\api\model\card\UserRiceCardConsume as UserRiceCardConsumeModel; use app\api\model\fullsend\FullSendActivity; use app\api\model\GoodsCategoryRel as GoodsCategoryRelModel; use app\api\model\GoodsPackage as GoodsPackageModel; use app\api\model\member\DeductionLimit as DeductionLimitModel; use app\api\model\member\GoldRice as GoldRiceModel; use app\api\model\OrderGoodsTaocan as OrderGoodsTaocanModel; use app\api\model\Order as OrderModel; use app\api\model\PromotionMonitor; use app\api\model\User as UserModel; use app\api\model\Goods as GoodsModel; use app\api\model\Setting as SettingModel; use app\api\model\shop\Shops; use app\api\model\UserAddress; use app\api\model\UserCoupon as UserCouponModel; use app\api\service\User as UserService; use app\api\service\Payment as PaymentService; use app\api\service\coupon\GoodsDeduct as GoodsDeductService; use app\api\service\ricecard\GoodsDeduct as RiceDeductService; use app\api\service\points\GoodsDeduct as PointsDeductService; use app\api\service\order\source\checkout\Factory as CheckoutFactory; use app\common\enum\Setting as SettingEnum; use app\common\enum\order\PayType as OrderPayTypeEnum; use app\common\enum\order\OrderStatus as OrderStatusEnum; use app\common\enum\order\OrderSource as OrderSourceEnum; use app\common\enum\order\DeliveryType as DeliveryTypeEnum; use app\common\service\BaseService; use app\common\service\card\UserRiceCard as UserRiceCardService; use app\common\service\commission\RecordWaitCommission; use app\common\service\delivery\Express as ExpressService; use app\common\service\goods\source\Factory as StockFactory; use app\common\library\helper; use app\common\exception\BaseException; use app\common\enum\order\PayStatus as PayStatusEnum; use app\common\model\ShopGoodsSku; use app\common\model\User; use http\Header\Parser; use app\api\model\za\{ZaActivityRelation,ZaActivityGood,ZaActivity}; /** * 订单结算台服务类 * Class Checkout * @package app\api\service\order */ class CheckoutZa extends BaseService { /* $model OrderModel 订单模型 */ public $model; /* @var UserModel $user 当前用户信息 */ private $user; // 订单结算商品列表 private $goodsList = []; // 错误信息 protected $error; // 错误信息状态 protected $errorStatus; /** * 订单结算api参数 * @var array */ private $param = [ 'delivery' => null, // 配送方式 默认:快递配送 'couponId' => 0, // 优惠券id 'riceCardId' => 0, // 现金米卡id 'isUsePoints' => 0, // 是否使用积分抵扣 'isUseGoldRice' => 1, // 默认使用金米粒 'remark' => '', // 买家留言 'payType' => OrderPayTypeEnum::WECHAT, // 支付方式 'addressId' => 0, //地址ID 'staffUserId' => 0, //分享链接用户ID ]; /** * 订单结算的规则 * @var array */ private $checkoutRule = [ 'isUserGrade' => false, // 会员等级折扣 'isCoupon' => true, // 优惠券抵扣 'isRiceCard' => true, // 现金米卡抵扣 'isUsePoints' => false, // 是否使用积分抵扣 ]; /** * 订单来源 * @var array */ private $orderSource = [ 'source' => OrderSourceEnum::ZA, 'source_id' => 0, ]; /** * 订单结算数据 * @var array */ private $orderData = []; /** * 构造函数 * Checkout constructor. * @throws BaseException */ public function __construct() { parent::__construct(); $this->user = UserService::getCurrentLoginUser(true); $this->model = new OrderModel; $this->storeId = $this->getStoreId(); } /** * 设置结算台请求的参数 * @param $param * @return array */ public function setParam($param) { $this->param = array_merge($this->param, $param); return $this->getParam(); } /** * 获取结算台请求的参数 * @return array */ public function getParam() { return $this->param; } /** * 订单结算的规则 * @param $data * @return $this */ public function setCheckoutRule($data) { $this->checkoutRule = array_merge($this->checkoutRule, $data); return $this; } /** * 设置订单来源(普通订单) * @param $data * @return $this */ public function setOrderSource($data) { $this->orderSource = array_merge($this->orderSource, $data); return $this; } /** * 订单确认-结算台 * @param $goodsList * @return array * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function onCheckout($goodsList) { // 订单确认-立即购买 $this->goodsList = $goodsList; return $this->checkout(); } /** * 订单结算台 * @return array * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function checkout() { // 整理订单数据 $this->orderData = $this->getOrderData(); // 验证商品状态, 是否允许购买 $this->validateGoodsList(); $this->setShopPickupData(); // 设置订单商品总金额() $this->setOrderTotalPrice(); //订单总运费金额 $this->setOrderExpress(); //金米粒抵扣-V1.4.0版本添加2022年6月6日 $this->setOrderGolRiceAmount(); //获取当前可用的现金卡列表 $userRiceCardList = $this->getUserRiceCardList(); //计算使用米卡现金券抵扣后的金额 $this->setOrderRiceCardMoney($userRiceCardList,(int)$this->param['riceCardId']); // 计算订单商品的实际付款金额 $this->setOrderGoodsPayPrice(); // 计算订单最终金额+运费 $this->setOrderPayPrice(); //订单商品的所有店铺集合2021年9月28日 10:56:45 $this->setOrderProviderIds(); // 订单商品总数量 $orderTotalNum = helper::getArrayColumnSum($this->goodsList, 'total_num'); // 返回订单数据 return array_merge([ 'goodsList' => $this->goodsList, // 商品信息 'orderTotalNum' => $orderTotalNum, // 商品总数量 // 'couponList' => array_values($couponList), // 优惠券列表 'hasError' => $this->hasError(), 'errorMsg' => $this->getError(), 'errorStatus' => $this->getErrorStatus(), ], $this->orderData); } /** * 门店自提处理 */ public function setShopPickupData() { $deliveryType = $this->param['delivery']; // 返回商品处理 $normalGoodsList = []; // 正常状态商品 $invalidGoodsList = []; // 无货状态商品 // 门店信息 $userStaff = User::detail($this->param['staffUserId']); $shopInfo = []; $isPickup = false; if (!empty($userStaff) && $userStaff['role'] == User::SHOP_SELLER) { $shopInfo = Shops::find($userStaff['shop_id']); if ($shopInfo['is_pickup']) { $isPickup = true; } } if ($deliveryType == DeliveryTypeEnum::SHOPS_DELIVERY) { if (empty($shopInfo)) { // 门店自提方式 且门店不存在 throwError("不支持门店自提方式"); } if (!$shopInfo['is_pickup']) { // 门店自提开关 throwError("不支持门店自提方式"); } } // 门店库存总和 $shopStockTotal = 0; foreach($this->goodsList as &$item) { // 获取商品门店库存 if ($shopInfo) { $shopGoodsSku = ShopGoodsSku::with('shopGoods')->where(['shop_id' => $shopInfo['shop_id'], 'goods_id' => $item['goods_id'], 'goods_sku_id' => $item['goods_sku_id']])->find(); if (!empty($shopGoodsSku) && $shopGoodsSku['stock_num'] > 0) { $shopStockTotal += $shopGoodsSku['stock_num']; } } // 判断配送方式 if ($deliveryType == DeliveryTypeEnum::EXPRESS) { // 快递配送 $normalGoodsList[] = $item; // 判断库存 todo 购买数量大于实际库存 取实际库存 // 有库存 if ($item['skuInfo']['stock_num'] >= $item['total_num']) { $item['stock_enough'] = true; } else { $item['stock_enough'] = false; $item['total_num'] = $item['skuInfo']['stock_num']; // 库存不够时,取最大库存 $item['total_price'] = helper::bcmul($item['goods_price'], $item['total_num']); } if($item['skuInfo']['stock_num'] < 2){ $item['stock_enough'] = false; } $item['is_pickup_invalid'] = false; } elseif ($deliveryType == DeliveryTypeEnum::SHOPS_DELIVERY) { // 门店自提 // 判断有无库存 if (!empty($shopGoodsSku)) { $item['stock_total'] = $shopGoodsSku['shopGoods']['stock_total']; $item['alarm_stock_total'] = $shopGoodsSku['shopGoods']['alarm_stock_total']; $item['skuInfo']['stock_num'] = $shopGoodsSku['stock_num']; $item['skuInfo']['alarm_stock_num'] = $shopGoodsSku['alarm_stock_num']; if ($shopGoodsSku['stock_num'] > 0) { // 有库存 if ($shopGoodsSku['stock_num'] >= $item['total_num']) { $item['stock_enough'] = true; } else { $item['stock_enough'] = false; $item['total_num'] = $shopGoodsSku['stock_num']; // 库存不够时,取最大库存 $item['total_price'] = helper::bcmul($item['goods_price'], $item['total_num']); } $normalGoodsList[] = $item; } else { // 没有库存 $item['stock_enough'] = false; $item['is_pickup_invalid'] = true; $invalidGoodsList[] = $item; } } else { // 无库存 // $item['stock_total'] = 0; // $item['alarm_stock_total'] = 0; // $item['skuInfo']['stock_num'] = 0; // $item['skuInfo']['alarm_stock_num'] = 0; $item['stock_enough'] = false; // $item['total_num'] = 0; // 无门店库存 // $item['total_price'] = 0; $item['is_pickup_invalid'] = true; $invalidGoodsList[] = $item; } } } if ($shopStockTotal <= 0) { // 门店总库存不大于0 $isPickup = false; } $this->shopInfo = $shopInfo; // 门店信息 $this->isPickup = $isPickup; // 是否支持门店自提 $this->orderData['shopInfo'] = $shopInfo; // $this->goodsList = $normalGoodsList; // $this->invalidGoodsList = $invalidGoodsList; } /** * 设置订单使用金米粒抵扣信息 * @return bool * @throws BaseException */ private function setOrderGolRiceAmount() { // 设置默认数据:订单信息 helper::setDataAttribute($this->orderData, [ 'goldRiceAmount' => 0, // 金米粒抵扣总数量 1金米粒=0.01元 'goldRiceMoney' => 0.00, // 金米粒抵扣总金额 ], false); // 设置默认数据:订单商品列表 helper::setDataAttribute($this->goodsList, [ 'gold_rice_amount' => 0, // 金米粒抵扣数量 'gold_rice_money' => 0, // 金米粒抵扣金额 ], true); $this->orderData['isUseGoldRice'] = -1; return false; // if($this->orderData['isUseGoldRice']<1){//没有使用金米粒 // return false; // } // $orderTotalPrice = $this->orderData['orderTotalBargainPrice']; //实际支付金额 // // 如果没有可用的金米粒,直接返回 // $DeductionLimit = DeductionLimitModel::where('id','>',0)->find(); // $score = floor($DeductionLimit['discount']*$orderTotalPrice); // //不够起用数量 // if($score<$DeductionLimit['score']){ // $this->orderData['isUseGoldRice'] = -1; // return false; // } // //用户可用金米粒数量不够起用数量 // if($this->user['gold_rice']<$DeductionLimit['score']){ // $this->orderData['isUseGoldRice'] = -1; // return false; // } // if($score>$this->user['gold_rice']){ // $score = $this->user['gold_rice']; // } // // 获取优惠券信息 // $goodsListTemp = []; // foreach ($this->goodsList as $key=> $good){ // $goodsListTemp[$key]['total_price'] = helper::bcsub($good['bargain_price'],0); // } // $RiceMoney = new RiceDeductService; // $gold_rice_money = helper::bcdiv($score,100); // $completed = $RiceMoney->setGoodsCouponMoney($goodsListTemp, $gold_rice_money); // // 分配订单商品抵扣的金米粒数量 // foreach ($this->goodsList as $key => &$goods) { // $goods['gold_rice_amount'] = isset($completed[$key]['rice_card_money']) ? $completed[$key]['rice_card_money'] : 0; // $goods['gold_rice_money'] = helper::bcdiv($goods['gold_rice_amount'],100); // } // // 记录订单抵扣的金米粒数量 // $this->orderData['goldRiceAmount'] = $score; // $this->orderData['goldRiceMoney'] = $gold_rice_money; // return true; } //我的可用现金卡 public function getUserRiceCardList(){ $user = UserService::getCurrentLoginUser(true); $list = UserRiceCardModel::getUserRiceCardList($user['user_id'])->toArray(); $data = []; foreach ($list as $key=>&$item){ $i = 0; $exceptGoodsId = helper::getArrayColumn($item['riceCardGoodsExcept'],'goods_id'); foreach ($this->goodsList as $good) { if(!empty($item['dk_cat_ids']) && strpos((string)$item['dk_cat_ids'],(string)$good['category']['category_id']) === false){ unset($list[$key]); $i = 1; } if(!empty($exceptGoodsId) && in_array($good['goods_id'],$exceptGoodsId)){ unset($list[$key]); $i = 1; } } if(!$i){ unset($item['riceCardGoodsExcept']); $data[$item['id']] = $item; } } if($this->param['riceCardId']==0){ //-1表示不使用米卡 $this->param['riceCardId'] = key($data)??0;//若果没有选择米卡,默认使用第一张 } return $data; } /** * 整理订单数据(结算台初始化) * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getOrderData() { // 系统支持的配送方式 (后台设置) $deliveryType = SettingModel::getItem(SettingEnum::DELIVERY)['delivery_type']; return [ 'order_source_id'=>$this->param['zaGoodsId'], // 当前配送类型 'delivery' => $this->param['delivery'] > 0 ? $this->param['delivery'] : $deliveryType[0], // 默认地址 'address' => '', // 是否存在收货地址 'existAddress' => $this->user['address_id'] > 0, // 配送费用 'expressPrice' => 0.00, //是否使用了金米粒 'isUseGoldRice' => $this->param['isUseGoldRice'], //金米粒数量 'userGoldRiceNum' => $this->user['gold_rice']??0, // 当前用户收货城市是否存在配送规则中 'isIntraRegion' => true, // 是否允许使用积分抵扣 'isAllowPoints' => false, // 是否使用积分抵扣 'isUsePoints' => $this->param['isUsePoints'], // 积分抵扣金额 'pointsMoney' => 0.00, // 赠送的积分数量 'pointsBonus' => 0, // 支付方式 'payType' => $this->param['payType'], // 系统设置 'setting' => $this->getSetting(), // 推广监控ID "promotionMonitorId" => $this->param['promotionMonitorId'] ?? 0 ]; } /** * 获取订单页面中使用到的系统设置 * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getSetting() { // 系统支持的配送方式 (后台设置) $deliveryType = SettingModel::getItem(SettingEnum::DELIVERY)['delivery_type']; // 积分设置 $pointsSetting = SettingModel::getItem(SettingEnum::POINTS); return [ 'deliveryType' => $deliveryType, // 支持的配送方式 'points_name' => $pointsSetting['points_name'], // 积分名称 'points_describe' => $pointsSetting['describe'], // 积分说明 ]; } /** * 验证订单商品的状态 * @return bool */ private function validateGoodsList() { $Checkout = CheckoutFactory::getFactory( $this->user, $this->goodsList, $this->orderData['delivery'], $this->shopInfo['shop_id'] ?? 0, $this->orderSource['source'] ); $status = $Checkout->validateGoodsList(); if(!$status){ $this->setError($Checkout->getError()); $this->setErrorStatus(422); } return $status; } /** * 设置订单的商品总金额(不含优惠折扣) */ private function setOrderTotalPrice() { // 订单商品的总金额 $this->orderData['orderTotalPrice'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_price')); // //砍价总金额 // $this->orderData['orderTotalBargainPrice'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'bargain_price')); } /** * 订单商品的所有店铺集合 */ private function setOrderProviderIds() { // 订单商品的所有店铺集合 $this->orderData['orderProviderIds'] = implode(',',array_values(array_unique(helper::getArrayColumn($this->goodsList, 'provider_id')))); } /** * 设置订单的实际支付金额(含配送费) */ private function setOrderPayPrice() { // 订单金额(含优惠折扣) //(商品总价 - N件X折 - 优惠券 - 分销员)+ 运费 = 微信支付+米卡抵扣+米卡抵扣运费 //(total_price-coupon_money-distrbutor_total_money)+express_price = pay_price+rice_card_money+rice_card_express_money $this->orderData['orderPrice'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_pay_price')); // 订单实付款金额(订单金额 + 运费 - 金米粒抵扣金额 - 现金卡运费抵扣金额) $this->orderData['orderPayPrice'] = helper::number2(helper::bcadd($this->orderData['orderPrice'], $this->orderData['expressPrice']-$this->orderData['riceCardExpressMoney'])); } /** * 计算订单商品的实际付款金额 * @return bool */ private function setOrderGoodsPayPrice() { // 商品总价 - 优惠抵扣 foreach ($this->goodsList as &$goods) { //减去金米粒抵扣金额和现金米卡抵扣的金额 $value = helper::bcsub($goods['total_price'], $goods['rice_card_money']+$goods['gold_rice_money']); $goods['total_pay_price'] = helper::number2($value); } return true; } /** * 设置订单现金米卡抵扣信息 * @param int $riceCardId 可使用米卡列表 * @param int $riceCardId 当前选择的现金米卡id * @return bool * @throws BaseException */ private function setOrderRiceCardMoney($userRiceCardList,int $riceCardId) { // 设置默认数据:订单信息 helper::setDataAttribute($this->orderData, [ 'riceCardId' => $riceCardId, // 用户现金米卡id 'riceCardMoney' => 0, // 现金米卡抵扣总金额 'riceCardExpressMoney' => 0, // 现金米卡抵扣运费 'userRiceCardList' => [], // 米卡列表 'userRiceCard' => [], // 已选择的米卡 ], false); // 设置默认数据:订单商品列表 helper::setDataAttribute($this->goodsList, [ 'rice_card_id' => 0, // 用户现金米卡id 'rice_card_money' => 0, // 金米卡抵扣金额 ], true); if($riceCardId<0){//如果米卡ID小于0表示不使用,但是也要返回可使用列表 $this->orderData['userRiceCardList'] = array_values($userRiceCardList); return true; } // 验证选择的优惠券ID是否合法 if (!$this->verifyUserRiceCard($riceCardId, $userRiceCardList)) { return false; } // 获取优惠券信息 $riceCard = $this->getRiceCardInfo($riceCardId, $userRiceCardList); $goodsListTemp = []; foreach ($this->goodsList as $key=> $good){ $goodsListTemp[$key]['total_price'] = helper::bcsub($good['total_price'],$good['gold_rice_money']); } $RiceMoney = new RiceDeductService; $completed = $RiceMoney->setGoodsCouponMoney($goodsListTemp, $riceCard['balance']); // 分配订单商品优惠券抵扣金额 $rice_card_money = 0; foreach ($this->goodsList as $key => &$goods) { $goods['rice_card_money'] = isset($completed[$key]['rice_card_money']) ? $completed[$key]['rice_card_money'] / 100 : 0; $goods['rice_card_id'] = $riceCardId; $rice_card_money += $goods['rice_card_money']; } $orderPrice = $this->orderData['orderTotalPrice']-$this->orderData['goldRiceMoney']; //实际支付金额 //有运费,并且现金米卡可用的金额大于商品总价 $rice_card_express_money = 0; if($riceCard['balance']>$orderPrice && $this->orderData['expressPrice']>0){ $residueMoney = $riceCard['balance']-$orderPrice; if($residueMoney-$this->orderData['expressPrice']>0){ $rice_card_express_money += $this->orderData['expressPrice']; }else{ $rice_card_express_money += $residueMoney; } } // 记录订单现金米卡信息 $this->orderData['userRiceCard'] = $userRiceCardList[$riceCardId]; $this->orderData['riceCardId'] = $riceCardId; $this->orderData['riceCardMoney'] = helper::bcmul($rice_card_money+$rice_card_express_money,1); $this->orderData['riceCardExpressMoney'] = helper::bcmul($rice_card_express_money,1); $this->orderData['userRiceCardList'] = array_values($userRiceCardList); return true; } /** * 验证用户选择的现金米卡 * @param $riceCard * @return bool * @throws BaseException */ private function verifyUserRiceCard($riceCardId,$userRiceCardList) { // 是否开启现金米卡抵扣 if (!$this->checkoutRule['isRiceCard']) { return false; } // 如果没有可用的现金米卡,直接返回 if ($riceCardId <= 0) { return false; } // 判断优惠券是否存在 $riceCard = $this->getRiceCardInfo($riceCardId, $userRiceCardList); // 如果没有现金米卡,直接返回 if (empty($riceCard)) { throwError('未找到米卡信息'); } return true; } /** * 查找指定的优惠券信息 * @param int $couponId 优惠券ID * @param array $couponList 优惠券列表 * @return false|mixed */ private function getRiceCardInfo(int $riceCardId, array $userRiceCardList) { return helper::getArrayItemByColumn($userRiceCardList, 'id', $riceCardId); } /** * 订单配送-快递配送 * @return bool * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function setOrderExpress() { // 设置默认数据:配送费用 helper::setDataAttribute($this->goodsList, [ 'expressPrice' => 0, ], true); $cityId = 0; // 当前用户收货城市id if($this->param['addressId']){ //有传参 $addredd = UserAddress::get(['user_id' => $this->user['user_id'], 'address_id' => $this->param['addressId']]); $cityId = $addredd ? (int)$addredd['city_id'] : 0; $this->orderData['address'] = $addredd; }else{ //没有传参读默认地址 // $cityId = $this->user['address_default'] ? (int)$this->user['address_default']['city_id'] : 0; // var_dump('default'); // var_dump($this->user['address_default']); // die(); if($this->user['address_id']){ $addredd = UserAddress::get(['user_id' => $this->user['user_id'], 'address_id' => $this->user['address_id']]); $cityId = $addredd ? (int)$addredd['city_id'] : 0; $this->orderData['address'] = $addredd; }else{ $addredd = UserAddress::where(['user_id' => $this->user['user_id'],'default'=>1,'is_delete'=>0])->find(); $cityId = $addredd ? (int)$addredd['city_id'] : 0; $this->orderData['address'] = $addredd; } } if ($this->param['delivery'] == DeliveryTypeEnum::EXPRESS) { // 普通快递 // 初始化配送服务类 $ExpressService = new ExpressService($cityId, $this->goodsList); // 验证商品是否在限购配送范围 $isDeliveryLimit = $ExpressService->isDeliveryLimit(); if($cityId > 0){ if ($isDeliveryLimit == false) { $this->setError("很抱歉,您的收货地址在限购地区的配送范围内"); $this->setErrorStatus(423); $this->orderData['isIntraRegion'] = $isDeliveryLimit; }else{ // 验证商品是否在配送范围 $isIntraRegion = $ExpressService->isIntraRegion(); if ($isIntraRegion == false) { $notInRuleGoodsName = $ExpressService->getNotInRuleGoodsName(); $this->setError("很抱歉,您的收货地址不在商品 [".limit_str((string)$notInRuleGoodsName)."] 的配送范围内"); $this->setErrorStatus(423); } $this->orderData['isIntraRegion'] = $isIntraRegion; } } // 订单总运费金额 $this->orderData['expressPrice'] = $ExpressService->getDeliveryFee(); } else { // 门店自提 $this->orderData['expressPrice'] = "0.00"; } return true; } /** * 创建新订单 * @param array $order 订单信息 * @return bool */ public function createOrder(array $order) { // 表单验证 if (!$this->validateOrderForm($order)) { return false; } // 创建新的订单 $status = $this->model->transaction(function () use ($order) { // dd($order); // 创建订单事件 return $this->createOrderEvent($order); }); // 余额支付标记订单已支付 if ($status && $order['payType'] == OrderPayTypeEnum::BALANCE) { return $this->model->onPaymentByBalance($this->model['order_no']); } return $status; } /** * 创建订单事件 * @param $order * @return bool * @throws BaseException * @throws \Exception */ private function createOrderEvent($order) { // 门店自提 if ($order['delivery'] == DeliveryTypeEnum::SHOPS_DELIVERY) { $order['hx_code'] = $this->model->hxCode(); $order['pickup_deadline'] = time() + OrderModel::getPickupDeadline() * 60; // 提货截止时间:提交订单2天内 $order['shop_id'] = $order['shopInfo']['shop_id']; // 订单自提门店id } // 新增订单记录 $status = $this->add($order, $this->param['remark']); if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) { // 记录收货地址 $this->saveOrderAddress($order['address']); } // 保存订单商品信息 $this->saveOrderGoods($order); // 保存订单套餐商品信息 $this->saveOrderGoodsTaocan($order); if($order['payType']!=OrderPayTypeEnum::ACTIVITY){ // 更新商品库存 (针对下单减库存的商品) $this->updateGoodsStockNum($order); // 更新多个活动的活动库存 $this->updateActivityStock($order); //写入买一赠一信息 $this->saveActivityRel($order); } //金米粒处理逻辑 if($order['orderPayPrice']>0){ //冻结金米粒数量 if($order['goldRiceAmount']>0) UserModel::setIncDecByField($this->user['user_id'],['gold_rice_frozen'=>(float)$order['goldRiceAmount']],['gold_rice'=>(float)$order['goldRiceAmount']]); }else{ if($order['goldRiceAmount']>0){ //写金米粒出账记录 GoldRiceModel::add($this->user['user_id'],$this->model['order_no'],'下单抵扣',$order['goldRiceAmount'],0); //用户直接扣除金米粒 UserModel::setDecByField($this->user['user_id'],'gold_rice',(float)$order['goldRiceAmount']); } } if($order['riceCardId']>0 && $order['riceCardMoney']>0){ //根据支付的金额来判断逻辑 if($order['orderPayPrice']>0){ //冻结现金卡金额 UserRiceCardModel::setIncDecByField($order['riceCardId'],['frozen_amount'=>(float)$order['riceCardMoney']],['balance'=>(float)$order['riceCardMoney']]); }else{//不需要结算金额 //写现金卡出账记录 UserRiceCardConsumeModel::add($order['userRiceCard'],$this->model['order_no'],$order['orderPayPrice'],$order['riceCardMoney']); //如果可用余额等于要抵扣的金额 if($order['riceCardMoney']==$order['userRiceCard']['balance']){ //现金卡直接减可用余额,并且状态改为已失效 UserRiceCardModel::setIncDecByField($order['riceCardId'],[],['balance'=>(float)$order['riceCardMoney']],['effect_state'=>2]); }else{ //现金卡直接减可用余额 UserRiceCardModel::setDecByField($order['riceCardId'],'balance',(float)$order['riceCardMoney']); } // 更新商品库存、销量(付款后减库存、加销量) $order['goods'] = $order['goodsList']; $order['delivery_type'] = $order['delivery']; StockFactory::getFactory($this->orderSource['source'])->updateStockSales($order); } } //待结算佣金计算 $RecordWaitCommission = new RecordWaitCommission; //分销记录放入队列 $RecordWaitCommission->recordWaitCommission($this->model['order_id']); return $status; } /** * 构建支付请求的参数 * @return array * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function onOrderPayment() { return PaymentService::orderPayment($this->model, $this->param['payType']); } /** * 表单验证 (订单提交) * @param array $order 订单信息 * @return bool */ private function validateOrderForm(array $order) { if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) { if (empty($order['address'])) { $this->error = '您还没有选择配送地址'; return false; } } // 余额支付时判断用户余额是否足够 if ($order['payType'] == OrderPayTypeEnum::BALANCE) { if ($this->user['balance'] < $order['orderPayPrice']) { $this->error = '您的余额不足,无法使用余额支付'; return false; } } return true; } /** * 当前订单是否存在和使用积分抵扣 * @param $order * @return bool */ private function isExistPointsDeduction($order) { return $order['isAllowPoints'] && $order['isUsePoints']; } /** * 新增订单记录 * @param $order * @param string $remark * @return false|int */ private function add($order, $remark = '') { // 根据推广监控ID判断活动效果归属 // $promotionMonitorId = PromotionMonitor::checkActEffectOwner(5, $order['promotionMonitorId'] ?? 0, $order['goodsList'][0]['bargain_id'] ?? 0); if($order['payType']==OrderPayTypeEnum::ACTIVITY){ $pay_type = OrderPayTypeEnum::ACTIVITY; }else{ $pay_type = $order['orderPayPrice'] > 0 ? $order['payType'] : OrderPayTypeEnum::MICAH_EXCHANGE; } // 订单数据 $data = [ 'user_id' => $this->user['user_id'], 'order_no' => $this->model->orderNo(), 'total_price' => $order['orderTotalPrice'], 'order_price' => $order['orderPrice'], 'pay_price' => $order['orderPayPrice'], 'delivery_type' => $order['delivery'], 'pay_type' => $pay_type, 'buyer_remark' => trim($remark), 'order_source' => $this->orderSource['source'], 'order_source_id' => $order['goodsList'][0]['za_goods_id'] ?? 0, // 'bargain_money' => helper::bcsub($this->orderData['orderTotalPrice'],$this->orderData['orderTotalBargainPrice']), 'order_status' => OrderStatusEnum::NORMAL, 'store_id' => $this->storeId, 'provider_ids' => $order['orderProviderIds']??0, 'gold_rice_amount' => $order['goldRiceAmount']??0, 'gold_rice_money' => $order['goldRiceMoney']??0, 'distributor_total_money' => $order['distributorTotalMoney']??0, 'rice_card_id' => $order['riceCardId']>0?$order['riceCardId']:0, 'rice_card_money' => $order['riceCardMoney']??0, 'rice_card_express_money' => $order['riceCardExpressMoney']??0, // 'promotion_monitor_id' => $promotionMonitorId, 'staff_user_id' => $order['goodsList'][0]['staffUserId'] ?? 0, 'staff_shop_id' => $order['goodsList'][0]['shopId'] ?? 0, ]; //米卡兑换直接成功 if($order['orderPayPrice']<=0 || $order['payType']==OrderPayTypeEnum::MICAH_EXCHANGE){ $data['pay_status'] = PayStatusEnum::SUCCESS; $data['pay_time'] = time(); $data['invoice_deadline'] = time() + OrderModel::getInvoiceDeadline() * 60; // 申请开票截止时间:订单付款后的40天内可以申请开票 } //活动赠送的 if($order['orderPayPrice']<=0 && $order['payType']==OrderPayTypeEnum::ACTIVITY){ $data['pay_status'] = PayStatusEnum::SUCCESS; $data['pay_time'] = time(); $data['invoice_deadline'] = time() + OrderModel::getInvoiceDeadline() * 60; // 申请开票截止时间:订单付款后的40天内可以申请开票 } if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) { $data['express_price'] = $order['expressPrice']; } // 保存订单记录 return $this->model->save($data); } /** * 保存订单商品信息 * @param $order * @return int */ private function saveOrderGoods($order) { // 当前订单是否存在和使用积分抵扣 $isExistPointsDeduction = $this->isExistPointsDeduction($order); // 订单商品列表 $goodsList = []; foreach ($order['goodsList'] as $goods) { $item = [ 'user_id' => $this->user['user_id'], 'store_id' => $this->storeId, 'goods_id' => $goods['goods_id'], 'goods_name' => $goods['goods_name'], 'goods_no' => $goods['goods_no'] ?: '', 'image_id' => (int)current($goods['goods_images'])['file_id'], 'deduct_stock_type' => $goods['deduct_stock_type'], 'spec_type' => $goods['spec_type'], 'goods_sku_id' => $goods['skuInfo']['goods_sku_id'], 'goods_props' => $goods['skuInfo']['goods_props'] ?: '', 'content' => $goods['content'] ?? '', 'goods_sku_no' => $goods['skuInfo']['goods_sku_no'] ?: '', 'goods_price' => $goods['skuInfo']['goods_price'], 'specs' => $goods['skuInfo']['specs'], 'supplier' => $goods['supplier'], 'line_price' => $goods['skuInfo']['line_price'], 'goods_weight' => $goods['skuInfo']['goods_weight'], 'is_user_grade' => (int)$goods['is_user_grade'], 'grade_ratio' => $goods['grade_ratio']??0, 'grade_goods_price' => $goods['grade_goods_price']??0, 'grade_total_money' => $goods['grade_total_money']??0, 'total_num' => $goods['total_num'], 'total_price' => $goods['total_price'], 'total_pay_price' => $goods['total_pay_price']??0, 'provider_id' => $goods['provider_id'], 'brand' => $goods['brand'], 'province_id' => $goods['province_id'], 'city_id' => $goods['city_id'], 'storage' => $goods['storage'], 'unit' => $goods['unit'], 'clearing_price' => $goods['skuInfo']['clearing_price']??'0.00', 'platform_rate' => $goods['skuInfo']['platform_rate']??'0.00', 'rice_card_id' => $goods['rice_card_id']??0, 'rice_card_money' => $goods['rice_card_money']??0, // 'bargain_id' => $goods['bargain_activity_id']??0, ]; // 记录订单商品来源id $item['goods_source_id'] = isset($goods['goods_source_id']) ? $goods['goods_source_id'] : 0; $goodsList[] = $item; } return $this->model->goods()->saveAll($goodsList) !== false; } /** * 保存订单套餐商品信息 * @param $order * @return int */ private function saveOrderGoodsTaocan($order) { // 当前订单是否存在和使用积分抵扣 $isExistPointsDeduction = $this->isExistPointsDeduction($order); // 订单商品列表 $goodsList = []; foreach ($order['goodsList'] as $key=> $goods) { if($goods['goods_type']!=30){//是套餐商品 continue; } $relGoodList = GoodsPackageModel::with(['relGood'=>['images','skuList']])->where('goods_id',$goods['goods_id'])->select(); foreach ($relGoodList as $relGood){ $relGood['skuList'] = []; foreach ($relGood['relGood']['skuList'] as $sku){ if($sku['goods_sku_id']==$relGood['rel_goods_sku_id']){ $relGood['skuList'] = $sku; } } $item = [ 'user_id' => $this->user['user_id'], 'order_id' => $this->model['order_id'], 'order_goods_id' => $this->model->goods[$key]['order_goods_id'], 'store_id' => $this->storeId, 'goods_id' => $relGood['relGood']['goods_id'], 'goods_name' => $relGood['relGood']['goods_name'], 'goods_no' => $relGood['relGood']['goods_no'] ?: '', 'image_id' => (int)$relGood['relGood']['images'][0]['image_id']??0, 'deduct_stock_type' => $relGood['relGood']['deduct_stock_type'], 'spec_type' => $relGood['relGood']['spec_type'], 'goods_sku_id' => $relGood['skuList']['goods_sku_id']??0, 'goods_props' => $relGood['skuList']['goods_props'] ?? '', 'content' => $relGood['relGood']['content'] ?? '', 'goods_sku_no' => $relGood['skuList']['goods_sku_no'] ?? '', 'goods_price' => $relGood['skuList']['goods_price']??'0.00', 'line_price' => $relGood['skuList']['line_price']??'0.00', 'goods_weight' => $relGood['skuList']['goods_weight']??'0.00', 'is_user_grade' => (int)$relGood['relGood']['is_user_grade'], 'grade_ratio' => $relGood['relGood']['grade_ratio']??0, 'grade_goods_price' => $relGood['relGood']['grade_goods_price']??0, 'grade_total_money' => $relGood['relGood']['grade_total_money']??0, 'coupon_id' => $relGood['relGood']['coupon_id']??0, 'coupon_money' => $relGood['relGood']['coupon_money']??0, 'points_money' => $isExistPointsDeduction ? $relGood['relGood']['points_money'] : 0.00, 'points_num' => $isExistPointsDeduction ? $relGood['relGood']['points_num'] : 0, 'points_bonus' => $relGood['relGood']['points_bonus']??0, 'total_num' => 1, 'total_price' => $relGood['relGood']['total_price']??0, 'total_pay_price' => $relGood['relGood']['total_pay_price']??0, 'provider_id' => $relGood['relGood']['provider_id'], 'brand' => $relGood['relGood']['brand'], 'province_id' => $goods['province_id'], 'city_id' => $relGood['relGood']['city_id'], 'storage' => $relGood['relGood']['storage'], 'unit' => $relGood['relGood']['unit'], 'clearing_price' => $relGood['skuList']['clearing_price']??'0.00', 'platform_rate' => $relGood['skuList']['platform_rate']??'0.00', 'goods_type' => 30, ]; // 记录订单商品来源id $item['goods_source_id'] = isset($relGood['goods_source_id']) ? $relGood['goods_source_id'] : 0; $goodsList[] = $item; } } return (new OrderGoodsTaocanModel())->saveAll($goodsList) !== false; } /** * 更新商品库存 (针对下单减库存的商品) * 普通快递、门店自提 分开扣库存 * @param $order * @return mixed */ private function updateGoodsStockNum($order) { return StockFactory::getFactory($this->model['order_source'])->updateGoodsStock($order); } /** * 更新商品库存 (针对下单减库存的商品) * 普通快递、门店自提 分开扣库存 * @param $order * @return mixed */ private function updateActivityStock($order) { return StockFactory::getFactory($this->model['order_source'])->updateActivityStock($order); } /** * 保存买一赠一信息 * @param $order * @return int */ private function saveActivityRel($order){ $id = $order['order_source_id']; $activityGood = ZaActivityGood::where("id",$id)->find(); if($activityGood){ $activity = ZaActivity::where("id", $activityGood->za_activity_id)->find(); $rel['is_pay'] =0; $rel['order_price'] = $order['orderTotalPrice']; $rel['za_goods_id'] = $id; $rel['order_id'] = $this->model['order_id']; $expire_day = $activity->expire_day??0; $rel['expire_time'] = Date("Y-m-d H:i:s",$expire_day*86400+time()); $rel['za_activity_id'] = $activityGood->za_activity_id; $sign_str = md5(md5(http_build_query($rel))); $rel['sign_str'] = $sign_str; ZaActivityRelation::create($rel); $this->model['sign_str'] = $sign_str; } } /** * 记录收货地址 * @param $address * @return false|\think\Model */ private function saveOrderAddress($address) { return $this->model->address()->save([ 'user_id' => $this->user['user_id'], 'store_id' => $this->storeId, 'name' => $address['name'], 'phone' => $address['phone'], 'province_id' => $address['province_id'], 'city_id' => $address['city_id'], 'region_id' => $address['region_id'], 'detail' => $address['detail'], ]); } /** * 设置错误信息 * @param $error */ protected function setError($error) { empty($this->error) && $this->error = $error; } /** * 获取错误信息 * @return mixed */ public function getError() { return $this->error ?: ''; } /** * 设置错误状态 * @param $errorStatus */ protected function setErrorStatus($errorStatus) { empty($this->errorStatus) && $this->errorStatus = $errorStatus; } /** * 获取错误信息 * @return mixed */ public function getErrorStatus() { return $this->errorStatus ?: 0; } /** * 是否存在错误 * @return bool */ public function hasError() { return !empty($this->error); } }