Also entwickle ich eine Laravel-Administratoranwendung, die eine externe API verwendet, nennen wir sie PlatformAPI. Die Funktionsweise der Plattform besteht darin, dass Benutzer meiner App ein Konto auf der Plattform haben. Meine Laravel-Anwendung fungiert als Admin-Dashboard, sodass Benutzer einige grundlegende Berichte anzeigen k?nnen, die sie von der PlatformAPI erhalten haben.
Jeder Benutzer meiner App muss seine Kunden-ID und sein Kundengeheimnis hinzufügen, die er auf der Plattform erstellen kann. Auf diese Weise kann meine Anwendung in ihrem Namen unter Verwendung der Anmeldeinformationen des Benutzers Anfragen an die PlatformAPI ausführen.
Ich habe einige Artikel und Tutorials gelesen, die im Wesentlichen beschreiben, wie man Anmeldeinformationen/Tokens für einen Dienst einrichtet und diesen Dienst wie folgt an einen ServiceProvider bindet:
<?php namespace AppServicesPlatformAPI; class Client { protected string $clientId; protected string $clientSecret; public function __construct(string $clientId, string $clientSecret) { $this->clientId = $clientId; $this->clientSecret = $clientSecret; } public function getSales(string $month) { // ... } } <?php use AppServicesPlatformApiClient; class PlatformApiServiceProvider extends ServiceProvider { public function register() { $this->app->singleton(Client::class, function ($app) { return new Client( clientId: config('services.platform-api.client-id'), clientSecret: config('services.platform-api.client-secret'), ); }); } }
Auf diese Weise müssen Sie die Client-Anmeldeinformationen nicht jedes Mal festlegen, wenn Sie die PlatformApi verwenden m?chten. Ich kann den Dienst einfach so aufrufen:
<?php namespace AppHttpControllers; use AppServicesPlatformApiClient; class RandomController extends Controller { protected Client $client; public function __construct(Client $client) { $this->client = $client; } public function index() { $this->client->getSales(string $month); } }
Da ich jedoch im Namen des Benutzers meiner App Anfragen an die PlatformApi mit den von ihm bereitgestellten (und in der Datenbank meiner App gespeicherten) Anmeldeinformationen ausführen muss, bin ich mir nicht sicher, ob dieser gleiche Ansatz wie der Singleton funktioniert nur einmal instanziiert werden?
Au?erdem ben?tige ich zur Nutzung der PlatformApi ein Zugriffstoken mit den Anmeldeinformationen des Benutzers. Dieses Zugriffstoken muss auch irgendwo gespeichert werden (im Cache, vermute ich).
Ich bin etwas ratlos, wie ich das beheben kann. Für Hinweise w?re ich sehr dankbar.
我假設(shè)您的所有應(yīng)用程序都將使用此客戶端服務(wù)。如果是這樣,您可以繼續(xù)使用單例設(shè)計模式(以停止進(jìn)一步的 oauth 請求),但嘗試將邏輯與提供程序的 register 方法分開。您可以在調(diào)用返回有效 access_token
的私有方法后實(shí)例化 Client 類(如果存在有效令牌,則檢查 DB
/ Cache
expires_in
時間戳值并返回它,或者向用戶請求一個新的client
/secret
并返回它)
/** * Register any application services. * * @return void */ public function register(): void { $this->app->singleton(Client::class, function () { return new Client( accessToken: $this->getUserToken()->access_token ); }); } /** * Tries to get the user token from the database. * * @return ClientCredentials */ private function getUserToken(): ClientCredentials { $credentials = ClientCredentials::query() ->latest() ->find(id: auth()->user()->id); if ($credentials === null || now() > $credentials->expires_at) { $credentials = $this->requestUserToken(); } return $credentials; } /** * Requests a new token for the user & stores it in the database. * * @return ClientCredentials */ private function requestUserToken(): ClientCredentials { $tokenResponse = API::requestToken( client: auth()->user()->client, secret: auth()->user()->secret, ); return ClientCredentials::query()->create( attributes: [ 'user_id' => auth()->user()->id, 'access_token' => $tokenResponse['access_token'], 'refresh_token' => $tokenResponse['refresh_token'], 'token_type' => 'Bearer', 'expires_at' => new DateTime(datetime: '+' . $tokenResponse['expires_in'] . ' seconds') ], ); }