Cái này mất của mình gần như 1 buổi để tìm ra 1 số troubles và hướng giải quyết.
Thứ nhất phải làm rõ là Socialite về bản chất nó đóng vai trò như Authenticate ! Và chỉ là Authenticate. Nó không phải là OAuth client thuần tuý ! Do đó không thể dùng nó ( native ) để request OAuth endpoint.
How to use Socialite ( Flickr )
Ok. Về cơ bản có thể ref document link sau
https://socialiteproviders.netlify.com/providers/flickr.html
Tuy nhiên sẽ cần có 1 note nhẹ. File config/session.php cần có update dưới nếu không sẽ gặp issue vui lắm.
'same_site' => null,
Ref
https://github.com/laravel/framework/issues/8390
Xem như xong phần này thì đã có được Access token & Access token secret.
Phần còn lại là dùng 2 cái này để request tới OAuth endpoint. Ở đây mình dùng GuzzleHttp.
<?php /** * Copyright (c) 2020 JOOservices Ltd * @author Viet Vu <jooservices@gmail.com> * @package XGallery * @license GPL * @license http://opensource.org/licenses/gpl-license.php GNU Public License */ namespace App\OAuth; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Subscriber\Oauth\Oauth1; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; class OauthClient { /** * @param string $method * @param string $uri * @param array $parameters * @return string|object */ public function request(string $method, string $uri, array $parameters = []) { $id = md5(serialize([$method, $uri, $parameters])); Log::stack(['oauth'])->info( Cache::has($id) ? 'Requesting '.$uri.' with CACHE' : 'Requesting '.$uri, [$method, $uri, $parameters] ); if (Cache::has($id)) { return Cache::get($id); } $client = $this->getClient(); $response = $client->request($method, $uri, $parameters); if ($response->getStatusCode() !== 200) { return null; } /** * @TODO Support decode content via event */ $header = $response->getHeader('Content-Type')[0] ?? ''; $content = (string) $response->getBody(); if (strpos($header, 'application/json') === false) { return $content; } $content = json_decode($content); Cache::put($id, $content, 3600); return Cache::get($id); } protected function getClient(): Client { $stack = HandlerStack::create(); $middleware = new Oauth1([ 'consumer_key' => env('FLICKR_KEY'), 'consumer_secret' => env('FLICKR_SECRET'), 'token' => env('FLICKR_ACCESS_TOKEN'), 'token_secret' => env('FLICKR_ACCESS_TOKEN_SECRET'), ]); $stack->push($middleware); return new Client(['handler' => $stack, 'auth' => 'oauth']); } }
- Sử dụng handler & stacker để sign OAuth
- Cache & Log thì không có gì để nói
Phần còn lại là request thôi
const REST_ENDPOINT = 'https://api.flickr.com/services/rest'; /** * @param string $method * @param array $parameters * @return object|null */ public function get(string $method, array $parameters = []): ?object { $content = $this->request( 'GET', static::REST_ENDPOINT, [ 'query' => array_merge( ['method' => 'flickr.'.$method], $this->getDefaultFlickrParameters(), $parameters ) ] ); if ($content->stat !== 'ok') { return null; } return $content; }
Xem như xong basic concept.
Thực tế sử dụng trong Command
public function handle() { $flickr = app(Flickr::class); if (!$contacts = $flickr->get('contacts.getList')) { return; } for ($page = 1; $page <= $contacts->contacts->pages; $page++) { \App\Jobs\FlickrContacts::dispatch($page)->onConnection('database'); } }
Do bản chất flickr method đều có prefix là “flickr.” do đó mình bỏ nó đi, đưa vào client class cho tiện. Khỏi mất công type.
Leave a Reply