all(), [ 'keyword' => 'min:1', // 查询-关键字 'industry' => 'exists:industry,content', // 查询-行业 'province' => 'exists:area,name', // 查询-省 'city' => 'exists:area,name', // 查询-市 'district' => 'exists:area,name', // 查询-区 'num' => 'required|integer', //查询-提取广告数量 'shop_master_id' => 'required|integer',// 防作弊-主商家id //'shop_slave_id' => 'required|integer',//防作弊-子商家id、 //'user_industry' => 'required|exists:industry,content', // 防作弊-当前登录用户的所在的行业 //'uid' => 'required|integer', //防作弊-用户id 'ip' => 'required|ipv4', // 防作弊-ip 'is_free' => 'required|integer|between:0,1', //防作弊 0-扣费 1-免费 'type' => 'required|integer|between:1,2' // 防作弊-1-点击、2-浏览、3-展现 ]); if ($validator->fails()) { return showJsonErr($validator->errors()->first()); } $adver = Advertising::select(['id', 'scene', 'title', 'image', 'scene', 'image_group', 'content', 'redirect']) ->where('residue_num', '>=', 1) ->where('status', 3) ->limit($param['num']) ->orderBy(\DB::raw('rand()')); // @TODO 随机待优化 // 关键字查询 if (!empty($param['keyword'])) { $adver->where('title', 'like', "%{$param['keyword']}%"); } // 行业查询 if (!empty($param['industry'])) { $adver->where('industry', Industry::whereContent($param['industry'])->select('id')->first()->id); } // 省级查询 if (!empty($param['province'])) { $adver->where('province', Area::whereName($param['province'])->select(['id'])->first()->id); } // 地级市查询 if (!empty($param['city'])) { $adver->where('city', Area::whereName($param['city'])->select(['id'])->first()->id); } // 县区查询 if (!empty($param['district'])) { $adver->where('district', Area::whereName($param['district'])->select(['id'])->first()->id); } $res = $adver->get(); if (empty($res)) { return showJsonErr(1012); } $param['adver'] = collect($res)->pluck('id'); $param['ip'] = $request->ip(); if (!empty($param['shop_slave_id'])) { } $param['shop_id'] = $param['shop_master_id'] . '-' . $param['shop_slave_id']; // 保存广告获取日志 AdverVisit::insertGetId($param); $remark = []; if ($res->isNotEmpty() && $param['is_free'] == 0) { foreach ($res as $ad) { $param['adver_id'] = $ad->id; // 扣费 $remark = $this->deduction($param); } } return showJsonSucc(1001, ['data' => $res, 'remark' => $remark]); } /** * 广告扣费 * @author lyh * @date 2019/4/3 * @description * 要求:支持批量 * 预计要做的防作弊规则是这样: * 1. 根据同用户点击同一个商家,某个时间段M内,最多只能N次生效 * 2. 根据同IP点击同一个商家,某个时间段M内,最多只能N次生效 * 3. 根据同一个用户,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效 * 4. 根据同一个IP,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效 * */ public function adverDeduction(Request $request) { $validator = \Validator::make($param = $request->all(), [ 'uid' => 'required|integer', 'shopId' => 'required|integer', 'ip' => 'required', 'industry' => 'required|exists:industry,content', 'adver_id' => 'required|exists:advertising,id', 'is_free' => 'required|integer|between:0,1', // 0-扣费 1-免费 'type' => 'required|integer|between:1,3' // 1-点击、2-浏览、3-展现 ]); if ($validator->fails()) { return showJsonErr($validator->errors()->first()); } $param['industry'] = Industry::whereContent($param['industry'])->first()->id; // 请求记录 AdverDeductLog::insertGetId([ 'uid' => $param['uid'], 'shop_id' => $param['shopId'], 'ip' => $param['ip'], 'industry' => $param['industry'], 'adver_id' => $param['adver_id'], 'is_free' => $param['is_free'], 'type' => $param['type'] ]); // 对广告统计 switch ($param['type']) { case 1: Advertising::whereId($param['adver_id'])->increment('click_num'); break; case 2: Advertising::whereId($param['adver_id'])->increment('browse_num'); break; case 3: Advertising::whereId($param['adver_id'])->increment('show_num'); break; default; } $remark = []; if ($param['is_free'] == 0) { /**********根据同用户点击同一个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', '=', $param['adver_id']], ['uid', ' = ', $param['uid']], ['shop_id', ' = ', $param['shopId']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'user', $keyEnd = 'shoper', $paramStart = $param['uid'], $paramEnd = $param['shopId'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同IP点击同一个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['ip', ' = ', $param['ip']], ['shop_id', ' = ', $param['shop_id']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'ip', $keyEnd = 'shoper', $paramStart = $param['ip'], $paramEnd = $param['shopId'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同一个用户,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['uid', ' = ', $param['uid']], ['industry', ' = ', $param['industry']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'user', $keyEnd = 'industry', $paramStart = $param['uid'], $paramEnd = $param['industry'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同一个IP,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['ip', ' = ', $param['ip']], ['industry', ' = ', $param['industry']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'ip', $keyEnd = 'industry', $paramStart = $param['ip'], $paramEnd = $param['industry'], $where); if (is_string($re)) { $remark[] = $re; } if (!empty($remark)) { return showJsonErr('扣费失败', $remark); } $adver = Advertising::find($param['adver_id']); if ($adver->residue_num <= 0) { return showJsonErr("广告[ID:{$param['adver_id']},剩余次数为{$adver->residue_num}"); } $res = Advertising::whereId($param['adver_id'])->decrement('residue_num'); if (empty($res)) { return showJsonErr("广告[id:{$param['adver_id']}]扣费失败"); } // 广告过期 $adver = Advertising::whereId($param['adver_id'])->select(['residue_num'])->first(); if ($adver->residue_num <= 0) { Advertising::whereId($param['adver_id'])->update(['status' => 9]); // todo 告诉广告发布者广告到期? } } return showJsonSucc("广告[id:{$param['adver_id']}]请求成功", $remark); } /** * 分享计费 * @author lyh * @date 2019/4/3 * @param \Request $request * @description * todo 待定 */ public function shareBilling(\Request $request) { } /** * @author lyh * @date 2019/4/4 * @param $duration * @param $time * @return array * @description */ private function sendMsg($adverId, $duration, $time, $where = [], $remark = '%s') { $afterTime = Carbon::now()->subMinute($duration); $requestNum = AdverDeductLog::whereBetween('created_at', [$afterTime, Carbon::now()]) ->where($where) ->count('id'); // 如果请求次数过多,则发送消息给城市运营商 // if ($requestNum > $time) { $remark = sprintf($remark, $requestNum); $adver = Advertising::find($adverId); // todo AdverAlarm::insert([ 'uid' => $adver->uid, // 广告发布人 'province' => $adver->province, 'city' => $adver->city, 'district' => $adver->district, 'remark' => $remark ]); // } } private function checkCache($adverId, $keyStart, $keyEnd, $paramStart, $paramEnd, $where) { $prefix = sprintf('%sAND%s_', strtoupper($keyStart), strtoupper($keyEnd)); $duration = Config::getValue("{$prefix}DURATION"); $time = Config::getValue("{$prefix}TIME"); $cachekey = sprintf(' %sAnd%s_%s_%s', $keyStart, $keyEnd, $paramStart, $paramEnd); $attri = [ 'user' => '用户', 'shoper' => '商家', 'ip' => 'IP', 'industry' => '行业' ]; $msgStart = $attri[$keyStart]; $msgEnd = $attri[$keyEnd]; $commonComment = sprintf('%s[%s]点击%s[%s],在%s分钟内', $msgStart, $paramStart, $msgEnd, $paramEnd, $duration); if (\Cache::has($cachekey)) { $usdtNum = \Cache::get($cachekey); if ($usdtNum >= $time) { // todo 发送消息给谁 $this->sendMsg($adverId, $duration, $time, $where, $remark = $commonComment . "请求了[%s]次"); // return showJsonErr('触发失败'); // todo 修改提示内容 $remark = sprintf("[对接提醒:该消息内容正式上线会去除]: %s生效了%s次", $commonComment, $usdtNum); return $remark; } else { \Cache::increment($cachekey); } } else { \Cache::add($cachekey, 1, $duration); } return true; } /** * 获取广告扣费 * @author lyh * @date 2019/4/19 * @param $param * @return array * @description */ private function deduction($param) { $param['industry'] = Industry::whereContent($param['user_industry'])->first()->id; // 请求记录 AdverDeductLog::insertGetId([ 'uid' => $param['uid'], 'shop_id' => $param['shop_id'], 'ip' => $param['ip'], 'industry' => $param['industry'], 'adver_id' => $param['adver_id'], 'is_free' => $param['is_free'], 'type' => $param['type'], 'shop_slave_id' => $param['shop_slave_id'], 'shop_master_id' => $param['shop_master_id'] ]); // 对广告统计 switch ($param['type']) { case 1: Advertising::whereId($param['adver_id'])->increment('click_num'); break; case 2: Advertising::whereId($param['adver_id'])->increment('browse_num'); break; case 3: Advertising::whereId($param['adver_id'])->increment('show_num'); break; default; } $remark = []; if ($param['is_free'] == 0) { /**********根据同用户点击同一个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', '=', $param['adver_id']], ['uid', ' = ', $param['uid']], ['shop_id', ' = ', $param['shop_id']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'user', $keyEnd = 'shoper', $paramStart = $param['uid'], $paramEnd = $param['shop_id'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同IP点击同一个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['ip', ' = ', $param['ip']], ['shop_id', ' = ', $param['shop_id']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'ip', $keyEnd = 'shoper', $paramStart = $param['ip'], $paramEnd = $param['shop_id'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同一个用户,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['uid', ' = ', $param['uid']], ['industry', ' = ', $param['industry']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'user', $keyEnd = 'industry', $paramStart = $param['uid'], $paramEnd = $param['industry'], $where); if (is_string($re)) { $remark[] = $re; } /**********根据同一个IP,点击同一个行业的某个商家,某个时间段M内,最多只能N次生效**********/ $where = [['adver_id', ' = ', $param['adver_id']], ['ip', ' = ', $param['ip']], ['industry', ' = ', $param['industry']]]; $re = $this->checkCache($adver_id = $param['adver_id'], $keyStart = 'ip', $keyEnd = 'industry', $paramStart = $param['ip'], $paramEnd = $param['industry'], $where); if (is_string($re)) { $remark[] = $re; } $adver = Advertising::find($param['adver_id']); if ($adver->residue_num <= 0) { $remark[] = "广告[ID:{$param['adver_id']},剩余次数为{$adver->residue_num}"; } $res = Advertising::whereId($param['adver_id'])->decrement('residue_num'); if (empty($res)) { $remark[] = "广告[id:{$param['adver_id']}]扣费失败"; } // 广告过期 $adver = Advertising::whereId($param['adver_id'])->select(['residue_num'])->first(); if ($adver->residue_num <= 0) { Advertising::whereId($param['adver_id'])->update(['status' => 9]); // todo 告诉广告发布者广告到期? } } return $remark; } }