Active.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php namespace App\Http\Controllers\Api\Redpacket;
  2. use App\Http\Controllers\Api\Api;
  3. use App\Models\Custom;
  4. use App\Models\CustomAmount;
  5. use Illuminate\Support\Facades\DB;
  6. use App\Models\Redpacket\ActiveRecord;
  7. use App\Models\Redpacket\ActiveReward;
  8. use App\Models\Redpacket\Active as Model;
  9. use App\Models\WeiBan\Tags as WeiBanTags;
  10. use App\Models\OrdersProduct;
  11. use App\Models\Product;
  12. /**
  13. * 红包活动
  14. *
  15. * @author 刘相欣
  16. *
  17. * */
  18. class Active extends Api{
  19. /**
  20. * 获取抽奖配置 /api/redpacket_active/get_detail
  21. *
  22. * */
  23. public function get_detail(Model $Model,Custom $Custom,ActiveReward $ActiveReward,ActiveRecord $ActiveRecord,WeiBanTags $WeiBanTags,OrdersProduct $OrdersProduct,Product $Product){
  24. // 接口验签
  25. // $this->verify_sign();
  26. // 检查登录
  27. $uid = $this->checkLogin();
  28. // 接收参数
  29. $id = request('id',0);
  30. // 获取活动
  31. $data = $Model->getOne($id);
  32. // 如果存在的话
  33. if( !$data ) return json_send(['code'=>'error','msg'=>'暂无活动','data'=>$data]);
  34. // 活动时间判断
  35. if( $data['end_time'] < time() ) return json_send(['code'=>'error','msg'=>'活动已结束','data'=>$data]);
  36. // 获取客户信息
  37. $custom = $Custom->getOne($uid);
  38. // 如果存在的话
  39. if( !$custom ) return json_send(['code'=>'no_login','msg'=>'请登录','data'=>['error'=>'无对应客户']]);
  40. // 如果城市限制并且不在在城市范围内,不允许参加
  41. if ( $data['city_ids'] && !in_array($custom['city_id'],explode(',',$data['city_ids'])) ) return json_send(['code'=>'error','msg'=>'账号不在城市范围,请核对您的城市','data'=>['error'=>'不在标签范围内']]);
  42. // 判断用户ID是否在活动参与范围
  43. if( $data['custom_scope'] && !in_array($uid,explode(',',$data['custom_scope']) ) ) return json_send(['code'=>'error','msg'=>'账号不在指定客户范围','data'=>['error'=>'不在客户范围内']]);
  44. // 判断用户手机是否在活动参与范围
  45. if( $data['phone_scope'] && !in_array($custom['phone'],explode(',',$data['phone_scope']) ) ) return json_send(['code'=>'error','msg'=>'账号不在指定手机号范围','data'=>['error'=>'不在手机号范围内']]);
  46. // 如果限制新老用户参与
  47. if( $data['custom_type'] ) {
  48. // 如果客户注册时间不在活动期间
  49. if( $data['custom_start_time'] > $custom['insert_time'] || $data['custom_end_time'] < $custom['insert_time'] ) return json_send(['code'=>'error','msg'=>'账号不在活动范围','data'=>['error'=>'不在活动时间内注册']]);
  50. }
  51. // 是否需要获取用户标签
  52. $tags = $data['tag_scope'] || $data['tag_except'] ? $WeiBanTags->getListByWeibanExtid($custom['weiban_extid']) : [];
  53. // 获取用户的标签
  54. $tags = $tags ? array_column($tags,'name') : [];
  55. // 判断是不是可以参与
  56. if( $data['tag_scope'] ) {
  57. // 解析数组
  58. $data['tag_scope'] = explode(',',$data['tag_scope']);
  59. // 计算交集
  60. $intersect = count(array_intersect($data['tag_scope'],$tags));
  61. // 判断标签是否必须同时满足
  62. if( $data['tag_scope_type'] == 1 ) {
  63. // 判断用户的标签是否全部满足于标签限制范围内
  64. if( $intersect != count($data['tag_scope']) ) return json_send(['code'=>'error','msg'=>'账号不在标签范围','data'=>['error'=>'不在标签范围内']]);
  65. }else{
  66. // 判断标签限制并且不在标签限制范围内,不允许参加
  67. if( !$intersect ) return json_send(['code'=>'error','msg'=>'账号不在标签范围','data'=>['error'=>'不在标签范围内']]);
  68. }
  69. }
  70. // 判断是不是可以参与
  71. if( $data['tag_except'] ) {
  72. // 解析数组
  73. $data['tag_except'] = explode(',',$data['tag_except']);
  74. // 计算交集
  75. $intersect = count(array_intersect($data['tag_except'],$tags));
  76. // 如果存在交集,在排除范围,即不可参与
  77. if( $intersect ) return json_send(['code'=>'error','msg'=>'账号不在范围','data'=>['error'=>'在标签排除范围内']]);
  78. }
  79. // 默认可以参加活动
  80. $data['allow_join'] = 1;
  81. // 获取商品
  82. $data['product_list'] = [];
  83. // 如果限制下单
  84. if( $data['is_order'] ) {
  85. // 查询结果
  86. $query = $OrdersProduct->query()->where([['custom_uid','=',$uid],['status','=',1],['insert_time','>=',$data['order_start_time']],['insert_time','<=',$data['order_end_time']]]);
  87. // 如果商品存在
  88. if( $data['product_scope'] )$query = $query->whereIn('product_id',explode(',',$data['product_scope']));
  89. // 获取时间段内下单数量
  90. $orderTotal = $query->groupBy('order_id')->count();
  91. // 如果没有下单数据
  92. if( !$orderTotal ) $data['allow_join'] = 0;
  93. // 获取产品列表
  94. if( $data['product_scope'] ) {
  95. // 产品列表
  96. $data['product_list'] = $Product->getListByIds(explode(',',$data['product_scope']));
  97. // 产品列表
  98. foreach ($data['product_list'] as $key => $value) {
  99. // 图片路径
  100. $value['product_thumb'] = path_compat($value['product_thumb']);
  101. // 重组数据
  102. $data['product_list'][$key] = $value;
  103. }
  104. }
  105. }
  106. // 奖品
  107. $reward = $ActiveReward->getListByLottery($data['id']);
  108. // 活动暂无奖品
  109. if( !$reward ) return json_send(['code'=>'error','msg'=>'活动暂未配置奖项','data'=>$data]);
  110. // 查询条件
  111. $map = [];
  112. // 判断周期
  113. if( !empty($data['freq']) ) {
  114. if( $data['freq'] == 1 ) $map = [['insert_time','>=',now()->startOfDay()->getTimestamp()],['insert_time','<=',now()->endOfDay()->getTimestamp()]];
  115. if( $data['freq'] == 2 ) $map = [['insert_time','>=',now()->startOfWeek()->getTimestamp()],['insert_time','<=',now()->endOfWeek()->getTimestamp()]];
  116. if( $data['freq'] == 3 ) $map = [['insert_time','>=',now()->startOfMonth()->getTimestamp()],['insert_time','<=',now()->endOfMonth()->getTimestamp()]];
  117. }
  118. // logo
  119. $data['logo'] = $data['logo'] ? path_compat($data['logo']) : '';
  120. // 查询用户已参与次数
  121. $data['join_num'] = (int)$ActiveRecord->query()->where([['custom_uid','=',$uid],['active_id','=',$id]])->where($map)->count();
  122. // 计算剩余次数
  123. $data['number'] = $data['allow_join'] ? ($data['lucky_num'] - $data['join_num']) : 0;
  124. // 最少为0,避免显示异常
  125. $data['number'] = $data['number'] < 0 ? 0 : $data['number'];
  126. // 时间处理
  127. $data['start_date'] = date('Y/m/d H:i',$data['start_time']);
  128. // 时间处理
  129. $data['end_date'] = date('Y/m/d H:i',$data['end_time']);
  130. // 通过活动ID,查询奖品
  131. $data['reward_list'] = [];
  132. // 奖品数据
  133. foreach ($reward as $value) {
  134. // 奖项
  135. $data['reward_list'][] = ['id'=>$value['id'],'money'=>$value['money']];
  136. }
  137. // 返回结果
  138. return json_send(['code'=>'success','msg'=>'获取成功','data'=>$data]);
  139. }
  140. /**
  141. * 抽奖 /api/redpacket_active/get_reward
  142. *
  143. * */
  144. public function get_reward(Model $Model,Custom $Custom,ActiveRecord $ActiveRecord,ActiveReward $ActiveReward,CustomAmount $CustomAmount,WeiBanTags $WeiBanTags,OrdersProduct $OrdersProduct){
  145. // 接口验签
  146. // $this->verify_sign();
  147. // 检查登录
  148. $uid = $this->checkLogin();
  149. // 获取活动
  150. $activeId = request('active_id',0);
  151. // 如果存在的话
  152. if( !$activeId ) return json_send(['code'=>'error','msg'=>'请选择参与的活动','data'=>['error'=>"抽奖活动ID有误"]]);
  153. // 获取客户信息
  154. $custom = $Custom->getOne($uid);
  155. // 如果存在的话
  156. if( !$custom ) return json_send(['code'=>'no_login','msg'=>'请登录','data'=>['error'=>'无对应客户']]);
  157. // 通过活动ID,查询奖品
  158. $data = $Model->getOne($activeId);
  159. // 如果存在的话
  160. if( !$data ) return json_send(['code'=>'error','msg'=>'活动不存在或未开始','data'=>$data]);
  161. // 活动时间判断
  162. if( $data['start_time'] > time() ) return json_send(['code'=>'error','msg'=>'活动暂未开始','data'=>$data]);
  163. // 活动时间判断
  164. if( $data['end_time'] < time() ) return json_send(['code'=>'error','msg'=>'活动已结束','data'=>$data]);
  165. // 如果城市限制并且不在在城市范围内,不允许参加
  166. if ( $data['city_ids'] && !in_array($custom['city_id'],explode(',',$data['city_ids'])) ) return json_send(['code'=>'error','msg'=>'账号不在城市范围,请核对您的城市','data'=>['error'=>'不在标签范围内']]);
  167. // 判断用户ID是否在活动参与范围
  168. if( $data['custom_scope'] && !in_array($uid,explode(',',$data['custom_scope']) ) ) return json_send(['code'=>'error','msg'=>'账号不在指定客户范围','data'=>['error'=>'不在客户范围内']]);
  169. // 判断用户手机是否在活动参与范围
  170. if( $data['phone_scope'] && !in_array($custom['phone'],explode(',',$data['phone_scope']) ) ) return json_send(['code'=>'error','msg'=>'账号不在指定手机号范围','data'=>['error'=>'不在手机号范围内']]);
  171. // 如果限制新老用户参与
  172. if( $data['custom_type'] ) {
  173. // 如果客户注册时间不在活动期间
  174. if( $data['custom_start_time'] > $custom['insert_time'] || $data['custom_end_time'] < $custom['insert_time'] ) return json_send(['code'=>'error','msg'=>'账号不在活动范围','data'=>['error'=>'不在活动时间内注册']]);
  175. }
  176. // 如果限制下单
  177. if( $data['is_order'] ) {
  178. // 查询结果
  179. $query = $OrdersProduct->query()->where([['custom_uid','=',$uid],['status','=',1],['insert_time','>=',$data['order_start_time']],['insert_time','<=',$data['order_end_time']]]);
  180. // 如果商品存在
  181. if( $data['product_scope'] ) $query = $query->whereIn('product_id',explode(',',$data['product_scope']));
  182. // 获取时间段内下单数量
  183. $orderTotal = $query->groupBy('order_id')->count();
  184. // 如果没有下单数据
  185. if( !$orderTotal ) return json_send(['code'=>'error','msg'=>'不符合下单条件','data'=>['error'=>'不符合订单条件']]);
  186. }
  187. // 是否需要获取用户标签
  188. $tags = $data['tag_scope'] || $data['tag_except'] ? $WeiBanTags->getListByWeibanExtid($custom['weiban_extid']) : [];
  189. // 获取用户的标签
  190. $tags = $tags ? array_column($tags,'name') : [];
  191. // 判断是不是可以参与
  192. if( $data['tag_scope'] ) {
  193. // 解析数组
  194. $data['tag_scope'] = explode(',',$data['tag_scope']);
  195. // 计算交集
  196. $intersect = count(array_intersect($data['tag_scope'],$tags));
  197. // 判断标签是否必须同时满足
  198. if( $data['tag_scope_type'] == 1 ) {
  199. // 判断用户的标签是否全部满足于标签限制范围内
  200. if( $intersect != count($data['tag_scope']) ) return json_send(['code'=>'error','msg'=>'账号不在标签范围','data'=>['error'=>'不在标签范围内']]);
  201. }else{
  202. // 判断标签限制并且不在标签限制范围内,不允许参加
  203. if( !$intersect ) return json_send(['code'=>'error','msg'=>'账号不在标签范围','data'=>['error'=>'不在标签范围内']]);
  204. }
  205. }
  206. // 判断是不是可以参与
  207. if( $data['tag_except'] ) {
  208. // 解析数组
  209. $data['tag_except'] = explode(',',$data['tag_except']);
  210. // 计算交集
  211. $intersect = count(array_intersect($data['tag_except'],$tags));
  212. // 如果存在交集,在排除范围,即不可参与
  213. if( $intersect ) return json_send(['code'=>'error','msg'=>'账号在不可参与范围','data'=>['error'=>'账号在标签排除范围内']]);
  214. }
  215. // 奖品
  216. $reward = $ActiveReward->getListByLottery($activeId);
  217. // 活动暂无奖品
  218. if( !$reward ) return json_send(['code'=>'error','msg'=>'活动暂未配置奖品','data'=>$data]);
  219. // 查询条件
  220. $map = [['insert_time','>=',$data['start_time']],['insert_time','<=',$data['end_time']]];
  221. // 判断周期
  222. if( !empty($data['freq']) ) {
  223. if( $data['freq'] == 1 ) $map = [['insert_time','>=',now()->startOfDay()->getTimestamp()],['insert_time','<=',now()->endOfDay()->getTimestamp()]];
  224. if( $data['freq'] == 2 ) $map = [['insert_time','>=',now()->startOfWeek()->getTimestamp()],['insert_time','<=',now()->endOfWeek()->getTimestamp()]];
  225. if( $data['freq'] == 3 ) $map = [['insert_time','>=',now()->startOfMonth()->getTimestamp()],['insert_time','<=',now()->endOfMonth()->getTimestamp()]];
  226. }
  227. // 查询用户已参与次数
  228. $data['join_num'] = (int)$ActiveRecord->query()->where([['custom_uid','=',$uid],['active_id','=',$activeId]])->where($map)->count();
  229. // 计算剩余次数
  230. $data['join_num'] = $data['lucky_num'] - $data['join_num'];
  231. // 如果次数不够
  232. if( $data['join_num'] <= 0 ) return json_send(['code'=>'error','msg'=>'抽奖次数已用完','data'=>['error'=>'抽奖次数已用完']]);
  233. // 限制中奖则获取中奖次数
  234. $rewarTotal = $data['max_reward'] ? $ActiveRecord->query()->where([['active_id','=',$data['id']],['custom_uid','=',$uid],['reward_id','>',0]])->where($map)->count() : 0;
  235. // 中奖上限以后不再中奖, 默认获取未中奖
  236. $rewardResult = ($data['max_reward'] && $rewarTotal >= $data['max_reward']) ? ['reward_list'=>$reward,'index'=>0] : $ActiveReward->getRewardResult($activeId);
  237. // 未抽中
  238. if( !$rewardResult ) return json_send(['code'=>'error','msg'=>'谢谢参与','data'=>['error'=>'谢谢参与']]);
  239. // 奖品索引
  240. $rewardIndex = $rewardResult['index'];
  241. // 奖品列表
  242. $reward = $rewardResult['reward_list'];
  243. // 获取奖品信息
  244. $rewardResult = $reward[$rewardIndex];
  245. // 抽奖记录
  246. $record = ['custom_uid'=>$uid,'active_id'=>$activeId,'reward_id'=>$rewardResult['id'],'money'=>$rewardResult['money'],'status'=>8];
  247. // 开启事务
  248. DB::beginTransaction();
  249. try{
  250. // 如果中奖,下标不是0
  251. if( $rewardIndex ) {
  252. // 奖品记录ID
  253. if( !empty($rewardResult['id']) ){
  254. // 是否直接发放
  255. if( $data['is_arrive'] ) {
  256. // 发放红包
  257. $result = $CustomAmount->trade($uid,$activeId,$rewardResult['money'],8,1,'红包活动');
  258. // 发放失败,改为未中奖
  259. if( isset($result['error']) ) {
  260. // 回退数据
  261. DB::rollBack();
  262. // 提示
  263. return json_send(['code'=>'error','msg'=>'发生了点意外,请重试']);
  264. }
  265. // 发放成功,状态为已完成
  266. $record['status']= 8;
  267. }else{
  268. // 发放状态为进行中
  269. $record['status']= 1;
  270. }
  271. // 扣减次数
  272. $result = $ActiveReward->edit($rewardResult['id'],['reward_total'=>DB::raw('reward_total+-1')]);
  273. // 发放失败,改为未中奖
  274. if( !$result ) {
  275. // 回退数据
  276. DB::rollBack();
  277. // 提示
  278. return json_send(['code'=>'error','msg'=>'抽取异常,请重试']);
  279. }
  280. }
  281. }
  282. // 写入记录
  283. $result = $ActiveRecord->add($record);
  284. // 写入失败
  285. if( !$result ) {
  286. // 回退数据
  287. DB::rollBack();
  288. // 提示
  289. return json_send(['code'=>'error','msg'=>'抽奖记录失败,请重试']);
  290. }
  291. // 提交事务
  292. DB::commit();
  293. // 通过活动ID,查询奖品
  294. $rewardList = [];
  295. // 奖品数据
  296. foreach ($reward as $value) {
  297. $rewardList[] = ['id'=>$value['id'],'money'=>$value['money']];
  298. }
  299. // 默认可以参加活动
  300. $data['allow_join'] = 1;
  301. // 返回结果
  302. return json_send(['code'=>'success','msg'=>'抽奖成功','data'=>['reward_list'=>$rewardList,'reward_index'=>$rewardIndex,'join_num'=>$data['join_num']-1]]);
  303. // 异常处理
  304. } catch (\Throwable $th) {
  305. // 回退数据
  306. DB::rollBack();
  307. // 下单失败提示
  308. return json_send(['code'=>'error','msg'=>'抽奖失败,请重试','data'=>['error'=>$th->getMessage().$th->getLine()]]);
  309. }
  310. }
  311. }