PHP实现抽奖功能实例代码


Posted in PHP onJune 30, 2020

在项目开发中经常会遇到花钱抽奖类型的需求。但是老板总是担心用户用小钱抽到大奖。这样会导致项目亏损。下边这段代码可以有效制止抽奖项目亏钱。

个人奖池:

语言:thinkphp redis mysql

表:desire抽奖商品表 desire_log用户抽奖奖品表 user_desire_log用户抽奖记录表   desire_risk抽奖风控表

需求:用户奖池分为进行中奖池 和已完成奖池 当用户抽到大奖后 用户个人奖池重置 否则将继续抽奖 最后一次抽奖必中大奖 通过风控金额来判断用户是否可以抽大奖

当所有用户已完成的抽奖 盈利大于风控金额的时候可以让用户抽大奖 否则用户抽不到大奖

<?php 

 //抽奖接口

 public function desire()
 {
  $userData = $this->userSessionData();///用户的唯一标识
  $time = time();
  $this->limit_reward_time($userData['id'], $time);///限制抽奖间隔时间 防止被恶意刷奖品
  //活动开启开关
  $num = input('num/d');
  if (!$num) {
   output('1008', '参数错误');
  }
  if ($num!=1){
   if ($num !=10){
    if ($num !=100){
     output('1008', '参数错误');
    }else{
     $send = $this->draw($num);
    }
   }else{
    $send = $this->draw($num);
   }
  }else{
   $send = $this->draw($num);
  }
  if ($send != '金币不足') {
   output('200', '列表', $send);
  } else {
   output('1012', $send);
  }
 }



