123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- <?php
- /**
- * 前台控制器
- * 书籍
- */
- namespace app\index\controller;
- use app\common\library\Redis;
- use app\common\controller\Frontend;
- use think\Db;
- use think\Env;
- use think\Config;
- use app\common\library\Ssdb;
- class Fee extends Frontend
- {
- /**
- * @var Redis
- */
- protected $redis;
- public function _initialize()
- {
- $this->redis = Redis::instance();
- //parent::_initialize();
- }
- public function test(){
- //$ur = new UserRecentlyRead();
- //$ur->getOneReadRecord('U1B11000000039');
- //$res = $ur->getRecentlyRead(1);
- //$pp = $this->redis->hgetall('U1B11000000029');
- //dump($pp);
- // $thismodel = new UserRecentlyRead();
- // $read = $thismodel->getRecentlyRead();
- // dump($read);die;
- $book_id = 11000000039;
- //echo $this->redis->get('hello');die;
- //$chapters = model('Book')::getChapterList($book_id);
- $bookinfo = model('Book')->bookinfo($book_id);
- dump($bookinfo);die;
- // echo "<pre/>";
- // print_r($chapters);
- echo(microtime());
- $res = $this->bookfee(3,$bookinfo,'测试章节1',142,196511666,1);
- dump($res);
- echo(microtime());
- }
- /**
- * 点击下一章
- * @param $userId $this->user->id; 如果没有userid 就写到cookie里(最多5本)
- * @param $bookId url上传的
- * @param $chapter_id url上带的chapter_id ,cookie里的chaper_id 和 sid 优先级低(高于)
- * @param $chapter_name
- * @param $idx 第几章
- * @param int $kandian config('site.book_chapter_price')
- * @return array $returnArr['type'] = 4; // type:1扣书币成功 2.书币不足,3扣书币失败,4缺少参数,5获取书籍信息失败,6未登录,7,游客到了计费章节 $returnArr['isRecharge']=1,扣费,返回数组里没有isRecharge这个参数是免费的
- * @throws \Exception
- */
- public function bookfee($admin_id,$book,$chapter_name,$idx,$chapter_id,$user){
- $freeChapter = config('site.book_free_chapter_num'); //全局免费章节数
- if(intval($book['free_chapter_num'])>0){ //如果本书籍设置了免费章节数,以本书籍的免费章节数为准
- $freeChapter = $book['free_chapter_num'];
- }
- //维护书阅读数量
- $bookNumKey = 'B-N';
- $this->redis->hincrby($bookNumKey, $book['id'], 1);
- $bookKey = 'B:'.$book['id'];
- if($this->redis->exists($bookKey)){ //判断有没有这个key
- $this->redis->hincrby($bookKey,'read_num',1);
- }
- $kandian = config('site.book_chapter_price'); //全局每章节书币数
- $returnArr = [];
- if(!$book || !$admin_id || !$chapter_id || !$chapter_name || !$idx){ //必传参数
- $returnArr['error'] = 1;
- $returnArr['type'] = 4;
- $returnArr['msg'] = '缺少参数';
- return $returnArr;
- }
- if(!empty($user)) {
- $userId = $user['id'];
- }else{
- $userId = null;
- }
- if(Config::get("site.free")==1){ //容灾处理,如果计费出现问题在后台配置read_free=true则所有书籍都免费
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '免费章节';
- return $returnArr;
- }
- if(intval($book['free_stime'])<time() && intval($book['free_etime'])>time()){ //此书设置了免费时长并且当前时间在免费时长内则免费阅读
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '免费章节';
- return $returnArr;
- }
- if($idx > $freeChapter && empty($userId)){
- $returnArr['error'] = 1;
- $returnArr['type'] = 7;
- $returnArr['isRecharge'] = 1;
- $returnArr['msg'] = '游客到了计费章节';
- return $returnArr;
- }
- if($idx<=$freeChapter && empty($userId)){ //记录游客最近阅读
- $this->recentlyRead($chapter_name,$chapter_id,$book);
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '免费章节';
- return $returnArr;
- }
- $bookId = $book['id']; //书籍id
- $consumeDB = model('Consume')->setConnect($userId);
- $book = model('Book')->bookinfo($bookId); //获取书籍信息
- if(!$book){
- $returnArr['error'] = 1;
- $returnArr['type'] = 5;
- $returnArr['msg'] = '获取书籍信息失败';
- return $returnArr;
- }
- $insertData = [];
- $insertData['user_id'] = $userId;
- $insertData['book_id'] = $bookId;
- $insertData['chapter_id'] = $chapter_id;
- $insertData['chapter_name'] = $chapter_name;
- $insertData['createtime'] = time();
- $insertData['updatetime'] = time();
- $insertConsume = []; //计费
- if($idx<=$freeChapter){ //免费章节
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '免费章节';
- return $returnArr;
- }else{
- $returnArr['isRecharge'] = 1;
- }
- if($user['vip_endtime']>time()){ //vip用户,全部章节免费
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '免费章节';
- return $returnArr;
- }
- //判断该本书是按本收费还是按章收费,是否自定义每章的价格
- $billing_type = $book['billing_type'];
- $price = $book['price'];
- $insertConsume['type'] = 1;
- $caseWhere = ['user_id'=>$userId,'book_id'=>$bookId,'type'=>1,'chapter_id'=>$chapter_id];
- if($billing_type == 2 && intval($price)>0){ //按本收费
- $chapter_id = null;
- $kandian = intval($price);
- $insertConsume['type'] = 2;
- $caseWhere = ['user_id'=>$userId,'book_id'=>$bookId,'type'=>2];
- }
- if($billing_type == 1 && intval($price)>0){ //自定义每章价格
- $kandian = intval($price);
- }
- //以下处理扣费章节
- $isConsume = $consumeDB->where($caseWhere)->find();
- if(!empty($isConsume)){
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '已经付过费';
- return $returnArr;
- }
- //未扣费处理
- $fee = [];
- $feeBook = [];
- $feeBook['spending_count_kandian'] = $kandian;
- $feeBook['spending_recharge_kandian'] = 0;
- //书币是否够用
- $total_free_kandian = model('Recharge')->getTotalFreeKandian($userId);
- if($total_free_kandian + $user['kandian'] < $kandian){
- $returnArr['error'] = 1; // 0:成功,1:失败
- $returnArr['type'] = 2; // type:1扣书币成功 2.书币不足,3扣书币失败,4缺少参数
- $returnArr['msg'] = '抱歉,您的书币不足'; //提示信息
- return $returnArr;
- }
- if($total_free_kandian>=$kandian){
- $fee['free_kandian'] = $total_free_kandian-$kandian;
- $feeBook['spending_free_kandian'] = $kandian;
- }else{
- $fee['free_kandian'] = 0;
- $fee['kandian'] = $user['kandian']+$total_free_kandian-$kandian;
- $feeBook['spending_free_kandian'] = $total_free_kandian;
- $feeBook['spending_recharge_kandian'] = $kandian-$total_free_kandian;
- }
- if(isset($fee['kandian']) && $fee['kandian'] != $user['kandian']){
- $userRes = model('user')->setConnect($userId)->update($fee,['id'=>$userId]); //减少用户书币
- if(!$userRes){
- $returnArr['error'] = 1;
- $returnArr['type'] = 3;
- $returnArr['msg'] = '抱歉,操作失败';
- return $returnArr;
- }
- //更新redis
- $userKey = 'UN:'.$userId;
- if($this->redis->exists($userKey)){
- $this->redis->hmset($userKey,$fee);
- //up by wanghy 0407 用户信息过期时间由24小时修改为10小时
- $this->redis->expire($userKey, 36000);
- }
- }
- $this->recentlyRead($chapter_name,$chapter_id,$book,$userId); //记录最近阅读
- //减少免费书币
- if($total_free_kandian > 0){
- $rid = model('Recharge')->getLastFreeRecord($userId);
- model('Recharge')->reduceFreeKandian($userId,$kandian,$rid);
- }
- //user表操作结束,以下处理consume表和user_recently_read表
- $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y'));
- //判断此用户今天有没有在这本书扣过费,放入缓存
- $everyDayKey = 'HC:'.$userId.':'.$bookId.':'.date("d");
- $isConsumeToday = false;
- if($this->redis->exists($everyDayKey)){
- $isConsumeToday = true;
- }else{
- $consumeToday = $consumeDB->where(['user_id'=>$userId,'book_id'=>$bookId])->order('id','desc')->find();
- if(isset($consumeToday['updatetime']) && $consumeToday['updatetime'] > $beginToday){
- $this->redis->setex($everyDayKey,86400,'1');
- $isConsumeToday = true;
- }
- }
- $insertConsume['user_id'] = $userId;
- $insertConsume['book_id'] = $bookId;
- $insertConsume['book_name'] = $book['name'];
- $insertConsume['chapter_id'] = $chapter_id;
- $insertConsume['chapter_name'] = $chapter_name;
- $insertConsume['kandian'] = $feeBook['spending_recharge_kandian'];
- $insertConsume['free_kandian'] = $feeBook['spending_free_kandian'];
- $insertConsume['createtime'] = time();
- $insertConsume['updatetime'] = time();
- $insertConsume['extend1'] = $bookId;
- $insertConsume['extend2'] = $chapter_id;
- //插入消费记录
- $consumeDB->insert($insertConsume);
- $feeBook['type'] = 1;
- $feeBookAll['type'] = 1;
- $feeBook['book_id'] = $bookId;
- $feeBookAll['book_id'] = $bookId;
- $feeBook['updatetime'] = time();
- $feeBookAll['updatetime'] = time();
- $feeBookAll['admin_id'] = 0;
- //0408 去掉用户喜好字段维护
- //记录用户喜好类目
- // if(!empty($user)){
- // $keyUBC = 'U-BC:' . $userId;
- // if ($this->redis->exists($keyUBC)) {
- // $user_cateIds = $this->redis->get($keyUBC);
- // if (!$user_cateIds) {
- // $user_cateIds = '';
- // }
- // } else {
- // $user_cateIds = $user['book_category_ids'];
- // }
- // $category_id = $book['book_category_id'];
- // $categoryString = '';
- // if (!empty($user_cateIds)) {
- // $categorys = explode(',', $user_cateIds);
- // if (!in_array($category_id, $categorys)) {
- // if (count($categorys) > 4) {
- // unset($categorys[0]);
- // foreach ($categorys as $key => $val) {
- // $categoryString .= $val . ',';
- // }
- // $categoryString .= $category_id;
- // } else {
- // $categoryString = $user_cateIds . ',' . $category_id;
- // }
- // } else {
- // $categoryString = $user_cateIds;
- // }
- // } else {
- // $categoryString = $category_id;
- // }
- // $this->redis->setex($keyUBC, 86400, $categoryString);
- // }
- //管理员数据汇总
- $this->bookConsumeCollect(0,$bookId,$isConsumeToday,$feeBook['spending_count_kandian'],$feeBook['spending_free_kandian'],$feeBook['spending_recharge_kandian']);
- //分销商,代理商插入小说汇总统计记录
- $this->bookConsumeCollect($admin_id,$bookId,$isConsumeToday,$feeBook['spending_count_kandian'],$feeBook['spending_free_kandian'],$feeBook['spending_recharge_kandian']);
- $returnArr['error'] = 0;
- $returnArr['type'] = 1;
- $returnArr['msg'] = '扣书币成功';
- return $returnArr;
- }
- /**
- * 书籍计费统计
- * @param $channel_id
- * @param $book_id
- * @param $isConsumeToday
- * @param $count_kandian
- * @param $free_kandian
- * @param $recharge_kandian
- * @throws \Exception
- */
- private function bookConsumeCollect($channel_id,$book_id,$isConsumeToday,$count_kandian,$free_kandian,$recharge_kandian){
- //设置渠道籍列表
- $collect_list_key = "BC-CL:".date("Ymd");
- $this->redis->sadd($collect_list_key,$channel_id);
- $this->redis->expire($collect_list_key,86400*2);
- //设置渠道商书籍列表
- $collect_channel_book_key = "BC-BL:{$channel_id}:".date("Ymd");
- $this->redis->sadd($collect_channel_book_key,$book_id);
- $this->redis->expire($collect_channel_book_key,86400*2);
- //设置渠道商对应书籍数据
- $collect_key = "BC:{$book_id}:{$channel_id}:".date("Ymd");
- if($data = json_decode($this->redis->get($collect_key),true)){
- if(!$isConsumeToday){
- $data['spending_users'] = intval($data['spending_users'] ?? 0)+1;
- }
- $data['spending_num'] = intval($data['spending_num'] ?? 0)+1;
- $data['spending_count_kandian'] = intval($data['spending_count_kandian'] ?? 0)+$count_kandian;
- $data['spending_free_kandian'] = intval($data['spending_free_kandian'] ?? 0)+$free_kandian;
- $data['spending_recharge_kandian'] = intval($data['spending_recharge_kandian'] ?? 0)+$recharge_kandian;
- $this->redis->setex($collect_key,86400*2,json_encode($data));
- }else{
- $data['spending_users'] = 1;
- $data['spending_num'] = 1;
- $data['spending_count_kandian'] = $count_kandian;
- $data['spending_free_kandian'] = $free_kandian;
- $data['spending_recharge_kandian'] = $recharge_kandian;
- $this->redis->setex($collect_key,86400*2,json_encode($data));
- }
- }
- /**
- * 最近阅读
- * @param $chapter_name
- * @param $chapter_id
- * @param $book array
- * @param null $userId
- * @return bool
- */
- public function recentlyRead($chapter_name,$chapter_id,$book,$userId=null){
- //记录最近阅读
- if(!$chapter_name || !$chapter_id || !$book){
- return false;
- }
- $bookId = $book['id'];
- $key = 'U-R:'.$userId; //最近阅读记录zset结构
- $hkey = 'U-B:'.$userId.':'.$bookId; //最近阅读阅读记录每条的数据:hash结构
- $RencentlyReadDB = model('UserRecentlyRead');
- $RencentlyReadDB = $RencentlyReadDB->setConnect($userId);
- if(empty($userId)){ //游客
- $chapterinfo = [];
- $chapterinfo['id'] = $chapter_id;
- $chapterinfo['name'] = $chapter_name;
- $RencentlyReadDB->recentCookie($book['id'], $chapterinfo); //阅读记录记入cookie 只记录5条数据
- return true;
- }
- $chapterInfo = [];
- $chapterInfo['id'] = $chapter_id;
- $chapterInfo['name'] = $chapter_name;
- $bookInfo = [];
- $bookInfo['image'] = $book['image'];
- $bookInfo['book_name'] = $book['name'];
- $bookInfo['last_chapter_name'] = $book['last_chapter_name'];
- $bookInfo['last_chapter_utime'] = $book['last_chapter_utime'];
- $bookInfo['state'] = $book['state'];
- $insertData = [];
- $insertData['user_id'] = $userId;
- $insertData['book_id'] = $bookId;
- $insertData['chapter_id'] = $chapter_id;
- $insertData['chapter_name'] = $chapter_name;
- $insertData['createtime'] = time();
- $insertData['updatetime'] = time();
- if(!$this->redis->exists($key)){ //如果redis里最近阅读记录为空拉取一下最近阅读记录(防灾)
- $RencentlyReadDB->getRecentlyRead(0, 10);
- }
- //判断redis里有没有记录
- $userRead = null;
- if($this->redis->exists($hkey) && $this->redis->exists($key)){
- $userRead = $this->redis->hgetall($hkey);
- }
- //如果redis里没有记录判断数据库里有没有记录
- if(empty($userRead)){
- $userRead = $RencentlyReadDB->where(['user_id'=>$userId,'book_id'=>$bookId])->find(); //是否阅读过此书
- }
- if (!empty($userRead)) { //更新
- $getId = $userRead['id'];
- $RencentlyReadDB->where(['id'=>$getId])->update(['chapter_id' => $chapter_id, 'updatetime' => time(),'chapter_name'=>$chapter_name,'flag'=>1]);
- if($getId){
- $insertData['id'] = $getId;
- $updateArr = array_merge($insertData,$bookInfo);
- $this->redis->hmset($hkey, $updateArr);
- if($this->redis->exists($key)) {
- $this->redis->zrem($key, $hkey);
- }
- $this->redis->zadd($key, $updateArr['updatetime'], $hkey);
- $this->redis->expire($key,43200); //设置失效时间
- $this->redis->expire($hkey,43200); //设置失效时间
- }
- } else {
- $RencentlyReadDB->insert($insertData);
- $id = $RencentlyReadDB->getLastInsID();
- $insertData['id'] = $id;
- $insertArr = array_merge($insertData, $bookInfo);
- $this->redis->hmset($hkey, $insertArr);
- $this->redis->expire($hkey,43200); //设置失效时间
- if($this->redis->exists($key)){
- $this->redis->zrem($key, $hkey);
- }
- if(!$this->redis->exists($key)){ //(如果redis里最近阅读记录为空拉取一下最近阅读记录防灾)
- $RencentlyReadDB->getRecentlyRead(time()+1, 10);
- }
- $this->redis->zadd($key, $insertArr['updatetime'], $hkey);
- $this->redis->expire($key,43200); //设置失效时间
- }
- }
- }
|