<?php
/**
* create by jxkshu
* Date 2017-09-28
* 用户签到领取红包
*/
/**
Redis
set: key signed:user:mark 标记已签到用户
val user_id zset key signed:user:today:share:num 记录当天用户分享的次数,凌晨4点删除
score 分享的次数
val 用户ID
zset key signed:user:today:replenishment:num 记录当天用户已经补签的次数,凌晨4点删除
score 当天补签的次数
val 用户ID
*/
header("content-type:text/html;charset=utf-8");
require_once('api.base.php'); class m_signed extends base
{
private $redis = null;
private $log_dir = null; public function __construct(){
parent::__construct(); $this->init();
// parent::signer($_POST);
// parent::tokengoon($_POST); // 连接redis
$this->redis = new MyRedis;
$this->redis = $this->redis->getRedisCli(); // 创建单个文件夹
$this->log_dir = __DIR__ . '/../log/return_red_envelope/signed/';
if(!is_dir($this->log_dir)):
mkdir($this->log_dir);
chmod($this->log_dir, 0777);
endif;
} /**
* 用户 签到或者补签
* @param array $post 客户端传递的数据
* @return array 抢红包后的数据
*/
public function signed($post){ parent::signer($_POST);
parent::tokengoon($_POST);
$user_id = (int)trim($post['user_id']); // 延迟0.2秒,防并发
usleep(200000);
// 判断用户是签到还是补签
if( empty($post['type']) || $post['type']==0):
// 判断用户是否已签
$key = 'signed:user:mark';
if(($this->redis->sIsMember($key, $user_id))):
return ['status'=>'fail', 'msg'=>'已签到'];
else:
// 二次判断用户是否已经签到
$day_start = strtotime(date('Y-m-d 0:0:0',time()));
$day_end = strtotime(date('Y-m-d 0:0:0',time()))+86399;
$sql = "SELECT count(id) as total from sign_red_envelopes where uid=$user_id and time>=$day_start and time<=$day_end and amount>0";
$sign_num = (int) parent::result_first($sql);
if($sign_num>0):
return ['status'=>'fail', 'msg'=>'已签到'];
endif;
endif;
// 用户签到
$res = $this->userSigned($user_id, $post['time']);
else:
if( $post['time'] >= strtotime(date('Y-m-d 0:0:0'))):
return ['status'=>'fail', 'msg'=>'日期错误'];
endif;
$res = $this->userReplenishment($user_id, $post['time']);
endif; if($res['status']=='fail'):
$this->writeLog(__FILE__, __LINE__, $res['msg']);
endif;
return $res;
} /**
* 用户补签
* @param int $user_id 用户ID
* @param int $time 用户签到时间
* @return array status:状态、msg:信息、amount:奖励金额、replenishment_num:剩余可以补签的次数
*/
protected function userReplenishment($user_id, $time){ // 获取用户当天已经补签的次数
$replenishment = $this->redis->zScore('signed:user:today:replenishment:num', $user_id);
// 获取用户当天线下消费额度
$tim = date('Ymd');
$sql = "SELECT sum(amount) as total_amount FROM payinfo where pay_dateint='$tim' and uid=$user_id and status=1 and is_ol_verify=0";
$total_amount = (int) parent::result_first($sql); // 判断用户补签次数是否超出
$total_amount = (int) ($total_amount/58);
$replenishment = (int)$replenishment;
if( $total_amount<=$replenishment ):
return ['status'=>'fail', 'msg'=>'补签失败,消费额度不足!'];
endif; // 补签次数累加1
$res = $this->redis->zIncrBy('signed:user:today:replenishment:num', 1, $user_id);
if(empty($res)):
return ['status'=>'fail', 'msg'=>'补签次数累加失败!'];
endif; //获取用户补签奖励金额
$amount = mt_rand(50, 100) / 100; // 记录用户补签信息
$data = [
'uid' => $user_id,
'type' => 1,
'amount' => $amount,
'time' => $time,
];
$res = parent::insert('sign_red_envelopes', $data);
if(empty($res)):
return ['status'=>'fail', 'msg'=>'写入补签红包记录数据库失败!'];
endif; // 累加用户签到奖励
$sql = "UPDATE userinfo SET sign_reward=(sign_reward+$amount),total_sign_reward=(total_sign_reward+$amount) where id=$user_id limit 1";
$res = parent::query($sql);
if(empty($res)):
return ['status'=>'fail', 'msg'=>'累加用户补签奖励失败!'];
endif;
return ['status'=>'success', 'msg'=>'用户补签成功', 'amount'=>$amount, 'replenishment_num'=>($total_amount-$replenishment)];
} /**
* 用户签到
* @param int $user_id 用户ID
* @param int $time 用户签到时间
* @return array
*/
protected function userSigned($user_id, $time){ // 获取签到奖励金额
$amount = self::getSignedAmount($user_id);
$data = [
'uid' => $user_id,
'amount' => $amount,
'time' => $time,
];
$res = parent::insert('sign_red_envelopes', $data);
if(empty($res)):
return ['status'=>'fail', 'msg'=>'写入签到红包记录数据库失败!'];
endif; // 累加用户签到奖励
$sql = "UPDATE userinfo SET sign_reward=(sign_reward+$amount),total_sign_reward=(total_sign_reward+$amount) where id=$user_id limit 1";
$res = parent::query($sql);
if(empty($res)):
return ['status'=>'fail', 'msg'=>'累加用户签到奖励失败!'];
endif; // 标记用户已经签到
$res = $this->redis->sAdd('signed:user:mark', $user_id);
return ['status'=>'success', 'amount'=>$amount];
} /**
* 获取用户签到奖励金额
* @param int $user_id
* @return float 奖励金额
*/
protected static function getSignedAmount($user_id){ // 判断用户是不是第一次签到
$sql = "SELECT count(id) as total FROM sign_red_envelopes where uid=$user_id limit 1";
$total = parent::result_first($sql); // 获取签到奖励金额
if(empty($total)):
// 首次签到
$amount = mt_rand(1,2);
else:
//提升红包额度
$sql = "SELECT share_num from userinfo where id=$user_id limit 1";
$share_num = parent::result_first($sql);
$share_num = ($share_num>20 ? 20 : $share_num);
$min = (0.1 + (0.1 * ($share_num*0.1))) * 100;
$max = (1 + (1*($share_num*0.05))) * 100;
$max = ($max>200 ? 200 : $max); $amount = mt_rand($min, $max) / 100;
$amount = number_format($amount, 2);
endif; return $amount;
} // -------------------------------- 用户将奖励提转到58券 /**
* 用户将奖励提转到58券
* @param array $post=>user_id 用户id
* @return array
*/
public function rewardTo58voucher($post){ parent::signer($_POST);
parent::tokengoon($_POST);
// 获取用户已经累计的签到红包
$sql = 'SELECT id,sign_reward FROM userinfo WHERE id='.$post['user_id'].' limit 1';
$userinfo = parent::fetch_first($sql);
if($userinfo['sign_reward']<20):
return ['errcode'=>'44','msg'=>'代金券未满20'];
endif; // 红包转换成58券
$sql='UPDATE userinfo SET sign_reward=0, red_reward=(red_reward+'.$userinfo['sign_reward'].') WHERE id='.$post['user_id'].' LIMIT 1';
$res = parent::query($sql);
if(empty($res)):
return ['errcode'=>'3','msg'=>'服务器异常!'];
endif;
// 记录行为到红包
$tim = time();
$data = [
'uid'=>$post['user_id'],
'orderid'=>'',
'amount'=>$userinfo['sign_reward'],
'packet_status'=>1,
'receive_time'=>date('Y-m-d H:i:s', $tim),
'packet_type'=>6,
'add_time'=>date('Y-m-d H:i:s', $tim),
'dateint'=>date('Ymd', $tim),
];
$res = parent::insert('redpacket', $data);
if(empty($res)):
return ['errcode'=>'400','msg'=>'提转成功!但记录提转信息失败!'];
endif;
return ['errcode'=>0,'msg'=>'提转成功!'];
} /**
* 获取剩余补签次数
* @param int $user_id 用户ID
* @return array
*/
public function getSignCard($user_id){ parent::signer($_POST);
parent::tokengoon($_POST);
// 获取用户当天已经补签的次数
$replenishment = $this->redis->zScore('signed:user:today:replenishment:num', $user_id);
// 获取用户当天线下消费额度
$tim = date('Ymd');
//$sql = "SELECT sum(amount) as total_amount FROM payinfo where pay_dateint='$tim' and uid=$user_id and status=1 and (order_type=0 or order_type=4)";
$sql = "SELECT sum(amount) as total_amount FROM payinfo where pay_dateint='$tim' and uid=$user_id and status=1 "; $total_amount = (int) parent::result_first($sql); // 判断用户补签次数是否超出
$total_amount = (int) ($total_amount/58);
$replenishment = (int) $replenishment; return ['card_num'=>($total_amount - $replenishment)];
} // 用户分享朋友圈来提升签到红包额度
public function userShareAppToPeople($user_id){ parent::signer($_POST);
// 将分享次数暂时记录到redis,每天凌晨定时任务在写入数据库
$key = 'signed:user:today:share:num';
$res = $this->redis->zIncrBy($key, 1, $user_id);
return ['signed_num'=>$res];
} // 写日志
private function writeLog($fil, $row, $remarks=''){
$file = $this->log_dir . 'signed-'.date('Y-m').'.txt';
$content = $fil.' Line ' . $row . ' failed '.date('Y-m-d H:i:s')." $remarks \n\r";
file_put_contents($file, $content, FILE_APPEND);
} //---------------------------- 获取用户签到界面的信息 public function getSignPageInfo($post){ parent::signer($_POST);
parent::tokengoon($_POST);
$user_id = parent::parseuid($post);
$data = []; // 分享URL
$tim = time();
$salt = '58_life_circle_sign_share';
$sign = mb_strcut(md5('58_life_circle_sign_share'.$tim), 0, 6, 'utf8');
$data['share_url'] = 'http://api.licheepay.com/lzf/html/sign_share/h5.html?uid='.$user_id.'&time='.$tim.'&sign='.$sign;
// 广告图
$data['header_advert'] = [
// [
// 'img'=> 'http://adm.licheepay.com/upload/mall/1509331172.png',
// 'url'=> 'app_web_$$$https://s.click.taobao.com/7IlNyYw$$$',
// ],
// [
// 'img'=> 'http://adm.licheepay.com/upload/mall/1509523936.png',
// 'url'=> 'app_web_>>>http://mp.weixin.qq.com/s/BDSD_jDgCmMxfCdieLxtxg<<<',
// ],
[
'img'=> 'http://adm.licheepay.com/upload/img/ad/20170508161142.png',
'url'=> 'app_web_>>>http://mp.weixin.qq.com/s/BDSD_jDgCmMxfCdieLxtxg<<<',
], ];
// 获取累计签到奖励
$sql = 'SELECT sign_reward,total_sign_reward FROM userinfo WHERE id='.$user_id.' limit 1';
$temp_user_sign = parent::fetch_first($sql);
$data['sign_reward'] = $temp_user_sign['sign_reward'];
$data['total_sign_reward'] = $temp_user_sign['total_sign_reward']; // 签到奖励提取状态【是否可提取】
$data['extract_status'] = 0;
if($temp_user_sign['sign_reward']>=20):
$data['extract_status'] = 1;
endif; // 签到说明
$data['sign_explain'] = '1、签到后可抢代金券红包,满20券可用
2、用户每天可签到一次,每次可获得随机劵奖励
3、代金券每月15号自动清零,满20券请及时领取
4、线下消费满58元,可手动补签1次,当天有效
5、签到后分享好友,好友参与可提高次日红包金额'; // 签到状态
// 判断用户是否已签
$data['signed_status'] = 0;
$key = 'signed:user:mark';
if(($this->redis->sIsMember($key, $user_id))):
$data['signed_status'] = 1;
endif;
// // 二次判断用户是否已经签到 2017-11-01屏蔽
$day_start = strtotime(date('Y-m-d 0:0:0',time()));
$day_end = strtotime(date('Y-m-d 0:0:0',time()))+86399;
$sql = "SELECT count(id) as total from sign_red_envelopes where uid=$user_id and time>=$day_start and time<=$day_end and amount>0";
$sign_num = (int) parent::result_first($sql);
if($sign_num<1):
$data['signed_status'] = 0;
else:
$data['signed_status'] = 1;
endif; // 时间戳
$data['time'] = time();
return $data;
} // 获取用户签到信息日历
public function getUserSignInfoCalendar($post){ parent::signer($_POST);
parent::tokengoon($_POST);
$user_id = parent::parseuid($post); // 当前月份
$total_day = date('t');
$current_month = date('m');
$first_day = strtotime(date("Y-m-01"));
$last_day = $first_day + ($total_day*86400) - 1;
$sql = "SELECT FROM_UNIXTIME(time,'%e') as day,type
FROM sign_red_envelopes
WHERE uid=$user_id and time>=$first_day and time<=$last_day";
//获取用户签到信息
$sign_info = parent::fetch_all($sql);
// 获取用户补签卡
$card_num = $this->getSignCard($user_id);
$card_num = $card_num['card_num']; $today = date('d');
// 1:未签、 2:已签到、3:已补签 4:可补签、 5:漏签、 6:不可签、
$temp_current = [];
for ($i=$total_day; $i>0; $i--) {
$status = 0;
// 签到或者补签
foreach ($sign_info as $sign) {
if($sign['day']==$i):
$status = empty($sign['type']) ? 2 : 3;
break;
endif;
}
// 1:未签
if($status==0 && $i==$today):
$status = 1;
endif;
//4:可补签
if($status==0 && $i<$today && $card_num>0):
$status = 4;
$card_num--;
endif;
// 6:不可签
if($status==0 && $i>$today):
$status = 6;
endif;
// 5:漏签
if($status==0):
$status = 5;
endif;
$temp_current[$i] = $status;
} // 上月份
$last_month = date('m', time()) - 1;
if( $last_month<1 ):
$last_month = 12;
$time_str = (date('Y',time()) - 1) . '-12-01';
$total_day = date('t', strtotime($time_str));
$first_day = strtotime($time_str);
$last_day = $first_day + ($total_day*86400) - 1;
else:
$time_str = date('Y',time()) .'-'.$last_month.'-01';
$total_day = date('t', strtotime( $time_str));
$last_month = date('m', strtotime( $time_str));
$first_day = strtotime( $time_str);
$last_day = $first_day + ($total_day*86400) - 1;
endif;
$sql = "SELECT FROM_UNIXTIME(time,'%e') as day,type
FROM sign_red_envelopes
WHERE uid=$user_id and time>=$first_day and time<=$last_day";
//获取用户签到信息
$sign_info = parent::fetch_all($sql);
// 2:已签到、3:已补签 4:可补签、 5:漏签、
$temp_last = [];
for ($i=$total_day; $i>0; $i--) {
$status = 0;
// 签到或者补签
foreach ($sign_info as $sign) {
if($sign['day']==$i):
$status = empty($sign['type']) ? 2 : 3;
endif;
}
//可补签
if($status==0 && $card_num>0):
$status = 4;
$card_num--;
endif;
// 5:漏签
if($status==0):
$status = 5;
endif; $temp_last[$i] = $status;
} ksort($temp_current); //当前月份
ksort($temp_last); //上月份
$data = [
[
'month'=>$current_month,
'status' =>array_values($temp_current)
],
[
'month' =>$last_month,
'status'=>array_values($temp_last)
],
];
return $data;
} }//end

