Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Qq Laravel Package

socialiteproviders/qq

QQ OAuth provider for Laravel Socialite, letting your app add Tencent QQ login with minimal setup. Install via Composer, configure your app ID and key, and authenticate QQ users through the familiar Socialite API.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a single-provider shim: it lets Laravel Socialite authenticate users against Tencent QQ's OAuth 2.0 ("QQ Connect") endpoints. It is a subtree split of the SocialiteProviders/Providers monorepo, so treat upstream as the source of truth.

1. Install

composer require socialiteproviders/qq

This pulls in socialiteproviders/manager (required) plus laravel/socialite.

2. Register the provider listener

In app/Providers/EventServiceProvider.php (or, in Laravel 11+, via Event::listen in a service provider):

protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        \SocialiteProviders\QQ\QQExtendSocialite::class.'@handle',
    ],
];

The concrete provider is SocialiteProviders\QQ\Provider; the QQExtendSocialite listener registers it under the driver name qq.

3. Add config

// config/services.php
'qq' => [
    'client_id'     => env('QQ_CLIENT_ID'),
    'client_secret' => env('QQ_CLIENT_SECRET'),
    'redirect'      => env('QQ_REDIRECT_URI'),
],

4. Get credentials

Create an app at https://connect.qq.com. The "App ID" is client_id; the "App Key" is client_secret. The callback domain you register must match QQ_REDIRECT_URI exactly (host at minimum — QQ is strict here).

5. First use case — a login button

Route::get('/auth/qq', fn () => Socialite::driver('qq')->redirect());

Route::get('/auth/qq/callback', function () {
    $qqUser = Socialite::driver('qq')->user();

    // $qqUser->getId()       => openid (per-app identifier)
    // $qqUser->getNickname() => nickname
    // $qqUser->getAvatar()   => figureurl_qq_2
    // $qqUser->getEmail()    => null (QQ does not expose email)
});

If you see Driver [qq] is not supported, the event listener in step 2 is missing or cached — run php artisan config:clear and php artisan event:clear.


Implementation Patterns

Standard redirect + callback controller

Keep the Socialite calls thin and push account resolution into a service/action. The typical shape:

public function redirect()
{
    return Socialite::driver('qq')->redirect();
}

public function callback(Request $request)
{
    try {
        $qq = Socialite::driver('qq')->user();
    } catch (\Throwable $e) {
        report($e);
        return redirect('/login')->withErrors('QQ login failed.');
    }

    $user = User::firstOrCreate(
        ['qq_openid' => $qq->getId()],
        ['name' => $qq->getNickname(), 'avatar' => $qq->getAvatar()]
    );

    Auth::login($user, remember: true);
    return redirect()->intended('/dashboard');
}

Store openid in its own indexed column rather than overloading email — QQ does not return an email, so email-based matching will fail.

Account linking for already-logged-in users

Because openid is a stable per-app identity, it works well as a link key. Use a separate route that requires auth middleware and attaches openid to the current user instead of logging in a fresh one.

Stateless / SPA / mobile flows

For token-based clients, use stateless(). Note the provider still performs the same server-side code exchange; you must forward the code (and state when applicable) from the client.

$qq = Socialite::driver('qq')->stateless()->user();

Requesting extra scopes

QQ scopes are comma-joined, not space-joined. The provider defaults to get_user_info. Add more only after Tencent has approved them for your app:

Socialite::driver('qq')
    ->scopes(['get_user_info', 'list_album'])
    ->redirect();

Refreshing tokens

QQ issues a refresh_token with the access token. Keep the raw token via $qq->token / $qq->refreshToken if you plan to call QQ APIs (e.g., Qzone) later. The Socialite User object exposes ->token, ->refreshToken, ->expiresIn on the manager user instance.

Multi-provider apps

The listener approach registers QQ alongside GitHub/Google etc. Keep a single OAuthController with a {provider} parameter, and map provider → identity column in a config array, rather than branching per provider inside the controller.

Testing

Socialite::shouldReceive('driver') mocks work, but for integration confidence, point QQ_CLIENT_ID/QQ_CLIENT_SECRET at a test app and assert on getRaw(). The raw payload is the single best debugging surface.


Gotchas and Tips

Read-only repository. Do not open PRs against socialiteproviders/qq; contribute to SocialiteProviders/Providers and the split is regenerated. Bug fixes you "make locally" will be overwritten on the next composer update unless you fork properly.

Release cadence is ancient. Last tagged release was 2022-07-25. The provider still works, but verify it against your Laravel/Socialite major (Laravel 11/12 need socialiteproviders/manager v3+ / Socialite 5). Pin versions deliberately and include this package in your upgrade testing.

JSONP responses. QQ's https://graph.qq.com/oauth2.0/me endpoint historically returns callback( {"client_id":"...","openid":"..."} ); rather than JSON. The provider strips the callback(...) wrapper, but if you ever call /me yourself, remember to strip it before json_decode.

openid is app-scoped, not global. The same QQ user gets a different openid for each QQ Connect app. If you need a cross-app identifier, you need the unionid via a different Tencent mechanism — this provider does not surface it. Design your schema knowing openid is only meaningful for your app.

Token endpoint returns a query string, not JSON. https://graph.qq.com/oauth2.0/token responds with access_token=...&expires_in=...&refresh_token=.... The provider parses this; don't assume json_decode when debugging with curl.

Errors can arrive with HTTP 200. QQ's get_user_info may return a 200 with ret != 0 and a msg (e.g., 100030 = app not authorized for the scope, 100016 = invalid token). The provider surfaces this by returning partial user data; guard against a missing nickname or openid and treat it as failure.

$raw = $qq->getRaw();
if (($raw['ret'] ?? 0) !== 0) {
    // log $raw['msg'], abort login
}

App review is a real gate. Unreviewed QQ apps only allow a small set of test accounts and often cannot call get_user_info. If logins succeed in the QQ sandbox but fail in production, check the app's review/publish status on connect.qq.com before blaming the package.

Redirect URI must match the registered domain. QQ validates the callback host against the app config. http vs https, www. vs apex, and trailing slashes all matter. Mismatches produce a QQ error page, not a Laravel exception.

email is always null. Do not make email required downstream; collect it separately after login if your product needs it.

Nickname encoding. QQ nicknames can contain emoji and CJK characters. Ensure the name/nickname column is utf8mb4 and that your connection charset is utf8mb4, or you will silently mangle names.

Avatar URLs are third-party CDN links. figureurl_qq_2 points at QQ's CDN and can change or expire. Download and rehost avatars on first login rather than storing the URL as canonical.

Stateless mode caveat. With stateless()->user(), the provider skips the session state check. That's correct for SPA/mobile, but it means you must enforce CSRF/state yourself in your own client.

Debugging recipe. Enable Guzzle logging on the Socialite HTTP client, or temporarily dump $qq->getRaw(). Most failures are one of: missing listener registration, services.qq not set, redirect URI mismatch, or an unapproved app — all of which appear before or in the raw payload, not in the returned User object.

Config caching. After editing config/services.php or the listener, run php artisan config:clear && php artisan cache:clear. QQ setup mistakes are frequently just stale config in bootstrap/cache.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager