Извлечение данных покровителя из Patreon API

#php #api #patreon

#php #API #Patreon

Вопрос:

Я разрабатываю веб-страницу с Laravel 8, и у меня возникли проблемы с получением сведений о покровителе по идентификатору из Patreon API. Вот мой пример использования.

Я добавил опцию «Войти с помощью Patreon» на свою веб-страницу, и она работает хорошо. Когда кто-то успешно входит в систему с помощью Patreon, я сохраняю его / ее идентификатор Patreon и устанавливаю токен запоминания для автоматического входа пользователя, когда он / она посетит мою страницу в следующий раз.

Первый процесс входа в систему проходит нормально. Проблема возникает, когда мой клиент посещает мою страницу в следующий раз. Потому что я хочу проверить, получил ли я какой-либо платеж, прежде чем позволить ей / ему увидеть весь контент. Вот почему мне нужно получить данные о моем покровителе из промежуточного программного обеспечения. Для этого я попытался:

  • fetch_user() возвращает данные моей учетной записи вместо зарегистрированного пользователя.
  • функция fetch_user() с токеном доступа, который возвращается из Patreon при входе пользователя в систему, возвращает несанкционированный доступ.
  • функция fetch_member_details() не работает с переданным мной идентификатором, который представляет собой целое число, например 5484646, потому что для этого требуется очень длинная строка, например 55153fds-f45fd5sfs-fds42ds, я не знаю, что это такое.
  • fetch_page_of_members_from_campaign() и fetch_member_details() вместе, чтобы получить правильный идентификатор, но для получения данных требуется время, что неприемлемо.

Итак, как это можно сделать?

Ответ №1:

https://further-reading.net/2020/06/getting-names-of-your-patreon-patrons-by-tier/

Это может быть полезно. Я считаю, что для этого не существует прямого единого API, но вы можете —

  1. Сначала извлеките данные всех кампаний / уровней
  2. А затем получение покровителей для каждой кампании / уровня

Комментарии:

1. Вопрос касается PHP, есть мысли о том, как это сделать с помощью PHP? В связанной статье вместо этого используется Python, и имена функций, похоже, не соответствуют эквивалентам PHP.

2. @LeigerGaming смотрите мой ответ.

Ответ №2:

Я хотел бы ответить на свой вопрос для тех, кому нужна помощь.

Прежде всего, я использую официальный PHP-пакет Patreon

Я создал промежуточное программное обеспечение, чтобы проверить, следует ли снова авторизовать пользователя. Чтобы предотвратить повторение одного и того же процесса каждый раз, я устанавливаю тайм-аут для таблицы users и проверяю, есть ли у него время до истечения срока действия. Если это произойдет, ничего не нужно делать. Конечно, это мой вариант использования, но без этого объяснения некоторые части кода могут показаться вам бессмысленными.

 // AppHttpMiddlewareAuthenticateMember.php


public function handle(Request $request, Closure $next)
{
    if (!Auth::check()) {
        return $next($request);
    }
    if (Carbon::parse(Auth::user()->timeout)->isFuture()) {
        return $next($request);
    }
    $this->refreshCredentials();
    return $next($request);
}
 

Если «тайм-аут» не наступит в будущем, refreshCredentials будет вызван метод. Это метод, который запускает привязку AuthGatewayContract к контейнеру сервиса.

 //  AppTraitUsers.php


public function refreshCredentials()
{
    $gateway = App::make('AppServicesAuthGatewaysContract');
    $gateway->ensureUserStillAuthenticated();
}

public function handleUserRecord($user)
{
    return User::updateOrCreate([
        'email' => $user['email']
    ], $user);
}

public function attemptToLogin($user, $remember = true)
{
    Auth::login($user, $remember);
    event(new Registered($user));
}

 

Вот как работает привязка:

 //  AppProvidersAppServiceProvider.php


public function register()
{
    $this->app->singleton(AuthGatewaysContract::class, function () {
        $routeParts = explode('/', url()->current());
        $gateway = array_pop($routeParts); // this is how I know which "Login with ..." button is clicked.
        $isGateway = Gateway::where('name', $gateway)->first();
        $gateway = $isGateway ? ucfirst($gateway) : ucfirst(Auth::user()->gateway->name);
        $class = "AppServicesAuthGateways\$gateway";
        return new $class();
    });
}
 

Итак Patreon.php сейчас шлюз активен и ensureUserStillAuthenticated может быть вызван:

 // AppServicesAuthGatewaysPatreon.php


public function ensureUserStillAuthenticated()
{
    $this->authenticate([
        'access_token' => Auth::user()->access_token,
        'refresh_token' => Auth::user()->refresh_token,
    ]);
}

private function authenticate($tokens)
{
    $patron = $this->fetchUserFromGateway($tokens);
    $user = $this->handleResponseData($patron, $tokens);
    $user = $this->handleUserRecord($user);
    return $this->attemptToLogin($user);
}

private function fetchUserFromGateway($tokens)
{
    // This is the only function that communicate with Patreon-php package.
    $api_client = new API($tokens['access_token']);
    return $api_client->fetch_user();
}

private function handleResponseData($data, $tokens)
{
    return [
        'name' => $data['data']['attributes']['full_name'],
        'email' => $data['data']['attributes']['email'],
        'password' => Hash::make(Str::random(24)),
        'role_id' => $this->assignRoleId($data),
        'payment_id' => Payment::where('name', 'patreon')->first()->id,
        'gateway_id' => Gateway::where('name', 'patreon')->first()->id,
        'access_token' => $tokens['access_token'],
        'refresh_token' => $tokens['refresh_token'],
        'timeout' => Carbon::today()->addMonth()->toDateString()
    ];
}