<?php
/**
 * Created by PhpStorm.
 * User: yanzai
 * Date: 2018/12/4
 * Time: 13:53
 * 刚发现jwt ,自己理解的是jwt就是一个加密思路，虽然按照规定写了，但是还是认为可以随意，或许以后能明白真正的Jwt
 */

class JWT
{
    //设置Jwt秘钥
    public static function GetSecret()
    {

        return env('JWT_KEY');
    }
    public static function GetGetSecretTimeOut()
    {
        date_default_timezone_set('PRC'); //token的有效期
        $mm=env('JWT_TIME_OUT')*60;//PHP的时间是按秒算的
        return date("Y-m-d H:i:s",strtotime(date('Y-m-d H:i:s',time()))+$mm);  //设置Token超时时间 单位：分钟
    }
    public static function GetRefreshTokenTimeOut()  //刷新token的有效期
    {
        date_default_timezone_set('PRC');
        $mm=env('JWT_REFRESH_TIME_OUT')*60;//PHP的时间是按秒算的

        return date("Y-m-d H:i:s",strtotime(date('Y-m-d H:i:s',time()))+$mm);  //设置RefreshToken超时时间 单位：分钟
    }
    public static function GetMian7TokenTimeOut()  //免登录7天token的有效期
    {
        date_default_timezone_set('PRC');
        $mm=10080*60;//PHP的时间是按秒算的

        return date("Y-m-d H:i:s",strtotime(date('Y-m-d H:i:s',time()))+$mm);  //设置RefreshToken超时时间 单位：分钟
    }
    //构建完整 JWT
    public static function BuildJWT($send_user,$tokenType,$userid,$role,$exp)
    {
        $head = self::BuildHead();
        $payload = self::BuildPayload($send_user,$tokenType,$userid,$role,$exp);
        $signature = self::BuildSignature($head,$payload);
        return $head.'.'.$payload.'.'.$signature;
    }
    //构建jwt head  base64转码
    public static function BuildHead()
    {
       $head =  self::urlsafe_b64encode('{
        "alg": "sha256",
        "typ": "JWT"
        }');
        return $head;
    }
    //构建jwt Payload base64转码
    public static function BuildPayload($send_user,$tokenType,$userid,$role='customer',$exp)
    {
        $payload = self::urlsafe_b64encode('{"senduser": "'.$send_user.'","tokentype": "'.$tokenType.'","userid": "'.$userid.'","role": "'.$role.'","exp": "'.$exp.'"}');
        return $payload;
    }
    //构建jwt Signature 加密生成签名
    public static function BuildSignature($head,$payload)
    {
        $s = hash_hmac('sha256', $head.'.'.$payload, self::GetSecret(), true);
        return self::urlsafe_b64encode($s);
    }

    //验证JWT
    public static function CheckJwt($code)
    {
        $code = substr($code,strpos($code,' ')+1);
        $result  = array();
        if(strlen($code)<10)
        {
            $result['status']='Toke_Error';
            $result['meg']= '签名异常，拒绝操作！';
            $result['code']=10001;
            return $result;
        }
        $array=explode('.', $code);
        $ReceiveSignature = $array[2];
        $ReceiveHead = $array[0];
        $ReceivePayload = $array[1];

        $Signature = self::BuildSignature($ReceiveHead,$ReceivePayload);
        if($ReceiveSignature==$Signature)                   //判断签名是否一致
        {
           $payload_string = self::urlsafe_b64decode($ReceivePayload);
           $payload=json_decode($payload_string,true);

            date_default_timezone_set('PRC');
            if($payload['exp']>date('Y-m-d H:i:s',time()))                         //判断Token是否过期
            {
                $result['status']='OK';
                $result['tokentype']=$payload['tokentype'];
                $result['role']=$payload['role'];
                $result['userid']=$payload['userid'];
                $result['meg']= 'Token验证通过';
            }else{
                $result['status']='Token_TimeOut';
                $result['meg']= 'Token已过期，请返回登录界面重新授权';
                $result['code']=10002;
            }

        }
        else{
            $result['status']='Toke_Error';
            $result['meg']= '签名异常，拒绝操作！';
            $result['code']=10001;
        }
        return $result;
    }


//URL安全的字符串编码：
    static function  urlsafe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }

//URL安全的字符串解码：
    static function urlsafe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }

}
