<?php
namespace Yurun\OAuthLogin\Weixin;
use Yurun\OAuthLogin\Base;
use Yurun\OAuthLogin\ApiException;
class OAuth2 extends Base
{
const API_DOMAIN = 'https://api.weixin.qq.com/';
const OPEN_DOMAIN = 'https://open.weixin.qq.com/';
public $lang = 'zh_CN';
public $openidMode = OpenidMode::OPEN_ID;
public function getUrl($name, $params = array())
{
if('http' === substr($name, 0, 4))
{
$domain = $name;
}
else
{
$domain = static::API_DOMAIN . $name;
}
return $domain . (empty($params) ? '' : ('?' . $this->http_build_query($params)));
}
public function getAuthUrl($callbackUrl = null, $state = null, $scope = null)
{
$option = array(
'appid' => $this->appid,
'redirect_uri' => null === $callbackUrl ? (null === $this->callbackUrl ? (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') : $this->callbackUrl) : $callbackUrl,
'response_type' => 'code',
'scope' => null === $scope ? (null === $this->scope ? 'snsapi_login' : $this->scope) : $scope,
'state' => $this->getState($state),
);
if(null === $this->loginAgentUrl)
{
return $this->getUrl(static::OPEN_DOMAIN . 'connect/qrconnect', $option) . '#wechat_redirect';
}
else
{
return $this->loginAgentUrl . '?' . $this->http_build_query($option);
}
}
public function getWeixinAuthUrl($callbackUrl = null, $state = null, $scope = null)
{
$option = array(
'appid' => $this->appid,
'redirect_uri' => null === $callbackUrl ? (null === $this->callbackUrl ? (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') : $this->callbackUrl) : $callbackUrl,
'response_type' => 'code',
'scope' => null === $scope ? (null === $this->scope ? 'snsapi_userinfo' : $this->scope) : $scope,
'state' => $this->getState($state),
);
if(null === $this->loginAgentUrl)
{
return $this->getUrl(static::OPEN_DOMAIN . 'connect/oauth2/authorize', $option) . '#wechat_redirect';
}
else
{
$option['isMp'] = 1;
return $this->loginAgentUrl . '?' . $this->http_build_query($option);
}
}
protected function __getAccessToken($storeState, $code = null, $state = null)
{
$this->result = $this->http->get($this->getUrl('sns/oauth2/access_token', array(
'appid' => $this->appid,
'secret' => $this->appSecret,
'code' => isset($code) ? $code : (isset($_GET['code']) ? $_GET['code'] : ''),
'grant_type' => 'authorization_code',
)))->json(true);
if(isset($this->result['errcode']) && 0 != $this->result['errcode'])
{
throw new ApiException($this->result['errmsg'], $this->result['errcode']);
}
else
{
switch((int)$this->openidMode)
{
case OpenidMode::OPEN_ID:
$this->openid = $this->result['openid'];
break;
case OpenidMode::UNION_ID:
$this->openid = $this->result['unionid'];
break;
case OpenidMode::UNION_ID_FIRST:
$this->openid = empty($this->result['unionid']) ? $this->result['openid'] : $this->result['unionid'];
break;
}
return $this->accessToken = $this->result['access_token'];
}
}
public function getUserInfo($accessToken = null)
{
$this->result = $this->http->get($this->getUrl('sns/userinfo', array(
'access_token' => null === $accessToken ? $this->accessToken : $accessToken,
'openid' => $this->openid,
'lang' => $this->lang,
)))->json(true);
if(isset($this->result['errcode']) && 0 != $this->result['errcode'])
{
throw new ApiException($this->result['errmsg'], $this->result['errcode']);
}
else
{
return $this->result;
}
}
public function refreshToken($refreshToken)
{
$this->result = $this->http->get($this->getUrl('sns/oauth2/refresh_token', array(
'appid' => $this->appid,
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
)))->json(true);
return isset($this->result['errcode']) && 0 == $this->result['errcode'];
}
public function validateAccessToken($accessToken = null)
{
$this->result = $this->http->get($this->getUrl('sns/auth', array(
'access_token' => null === $accessToken ? $this->accessToken : $accessToken,
'openid' => $this->openid,
)))->json(true);
return isset($this->result['errcode']) && 0 == $this->result['errcode'];
}
public function getSessionKey($jsCode)
{
$this->result = $this->http->get($this->getUrl('sns/jscode2session', array(
'appid' => $this->appid,
'secret' => $this->appSecret,
'js_code' => $jsCode,
'grant_type'=> 'authorization_code',
)))->json(true);
if(isset($this->result['errcode']) && 0 != $this->result['errcode'])
{
throw new ApiException($this->result['errmsg'], $this->result['errcode']);
}
else
{
switch((int)$this->openidMode)
{
case OpenidMode::OPEN_ID:
$this->openid = $this->result['openid'];
break;
case OpenidMode::UNION_ID:
$this->openid = $this->result['unionid'];
break;
case OpenidMode::UNION_ID_FIRST:
$this->openid = empty($this->result['unionid']) ? $this->result['openid'] : $this->result['unionid'];
break;
}
}
return $this->result['session_key'];
}
public function descryptData($encryptedData, $iv, $sessionKey)
{
if (strlen($sessionKey) != 24)
{
throw new \InvalidArgumentException('sessionKey 格式错误');
}
if (strlen($iv) != 24)
{
throw new \InvalidArgumentException('iv 格式错误');
}
$aesKey = base64_decode($sessionKey);
$aesIV = base64_decode($iv);
$aesCipher = base64_decode($encryptedData);
$result = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, 1, $aesIV);
$dataObj = json_decode($result, true);
if (!$dataObj)
{
throw new \InvalidArgumentException('反序列化数据失败');
}
return $dataObj;
}
}