<?php

namespace app\api\controller;

use think\Controller;
use think\Request;
use app\common\model\User as UserModel;

/**
 * 基础控制器
 */
class Base extends Controller
{
    protected $userinfo;

    // 控制器方法的前置执行的操作方法，可以指定某1个方法为其他方法的前置操作  
    // 在所有接口执行之前执行validSignature验证签名和token，如果不需验证则将方法名写入except数组中，以逗号分割
    protected $beforeActionList = [
        'validSignature' => ['except' => 'login,token,callback'],
    ];

    // 检查签名和用户token
    protected function validSignature()
    {
        $params = input('post.');

        // var_dump($params);
        // echo $this->getSignature($params); exit;

       //  验证签名
        if (!$this->checkSignature($params)) {
            echo json_encode(["code" => 1, "msg" => "auth failed"]);
            die;
        }

        // 用户信息
        if (input('post.token')) {
            $token          = input('post.token');
            $this->userinfo = explode("|", $this->decode($token));
            //检测一下用户不存在的情况
            $user = UserModel::get($this->userinfo[0]);
            if (!$user) {
                echo json_encode(["code" => 1, "msg" => "auth failed"]);
                die;
            }
        }
    }

    public function _initialize()
    {
        define('API_CONTROLLER_NAME', Request::instance()->controller());
        define('API_MODULE_NAME', Request::instance()->module());
        define('API_ACTION_NAME', Request::instance()->action());

        // 解决跨域请求
        // header('Access-Control-Allow-Origin:*');
        // header('Access-Control-Allow-Headers:*');

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
        header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE');

        if (Request::instance()->isOptions()) {
            echo json_encode(["code" => 1, "msg" => "options method"]);
            exit;
        }
    }

    /**
     * UTF8字符串加密
     * @param string $string
     * @author Anyon <zoujingli@qq.com>
     * @date 2017/06/26
     * @return string
     */
    protected function encode($string)
    {
        $chars = '';
        $len   = strlen($string = iconv('utf-8', 'gbk', $string));
        for ($i = 0; $i < $len; $i++) {
            $chars .= str_pad(base_convert(ord($string[$i]), 10, 36), 2, 0, 0);
        }
        return strtoupper($chars);
    }

    /**
     * UTF8字符串解密
     * @param string $string
     * @author Anyon <zoujingli@qq.com>
     * @date 2017/06/26
     * @return string
     */
    protected function decode($string)
    {
        $chars = '';
        foreach (str_split($string, 2) as $char) {
            $chars .= chr(intval(base_convert($char, 36, 10)));
        }
        return iconv('gbk', 'utf-8', $chars);
    }

    /**
     * 签名生成算法
     * @param  array $params API调用的请求参数集合的关联数组，不包含sign参数
     * @return string 返回参数签名值
     */
    protected static function getSignature($params)
    {
        $str = '';  //待签名字符串
        //先将参数以其参数名的字典序升序进行排序
        ksort($params);
        //遍历排序后的参数数组中的每一个key/value对
        foreach ($params as $k => $v) {
            //为key/value对生成一个key=value格式的字符串，并拼接到待签名字符串后面
            $str .= "$k=$v";
        }
        return sha1($str);
    }

    protected static function checkSignature($args)
    {
        if (!$args) {
            return false;
        }
        //请求的时间戳过期时间：100分钟，过期这次请求失效
        if (!isset($args['timestamp']) || time() - $args['timestamp'] > 60 * 100) {
            return false;
        }
        ksort($args);  // 按数组的键排序
        $sign      = '';
        $signature = '';
        foreach ($args as $k => $v) {
            if ($k == 'sign') {
                $signature = $v;
                continue;
            }
            $sign .= $k . '=' . $v;
        }

        // 加密
        $sign = sha1($sign);
        if ($sign == $signature) {
            return true;
        }
        return false;
    }

    /**
     * @des  生成用户token
     * @param  $uid    用户uid
     * @param  $content    内容
     * @param  $override_msg_id   覆盖的上一条消息id
     * @return object
     */
    protected function usertoken($user)
    {
        // username可能有表情，需要用json编解码
        $nickname = json_encode($user['nickname']);

        $encode_arr = [$user['id'], $nickname, $user['openid'], time()];
        $encode_str = implode("|", $encode_arr);
        $token      = $this->encode($encode_str);

        return $token;

    }
}