user_id; //虚拟商品交易成功 if($order->order_type == 'physical'){ $order->status = \app\common\constant\order\Status::STATUS_UNSEND; \app\common\model\order\Log::set($order->order_no,"订单已完成支付,等待发货"); $orderItemList = (new Item())->getItemList($order->order_no); if(!empty($orderItemList)){ $stockSale = new \app\common\service\app\physical\StockSale(); $stockSale->forwardStockSale($orderItemList); } } else { $order->status = \app\common\constant\order\Status::STATUS_SUCCESS; //增加销量 \app\common\model\order\Log::set($order->order_no,"订单已完成交易"); // 订单支付成功 $this->courseSubscriptionBind($order); } $order->save(); //分销 检查升级 (new \app\api\model\app\agent\Level())->handle($userId); //消息推送收集 \app\admin\library\app\msgpush\Msg::collect('order_success',['order_no'=>$order->order_no]); } /** * 授权用户购买的课程 * @param $order * @return bool */ public function courseSubscriptionBind($order){ $orderItemList = (new Item())->getItemList($order->order_no); $SubscriptionModel = new Subscription(); if(!empty($orderItemList)){ foreach ($orderItemList as $orderItem){ switch ($order->order_type){ case 'vipcard': $cardSku = explode("_",$orderItem['extend_data']); if($cardSku){ \app\common\model\app\vip\CardUser::openVip($order->user_id,$orderItem['item_id'],$cardSku[1]); } break; case 'live_gift': $messageInfo = explode("_",$orderItem['extend_data']); \app\common\model\live\Message::sendMessage($order->user_id,$messageInfo[0],$messageInfo[1],'gift',$orderItem['item_name']."×".$orderItem['count'],1); //增加送礼物记录 \app\admin\model\live\GiftLog::insert([ 'uniacid'=>UNIACID, 'live_id'=>$messageInfo[0], 'user_id'=>$order->user_id, 'order_no'=>$order->order_no, 'name'=>$orderItem['item_name'], 'price'=>$order->real_price, 'count'=>$orderItem['count'], 'createtime'=>time() ]); break; case 'exercises': \app\common\model\app\exam\ExercisesSubscribe::subscribe($order->user_id,$orderItem['item_id'],'pay'); break; case 'activity': $ticketInfo = $orderItem->snapshoot; \app\api\model\app\activity\Activity::setUserTicket($orderItem->user_id,$orderItem->item_id,$ticketInfo['ticket_id'],$ticketInfo['apply_info_id'],$orderItem->count,$orderItem->real_price,$orderItem->order_no,$orderItem->extend_data); //增加销量 //活动增加销量 \app\api\model\app\activity\Activity::where(['id'=>$orderItem['item_id']])->setInc('sales'); //活动票也要增加 \app\api\model\app\activity\Ticket::where(['id'=>$ticketInfo['ticket_id']])->setInc('sales'); break; case 'composite': // 组合商品处理:授权子商品权限 + 增加销量 if (\app\admin\library\project\App::isInstall('composite')) { $this->compositePurchaseHandle($orderItem, $order); } break; default: $this->addSales($orderItem['item_id'],$order); $getType = ''; $mobile = ''; if($order->source == 'channels'){ $channelsOrder = \think\Db::name("app_channels_order")->where(['order_id'=>$order->order_no])->find(); if($channelsOrder){ $getType = 'channels'; $mobile = $channelsOrder['mobile']; } } $SubscriptionModel->setUserCourse($order->user_id,$orderItem['item_id'],$getType,$mobile); break; } } } return true; } /** * 增加销量 * @param $courseId * @return void */ public function addSales($goodsId,$order){ switch ($order->order_type){ case 'score': //积分商品增加销量 减少库存 $scoreGoodsModel = new \app\api\model\app\score\Goods; $scoreGoodsModel->where(['goods_id'=>$goodsId])->setInc('sales'); $scoreGoodsModel->where(['goods_id'=>$goodsId])->setDec('stock'); break; case 'goods': Course::where(['id'=>$goodsId])->setInc('sales'); break; } return true; } /** * 处理组合商品购买:授权子商品 + 增加销量 * @param array $orderItem 订单商品 * @param object $order 订单对象 */ protected function compositePurchaseHandle($orderItem, $order) { $snapshoot = $orderItem['snapshoot']; if (is_string($snapshoot)) { $snapshoot = json_decode($snapshoot, true); } if (empty($snapshoot)) { return; } $subGoodsList = $snapshoot['sub_goods_list'] ?? []; $userId = $order->user_id; $compositeGoodsId = $orderItem['item_id']; // 授权每个子商品 $SubscriptionModel = new Subscription(); foreach ($subGoodsList as $subGoods) { $subGoodsId = $subGoods['sub_goods_id']; $subGoodsType = $subGoods['sub_goods_type']; // 构建有效期覆盖配置(组合商品自定义有效期优先于商品本身有效期) $validityOverride = null; if (!empty($subGoods['validity_type']) && intval($subGoods['validity_type']) > 1) { $validityOverride = [ 'validity_type' => intval($subGoods['validity_type']), 'validity_value' => $subGoods['validity_value'] ?? '', ]; } switch ($subGoodsType) { case 'course': // 视频/音频/图文/直播都统一为 course 授权 $SubscriptionModel->setUserCourse($userId, $subGoodsId, '', '', $validityOverride); // 增加子商品销量 Course::where(['id' => $subGoodsId])->setInc('sales'); break; case 'vipcard': // 会员卡:从快照中取有效期信息 $cardSku = $subGoods['sub_goods_price'] . '_' . ($subGoods['validity_value'] ?? '30'); \app\common\model\app\vip\CardUser::openVip($userId, $subGoodsId, $cardSku); break; case 'exercises': \app\common\model\app\exam\ExercisesSubscribe::subscribe($userId, $subGoodsId, 'pay'); // 增加练习销量 \think\Db::name('app_exam_exercises')->where(['id' => $subGoodsId])->setInc('sales'); break; case 'audio': case 'live': case 'article': case 'column': // 音频/直播/图文/专栏统一存储于 tuzhi_course 表,按 id 累加销量 $SubscriptionModel->setUserCourse($userId, $subGoodsId, '', '', $validityOverride); \think\Db::name('course')->where(['id' => $subGoodsId])->setInc('sales'); break; } } // 增加组合商品自身销量 \app\admin\model\app\composite\Goods::where([ 'id' => $compositeGoodsId, 'uniacid' => UNIACID ])->setInc('total_sales'); } /** * 处理组合商品退款:关闭子商品权限 + 返还销量 * @param array $orderItem 订单商品 * @param object $order 订单对象 * @param bool $isFullRefund 是否全额退款 */ public static function compositeRefundHandle($orderItem, $order, $isFullRefund = false) { $snapshoot = $orderItem['snapshoot']; if (is_string($snapshoot)) { $snapshoot = json_decode($snapshoot, true); } if (empty($snapshoot)) { return; } $subGoodsList = $snapshoot['sub_goods_list'] ?? []; $userId = $order['user_id'] ?? $order->user_id; $compositeGoodsId = $orderItem['item_id']; // 如果全额退款,返还销量 if ($isFullRefund) { // 组合商品销量 -1 \app\admin\model\app\composite\Goods::where([ 'id' => $compositeGoodsId, 'uniacid' => UNIACID ])->setDec('total_sales'); // 子商品销量 -1 foreach ($subGoodsList as $subGoods) { switch ($subGoods['sub_goods_type']) { case 'course': Course::where(['id' => $subGoods['sub_goods_id']])->setDec('sales'); break; case 'exercises': \think\Db::name('app_exam_exercises')->where(['id' => $subGoods['sub_goods_id']])->setDec('sales'); break; case 'audio': case 'live': case 'article': case 'column': // 音频/直播/图文/专栏统一存储于 tuzhi_course 表,按 id 扣减销量 \think\Db::name('course')->where(['id' => $subGoods['sub_goods_id']])->setDec('sales'); break; } } } } }