amocrm / amocrm-api-php

Библиотека на PHP для работы с API amoCRM
MIT License
150 stars 108 forks source link

Uncaught TypeError: {closure}(): Argument #1 ($accessToken) must be of type AccessTokenInterface, League\OAuth2\Client\Token\AccessToken given, called in #473

Open sezerkaratas opened 2 years ago

sezerkaratas commented 2 years ago

Uncaught TypeError: {closure}(): Argument #1 ($accessToken) must be of type AccessTokenInterface, League\OAuth2\Client\Token\AccessToken given, called in

Sometimes I get such an error and I couldn't understand why. Could you help

sezerkaratas commented 2 years ago

please help me

sezerkaratas commented 2 years ago

function (AccessTokenInterface $accessToken, string $baseDomain) {

I am getting the error on this line 😕

eugene-borovov commented 2 years ago

It seems like you get thephpleague/oauth2-client prior 2.4.0 version but this library requires >=2.6.0. In this version AccessToken do not implement AccessTokenInterface. Maybe you should debug your setup first? I do not think this is the library issue.

sezerkaratas commented 2 years ago

ı check but version 2.6.1

eugene-borovov commented 2 years ago

I supose you use AmoCRMApiClientFactory. You may create your own factory with AccessToken typehint. I believe this resolve your problem.

sezerkaratas commented 2 years ago

Last question 😊

my code is

$apiClient = new \AmoCRM\Client\AmoCRMApiClient($clientId, $clientSecret, $redirectUri); $apiClient->setAccessToken($accessToken) ->setAccountBaseDomain($accessToken->getValues()['baseDomain']) ->onAccessTokenRefresh( function (\League\OAuth2\Client\Token\AccessTokenInterface $accessToken, string $baseDomain) { saveToken( [ 'accessToken' => $accessToken->getToken(), 'refreshToken' => $accessToken->getRefreshToken(), 'expires' => $accessToken->getExpires(), 'baseDomain' => $baseDomain, ] ); }); $leadsService = $apiClient->leads();

It looks like this

You mean should I change it like this?

$apiClientFactory = new \AmoCRM\Client\AmoCRMApiClientFactory($oAuthConfig, $oAuthService); $apiClient = $apiClientFactory->make();

$apiClient->setAccessToken($accessToken) ->setAccountBaseDomain($accessToken->getValues()['baseDomain']) ->onAccessTokenRefresh( function (\League\OAuth2\Client\Token\AccessTokenInterface $accessToken, string $baseDomain) { saveToken( [ 'accessToken' => $accessToken->getToken(), 'refreshToken' => $accessToken->getRefreshToken(), 'expires' => $accessToken->getExpires(), 'baseDomain' => $baseDomain, ] ); });

eugene-borovov commented 2 years ago

No, I didn`t. The factory do the same thing. In case you use your own set up code you free to change type. But we did not find the cause of the issue :-)

Factory example PHP 8.0 and anonymous classes:

$clientId = '****';
$clientSecret = '****';
$redirectUri = '****';
$baseDomain = '****';
$tokenPath = '/path/to/token';

$apiClient = (new \AmoCRM\Client\AmoCRMApiClientFactory(
    new class($clientId, $clientSecret, $redirectUri) implements \AmoCRM\OAuth\OAuthConfigInterface {
        public function __construct(
            private string $integrationId,
            private string $secretKey,
            private string $redirectDomain,
        ) {
        }

        public function getIntegrationId(): string
        {
            return $this->integrationId;
        }

        public function getSecretKey(): string
        {
            return $this->secretKey;
        }

        public function getRedirectDomain(): string
        {
            return $this->redirectDomain;
        }
    },
    new class($tokenPath) implements \AmoCRM\OAuth\OAuthServiceInterface {

        public function __construct(
            private string $tokenPath,
        ) {
        }

        public function saveOAuthToken(\League\OAuth2\Client\Token\AccessTokenInterface $accessToken, string $baseDomain): void
        {
            if (isset(
                $accessToken['accessToken'], $accessToken['refreshToken'],
                $accessToken['expires'], $accessToken['baseDomain']
            )) {
                $data = [
                    'accessToken' => $accessToken['accessToken'],
                    'expires' => $accessToken['expires'],
                    'refreshToken' => $accessToken['refreshToken'],
                    'baseDomain' => $accessToken['baseDomain'],
                ];

                file_put_contents($this->tokenPath, json_encode($data));
            } else {
                exit('Invalid access token ' . var_export($accessToken, true));
            }
        }
    }

))->make();
$apiClient->setAccountBaseDomain($baseDomain);

$leadsService = $apiClient->leads();