// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\controller\groupbuy; use app\api\model\Goods as GoodsModel; use app\api\model\groupbuylb\GroupBuyLbActivity as GroupBuyLbActivityModel; use app\api\model\groupbuylb\GroupBuyLbHelp; use app\api\model\groupbuylb\GroupBuyLbJoin; use app\api\model\PromotionMonitor; use app\api\service\User as UserService; use app\common\enum\order\PayType as OrderPayTypeEnum; use app\common\library\helper; use app\common\model\BrowseRecords; use app\common\model\User as UserModel; use app\common\service\delivery\Express as ExpressService; use app\api\model\Category; use app\api\model\GoodsCategoryRel; use app\api\controller\Controller; use app\api\model\groupbuy\GroupBuyActivity; use app\api\model\groupbuy\GroupBuyGoods; use app\api\model\groupbuy\GroupBuyHelp; use app\api\model\groupbuy\GroupBuyJoin; use app\common\service\Order as OrderService; use app\common\service\order\Refund as RefundService; use think\facade\Db; use app\api\model\order\GroupBuyPay; use app\api\model\card\UserRiceCard as UserRiceCardModel; use app\api\model\card\UserRiceCardConsume; use app\api\model\card\UserRiceCard; use app\common\service\goods\source\Factory as StockFactory; use app\common\enum\order\OrderSource as OrderSourceEnum; use app\api\model\subscribe\WechatSub; /** * 活动 * Class service * @package app\api\controller\user\order */ class Activity extends Controller { //如果真有拼团不成功 public function toCheckPtFail(){ $now = Date("Y-m-d H:i:s",time()); $joinList = GroupBuyJoin::where('status',0)->where('end_time','<',$now)->select(); foreach($joinList as $row){ if($row->people_count>$row->help_count){ $join = GroupBuyJoin::where('id',$row->id)->lock('for update')->find(); $join->status = 2; $join->save(); // (new GroupBuyPay)->activityEnd($join->user_id,$join->id); } } } //测试回退库存 public function testStock(){ $goods_id = 10137; $goods_sku_id = 0; $total_num = 1; // $res = StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->backGoodsSkuStockExpress($goods_id,$goods_sku_id,$total_num); // $res = StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->updateStockSalesExpress($goods_id,$total_num); // var_dump($res); } public function cancel(int $order_id){ $user = UserService::getCurrentLoginUser(true); Db::startTrans(); $help = GroupBuyHelp::where("pay_state",0)->where(' id',$order_id)->find(); $k = 0; if($help){ $help->pay_state = 2; $help->save(); //有金米粒抵扣 if($help->gold_rice_amount>0){ UserModel::setIncDecByField($help->user_id,['gold_rice'=>(float)$help->gold_rice_amount],['gold_rice_frozen'=>(float)$help->gold_rice_amount]); } if($help->rice_card_id > 0){ riceCardReturn($help->rice_card_id,$help->rice_card_money,$help->order_no,$help->pay_money); } $k++; $join = GroupBuyJoin::where('id',$help->join_id)->find(); if($join){ //说明是团长发起的,但没有付款 if($join->help_count == 0){ $join->end_time = Date("Y-m-d H:i:s",time()); $join->status = 3; $join->save(); $k++; } } $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$help->group_buy_activity_id)->find(); //取消订单 回退库存 if($groupgoods){ StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->backGoodsSkuStockExpress($groupgoods->goods_id,$groupgoods->goods_sku_id,$help->goods_num); } } Db::commit(); echo 'success:'.$k; } public function headPicture(){ $host = env('APP_URL'); $rel = rand(1,16); $url = $host.'/uploads/image/'.$rel.'.jpeg'; return $url; } //自动补位逻辑 public function toIncHelp(){ $nts = time() + 3600; $now = Date("Y-m-d H:i:s",time()); $time = Date("Y-m-d H:i:s",$nts); $list = GroupBuyJoin::where('status','=',0)->where('end_time','>',$now)->where('end_time','<',$time)->where('help_count','>',0)->select(); $k = 0; foreach($list as $row){ $group_buy_activity_id = $row['group_buy_activity_id']; $activity = GroupBuyActivity::where('id',$group_buy_activity_id)->find(); //这一拼团的真实付费用户有几个 $real_pay_cnt = GroupBuyHelp::where('join_id',$row['id'])->where('pay_state',1)->where("fans",0)->count(); if($activity->tb_cnt>=0&&$real_pay_cnt>=$activity->tb_cnt){ if($row['people_count']>$row['help_count']){ $k++; //开始补位 Db::startTrans(); $join = GroupBuyJoin::where('id',$row['id'])->lock('for update')->find(); $help['group_buy_activity_id'] = $row['group_buy_activity_id']; $help['join_id'] = $row['id']; $help['user_id'] = 0; $help['pay_state'] = 1; $help['pay_time'] = time(); $help['order_id'] = -1;//补位的统一用-1 $help['fans'] = 1; $help['goods_num'] = 0; $help['head_picture'] = $this->headPicture(); $model = new GroupBuyHelp; $model->save($help); $join->help_count += 1; // 拼团人数+1 $flag = false; //拼团人数够了 if($join->help_count==$join->people_count){ $flag = true; } $join->save(); if($flag){ //成功了话写真实订单 $pay = new GroupBuyPay; $pay->ptSuccessNotify($join->id); } Db::commit(); } } } echo 'success:k:'.$k; } //订单处理 public function orderDeal(){ $this->toIncHelp(); //自动补单 $this->cancelOrder();//取消未支付订单 $this->toCheckPtFail();//拼团没成功的 join status =2 } //取消订单 public function cancelOrder(){ $list = GroupBuyHelp::where("pay_state",0)->limit(5)->order(['create_time'=>'asc'])->field('id')->select(); $now = time(); $k = 0; foreach($list as $row){ Db::startTrans(); $one = GroupBuyHelp::where('id',$row['id'])->lock('for update')->find(); $ts = time()-strtotime($one->create_time); if($ts>300){ //超过5分钟没支付 $order_no = $one->order_no; $one->pay_state = 2; $one->save(); //有金米粒抵扣 if($one->gold_rice_amount>0){ UserModel::setIncDecByField($one->user_id,['gold_rice'=>(float)$one->gold_rice_amount],['gold_rice_frozen'=>(float)$one->gold_rice_amount]); } //有米卡支付的话 if($one->rice_card_id > 0){ riceCardReturn($one->rice_card_id,$one->rice_card_money,$one->order_no,$one->pay_money); } $join = GroupBuyJoin::where('id',$one->join_id)->find(); if($join){ //说明是团长发起的,但没有付款 if($join->help_count == 0){ $join->end_time = Date("Y-m-d H:i:s",time()); $join->status = 3; $join->save(); } } $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$one->group_buy_activity_id)->find(); //取消订单 回退库存 if($groupgoods){ StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->backGoodsSkuStockExpress($groupgoods->goods_id,$groupgoods->goods_sku_id,$one->goods_num); } $k++; } Db::commit(); } echo 'success:k:'.$k; } public function testWx(){ $order_no = 'ysc2022041698489710'; $result = $this->reqWx($order_no); echo $result; } //回调微信 public function reqWx($order_no){ $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/'.$order_no.'?mchid=1615908904'; $data['mchid'] = '1615908904'; $data['out_trade_no'] = $order_no; $result = curl_post($url,json_encode($data)); return $result; } public function getActivity($activity_id){ $activity = GroupBuyActivity::where("id",$activity_id)->find(); if(empty($activity)){ return false; } $now = Date("Y-m-d H:i:s",time()); if($now > $activity->end_time){ return false; } if($activity->start_time>$now){ return false; } if($activity->audit_status!=1||$activity->status!=1){ return false; } return $activity; } /** * 获取商品详情 * @param int $id * @return array */ public function detail($activity_id =0) { if(empty($activity_id)){ $activity_id = 5; } $activity = $this->getActivity($activity_id); if(!$activity){ return $this->renderError("活动已结束"); } $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$activity_id)->find(); $id = $groupgoods->goods_id; $addressId = 0; $staffUserId = 0; $user = UserService::getCurrentLoginUser(false); $user_id = $user->user_id??0; // 商品详情 $model = new GoodsModel; $goodsInfo = $model->getDetails($id, $user, $addressId, $staffUserId); $goodsInfo->inc('view_num', 1)->update(); if ($user) { $browseRecord = BrowseRecords::whereDay('create_time')->where(['user_id' =>$user_id, 'source_type' => 1, 'source_id' => $id])->find(); if (!$browseRecord) { BrowseRecords::create([ 'user_id' => $user_id, 'source_type' => 1, 'source_id' => $id ]); $goodsInfo->inc('view_distinct_num', 1)->update(); } else { $browseRecord->update_time = time(); $browseRecord->save(); } } $goods = $goodsInfo->toArray(); $goods['goods_sku_id'] = $groupgoods->goods_sku_id; $data['goods'] = $goods; $help = GroupBuyHelp::where("group_buy_activity_id",$activity_id)->where('user_id',$user_id)->where('pay_state',1)->where('order_id',0)->find(); $helpdata = null; if($help){ $thatjoin = GroupBuyJoin::where('id',$help->join_id)->where('status','in',[0,1])->find(); } if($help&&$thatjoin){ $helpdata['join_id'] = $help->join_id; $helpdata['pay_state'] = $help->pay_state; $helpdata['activity_id'] = $help->group_buy_activity_id; } $now = Date("Y-m-d H:i:s",time()); $joinIdArr = GroupBuyJoin::where("status",0)->where('group_buy_activity_id',$activity_id)->where('end_time','>',$now)->order(['id'=>'desc'])->column("id"); $toPtList = [];//去拼团列表 if(!empty($joinIdArr)){ $joinIdStr = implode(",",$joinIdArr); $idSql = 'select min(id) as ids from yoshop_group_buy_activity_help where join_id in ('.$joinIdStr.') and pay_state=1 and group_buy_activity_id='.$activity_id.' group by join_id order by join_id desc limit 7'; $result = Db::query($idSql); $idArray = array_column($result,'ids'); // $joinList = GroupBuyHelp::with(['user'])->field("id,join_id,user_id,head_picture")->where('pay_state',1)->limit(7)->where('id','in',$idArray)->order(['join_id'=>'desc'])->select(); $now = Date("Y-m-d H:i:s",time()); $joinList = GroupBuyJoin::where("status",0)->with(['user'=>['avatar']])->where('group_buy_activity_id',$activity_id)->where('end_time','>',$now)->order(['help_count'=>'desc'])->limit(7)->select(); foreach($joinList as $row){ $toPtList[] = [ 'join_id'=>$row['id'], 'head_picture'=>$row['user']['avatar']['preview_url']??'', 'nick_name'=>$row['user']['nick_name']??'', 'user_id'=>$row['user_id'], 'id'=>$row['id'], 'hc_count' =>$row['hc_count'], ]; } } $data['groupbuy'] = ['fmt_end_time'=> $activity->fmt_end_time, 'group_price'=> $groupgoods->group_price, 'help'=> $helpdata, 'to_pt_list'=>$toPtList, 'people_count'=>$activity->people_count ]; return $this->renderSuccess(compact('data')); } //分享详情 public function joininfo(int $join_id){ $user = UserService::getCurrentLoginUser(false); $user_id = $user->user_id??0; $joinInfo = GroupBuyJoin::with(['help'])->where("id",$join_id)->find(); $join = $joinInfo->toArray(); // var_dump($user_id); // die(); if(empty($join)){ return $this->renderError("找不到记录"); } $groupgoods = GroupBuyGoods::where('group_buy_activity_id',$join['group_buy_activity_id'])->find(); if(empty($groupgoods)){ return $this->renderError("找不到商品"); } $id = $groupgoods->goods_id; $addressId = 0; $staffUserId =0; $activity = GroupBuyActivity::where("id",$join['group_buy_activity_id'])->find(); $model = new GoodsModel; $goodsInfo = $model->getDetails($id, $user, $addressId, $staffUserId); $join['hc_count'] = $joinInfo->hc_count; $join['fmt_end_time'] = $joinInfo->fmt_end_time; if($user){ $join['is_self'] = $user->user_id==$join['user_id']?true:false; }else{ $join['is_self'] = false; } $cur_user_help = GroupBuyHelp::where('user_id',$user_id)->where('join_id',$join_id)->field("user_id,pay_state,order_id")->order(['id'=>'desc'])->find(); $join['cur_user_have_help'] = $cur_user_help; $help = $joinInfo['help']; $newhelp = []; $k = 0; if(!empty($help)){ foreach($help as $row){ $newhelp[] = ['head_picture'=>$row['head_picture'], 'pay_state'=>$row['pay_state'],'is_tz'=>$row['user_id']==$join['user_id']?true:false ]; } } $join['help'] = $newhelp; $data['join'] = $join; $goods = $goodsInfo->toArray(); $goods['goods_sku_id'] = $groupgoods->goods_sku_id; $data['goods'] = $goods; $data['groupbuy'] = [ 'group_price'=> $groupgoods->group_price, 'share_title'=>$join['share_title'], 'an_share_title'=>$activity['an_share_title']??0 ]; return $this->renderSuccess(compact('data')); } //我的拼团列表 public function myptlist(){ $user = UserService::getCurrentLoginUser(); $user_id = $user->user_id??0; $model = new GroupBuyHelp; $list = $model->getList($user_id); return $this->renderSuccess(compact('list')); } //我的拼团列表1.4.2 public function myptlist1(){ $user = UserService::getCurrentLoginUser(); $user_id = $user->user_id??0; $model = new GroupBuyHelp; $page = intval($this->request->get('page',1)); $list = $model->getListUnionGroup($user_id,15,$page); return $this->renderSuccess(compact('list')); } /** * 取消拼团 * @return array|\think\response\Json * @throws \app\common\exception\BaseException * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function ptaCancel(){ $userId = UserService::getCurrentLoginUserId(); $help_id = intval($this->request->get('help_id',0)); if (!$help_id){ return $this->renderError('参数有误'); } $modelHelp = new GroupBuyHelp; $help = $modelHelp->find($help_id); if (!$help){ return $this->renderError('参数有误'); } $needCloseGroup = false; $joinM = new GroupBuyJoin(); $join = $joinM->find($help->join_id); if ($join->user_id == $userId){ //如果团长是自己,判断团中有没有真实团员,如没有真实团员参加,允许取消拼团并退款 $exitRealHelper = $modelHelp->where('join_id',$help->join_id)->where('fans',0) ->where('user_id','<>',$userId) ->where('pay_state',1) ->where('finance_refund',0)->find(); if ($exitRealHelper){ return $this->renderError( '已有团员参团,请成团后申请退款'); } $needCloseGroup = true; } $help['pay_price'] = $help['pay_money']; $flag1 = false; //退到米卡 if($help->rice_card_id > 0){ $flag = riceCardReturn($help->rice_card_id,$help->rice_card_money,$help->order_no,$help->pay_money); if ($flag == false){ log_record('groupBuyHelpId::'.$help_id.'::退款退到米卡失败','error'); return $this->renderError('系统繁忙,稍后再试'); } } $data['finance_refund'] = 0; $data['finance_time'] = time(); if ($help['pay_money'] > 0){ $refund_number = OrderService::createOrderNoPrefix('TKGB'); //申请单编号 //直接退款逻辑 $RefundService = new RefundService(); $refund_ret = $RefundService->execute($help,$refund_number,$help['pay_money']); $data['refund_number'] = $refund_number; if ($refund_ret['status'] == 200) { $data['refund_transaction_id'] = $refund_ret['data']['transaction_id']; // 微信退款交易号 $flag1 = true; }else{ //退款失败 log_record('groupBuyHelpId::'.$help_id.'::微信退款失败','error'); $data['finance_refund'] = 2; } }else{ $flag1 = true; } if ($flag1 == true){ $data['finance_refund'] = 1 ; $msg = '已尝试退款,请联系用户核对'; }else{ $msg = '退款失败'; return $this->renderError($msg); } try { $data['has_canceled'] = 1; $help->where('id',$help_id)->update($data); }catch (\Exception $e){ log_record('groupBuyHelpId::'.$help_id.'::更新groupBuyHelp失败::'.$e->getMessage(),'error'); return $this->renderError('系统繁忙,稍后再试'); } //取消订单 回退库存 $groupgoods = \app\store\model\groupbuy\GroupBuyGoods::where('group_buy_activity_id',$help['group_buy_activity_id'])->find(); if($groupgoods){ StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->backGoodsSkuStockExpress($groupgoods->goods_id,$groupgoods->goods_sku_id,$help['goods_num']); StockFactory::getFactory(OrderSourceEnum::GROUPBUY)->updateStockSalesExpress($groupgoods->goods_id,$help['goods_num'],false); } $joinUpdates['help_count'] = $join->help_count>=1?($join->help_count- 1):0; if ($needCloseGroup == true){ //团长退款关闭团 $joinUpdates['status'] = 4;//取消拼团 } $join->where('id',$help->join_id)->update($joinUpdates); return $this->renderSuccess($msg); } /** * 普通拼团和裂变拼团每5分钟,虚拟自动发起5个虚拟团,后续活动拼团中的数量不足5个时就新增虚拟团达到5个 * @return array|\think\response\Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function addVirJoinCrontab() { $now = date('Y-m-d H:i:s'); $acts = GroupBuyActivity::field('id,(select count(*) from yoshop_group_buy_activity_join where yoshop_group_buy_activity_join.group_buy_activity_id=yoshop_group_buy_activity.id) as counts') ->where('start_time','<=',$now) ->where('end_time','>=',$now) ->where('audit_status','=',1) ->where('status','=',1) ->where('need_fake_group','=',1) ->having('counts < 5') ->select(); if ($acts->isEmpty() == false){ foreach ($acts as $item){ for ($i=0;$i<5-$item['counts'];$i++){ $this->addVirJoin(1,$item['id']); } } } $actsLb = GroupBuyLbActivityModel::field('id,(select count(*) from yoshop_group_buy_lb_activity_join where yoshop_group_buy_lb_activity_join.group_buy_lb_activity_id=yoshop_group_buy_lb_activity.id and status=0) as counts') ->where('start_time','<=',$now) ->where('end_time','>=',$now) ->where('audit_status','=',1) ->where('status','=',1) ->where('need_fake_group','=',1) ->having('counts < 5') ->select(); foreach ($actsLb as $item){ for ($i=0;$i<5-$item['counts'];$i++){ $this->addVirJoin(2,$item['id']); } } return $this->renderSuccess(); } /** * 新增FAKE系统拼团 * @param $type * @param $group_buy_activity_id * @return false|int * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function addVirJoin($type ,$group_buy_activity_id){ $user_id = 0; $address['user_name'] = ''; $address['phone'] = ''; $address['province_id'] = 0; $address['city_id'] = 0; $address['region_id'] = 0; $address['detail'] = ''; if ($type == 1){ //发起拼团 // 根据推广监控ID判断活动效果归属 $promotionMonitorId = PromotionMonitor::checkActEffectOwner(4, $order['promotionMonitorId'] ?? 0, $group_buy_activity_id); $activity = GroupBuyActivity::where("id",$group_buy_activity_id)->find(); $join = [ 'group_buy_activity_id' => $group_buy_activity_id, 'people_count'=> $activity['people_count'], 'end_time' => Date("Y-m-d H:i:s",time() + $activity['during_time']*60*60), 'share_title'=>$activity['share_title'], 'create_time'=>time(), 'update_time'=>time(), 'user_id'=>$user_id, 'help_count'=>1 ]; $buyjoinModel = new GroupBuyJoin(); $joinId = $buyjoinModel->insertGetId($join); $help = [ 'user_id' => $user_id, 'order_no' => '0', 'group_buy_activity_id' => $group_buy_activity_id, 'join_id'=>$joinId, 'goods_num' =>0, 'head_picture'=>$this->headPicture(), 'gold_rice_amount' => 0, 'gold_rice_money' => 0, 'rice_card_id'=>0, 'rice_card_money'=>0, 'rice_card_express_money'=>0, 'pay_money'=> 0, 'express_money'=> 0, 'order_money'=> 0, 'provider_ids'=>0, 'good_rice_card_money'=>0, 'promotion_monitor_id' => $promotionMonitorId, 'staff_user_id' => 0, 'staff_shop_id' => 0, 'fans'=>1, 'pay_state' => 1, 'pay_time' => time(), 'pay_type' => OrderPayTypeEnum::WECHAT, ]; $help = array_merge($help,$address); // 保存参团记录 $buyhelpModel = new GroupBuyHelp(); $buyhelpModel->save($help); } if ($type == 2){ $user_id = 0; //发起拼团 $activity = GroupBuyLbActivityModel::where("id",$group_buy_activity_id)->find(); $share_title = $activity['share_title']; if($activity->an_share_title==1){ $share_title = '用户'.rand(1000,9999).$share_title; } $join = [ 'group_buy_lb_activity_id' => $group_buy_activity_id, 'people_count'=> $activity['people_count'], 'end_time' => Date("Y-m-d H:i:s",time() + $activity['during_time']*60*60), 'share_title'=>$share_title, 'share_copy_writing'=>$activity['share_copy_writing'], 'create_time'=>time(), 'update_time'=>time(), 'user_id'=>$user_id, 'is_virtual'=>1, 'help_count'=>1 ]; $buyjoinModel = new GroupBuyLbJoin(); $joinId = $buyjoinModel->insertGetId($join); $help = [ 'user_id' => $user_id, 'order_no' => '0', 'group_buy_lb_activity_id' => $group_buy_activity_id, 'join_id'=>$joinId, 'goods_num' =>0, 'head_picture'=>$this->headPicture(), 'rice_card_id'=>0, 'rice_card_money'=>0, 'rice_card_express_money'=>0, 'order_id'=> -1,//补位的统一用-1 'pay_money'=> 0, 'express_money'=> 0, 'order_money'=> 0, 'provider_ids'=>0, 'good_rice_card_money'=>0, 'is_virtual_join_user'=>0, 'virtual_join_id'=>1, 'pay_state'=>1, 'fans'=>1, 'pay_time' => time(), 'pay_type' => OrderPayTypeEnum::WECHAT, ]; $help = array_merge($help,$address); // 保存参团记录 $buyhelpModel = new GroupBuyLbHelp(); $buyhelpModel->save($help); } return true; } }