[API 写法] QQ 登录、微信登录、Facebook、google、苹果登录

简单说明

前端 传 code 参数 ,都可以

weixin 传 code 或者 access_token

apple 传 id_token 或 access_token

EventServiceProvider

protected $listen = [

 \SocialiteProviders\Manager\SocialiteWasCalled::class => [
      'SocialiteProviders\QQ\QqExtendSocialite@handle', // QQ登录
      'SocialiteProviders\Weixin\WeixinExtendSocialite@handle', // 微信登录
  ],
];

AuthorizationsController 实例代码

<?php
namespace App\Http\Controllers\Api;
use App\Models\User;
use Faker\Generator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
class AuthorizationsController extends Controller {
    public function socialStore($type, Request $request) {
        if (!in_array($type, ['weixin', 'qq', 'facebook', 'google', 'apple'])) {
            return $this->failed('请求方式错误');
        }
        if (in_array($type, ['weixin', 'qq', 'facebook', 'google', ])) {
            $driver = Socialite::driver($type);
            try {
                if ($code = $request->code) {
                    $response = $driver->getAccessTokenResponse($code);
                    $token = array_get($response, 'access_token');
                } else {
                    $token = $request->access_token;
                    if ($type == 'weixin') {
                        $driver->setOpenId($request->openid);
                    }
                }
                $oauthUser = $driver->userFromToken($token);
            }
            catch(\Exception $e) {
                return $this->failed('参数错误,未获取用户信息');
            }
        } else {
            // apple 登录
            try {
                if ($code = $request->code) {
                    $response = http('https://appleid.apple.com/auth/token', [
                        'grant_type' => 'authorization_code',
                        'code' => $code, 
                        'redirect_uri' => config('services.apple.redirect') , 
                        'client_id' => config('services.apple.client_id') ,
                        'client_secret' => config('services.apple.client_secret') , 
                    ]);
                    $id_token = $response->id_token;
                } else {
                    $id_token = $request->access_token;
                }
                $oauthUser = json_decode(base64_decode(explode('.', $id_token) [1]));
            }
            catch(\Exception $e) {
                return $this->failed('apple 参数错误');
            }
        }
        $user = null;
        switch ($type) {
            case 'qq':
                $user = User::query()->where('open_id', $oauthUser->getId())->first();
                // 没有用户,默认创建一个用户
                if (!$user) {
                    $user = User::create([
                        'type' => User::TYPE_QQ,
                        'nickname' => $oauthUser->getNickname() ,
                        'avatar' => $oauthUser->getAvatar() ,
                        'open_id' => $oauthUser->getId() , 
                    ]);
                }
                break;

            case 'weixin':
                $user = User::query()->where('open_id', $oauthUser->getId())->first();
                // 没有用户,默认创建一个用户
                if (!$user) {
                    $user = User::create([
                        'type' => User::TYPE_WECHAT,
                        'nickname' => $oauthUser->getNickname() ,
                        'avatar' => $oauthUser->getAvatar() ,
                        'open_id' => $oauthUser->getId() ,
                        'sex' => $oauthUser['sex'] == 1 ? '男' : '女', 
                    ]);
                }
                break;

            case 'facebook':
                $user = User::query()->where('open_id', $oauthUser->getId())->first();
                // 没有用户,默认创建一个用户
                if (!$user) {
                    $user = User::create([
                    'type' => User::TYPE_FACEBOOK,
                    'nickname' => $oauthUser->getName() , 
                    'avatar' => $oauthUser->getAvatar() , 
                    'open_id' => $oauthUser->getId() ,
                    ]);
                }
                break;

            case 'google':
                $user = User::query()->where('open_id', $oauthUser->getId())->first();
                // 没有用户,默认创建一个用户
                if (!$user) {
                    $user = User::create([
                        'type' => User::TYPE_GOOGLE, 
                        'nickname' => $oauthUser->getName() , 
                        'avatar' => $oauthUser->getAvatar() ,
                        'open_id' => $oauthUser->getId() , 
                    ]);
                }
                break;

            case 'apple':
                $user = User::query()->where('open_id', $oauthUser->sub)->first();
                // 没有用户,默认创建一个用户  Faker\Generator::class
                $faker = app(Generator::class);
                if (!$user) {
                    $user = User::create([
                        'type' => User::TYPE_APPLE, 
                        'nickname' => array_key_exists('email', $oauthUser) ? $oauthUser->email : $faker->unique()->safeEmail, 
                        'open_id' => $oauthUser->sub,
                    ]);
                }
                break;
            }
            $token = Auth::guard('api')->setTTL(60 * 24 * 365)->fromUser($user);
            return $this->respondWithToken($token)->setStatusCode(201);
    }
    protected function respondWithToken($token) {
        return $this->success([
        'access_token' => 'Bearer ' . $token,
        'expires_in' => Auth::guard('api')->factory()->getTTL() ,
        ]);
    }
}

apple 登录的 http 方法

function http($url, $params = false)
{
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  if ($params) {
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
 }  curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'Accept: application/json',
  'User-Agent: curl', # Apple requires a user agent header at the token endpoint
  ]);
  $response = curl_exec($ch);
  return json_decode($response);
}

路由

Route::post('socials/{social_type}/authorizations', 'AuthorizationsController@socialStore')->name('api.socials.authorizations.store'); // 第三方登录
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 7

socialStore 方法可以考虑再优化下

6个月前 评论

很实用...

5个月前 评论

不用composer加载吗

3个月前 评论

干嘛不用, 驱动方式写呢?

3个月前 评论

手艺良多 感谢分享!

2个月前 评论

您好 为啥我用不了啊
Target [Laravel\Socialite\Contracts\Factory] is not instantiable.

1周前 评论

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!