## BaseApi.php
~~~
namespace app\api\controller;
use think\App;
use think\captcha\CaptchaWithRedis;
use think\Cache;
use think\Response;
use think\Db;
use think\Controller;
use think\Request;
use app\admin\model\Users as UsersModel;
class BaseApi extends Controller
{
public $send_scene;
const PC_SMS_CODE_PREFIX = 'cookie_sms_code_';// 短信验证码缓存前缀
const CODE_EXPIRE = 180;// 短信及图形验证码有效时间180s
const TOKEN_EXPIRE_TIME = 86400;// token过期时间 86400
const PC_BIND_HASH_KEY = 'pc_bind_token_tag';
const USER_WITHOUT_SINGLE_DEVICE_HASH_KEY = 'user_group_without_single_device';
protected $token = '';
protected $domain = '';
//设备类型
protected $deviceType = '';
protected $version = '';
protected $apiVersion;
//用户 id
protected $userId = 0;
protected $request;
//用户
protected $user;
protected $distribut_level;
protected $app;
//用户类型
protected $userType;
protected $allowedDeviceTypes = ['mobile'];
private $salt = 'ddddddddddddddddddddd';
const CURRENT_REQUEST_KEY = 'pc_current_request_num';
const CURRENT_MAX_REQUEST_NUM = 300;
public function __construct(App $app = null)
{
$this->token;
$this->request = Request::instance();
$this->domain = Request::instance()->domain();
$this->_initUser();
}
// 初始化
protected function initialize()
{
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods:POST,GET");
header("Access-Control-Allow-Headers:ATJ-Device-Type,ATJ-Token");
header("Content-type:text/json;charset=utf-8");
}
private function _initUser()
{
$token = $this->request->header('ATJ-Token');
$deviceType = $this->request->header('ATJ-Device-Type');
$controller = $this->request->controller() ?: '';
if (empty($deviceType) || ! in_array($deviceType, $this->allowedDeviceTypes)) {
$this->success('获取成功0');
}
$analysis_data = [
'controller_name' => $controller,
'action_name' => $this->request->action() ?: '',
'token' => $token ?: '',
'page_path' => $this->request->baseUrl(true),
'page_query' => $this->request->param(),
'user_agent' => $this->request->header('user-agent'),
'ip_address' => get_ip()
];
if ($this->withoutTokenPass($analysis_data)) {
return true;
}
if (empty($token)) {
$this->error('请先登录');
}
$this->token = $token;
$user_id = $this->userTokenDecode();
if ( ! $user_id) {
$this->error('请先登录');
}
$user = UsersModel::where('user_id', $user_id)->find();
if (empty($user)) {
$this->error('会员不存在');
}
$this->userId = $user['user_id'];
$this->distribut_level = $user['distribut_level'];
}
private function userTokenDecode()
{
$token = $this->token;
if (empty($token)) {
$this->error('请先登录');
}
if (Cache::has($token)) {
$token_str = Cache::get($token);
if (is_numeric($token_str)) {
$user_id = $token_str;
$token_arr = [
'user_id' => $user_id,
'create_time' => time(),
'last_login' => time(),
'last_ip' => get_ip(),
'update_time' => time()
];
$this->updateTokenExpire($token, json_encode($token_arr), self::TOKEN_EXPIRE_TIME);
} else {
$token_arr = json_decode($token_str, true);
if (is_array($token_arr) && count($token_arr)) {
$user_id = $token_arr['user_id'];
UsersModel::where('user_id', $user_id)->data([
'token' => $token,
'token_time' => time()
])->update();
} else {
$user_id = 0;
}
}
} else {
$user_id = 0;
}
return $user_id;
}
protected function setExpireKey($key_name, $message, $expire_time = 60)
{
if (Cache::has($key_name)) {
$this->error($message);
} else {
Cache::set($key_name, 1, $expire_time);
}
return true;
}
protected function deleteExpireKey($key_name)
{
if (Cache::has($key_name)) {
Cache::rm($key_name);
}
return true;
}
protected function getCaptchaCode($key)
{
$config = ['useCurve' => true, 'useNoise' => true];// 验证码设置
$captcha = new CaptchaWithRedis($key, self::CODE_EXPIRE, $config);
return $captcha->entry();
}
/**
* 获取当前的response 输出类型
* @access protected
* @return string
*/
protected function getResponseType()
{
return 'json';
}
protected function deleteRequestNum()
{
$cache_key = self::CURRENT_REQUEST_KEY;
// 如果缓存只存在且大于0,则将缓存减1
if (Cache::has($cache_key) && Cache::get($cache_key) > 0) {
Cache::dec($cache_key, 1);
}
return true;
}
// 生成用户token
protected function createToken($user_id)
{
$token = md5('base_user_'.$user_id.'_'.time());
return $token;
}
// 生成用户token
protected function createTokenWithTime($user_id, $time)
{
if ($time) {
$token = md5('base_user_'.$user_id.'_'.$time);
} else {
$token = md5('base_user_'.$user_id.'_'.time());
}
return $token;
}
// 更新token缓存时间
protected function updateTokenExpire($token, $user_id, $time = 0)
{
if ( ! $token || ! $user_id) {
return false;
}
return Cache::set($token, $user_id, $time);
}
// 更新token_time
protected function updateTokenTime($user, $time, $ip_address)
{
$user->last_login_time = $time;
$user->last_login_ip = $ip_address;
$user->token_time = $time;
$user->save();
return $user;
}
protected function createInviteCode($user_id)
{
return md5(md5($user_id.random(4).time()));
}
protected function withoutTokenPass($analysis)
{
if (empty($analysis)) {
return false;
}
if (isset($analysis['controller_name']) && in_array($analysis['controller_name'], ['Login', 'Captcha'])) {
return true;
}
if ($analysis['controller_name'] == 'Index') {
$ActionName = ['category', 'article_list', 'article_article', 'banner_list', 'active_page', 'about_us'];
if (isset($analysis['action_name']) && in_array($analysis['action_name'], $ActionName)) {
return true;
}
}
return false;
}
}
~~~
## login.php
~~~
class Login extends BaseApi
{
const SMS_TEMPLATE_LOGIN = 'SMS_1111111111';
const SMS_CODE_EXPIRE = 180;// 短信验证码有效时间180s
const VERIFY_CODE_EXPIRE = 300;// 短信验证码有效时间300s
const TX_APPID = '88888888888';
const TX_AppSecretKey = 'gggggggggggggggggggggggg**';
/**
* @title 手机验证码登录
* @url /api/login/login
* @method POST
*
* @param string phone 手机号
* @param string code 手机验证码
* @param string invite_code 邀请码 空 允许
*
* @header string ATJ-Device-Type 设备类型 空 必须
* @code 1 成功
* @code 0 失败
* @json {"code":1,"msg":"登陆成功","data":{"token":"48df4682bf422797d1d6a3e6c8b7b983","token_time":1617967109,"user_info":{"user_id":11,"nickname":"","sex":0,"mobile":"16637102876","reg_time":1617956763,"last_login":1617967052,"last_ip":"127.0.0.1","head_pic":"","distribut_money":"0.00","underling_number":0,"distribut_level":3}}}
* @return int status 状态码 (具体参见状态码说明)
* @return string msg 提示信息
*/
public function login()
{
$validate = new \think\Validate([
'phone' => 'require',
'code' => 'require'
]);
$validate->message([
'phone.require' => '请输入手机号',
'code.require' => '请输入短信验证码'
]);
$data = $this->request->post();
if ( ! $validate->check($data)) {
return json(['code' => 0, 'msg' => $validate->getError()]);
}
$cache_key = 'login_pc_phone_'.$data['phone'];
$cache_sms_time = 'cookie_sms_time_'.$data['phone'];
//$this->setExpireKey($cache_key, '登录中,请稍侯...');
if (cmf_check_mobile($data['phone'])) {
$key = self::PC_SMS_CODE_PREFIX.$data['phone'];
if (Cache::has($key)) {
if ($data['code'] != Cache::get($key)) {
$this->deleteExpireKey($cache_key);
return json(['code' => 0, 'msg' => '请输入正确的验证码']);
}
} else {
$this->deleteExpireKey($cache_key);
return json(['code' => 0, 'msg' => '验证码已失效,请重新获取']);
}
Cache::rm($key);
Cache::rm($cache_sms_time);
Cache::rm($this->token);
} else {
$this->deleteExpireKey($cache_key);
return json(['code' => 0, 'msg' => '请输入正确手机号']);
}
$ip_address = get_ip();
$findId = 0;
$leader = 0;
$first_leader = 0;
$second_leader = 0;
$third_leader = 0;
if ( ! empty($data['invite_code'])) {
$findUsersss = UsersModel::where('invite_code', $data['invite_code'])->find();
$findId = $findUsersss['user_id'];
if (empty($findId)) {
$findId = 0;
}
$leader = ! empty($findUsersss['distribut_level']) ? $findUsersss['distribut_level'] : 3;
}
$distribut_level = 3;
switch ($leader) {
case 1:
$is_distribut = 1;
$first_leader = $findId;
break;
case 2:
$is_distribut = 0;
$second_leader = $findId;
break;
default:
$is_distribut = 0;
$third_leader = $findId;
break;
}
//判断会员 存在,如果不存在则注册
$time = time();
$findUser = UsersModel::where('mobile', $data['phone'])->find();
$token = $this->createToken($findUser['user_id']);
if ( ! empty($findUser)) {
$upData = [
'last_login' => $time,
'last_ip' => $ip_address,
'update_time' => $time,
'token_time' => $time,
'token' => $token
];
UsersModel::where('mobile', $data['phone'])->data($upData)->update();
$msg = '登陆成功';
} else {
//判断客户是否为老用户(客户表对应手机号,有为二级分销商,否则为普通会员)
$findCustomer = CustomerModel::where('contact_phone', $data['phone'])->find();
if ( ! empty($findCustomer)) {
$distribut_level = 2;
$second_leader = 0;
$third_leader = 0;
} else {
$distribut_level = 3;
}
$insData = [
'password' => cmf_password($data['phone']),
'reg_time' => $time,
'last_login' => $time,
'last_ip' => $ip_address,
'mobile' => $data['phone'],
'mobile_validated' => 1,
'distribut_level' => $distribut_level,
'is_distribut' => $is_distribut,
'first_leader' => $first_leader,
'second_leader' => $second_leader,
'third_leader' => $third_leader,
'perpetual' => 0,
'invite_code' => $this->createInviteCode($time),
'create_time' => $time,
'update_time' => $time
];
$userId = UsersModel::insertGetId($insData);
$createToken = $this->createTokenWithTime($userId, $time);
UsersModel::where('user_id', $userId)->data([
'token' => $createToken,
'token_time' => $time
])->update();
$findUser = UsersModel::where('user_id', $userId)->find();
$msg = '注册成功';
if ( ! empty($findId) && (in_array($leader, [1, 2]))) {
//给上级增加奖励
$this->user_award($findId, 1, $findUser['user_id'], $findUser['mobile']);
}
}
$result = $this->updateTokenExpire($token, $findUser['user_id'], self::TOKEN_EXPIRE_TIME);
if ( ! $result) {
$this->deleteExpireKey($cache_key);
return json(['code' => 0, 'msg' => '登录失败,请重试!']);
}
$userInfo = [
'token' => $token,
'token_time' => $findUser['token_time'],
'user_info' => [
'user_id' => $findUser['user_id'],
'nickname' => ! empty($findUser['nickname']) ? $findUser['nickname'] : '',
'sex' => $findUser['sex'],
'mobile' => $findUser['mobile'],
'reg_time' => $findUser['reg_time'],
'last_login' => $findUser['last_login'],
'last_ip' => $findUser['last_ip'],
'head_pic' => ! empty($findUser['head_pic']) ? $findUser['head_pic'] : '',
'distribut_money' => $findUser['distribut_money'],
'underling_number' => $findUser['underling_number'],
'distribut_level' => $findUser['distribut_level']
]
];
return json(['code' => 1, 'msg' => $msg, 'data' => $userInfo]);
}
/**
* @title 发送短信验证码
* @url /api/login/send_sms_code
* @header string ATJ-Device-Type 设备类型 空 必须
*
* @param string phone 手机号 空 必须
* @param string ticket ticket 空 必须
* @param string randstr randstr 空 必须
* @method POST
*
* @code 1 成功
* @code 0 失败
* @json {"code":1,"msg":"验证码发送成功"}
* @return int status 状态码 (具体参见状态码说明)
* @return string msg 提示信息
*/
public function send_sms_code()
{
$config = [
'accessKeyId' => tpCache('sms.sms_appkey'),
'accessKeySecret' => tpCache('sms.sms_secretKey'),
'signName' => tpCache('sms.sms_product'),
'templateCode' => self::SMS_TEMPLATE_LOGIN
];
$param = input('post.');
$mobile = ! empty($param['phone']) ? $param['phone'] : '';
if (empty($mobile)) {
return json(['code' => 0, 'msg' => '手机号不能为空']);
}
$host = 'captcha.tencentcloudapi.com';
$params = [
'CaptchaType' => 9,
'Ticket' => $param['ticket'],
'UserIp' => get_ip(),
'Randstr' => $param['randstr'],
'CaptchaAppId' => self::TX_APPID,
'AppSecretKey' => self::TX_AppSecretKey
];
$headers = $this->makeHeader($host, $params);
try {
$result = self::curl_post('https://'.$host, json_encode($params), $headers);
} catch (Exception $e) {
$this->error($e->getCode(), ['code' => '']);
}
$result = json_decode($result, true);
/*if (empty($result) || ! isset($result['Response']) || ! isset($result['Response']['CaptchaCode']) || $result['Response']['CaptchaCode'] != 1) {
$this->error(isset($result['Response']) && isset($result['Response']['CaptchaMsg']) && ! empty($result['Response']['CaptchaMsg']) ? $result['Response']['CaptchaMsg'] : "验证失败,请重试");
}*/
//获取时间配置
$sms_time_out = tpCache('sms.sms_time_out');
$sms_time_out = $sms_time_out ? $sms_time_out : 120;
$code = rand(100000, 999999);
$cookie_sms_code_time = Cache::get('cookie_sms_time_'.$mobile);
//120秒以内不可重复发送
if ( ! empty($cookie_sms_code_time && (time() - $cookie_sms_code_time < $sms_time_out))) {
return json(['code' => $code, 'msg' => $sms_time_out.'秒内不允许重复发送']);
}
$SmsAli = new SmsAli($config);
Cache::set('cookie_sms_code_'.$mobile, $code, 300);
Cache::set('cookie_sms_time_'.$mobile, time(), 300);
$cookie_code = Cache::get('cookie_sms_code_'.$mobile);
$sendSms = $SmsAli->send_sms($mobile, json_encode(['code' => $cookie_code]));
if ($sendSms['Code'] == 'OK') {
return json(['code' => 1, 'msg' => '验证码发送成功', 'yzm' => $cookie_code]);
} else {
return json(['code' => 0, 'msg' => $sendSms['Message']]);
}
}
private function makeHeader($host, $params)
{
$headers = [
'X-TC-Action' => 'DescribeCaptchaResult',
'X-TC-Timestamp' => time(),
'X-TC-Version' => '2019-07-22',
'Content-Type' => 'application/json',
'Host' => $host
];
$algo = "TC3-HMAC-SHA256";
$date = gmdate("Y-m-d", $headers["X-TC-Timestamp"]);
$service = 'captcha';
$canonicalUri = '/';
$reqmethod = 'POST';
$canonicalQueryString = '';
$canonicalHeaders = "content-type:".$headers["Content-Type"]."\n"."host:".$headers["Host"]."\n";
$signedHeaders = "content-type;host";
$payloadHash = hash("SHA256", json_encode($params));
$canonicalRequest = $reqmethod."\n".$canonicalUri."\n".$canonicalQueryString."\n".$canonicalHeaders."\n".$signedHeaders."\n".$payloadHash;
$credentialScope = $date."/".$service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$str2sign = $algo."\n".$headers["X-TC-Timestamp"]."\n".$credentialScope."\n".$hashedCanonicalRequest;
$secretKey = 'hhhhhhhhhhhhhhhhhhhhhhhh';
$signature = $this->signTC3($secretKey, $date, $service, $str2sign);
$sid = 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii';
$auth = $algo." Credential=".$sid."/".$credentialScope.", SignedHeaders=content-type;host, Signature=".$signature;
$headers["Authorization"] = $auth;
$temp = [];
foreach ($headers as $key => $value) {
array_push($temp, $key.':'.$value);
}
return $temp;
}
protected function signTC3($skey, $date, $service, $str2sign)
{
$dateKey = hash_hmac("SHA256", $date, "TC3".$skey, true);
$serviceKey = hash_hmac("SHA256", $service, $dateKey, true);
$reqKey = hash_hmac("SHA256", "tc3_request", $serviceKey, true);
return hash_hmac("SHA256", $str2sign, $reqKey);
}
protected function curl_post($post_url, $post_data, $header = [])
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_USERAGENT,
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
}
~~~
- thinkphp
- thinkphp笔记
- 后台登陆退出
- config配置
- 隐藏后台模块
- 单独调用腾讯云行为验证码
- api接口跨域问题
- api接口创建案例代码
- 使用gateway worker
- 使用swoole代码笔记
- 使用队列 think-queue笔记
- 后台布局
- MySQL
- 1、关于lnmp mysql的一个坑
- 2、mysql实现group by后取各分组的最新一条
- 其他
- 搞笑的注释代码
- 分页类
- nodejs 打包网址为exe
- 免费天气预报API接口
- Ajax
- 简单的ajax分页1
- 通用ajax-post提交
- 引用的类库文件
- Auth.php
- Auth.php权限控制对应的数据库表结构
- Layui.php
- Pinyin.php
- Random.php
- Tree.php
- Tree2.php
- Js-Jq
- Git的使用
- 3、bootstrap-datetimepicker实现两个时间范围输入
- CentOS安装SSR做梯子
- Python爬虫
- 1、安装Gerapy
- 2、安装Scrapy
- 3、Scrapy使用
- 4、Scrapy框架,爬取网站返回json数据(spider源码)
- 0、Python pip更换国内源(一句命令换源)
- 服务器运维
- 1、宝塔使用webhook更新服务器代码
- 2、搭建内网穿透
- 3、数据库主从同步
- 4、数据库复制
- hui-Shop问题
- 1、前端模板的注意事项
- 2、模板标签