| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 | <?phpnamespace 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:                $isWin = Db::table('configs')->where('c_key',$key)->value('c_value');                if ($isWin){                    Db::table('configs')                        ->where('c_key', $key)                        ->update([                            'c_value'   => $token,                            'c_expired' => time() + 7000,                            'c_updated' => date('Y-m-d H:i:s')                        ]);                }else{                    Db::table('configs')                        ->insert([                            'c_key'     => $key,                            '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'];            }        }    }}
 |