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 相关文章推荐
用php获取远程图片并把它保存到本地的代码
Apr 07 PHP
PHP 简单日历实现代码
Oct 28 PHP
PHP filter_var() 函数 Filter 函数
Apr 25 PHP
php常用ODBC函数集(详细)
Jun 24 PHP
php使用pdo连接mssql server数据库实例
Dec 25 PHP
php使用google地图应用实例
Dec 31 PHP
如何使用php实现评委评分器
Jul 31 PHP
thinkphp3.x中display方法及show方法的用法实例
May 19 PHP
thinkphp3.2中实现phpexcel导出带生成图片示例
Feb 14 PHP
ThinkPHP 3.2.3实现页面静态化功能的方法详解
Aug 03 PHP
php 读取文件夹下所有图片、文件的实例
Oct 17 PHP
PHP实现文件上传后台处理脚本
Mar 04 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
针对初学PHP者的疑难问答(2)
2006/10/09 PHP
php下实现在指定目录搜索指定类型文件的函数
2008/10/03 PHP
php学习笔记 面向对象中[接口]与[多态性]的应用
2011/06/16 PHP
PHP错误Warning:mysql_query()解决方法
2015/10/24 PHP
PHP面向对象程序设计实例分析
2016/01/26 PHP
php制作基于xml的RSS订阅源功能示例
2017/02/08 PHP
php生成毫秒时间戳的实例讲解
2017/09/22 PHP
在Javascript中定义对象类别
2006/12/22 Javascript
JavaScript判断两种格式的输入日期的正确性的代码
2007/03/25 Javascript
JS 实现完美include载入实现代码
2010/08/05 Javascript
解析使用js判断只能输入数字、字母等验证的方法(总结)
2013/05/14 Javascript
JS短路原理的应用示例 精简代码的途径
2013/12/13 Javascript
jquery.mobile 共同布局遇到的问题小结
2015/02/10 Javascript
jQuery实现在下拉列表选择时获取json数据的方法
2015/04/16 Javascript
jquery实现清新实用的网页菜单效果
2015/08/28 Javascript
JS实现的另类手风琴效果网页内容切换代码
2015/09/08 Javascript
全面解析DOM操作和jQuery实现选项移动操作代码分享
2016/06/07 Javascript
jquery设置表单元素为不可用的简单代码
2016/07/04 Javascript
vue.js 实现点击按钮动态添加li的方法
2018/09/07 Javascript
微信小程序实现的日期午别医生排班表功能示例
2019/01/09 Javascript
js实现for循环跳过undefined值示例
2019/07/02 Javascript
vue悬浮可拖拽悬浮按钮的实例代码
2019/08/20 Javascript
python实现单向链表详解
2018/02/08 Python
scrapy-redis的安装部署步骤讲解
2019/02/27 Python
详解10个可以快速用Python进行数据分析的小技巧
2019/06/24 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
2020/04/30 Python
selenium+headless chrome爬虫的实现示例
2021/01/08 Python
小学生读书感言
2014/02/12 职场文书
保安队长职务说明书
2014/02/23 职场文书
寄语学生的话
2014/04/10 职场文书
新农村建设典型材料
2014/05/31 职场文书
苏州园林导游词
2015/02/03 职场文书
演讲开场白和结束语
2015/05/29 职场文书
导游词之河北野三坡
2019/12/11 职场文书
关于nginx 实现jira反向代理的问题
2021/09/25 Servers
keepalived + nginx 实现高可用方案
2022/12/24 Servers