<?php
namespace app\common\middleware;
use think\facade\View;
use think\facade\Cache;
use think\facade\Cookie;
use think\facade\Db;
use app\common\variable\MsgCode;
use app\common\model\ApiLog;
use app\common\model\User as UserModel;
use app\common\model\UserTimer as UserTimerModel;
use app\common\model\UserDevices as UserDevicesModel;

class VerificationApi
{
    public function handle($request, \Closure $next)
    {
        $authRet=$this->auth($request);
        if (true!==$authRet['status'])
            return $this->ajaxReturn($authRet['msg'],$authRet['code']);
        $this->get_device_type($request);
	    return $next($request);
    }
    protected function auth($request)
    {
        $modul=app('http')->getName();
        $controller=request()->controller();
        $action=request()->action();
        /*获取当前应用*/
        $AppInfo=Cache::get('client.app.'.$modul);
        if (!$AppInfo) 
            return ['status'=>false,'msg'=>'应用不存在','code'=>MsgCode::$apiError];
        /*判断当前应用状态*/
        if (!$AppInfo['app_status'])
            return ['status'=>false,'msg'=>$AppInfo['app_status_msg'],'code'=>MsgCode::$apiError];
        /*接口安全认证*/
        $header=request()->header();
        $request->_uid=0;
        $request->_role_type=0;
        $request->_resume_id=0;
        $request->_company_id=0;
        if (!empty($header['xycms-uid'])){
            $request->_uid=intval($header['xycms-uid']);
            $request->_role_type=intval($header['xycms-role-type']);
            if (isset($header['xycms-resume-id'])){
                $request->_resume_id=intval($header['xycms-resume-id']);
            }
            if (isset($header['xycms-company-id'])){
                $request->_company_id=intval($header['xycms-company-id']);
            }
        }
        /*获取当前应用下的所有接口*/
        $ApiData=Cache::get('client.api.'.$modul);
        if (!$ApiData) 
            return ['status'=>false,'msg'=>'接口不存在','code'=>MsgCode::$apiError];
        /*判断当前接口是否存在*/
        if (empty($ApiData[$controller.'/'.$action]))
            return ['status'=>false,'msg'=>'接口不存在','code'=>MsgCode::$apiError];
        /*判断当前接口状态*/
        $ApiInfo=$ApiData[$controller.'/'.$action];
        if (!$ApiInfo['api_status'])
            return ['status'=>false,'msg'=>$ApiInfo['api_status_msg'],'code'=>MsgCode::$apiError];
        /*判断当前接口是否需要登录*/
        if ($ApiInfo['api_is_login']){
        	if(empty($header['xycms-token']))
            return ['status'=>false,'msg'=>'请先登录','code'=>MsgCode::$login];
        	$decrypted=$this->decrypt($header['xycms-token'],$AppInfo['app_key_secret']);
            $TokenData=[
                'uid'=>$request->_uid,
                'resume_id'=>$request->_resume_id,
                'company_id'=>$request->_company_id
            ];
            if($decrypted!=base64_encode(json_encode($TokenData,JSON_UNESCAPED_UNICODE)))
            return ['status'=>false,'msg'=>'接口校验失败，请重新登录','code'=>MsgCode::$login];
            if(!$request->_uid)
            return ['status'=>false,'msg'=>'请先登录','code'=>MsgCode::$login];
            if($modul=='appapiv1'&&!UserDevicesModel::where(['uid'=>$request->_uid,'appid'=>$ApiInfo['app_id'],'devices_id'=>$header['xycms-deviceid']])->count())
            return ['status'=>false,'msg'=>'请先登录','code'=>MsgCode::$login];
            $UserModel=UserModel::where(['id'=>$request->_uid])->field('status,disable_msg')->find();
            if(!$UserModel->status)
            return ['status'=>false,'msg'=>$UserModel->disable_msg,'code'=>MsgCode::$apiError];
        }
        if (config('basic.api_xycms_concurrent_sum')&&ApiLog::where(['ip'=>request()->ip()])->whereTime('create_time','between',[time()-3,time()+1])->count()>config('basic.api_xycms_concurrent_sum'))
            return ['status'=>false,'msg'=>'访问过于频繁','code'=>MsgCode::$apiError];

        if (isset($header['xycms-province']))
            $request->sub_province=intval($header['xycms-province']);
        if (isset($header['xycms-city']))
            $request->sub_city=intval($header['xycms-city']);
        if (isset($header['xycms-area']))
            $request->sub_area=intval($header['xycms-area']);
        /*记录访问日志*/
        $api_log=new ApiLog;
        $api_log->title     = $ApiInfo['api_name'];
        $api_log->uid       = $request->_uid;
        $api_log->app       = $ApiInfo['app_id'];
        $api_log->api       = $ApiInfo['api_id'];
        $api_log->route     = request()->url();
        $api_log->mca       = $modul.'/'.$controller.'/'.$action;
        $api_log->param     = json_encode(request()->param(),JSON_UNESCAPED_UNICODE);
        $api_log->ip        = request()->ip();
        $api_log->systype   = substr($header['xycms-platform'],0,200);
        $api_log->save();
        if($request->_uid){
            $UserTimer = UserTimerModel::where(['uid'=>$request->_uid])->find();
            if($UserTimer){
                $UserTimer->online_time=time();
                $UserTimer->online_ip=request()->ip();
                $UserTimer->online_devices=$header['xycms-deviceid'];
                $UserTimer->save();
            }
        }
        unset($AppInfo['app_key_secret']);
        $request->AppInfo=$AppInfo;
        $request->ApiInfo=$ApiInfo;
        return ['status'=>true];
    }
    protected function get_device_type($request){
        $type='pc';
        $is_wx=0;
        if(request()->isMobile()){
            //全部变成小写字母 
            $agent = strtolower(request()->header('user-agent'));
            //分别进行判断 
            (strpos($agent, 'iphone') || strpos($agent, 'ipad'))?$type='ios':'';
            strpos($agent, 'android')?$type = 'android':'';
            strpos($agent,'micromessenger')?$is_wx=1:0;
        }
        $request->device=$type;
        $request->is_wx=$is_wx;
    }
    /**
     * [ajaxReturn 返回json]
     * @param  integer $code [description]
     * @param  [type]  $data [description]
     * @return [type]        [description]
     */
    protected function ajaxReturn($msg='Success',$code=0){
        if (!$code)$code=MsgCode::$success;
        return json(['code'=>$code,'msg'=>$msg]);
    }
    protected function decrypt($data, $rsa_privatekey){
        $split = str_split($data, 172);  // 1024 bit  固定172
        $crypto = '';
        foreach ($split as $chunk) {
            $isOkay = openssl_private_decrypt(base64_decode($chunk), $decryptData, $rsa_privatekey);  // base64在这里使用，因为172字节是一组，是encode来的
            if(!$isOkay){
                return false;
            }
            $crypto .= $decryptData;
        }
        return $crypto;
    }
    protected function encrypt($data, $rsa_publickey){
        $split = str_split($data, 117);  // 1024 bit && OPENSSL_PKCS1_PADDING  不大于117即可
        $crypto = '';
        foreach ($split as $chunk) {
            $isOkay = openssl_public_encrypt($chunk, $encryptData, $rsa_publickey);
            if(!$isOkay){
                return false;
            }
            $crypto .= base64_encode($encryptData);
        }
        return $crypto;
    }
}