[API 寫法] QQ 登入、微信登入、Facebook、google、蘋果登入

gyp719發表於2020-02-06

簡單說明

前端 傳 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 協議》,轉載必須註明作者和本文連結

相關文章