<?php
// +----------------------------------------------------------------------
// | [RhaPHP System] Copyright (c) 2017-2020 http://www.rhaphp.com/
// +----------------------------------------------------------------------
// | [RhaPHP] 并不是自由软件,你可免费使用,未经许可不能去掉RhaPHP相关版权
// +----------------------------------------------------------------------
// | Author: Geeson <qimengkeji@vip.qq.com>
// +----------------------------------------------------------------------

namespace app\common\controller;


use app\common\model\Miniapp;
use app\common\model\MiniappUser;
use think\Controller;
use think\facade\Request;
use think\facade\Session;

class MiniappAddon extends Controller
{
    public $_mid;
    public $miniappInfo;//小程序信息
    public $adminLogin = false;//为 TRUE 需要管理登录，一般后台管理应用的控制器需要设为 true
    private $addonName;//应用名称
    private $addonController;
    private $addonAction;
    public $addonInfoByDb;//应用配置已保存的信息
    public $addonInfoByFile;//应用配置Config文件信息
    public $getAaddonConfigByMp;//获取应用对应当前的公众号保存的配置信息
    public $addonRoot;//应用的根目录
    public $isCheckLogin = false;//默认 FALSE，开启之后是需要接收验证相关参数$code, $encryptedData, $iv, $rawData, $signature
    public $rd_session = '';//3rd_session,非常重要，验证请求是否合法票据，应返回到小程序本地存储缓存起来
    public $rd_session_time = 7200;//单位为S，默认2两个小时，可返回到小程序本地存储缓存起来
    public $userinfo = []; //授权时用户信息
    public $userId = '';//用户 ID

    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        if ($this->adminLogin == true) {
            if (empty(getAdmin())) {
                $this->redirect('admin/Login/index');
            }
        }
        $this->_mid = input('_mid');
        $this->miniappInfo = getMimiappInfo();
        $options['appid'] = $this->miniappInfo['appid'];
        $options['appsecret'] = $this->miniappInfo['appsecret'];
        $options['token'] = $this->miniappInfo['token'];
        $options['encodingaeskey'] = $this->miniappInfo['encodingaeskey'];
        Session::set('miniapp_options', $options);
        if ($this->miniappInfo['status'] == 0) {
            $msg = $this->miniappInfo['close_msg'] ? $this->miniappInfo['close_msg'] : '系统正在维护中！';
            ajaxMsg(0, $msg);
        }
        $addonRule = session('addonRule');
        $this->addonName = $addonRule['addon'];
        $this->addonController = $addonRule['col'];
        $this->addonAction = $addonRule['act'];
        $model = new \app\common\model\MiniappAddon();
        $this->addonInfoByFile = $model->getAddonByFile($this->addonName);//获取应用config.php的信息
        $this->addonInfoByDb = $model->getAddonByDb($this->addonName);//获取应用config.php已经保存数据中的信息
        $this->getAaddonConfigByMp = $model->getAaddonConfigByMp($this->addonName, $this->_mid);//获取应用与小程序一对一的关系config.php配置信息
        $this->addonRoot = MINIAPP_PATH . $this->addonName . '/';
        if ($this->isCheckLogin == true) {
            if (!$rd_session_value = cache($this->rd_session)) {
                /**
                 * 返回空必会要重新检查登录与信息验证。
                 *
                 */
                $data = input();
                if(!isset($data['code']) || !isset($data['encryptedData']) ||!isset($data['iv']) ||!isset($data['rawData']) ||!isset($data['signature'])){
                    exit(json_encode(['errcode' => -1, 'errmsg' => 'rd_session不存在或者失效，系统进入检查验证登录,因缺少验证登录参数导致任务停止'], JSON_UNESCAPED_UNICODE));
                }
                $result = $this->checkLogin($data['code'], $data['encryptedData'], $data['iv'], $data['rawData'], $data['signature']);
                $this->rd_session = $result['3rd_session'];
                $this->userId=$result['userinfo']['id'];
                $this->userinfo=$result['userinfo'];
                //缓存3rd_session,微信官方是建议值为 OPENID+SESSION_KEY,如果咱们要求用户信息唯一与更合法性可以再判断缓存的rd_session的值。
                cache($this->rd_session, $result['3rd_session_value'], $this->rd_session_time);
                //缓存授权时用户的信息+id(数据库)
                cache($this->rd_session . 'userinfo', $result['userinfo'], $this->rd_session_time);
            }else{
                $userinfo=cache($this->rd_session . 'userinfo');
                $this->userId=$userinfo['id'];
                $this->userinfo=$userinfo;
            }
        }
    }

    /**
     * @param Geeson RhaPHP.com
     * @param string $template
     * @param array $vars
     * @param array $replace
     * @param array $config
     * @return mixed|void
     */
    public function fetch($template = '', $vars = [], $replace = [], $config = [])
    {
        if ($template == null) {
            $template = $this->addonAction;
        }
        if ($template == 'default') {
            $template = APP_PATH . 'common/view/default.' . config('template.view_suffix');
            echo parent::fetch($template, $vars, $replace, $config); // TODO: Change the autogenerated stub
        } else {
            if (strpos($template, "@") === false) {
                $tpls = explode('/', $template);
                $count = count($tpls);
                $suffix = config('template.view_suffix');
                $isSuffix = false;
                if (count($tpl_suffix = explode('.', $tpls[$count - 1])) == 2) {
                    $isSuffix = true;
                    if ($suffix != $tpl_suffix[1]) {
                        $suffix = $tpl_suffix[1];
                    }
                    $suffixLen = strlen($suffix) + 1;
                    $template = substr($tpls[$count - 1], 0, -$suffixLen);
                }
                switch ($count) {
                    case 1:
                        $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($this->addonController) . '/' . $template . '.' . $suffix;
                        break;
                    case 2:
                        if (!empty($tpls[0]) && $isSuffix == true) {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . $template . '.' . $suffix;
                        } else {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . $tpls[1] . '.' . $suffix;
                        }
                        break;
                }
            } else {
                $template = substr($template, 1);
                $tpls = explode('/', $template);
                $count = count($tpls);
                $suffix = config('template.view_suffix');
                $isSuffix = false;
                if (count($tpl_suffix = explode('.', $tpls[$count - 1])) == 2) {
                    $isSuffix = true;
                    if ($suffix != $tpl_suffix[1]) {
                        $suffix = $tpl_suffix[1];
                    }
                    $suffixLen = strlen($suffix) + 1;
                    $template = substr($tpls[$count - 1], 0, -$suffixLen);
                }
                switch ($count) {
                    case 2:
                        if ($isSuffix == true) {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . $this->addonController . '/' . $template . '.' . $suffix;
                        } else {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . $this->addonController . '/' . $tpls[1] . '.' . $suffix;
                        }
                        break;
                    case 3:
                        if ($isSuffix == true) {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . strtolower($tpls[1]) . '/' . $template . '.' . $suffix;
                        } else {
                            $template = MINIAPP_PATH . $this->addonName . '/view/' . strtolower($tpls[0]) . '/' . strtolower($tpls[1]) . '/' . $tpls[2] . '.' . $suffix;
                        }
                        break;
                }
            }
            $config['view_path'] = MINIAPP_PATH . $this->addonName . '/view/';
            echo parent::fetch($template, $vars, $config); // TODO: Change the autogenerated stub
        }

    }

    public function assign($name, $value = '')
    {
        parent::assign($name, $value); // TODO: Change the autogenerated stub
    }

    /**
     * 检测登录，用户自动入库
     * 检测登录，按照微信官方要求，登录时序图机制
     * 成功返回后，3rd_seession为KEY,3rd_session_value为值，存在你的 SESSION中或者缓存中
     * @author geeson rhaphp.com
     * @param $code
     * @param $encryptedData
     * @param $iv
     * @param $rawData
     * @param $signature
     * @return json || array userinfo
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function checkLogin($code, $encryptedData, $iv, $rawData, $signature)
    {
        $miniprogram = getMiniProgramObj();
        if ($result = $miniprogram->checkLogin($code, $encryptedData, $iv, $rawData, $signature)) {
            array_key_case($result);
            $result['userinfo']['mpid'] = $this->_mid;
            unset($result['userinfo']['watermark']);
            $model = new MiniappUser();
            if ($user = $model->where([['openid', '=', $result['userinfo']['openid']], ['mpid', '=', $this->_mid]])->find()) {
                $result['userinfo']['id'] = $user['id'];
                $result['userinfo']['last_time'] = time();
                $model->isUpdate(true)->allowField(true)->save($result['userinfo'], ['openid' => $result['userinfo']['openid']]);
            } else {
                $result['userinfo']['create_time'] = time();
                $result['userinfo']['last_time']=time();
                $result['userinfo']['id'] = $model->allowField(true)->insertGetId($result['userinfo']);
            }
            return $result;
        } else {
            exit(json_encode(['errcode' => $miniprogram->errcode, 'errmsg' => $miniprogram->errmsg], JSON_UNESCAPED_UNICODE));
        }

    }

}