下载地址

php用户签到,领取红包的更多相关文章

  1. Redis位图实现用户签到功能

    场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...

  2. 基于Redis位图实现用户签到功能

    场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 当月签到满 ...

  3. 记我的小网站发现的Bug之一 —— 某用户签到了两次

    1.故事背景 今天上午我忙完手中的事情之后突然想起来我还没签到,于是赶紧打开签到页面,刚点击了签到按钮,提示"签到成功,获得25阅读额度!",正准备退出浏览器,忽然发现签到列表有异 ...

  4. Redis实战篇(二)基于Bitmap实现用户签到功能

    很多应用上都有用户签到的功能,尤其是配合积分系统一起使用.现在有以下需求: 签到1天得1积分,连续签到2天得2积分,3天得3积分,3天以上均得3积分等. 如果连续签到中断,则重置计数,每月重置计数. ...

  5. 利用redis的bitmap实现用户签到功能

    一.场景需求 适用场景如签到送积分.签到领取奖励等,大致需求如下: 比如签到1天送1积分,连续签到2天送2积分,3天送3积分,3天以上均送3积分等. 如果连续签到中断,则重置计数,每月初重置计数. 显 ...

  6. java redis 实现用户签到功能(很普通简单的签到功能)

    业务需求是用户每天只能签到一次,而且签到后用户增加积分,所以把用户每次签到时放到redis 缓存里面,然后每天凌晨时再清除缓存,大概简单思想是这样的 直接看代码吧如下 @Transactional @ ...

  7. 用NSCalendar和UICollectionView自定义日历,并实现签到显示

    前一段时间因为工作需要实现了一个可以签到的日历,来记录一下实现的思路 效果如图:   这里的基本需求是: 1,显示用户某个月的签到情况,已经签到的日子打个圈,没有签到且在某个时间范围内的可以签到,其他 ...

  8. php实现签到功能

    首先我在数据库里建了两张表,一个是用户的积分表,一个是签到状态表,分来用来记录用户的积分数和先到状态 在用户签到状态表中我们有一个字段,last_sign_time,即上一次签到时间,每次可以签到的时 ...

  9. TOJ5398: 签到大富翁(简单模拟) and TOJ 5395: 大于中值的边界元素(数组的应用)

    Python代码!!! 5395 传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=53 ...

