You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

190 lines
5.2 KiB

  1. <?php
  2. namespace Kuxin\Weixin;
  3. use Kuxin\Helper\Http;
  4. use Kuxin\Helper\Url;
  5. use Kuxin\Input;
  6. /**
  7. * 网页授权
  8. * Class Auth
  9. *
  10. * 1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
  11. * 2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
  12. *
  13. * @package Weixin
  14. */
  15. class Oauth extends Weixin
  16. {
  17. public $user;
  18. protected $lastPermission;
  19. protected $authorizedUser;
  20. const API_USER = 'https://api.weixin.qq.com/sns/userinfo';
  21. const API_TOKEN_GET = 'https://api.weixin.qq.com/sns/oauth2/access_token';
  22. const API_TOKEN_REFRESH = 'https://api.weixin.qq.com/sns/oauth2/refresh_token';
  23. const API_TOKEN_VALIDATE = 'https://api.weixin.qq.com/sns/auth';
  24. const API_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize';
  25. /**
  26. * 生成outh URL
  27. *
  28. * @param string $to
  29. * @param string $scope
  30. * @param string $state
  31. *
  32. * @return string
  33. */
  34. public function url($to = null, $scope = 'snsapi_userinfo', $state = 'STATE')
  35. {
  36. $to !== null || $to = Url::current();
  37. $params = array(
  38. 'appid' => $this->appId,
  39. 'redirect_uri' => $to,
  40. 'response_type' => 'code',
  41. 'scope' => $scope,
  42. 'state' => $state,
  43. );
  44. return self::API_URL . '?' . http_build_query($params) . '#wechat_redirect';
  45. }
  46. /**
  47. * 直接跳转
  48. *
  49. * @param string $to
  50. * @param string $scope
  51. * @param string $state
  52. */
  53. public function redirect($to = null, $scope = 'snsapi_userinfo', $state = 'STATE')
  54. {
  55. header('Location:' . $this->url($to, $scope, $state));
  56. exit;
  57. }
  58. /**
  59. * 获取已授权用户
  60. *
  61. * @return mixed
  62. */
  63. public function user()
  64. {
  65. if ($this->authorizedUser
  66. || !Input::has('state', $_GET)
  67. || (!$code = Input::get('code','str')) && !Input::has('state', $_GET)
  68. ) {
  69. return $this->authorizedUser;
  70. }
  71. $permission = $this->getAccessPermission($code);
  72. if ($permission['scope'] !== 'snsapi_userinfo') {
  73. $user = ['openid' => $permission['openid']];
  74. } else {
  75. $user = $this->getUser($permission['openid'], $permission['access_token']);
  76. }
  77. return $this->authorizedUser = $user;
  78. }
  79. /**
  80. * 通过授权获取用户
  81. *
  82. * @param string $to
  83. * @param string $state
  84. * @param string $scope
  85. *
  86. * @return null
  87. */
  88. public function authorize($to = null, $scope = 'snsapi_userinfo', $state = 'STATE')
  89. {
  90. if (!Input::has('state', $_GET) && !Input::has('code', $_GET)) {
  91. $this->redirect($to, $scope, $state);
  92. }
  93. return $this->user();
  94. }
  95. /**
  96. * 检查 Access Token 是否有效
  97. *
  98. * @param string $accessToken
  99. * @param string $openId
  100. *
  101. * @return boolean
  102. */
  103. public function accessTokenIsValid($accessToken, $openId)
  104. {
  105. $params = array(
  106. 'openid' => $openId,
  107. 'access_token' => $accessToken,
  108. );
  109. try {
  110. Http::get(self::API_TOKEN_VALIDATE, $params);
  111. return true;
  112. } catch (\Exception $e) {
  113. return false;
  114. }
  115. }
  116. /**
  117. * 刷新 access_token
  118. *
  119. * @param string $refreshToken
  120. *
  121. * @return mixed
  122. */
  123. public function refresh($refreshToken)
  124. {
  125. $params = [
  126. 'appid' => $this->appId,
  127. 'grant_type' => 'refresh_token',
  128. 'refresh_token' => $refreshToken,
  129. ];
  130. $permission = $this->parseJSON(Http::get(self::API_TOKEN_REFRESH, $params));
  131. $this->lastPermission = array_merge($this->lastPermission, $permission);
  132. return $permission;
  133. }
  134. /**
  135. * 获取用户信息
  136. *
  137. * @param string $openId
  138. * @param string $accessToken
  139. *
  140. * @return array
  141. */
  142. public function getUser($openId, $accessToken)
  143. {
  144. $queries = array(
  145. 'access_token' => $accessToken,
  146. 'openid' => $openId,
  147. 'lang' => 'zh_CN',
  148. );
  149. return $this->parseJSON(Http::get(self::API_USER,$queries));
  150. }
  151. /**
  152. * 获取access token
  153. *
  154. * @param string $code
  155. *
  156. * @return string
  157. */
  158. public function getAccessPermission($code)
  159. {
  160. $params = array(
  161. 'appid' => $this->appId,
  162. 'secret' => $this->appSecret,
  163. 'code' => $code,
  164. 'grant_type' => 'authorization_code',
  165. );
  166. $res=$this->parseJSON(Http::post(self::API_TOKEN_GET.'?'.http_build_query($params)));
  167. if(isset($res['errorcode'])){
  168. trigger_error('get access_token error: '.$res['errormsg'], E_USER_ERROR);
  169. }
  170. return $this->lastPermission = $res;
  171. }
  172. }