/////抽奖核心

 public function draw($num)
 {
  $userData = $this->userSessionData();
  $resultSend = Cache::get('奖池名称加上用户的唯一标识,确保一人一奖池' . $userData['id']);//获取个人奖池
  if (!empty($resultSend)) {
   $userRedis = unserialize(Cache::get('newdesiredraw' . $userData['id']));///将奖池序列化
  } else {
   $userRedis = '';///当前用户不存在奖池
  }
 ///查询当前用户的金币
  $desireDiamonds = Db::connect('db_qmconfig')->name('user_money')->where(['uid' => $userData['id']])->field('diamonds')->find();
  $sendNum = $num;
  if ($desireDiamonds['diamonds'] < $num) {
   return ['msg' => '金币不足'];///判断当前用户的金币是不是够抽奖
  }
  $gift_height = 0;///检测是否更新个人奖池和抽奖数量
  $newNum = 0;///检测下一轮抽奖数量
  $suiji = Db::connect('db_qmconfig')->name('desire')->order('num desc')->find();///随机小礼物
  if ($userRedis) {///如果用户奖池存在
   $joins = [
    ['gift_info f', 'd.giftid = f.id']
   ];
   $gift = Db::connect('db_qmconfig')->name('desire')
    ->alias('d')
    ->join($joins)
    ->where(['d.state' => 1])
    ->order('f.price desc')
    ->field('f.name,f.price,f.egif,d.num,f.id,d.position')->find();
///查询抽奖表的礼物
   if (!$gift){
    return ['msg'=>'礼物查询错误'];
   }
 ///查询用户的总抽奖数量
   $user_all = Db::connect('db_qmconfig')->name('user_desire_log')->order('kind desc')
    ->where(['uid'=>$userData['id'],'state'=>0])->field('SUM(num) as kindNum')->find();
   //十次抽奖 必中
   $count = count($userRedis);
   if ($num == 10) {
    $where[] = ['d.state', '=', 1];
    $where[] = ['d.ten', '=', 1];
    $giftId = $this->giftInfo($where);
    if ($giftId) {
     $result[] = $giftId[0]['id'];
    }
    $num = $num - 1;
   }

   ///百次抽奖 必中
   if ($num == 100) {
    $where[] = ['d.state', '=', 1];
    $where[] = ['d.hundred', '=', 1];
    $giftId = $this->giftInfo($where);

    $lwhere[] = ['d.state', '=', 1];
    $lwhere[] = ['d.ten', '=', 1];
    $lgiftId = $this->giftInfo($lwhere);
    if ($lgiftId) {
     for ($l=0;$l<10;$l++){
      $result[] = $lgiftId[0]['id'];
     }
    }

    if ($giftId) {
     $result[] = $giftId[0]['id'];
    }
    $num = $num - 11;
   }
   if ($num ==1){
    if ($user_all){
     $number1 = '';
     $num1 = str_split($user_all['kindNum']);
     $number = $num1[count($num1) - 1];
     if ($user_all['kindNum']>98){
      $number1 = $num1[count($num1) - 2];
     }
     if (($number==9)&& ($number1 !=9)){ //十抽必中
      $where[] = ['d.state', '=', 1];
      $where[] = ['d.ten', '=', 1];
      $giftId = $this->giftInfo($where);
      if ($giftId) {
       $result[] = $giftId[0]['id'];
      }
      $num = $num - 1;
     }

     if (($number1==9) && ($number==9)){//百抽必中
      $where[] = ['d.state', '=', 1];
      $where[] = ['d.hundred', '=', 1];
      $giftId = $this->giftInfo($where);
      if ($giftId) {
       $result[] = $giftId[0]['id'];
      }
      $num = $num - 1;
     }
    }
   }
  ////判断当前奖池的奖品是否够此次抽奖 如果奖池奖品数量不够此次抽奖 将此次奖池抽完后 获取剩下要抽将的数量 重置奖池 并且递归此方法传入剩下要抽的数量
   if ($count < $num) {
    $newNum = $num - $count;
    $num = $count;
   }
   $user = Db::connect('db_qmconfig')
    ->name('desire_log')->where(['uid' => $userData['id']])
    ->field('SUM(num) as num')
    ->find();///已抽数量
   if (!$user){
    return ['msg'=>'已抽数量有误'];
   }
   $res['zongshu'] = Db::connect('db_qmconfig')
    ->name('desire')->where(['state' => 1])
    ->field('SUM(num) as num,checksum')
    ->find();///总数量
   if (!$res['zongshu']){
    return ['msg'=>'总数量有误'];
   }
   $resNum = 0;
   ////获取个人多少次抽奖
   if (($user['num']+$sendNum) > $res['zongshu']['checksum']) {
    $res['zongshu']['user_num'] = $user['num'] % $res['zongshu']['checksum']; ///获取余数
    if (($res['zongshu']['user_num'] + $sendNum) > $res['zongshu']['checksum']) {
     ///获取这次抽奖的数量
     $resNum = $sendNum - (($res['zongshu']['user_num'] + $sendNum) - $res['zongshu']['checksum']);
    }
//    return ['msg'=>$res['zongshu']['user_num']];
   }else{
    $res['zongshu']['user_num'] = $user['num'];
   }
   $cruuy = 0;
   ///随机选择奖池
   for ($i = 0; $i < $num; $i++) {
    $send = array_rand($userRedis);
    if ($resNum > 0) {
     ///如果本轮奖池抽完 并且没有抽到大奖 那么必中大奖
     $result[] = $gift['id'];
     $gift_height = 1;//抽到大奖后更改三个变量状态
     $resNum=0;
     $cruuy = 1;
    } else {
     if ($userRedis[$send]==$gift['id']){
      $haveJoin = [
       ['desire_log d', 'd.cid = u.id'],
       ['gift_info f', 'd.giftid = f.id']
      ];
      $all = Db::connect('db_qmconfig')
       ->name('user_desire_log')
       ->alias('u')
       ->where(['u.state'=>1])
       ->field('SUM(u.num) as num')->find();
//      var_dump($all);
///如果抽到大奖
      if ($all['num']==null){
 ///如果这是整个奖池第一轮抽奖 那么可以中大奖
       $result[] = $suiji['giftid'];
      }else{
 
       $alls = Db::connect('db_qmconfig')->name('user_desire_log')
        ->alias('u')
        ->where(['u.state'=>1])
        ->join($haveJoin)
        ->field('SUM(f.price*d.num) as num')->find();
 ///查询奖池风控金额
       $reskList = Db::connect('db_qmconfig')->name('desire_risk')->find();
       $riskPrice = $all['num'] * 20 - $alls['num'];
 ///如果风控金额小于当前已完成抽奖的金额 那么代表软件处于盈利状态 可以中大奖
       if (($riskPrice >= $reskList['price'])&&($cruuy==0)){
        $result[] = $userRedis[$send];
        $gift_height = 1;
        $cruuy = 1;
       } else{
 ///如果风控金额大于当前已完成抽奖金额 不能中大奖 随机选择一次小奖品 替换大奖
        $result[] = $suiji['giftid'];
       }
      }

     }else{
      $result[] = $userRedis[$send];
     }
    }
///清空个人奖池此次抽奖的礼物
    unset($userRedis[$send]);
   }
 ////新增用户抽奖次数 
   $result = array_count_values($result);
   $user_desire_list = Db::connect('db_qmconfig')->name('user_desire_log')->order('id desc')->where(['uid'=>$userData['id']])->find();
   if ($user_desire_list){
    if ($user_desire_list['state']==0){
     $user_desire_logData[ 'kind'] = $user_desire_list['kind']+1;
    }else{
     $user_desire_logData[ 'kind'] = 1;
    }
   }else{
    $user_desire_logData[ 'kind'] = 1;

   }
   $user_desire_logData['uid'] =$userData['id'];
   $user_desire_logData['ctime'] =time();
   $user_desire_logData['num'] =$sendNum;
 ////更改此轮抽奖后 用户奖池的状态
   if ($gift_height==1){
    $user_desire_log_update = Db::connect('db_qmconfig')->name('user_desire_log')
     ->where(['uid'=>$userData['id'],'state'=>0])->update(['state'=>1]);
    $user_desire_logData[ 'state'] = 1;
   }else{
    $user_desire_logData[ 'state'] = 0;
   }
   $user_desire_log = Db::connect('db_qmconfig')->name('user_desire_log')->insertGetId($user_desire_logData);
   foreach ($result as $k => $v) {
    if ($resNum == ($k + 1)) {
     ///如果这次抽奖大于奖池总数 那么更新奖池并且抽奖剩下的次数
     Cache::set('newdesiredraw' . $userData['id'], serialize([]));
     return $this->draw($sendNum - ($k + 1));
    }

 ////礼物新增用户背包
    $data = [
     'uid' => $userData['id'],
     'giftid' => $k,
     'num' => $v,
     'ctime' => time(),
     'cid' => $user_desire_log
    ];
    $join = [
     ['gift_info f', 'd.giftid = f.id']
    ];
    $gift_info = Db::connect('db_qmconfig')->name('desire')
     ->alias('d')
     ->join($join)
     ->where(['d.giftid' => $k])
     ->field('f.name,f.egif,d.position')->find();
    $gift_infonum['num'] = $v;
    $list['gift'][] = array_merge($gift_info, $gift_infonum);
    $desireLog = Db::connect('db_qmconfig')->name('desire_log')->insert($data);
    $userKnapsack = Db::connect('db_qmconfig')->name('gift_knapsack')->where(['uid' => $userData['id'], 'giftid' => $k])->field('id,num')->find();
    if ($userKnapsack) {
     $userKnapsackData = [
      'num' => $v + $userKnapsack['num'],
      'updatetime' => time()
     ];
     $userKnapsackUpdate = Db::connect('db_qmconfig')->name('gift_knapsack')->where(['id' => $userKnapsack['id']])->update($userKnapsackData);
    } else {
     $userKnapsackData = [
      'num' => $v,
      'giftid' => $k,
      'uid' => $userData['id'],
      'createtime' => time()
     ];
     $userKnapsackInsert = Db::connect('db_qmconfig')->name('gift_knapsack')->insert($userKnapsackData);
    }
   }
  ///增加用户消费记录
   $userXfData = [
    'uid' => $userData['id'],
    'xf_price' => $sendNum,
    'xf_method' => 5,
    'scene' => 19,
    'status' => 1,
    'ctime' => time()
   ];
   $userXf = Db::connect('db_qmconfig')->name('xfprice')->insert($userXfData);
   if ($desireLog && $userXf) {
///扣除用户金币
    $newDiamondsData = [
     'diamonds' => $desireDiamonds['diamonds'] - $sendNum
    ];
    $newDiamonds = Db::connect('db_qmconfig')->name('user_money')->where(['uid' => $userData['id']])->update($newDiamondsData);
   }


   if ($userRedis) {
    Cache::set('用户奖池名称' . $userData['id'], serialize($userRedis));
  ////如果此轮抽奖抽到大奖 重置用户个人奖池
    if ($gift_height == 1) {
     Cache::set('用户奖池名称' . $userData['id'], serialize([]));
     $userChecksum = $res['zongshu']['checksum'] - ($res['zongshu']['user_num'] + $sendNum);
     $desireLogUserWhere = [
      'uid' => $userData['id'],
      'giftid' => 0,
      'num' => $userChecksum,
      'ctime' => time(),
      'cid' => $user_desire_log,
     ];
///添加礼物抽中记录
     $desireLogUser = Db::connect('db_qmconfig')->name('desire_log')->insert($desireLogUserWhere);
    }
    $swhere[] = ['d.state', '=', 1];
    $swhere[] = ['d.kind', '=', 1];
    $res['data'] = $this->giftInfo($swhere);
    if (empty($res['data'])) {
     output('1008', '奖池更新中');
    }
////获取用户此轮抽奖数量 返回给前端 控制奖池动画百分比
    $res['zongshu'] = Db::connect('db_qmconfig')
     ->name('desire')->where(['state' => 1, 'kind' => 1])
     ->field('checksum as num')
     ->find();
    $user = Db::connect('db_qmconfig')
     ->name('desire_log')->where(['uid' => $userData['id']])
     ->field('SUM(num) as num')
     ->find();
    $res['diamonds'] = Db::connect('db_qmconfig')
     ->name('user_money')->where(['uid' => $userData['id']])
     ->value('diamonds');

    if ($user) {
     if ($user['num'] > $res['zongshu']['num']) {
      $res['zongshu']['user_num'] = $user['num'] % $res['zongshu']['num'];

     } else {
      $res['zongshu']['user_num'] = $user['num'];
     }
    } else {
     $res['zongshu']['user_num'] = 0;
    }
    $list['info'] = $res;
    return $list;
//    return ['msg'=>$res['zongshu']['user_num']];
   } else {
////如果当前用户奖池抽完奖了 那么重置此用户奖池
    $where[] = ['d.state', '=', 1];
    $where[] = ['d.kind', '=', 1];
    $res = $this->giftInfo($where);
    if (empty($res)) {
     return ['msg' => '奖池更新中'];
    }
    $c = [];
    foreach ($res as $m => $n) {
///十抽必中奖品
     if ($n['ten']==1){
      $n['num'] = $n['num'] - $n['checksum']/10;
      $giftarr = array_fill(0, $n['num']+$n['checksum']/10, $suiji['giftid']);
      $c = array_merge($c, $giftarr);
      if ($n['num']<=0){
       continue;
      }
     }
///百抽必中奖品
     if ($n['hundred']==1){
      $n['num'] = $n['num'] - $n['checksum']/100;
      $giftarr = array_fill(0, $n['num']+$n['checksum']/100, $suiji['giftid']);
      $c = array_merge($c, $giftarr);
      if ($n['num']<=0){
       continue;
      }
     }
     $giftarr = array_fill(0, $n['num'], $n['id']);
     $c = array_merge($c, $giftarr);
    }
///随机打乱奖池
    shuffle($c);
    Cache::set('用户奖池名称' . $userData['id'], serialize($c));
    if ($newNum>0){
 ///递归此方法 抽剩下的奖品
     return $this->draw($newNum);
    }
   }
  } else {
   ///如果没有奖池 生成奖池
   $where[] = ['d.state', '=', 1];
   $where[] = ['d.kind', '=', 1];
   $res = $this->giftInfo($where);
   if (empty($res)) {
    return ['msg' => '奖池更新中'];
   }
   $c = [];
   foreach ($res as $m => $n) {
    if ($n['ten']==1){
     $n['num'] = $n['num'] - $n['checksum']/10;
     $giftarr = array_fill(0, $n['num']+$n['checksum']/10, $suiji['giftid']);
     $c = array_merge($c, $giftarr);
     if ($n['num']<=0){
      continue;
     }
    }
    if ($n['hundred']==1){
     $n['num'] = $n['num'] - $n['checksum']/100;
     $giftarr = array_fill(0, $n['num']+$n['checksum']/100, $suiji['giftid']);
     $c = array_merge($c, $giftarr);
     if ($n['num']<=0){
      continue;
     }
    }
    $giftarr = array_fill(0, $n['num'], $n['id']);
    $c = array_merge($c, $giftarr);
   }
   shuffle($c);
   Cache::set('用户奖池名称' . $userData['id'], serialize($c));
 ///递归此方法抽奖
   return $this->draw($num);
  }
 }