随机推荐

  1. MethodBase.GetCurrentMethod 方法

    如果当前正在执行的方法定义泛型类型上MethodInfo返回GetCurrentMethod通过泛型类型定义 (即,MethodInfo.ContainsGenericParameters返回true ...

  2. Git-第三篇廖雪峰Git教程学习笔记(2)回退修改,恢复文件

    1.工作区 C:\fyliu\lfyTemp\gitLocalRepository\yangjie 2.版本库 我们使用git init命令创建的.git就是我们的版本库.Git的版本库里存了很多东西 ...

  3. docker添加加速器

    通过 Docker 官方镜像加速,中国区用户能够快速访问最流行的 Docker 镜像.该镜像托管于中国大陆,本地用户现在将会享受到更快的下载速度和更强的稳定性,从而能够更敏捷地开发和交付 Docker ...

  4. Python 函数知识总汇

    函数在一个程序起到很重要的作用,那么如何学好函数呢,那函数有什么内容的,总结一下函数的知识归类 1,函数定义 def  函数名(): print("...") 2,函数返回值 re ...

  5. MicroPython 的优势

    定位的场景 MicroPython 在设计上最初就是为了嵌入式微处理器运行,例如在 nRF51822 (256kB flash + 16kB RAM) 的芯片上也可以运行起来,也有人肾得慌在 STM3 ...

  6. 【推荐系统】知乎live入门5.常用技能与日常工作

    参考链接 [推荐系统]知乎live入门 目录 1. 实习与求职 2. 推荐算法职责 3. 解构算法 4. 参考资料 5. 其他强关联岗位 6. 工作模型和日常工作 7. 2017年相关论文 8. 找工 ...

  7. Python之路-初识python及环境搭建与测试(Python安装、Anaconda安装、PyCharm安装)

    一.认识Python 起源 Python的作者是著名的“龟叔”Guido van Rossum,他希望有一种语言,这种语言能够像C语言那样,能够全面调用计算机的功能接口,又可以像shell那样,可以轻 ...

  8. HBase的访问方式

    这里只介绍三种最常用的方式 1.HBase shell HBase的命令行工具是最简单的接口,主要用于HBase管理 首先启动HBase 帮助 hbase(main):001:0> help 查 ...

  9. MiniUI学习笔记1-表单控件

    1.输入框样式 class="mini-textbox" //普通输入框 class="mini-password" //密码输入框 class="m ...

  10. 利用docker创建包含需要python包的python镜像

    一.拉取python镜像 需要先安装docker,这里读者自行搜索docker的安装过程,下面我们拉取python镜像:以3.7.4为例 docker pull python:3.7.4 二.进入容器 ...