123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- <?php
- namespace App\libs\wechat\auth\Gateways;
- use Illuminate\Support\Facades\Redis;
- use App\libs\helpers\Curl;
- use Illuminate\Support\Facades\DB;
- class General extends Base
- {
- private $appId;
- private $secret;
- public function __construct()
- {
- parent::__construct();
- $this->appId = $this->config['appid'];
- $this->secret = $this->config['secret'];
- }
- /**
- * @link 第一步 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
- * @desc 获取授权地址
- * @param string $scope 授权类型snsapi_base|snsapi_userinfo
- * @param string|null $redirect 授权回跳地址
- * @return string
- */
- public function authUrl(string $scope = 'snsapi_base', string $redirect = null): string
- {
- $redirect = $redirect ? $redirect : "https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
- $query = http_build_query([
- 'appid' => $this->appId,
- 'redirect_uri' => $redirect,
- 'response_type' => 'code',
- 'scope' => $scope
- ]);
- return "https://open.weixin.qq.com/connect/oauth2/authorize?{$query}#wechat_redirect";
- }
- /**
- * @link 第二步 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
- * @desc 使用授权code换取openid
- * @param string $code
- * @return array
- */
- public function code2Openid(string $code): array
- {
- $url = 'https://api.weixin.qq.com/sns/oauth2/access_token';
- $res = Curl::requestCurl($url, 'GET', [], http_build_query([
- 'appid' => $this->appId,
- 'secret' => $this->secret,
- 'code' => $code,
- 'grant_type' => 'authorization_code'
- ]));
- return $res ? json_decode($res, true) : [];
- }
- /**
- * @link 第四步 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
- * @desc 获取用户信息
- * @param string $accessToken
- * @param string $openid
- * @return bool|mixed|string
- */
- public function userSimpleInfo(string $accessToken, string $openid): array
- {
- $url = 'https://api.weixin.qq.com/sns/userinfo';
- $res = Curl::requestCurl($url, 'GET', [], http_build_query([
- 'access_token' => $accessToken,
- 'openid' => $openid,
- 'lang' => 'zh_CN',
- ]));
- return $res ? json_decode($res, true) : [];
- }
- /**
- * @link https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
- * @desc 获取用户详细信息
- * @param string $openid
- * @return array
- */
- public function userDetailInfo(string $openid): array
- {
- $url = 'https://api.weixin.qq.com/cgi-bin/user/info';
- $res = Curl::requestCurl($url, 'GET', [], http_build_query([
- 'access_token' => $this->accessToken(),
- 'openid' => $openid,
- 'lang' => 'zh_CN',
- ]));
- return $res ? json_decode($res, true) : [];
- }
- /**
- * @link 附录1-JS-SDK使用权限签名算法 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
- * @desc 获取 JSAPI TICKET
- * @param int $repeatCnt
- * @return string
- */
- public function jsApiTicket(&$repeatCnt = 1): string
- {
- $drive = $this->config['token_drive'] ?? 'redis';
- $key = 'wechat_' . $this->appId . '_jsApiTicket';
- switch ($drive) {
- case 'redis':
- $redis = Redis::instance();
- $redis->select(15);
- $ticket = $redis->get($key);
- break;
- case 'db':
- default:
- $ticket = Db::table('configs')->where('c_key', $key)->where('c_expired > ' . time())->value('c_value');
- break;
- }
- if ($ticket) {
- return $ticket;
- }
- $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';
- $res = Curl::requestCurl($url, 'GET', [], http_build_query([
- 'access_token' => $this->accessToken(),
- 'type' => 'jsapi'
- ]));
- $data = json_decode($res, true);
- if (isset($data['ticket'])) {
- $ticket = $data['ticket'];
- switch ($drive) {
- case 'redis':
- $redis->setex($key, 7000, $ticket);
- break;
- case 'db':
- default:
- Db::table('configs')
- ->where('c_key', $key)
- ->update([
- 'c_value' => $ticket,
- 'c_expired' => time() + 7000,
- 'c_updated' => date('Y-m-d H:i:s')
- ]);
- break;
- }
- return $ticket;
- } else {
- if ($repeatCnt <= 3) {
- $repeatCnt++;
- return $this->jsApiTicket($repeatCnt);
- } else {
- return $data['errcode'];
- }
- }
- }
- /**
- * @link https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
- * @desc 获取全局唯一接口调用凭据
- * @param int $repeatCnt
- * @return string
- */
- public function accessToken(&$repeatCnt = 1)
- {
- $drive = $this->config['token_drive'] ?? 'redis';
- $key = 'wechat_' . $this->appId . '_accessToken';
- switch ($drive) {
- case 'redis':
- $redis = Redis::instance();
- $redis->select(15);
- $token = $redis->get($key);
- break;
- case 'db':
- default:
- $token = Db::table('configs')->where('c_key',$key)->where('c_expired',' > ',time())->value('c_value');
- break;
- }
- if ($token) {
- return $token;
- }
- $url = 'https://api.weixin.qq.com/cgi-bin/token';
- $res = Curl::requestCurl($url, 'GET', [], http_build_query([
- 'grant_type' => 'client_credential',
- 'appid' => $this->appId,
- 'secret' => $this->secret
- ]));
- $data = json_decode($res, true);
- if (isset($data['access_token'])) {
- $token = $data['access_token'];
- switch ($drive) {
- case 'redis':
- $redis->setex($key, 7000, $token);
- break;
- case 'db':
- default:
- Db::table('configs')
- ->where('c_key', $key)
- ->update([
- 'c_value' => $token,
- 'c_expired' => time() + 7000,
- 'c_updated' => date('Y-m-d H:i:s')
- ]);
- break;
- }
- return $token;
- } else {
- if ($repeatCnt <= 3) {
- $repeatCnt++;
- return $this->accessToken($repeatCnt);
- } else {
- return $data['errcode'];
- }
- }
- }
- }
|