?>

以上就是PHP实现抽奖功能实例代码的详细内容,更多关于PHP实现抽奖功能的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
一个连接两个不同MYSQL数据库的PHP程序
Oct 09 PHP
PHP 编写大型网站问题集
May 07 PHP
php cookie的操作实现代码(登录)
Dec 29 PHP
PHP转换文件夹下所有文件编码的实现代码
Jun 06 PHP
PHP实现将浏览历史页面网址保存到cookie的方法
Jan 26 PHP
PHP调用Linux命令权限不足问题解决方法
Feb 07 PHP
WordPress中设置Post Type自定义文章类型的实例教程
May 10 PHP
php微信开发之批量生成带参数的二维码
Jun 26 PHP
php实现简单加入购物车功能
Mar 07 PHP
Laravel 集成 Geetest验证码的方法
May 14 PHP
php微信开发之音乐回复功能
Jun 14 PHP
PHP7数组的底层实现示例
Aug 25 PHP
七种PHP开发环境搭建工具
Jun 28 #PHP
如何在PHP中使用AES加密算法加密数据
Jun 24 #PHP
基于PHP实现解密或加密Cloudflar邮箱保护
Jun 24 #PHP
解决PhpStorm64不能启动的问题
Jun 20 #PHP
php实现断点续传大文件示例代码
Jun 19 #PHP
PHP基于openssl实现非对称加密代码实例
Jun 19 #PHP
如何在PHP环境中使用ProtoBuf数据格式
Jun 19 #PHP
You might like
星际争霸任务指南——虫族
2020/03/04 星际争霸
Laravel 5.0 发布 新版本特性详解
2015/02/10 PHP
Zend Framework教程之连接数据库并执行增删查的方法(附demo源码下载)
2016/03/21 PHP
php resizeimage 部分jpg文件 生成缩略图失败的原因分析及解决办法
2016/03/23 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
PHP数组相加操作及与array_merge的区别浅析
2016/11/26 PHP
js 利用className得到对象的实现代码
2011/11/15 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
2012/07/17 Javascript
js怎么终止程序return不行换jfslk
2013/05/30 Javascript
Jquery创建一个层当鼠标移动到层上面不消失效果
2013/12/12 Javascript
不到30行JS代码实现Excel表格的方法
2014/11/15 Javascript
IE下支持文本框和密码框placeholder效果的JQuery插件分享
2015/01/31 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
微信小程序加载更多 点击查看更多
2016/11/29 Javascript
jQuery特殊符号转义的实现
2016/11/30 Javascript
socket.io学习教程之基本应用(二)
2017/04/29 Javascript
JS实现点击Radio动态更新table数据
2017/07/18 Javascript
vue input 输入校验字母数字组合且长度小于30的实现代码
2018/05/16 Javascript
vue点击页面空白处实现保存功能
2019/11/06 Javascript
如何利用JavaScript编写更好的条件语句详解
2020/08/10 Javascript
[00:57]林俊杰助阵DOTA2亚洲邀请赛
2015/01/28 DOTA
[02:54]辉夜杯主赛事第二日败者组 iG.V赛后采访
2015/12/26 DOTA
[46:14]VGJ.T vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
零基础写python爬虫之抓取百度贴吧代码分享
2014/11/06 Python
Python常用的文件及文件路径、目录操作方法汇总介绍
2015/05/21 Python
使用Python爬了4400条淘宝商品数据,竟发现了这些“潜规则”
2018/03/23 Python
python环形单链表的约瑟夫问题详解
2018/09/27 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
Python3标准库之functools管理函数的工具详解
2020/02/27 Python
东方红海科技面试题软件测试方面
2012/02/08 面试题
易程科技软件测试笔试
2013/03/24 面试题
应聘收银员个人的求职信
2013/11/30 职场文书
解除劳动合同协议书范本2014
2014/09/25 职场文书
六查六看个人剖析材料
2014/10/14 职场文书
2014年社区宣传工作总结
2014/12/02 职场文书
初中班主任培训心得体会
2016/01/07 职场文书