<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace User\Service\Common\AppLogin;

use Admin\Data\Common;
use Laminas\Json\Json;
use Laminas\Session\Container;

class WechatLogin
{
    const GET_ACCESS_TOKEN_URL  = "https://api.weixin.qq.com/sns/oauth2/access_token";
    const GET_USERINFO_URL      = "https://api.weixin.qq.com/sns/userinfo";
    const GET_AUTH_CODE_URL     = "https://open.weixin.qq.com/connect/oauth2/authorize";

    public $redirectUri;

    private $customerConfig = [];
    private $loginSession;

    public function __construct()
    {
        $this->customerConfig   = Common::readConfigFile('customer');
        $this->loginSession     = new Container('wechatSession');
    }

    public function toLogin()
    {
        $loginKey = [
            'appid'         => $this->customerConfig['weixin_app_id'],
            'redirect_uri'  => $this->redirectUri,
            'response_type' => 'code',
            'scope'         => 'snsapi_userinfo',
            'state'         => md5(uniqid(rand(), TRUE))
        ];

        $this->loginSession->offsetSet('wechatState', $loginKey['state']);

        header("Location: ".$this->combineUrl(self::GET_AUTH_CODE_URL, $loginKey).'#wechat_redirect');
        exit();
    }

    /**
     * 跳转返回处理
     */
    public function loginCallBock()
    {
        if ($this->loginSession->offsetGet('wechatState') != $_GET['state']) {
            exit('<h2>The state does not match. You may be a victim of CSRF.</h2>');
        }

        $loginKey = [
            'grant_type'    => 'authorization_code',
            'appid'         => $this->customerConfig['weixin_app_id'],
            'secret'        => $this->customerConfig['weixin_app_key'],
            'code'          => $_GET['code']
        ];

        $response = Common::httpGet($this->combineUrl(self::GET_ACCESS_TOKEN_URL, $loginKey));
        if (strpos($response, "access_token") !== false) {
            $result = Json::decode($response);
            if (isset($result->errcode)) {
                exit('error:' . $result->errcode . 'error:' . $result->errmsg);
            }

            $this->loginSession->offsetSet('wechatAccessToken', $result->access_token);
            $this->loginSession->offsetSet('wechatOpenId',  $result->openid);
        }
    }

    /**
     * openId
     * @return mixed|null
     */
    public function openId()
    {
        return $this->loginSession->offsetGet('wechatOpenId');
    }

    /**
     * unionId
     * @return mixed|null
     */
    public function unionId()
    {
        $infoKey = [
            'access_token'  => $this->loginSession->offsetGet('wechatAccessToken'),
            'openid'        => $this->loginSession->offsetGet('wechatOpenId')
        ];

        $responseArray = Json::decode(Common::httpGet($this->combineUrl(self::GET_USERINFO_URL, $infoKey)), Json::TYPE_ARRAY);

        //检查返回ret判断api是否成功调用
        if(isset($responseArray['openid']) and !empty($responseArray['openid'])){
            return isset($responseArray['unionid']) ? $responseArray['unionid'] : '';
        }else{
            exit('error:' . $responseArray['errcode'] . 'error:' . $responseArray['errmsg']);
        }
    }

    /**
     * 账户信息
     * @return mixed
     */
    public function loginUserInfo()
    {
        $infoKey = [
            'access_token'  => $this->loginSession->offsetGet('wechatAccessToken'),
            'openid'        => $this->loginSession->offsetGet('wechatOpenId')
        ];

        $responseArray = Json::decode(Common::httpGet($this->combineUrl(self::GET_USERINFO_URL, $infoKey)), Json::TYPE_ARRAY);

        if(isset($responseArray['openid']) and !empty($responseArray['openid'])){
            return $responseArray;
        }else{
            exit('error:' . $responseArray['errcode'] . 'error:' . $responseArray['errmsg']);
        }
    }

    /**
     * 清除使用过的session
     */
    public function clearOtherLoginSession()
    {
        $this->loginSession->getManager()->getStorage()->clear($this->loginSession->getName());
    }

    /**
     * 拼接Url
     * @param $baseUrl
     * @param $keyArray
     * @return string
     */
    private function combineUrl($baseUrl, $keyArray)
    {
        return $baseUrl . '?' . Common::toUrlParams($keyArray);
    }
}