Heim > Fragen und Antworten > Hauptteil
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.
P粉5236250802023-12-14 13:41:31
我假设您的所有应用程序都将使用此客户端服务。如果是这样,您可以继续使用单例设计模式(以停止进一步的 oauth 请求),但尝试将逻辑与提供程序的 register 方法分开。您可以在调用返回有效 access_token
的私有方法后实例化 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') ], ); }