【问题标题】:Quickbooks PHP API: Refresh OAuth 2 Token FailedQuickbooks PHP API:刷新 OAuth 2 令牌失败
【发布时间】:2020-01-02 18:42:49
【问题描述】:

我正在尝试使用 PHP SDK 访问 Quickbooks API,但出现以下错误:

使用刷新令牌刷新 OAuth 2 访问令牌失败。正文:[{"error":"invalid_grant"}]。

我的令牌似乎可以工作 24 小时,但之后我收到上述错误。每次调用 API 时,我都会将更新的令牌保存到我的数据库中:

//Client ID & Secret
$qbClientId = $this->scopeConfig->getValue('quickbooks/api/qb_client_id', $storeScope);
$qbClientSecret = $this->scopeConfig->getValue('quickbooks/api/qb_client_secret', $storeScope);

//Retrieve currently saved Refresh_Token from DB
$qbRefreshToken = $this->scopeConfig->getValue('quickbooks/api/qb_refresh_token', $storeScope);

$OAuth2LoginHelper = new OAuth2LoginHelper($qbClientId, $qbClientSecret);
$accessTokenObj = $OAuth2LoginHelper->refreshAccessTokenWithRefreshToken($qbRefreshToken);

$error = $OAuth2LoginHelper->getLastError();

if($error) {
  throw new \Exception($error);
} else {
  // The refresh token and access token expiration
  $refreshTokenValue = $accessTokenObj->getRefreshToken();
  $refreshTokenExpiry = $accessTokenObj->getRefreshTokenExpiresAt();

  // Save new Refresh Token & Expiry to DB
  $this->configInterface->saveConfig('quickbooks/api/qb_refresh_token', $this->encryptor->encrypt($refreshTokenValue), 'default', 0);
  $this->configInterface->saveConfig('quickbooks/api/qb_refresh_token_expiry', $refreshTokenExpiry, 'default', 0);

  // The access token and access token expiration
  $accessTokenValue = $accessTokenObj->getAccessToken();
  $accessTokenExpiry = $accessTokenObj->getAccessTokenExpiresAt();

  // Save new Access Token & Expiry to DB
  $this->configInterface->saveConfig('quickbooks/api/qb_access_token', $this->encryptor->encrypt($accessTokenValue), 'default', 0);
  $this->configInterface->saveConfig('quickbooks/api/qb_access_token_expiry', $accessTokenExpiry, 'default', 0);

  return DataService::Configure(array(
    'auth_mode' => 'oauth2',
    'ClientID' => $qbClientId,
    'ClientSecret' => $qbClientSecret,
    'accessTokenKey' => $accessTokenValue,
    'refreshTokenKey' => $refreshTokenValue,
    'QBORealmID' => 'MyRealmID',
    'baseUrl' => 'Development'
  ));
}

如您所见,在每次 API 调用中,我都使用 refreshAccessTokenWithRefreshToken($qbRefreshToken) 方法获取新的刷新和访问令牌并将它们保存到我的数据库以供下次使用,但是 24 小时后我仍然收到 invalid_grant 错误。

有什么想法吗?

【问题讨论】:

    标签: php oauth-2.0 quickbooks-online


    【解决方案1】:

    我也遇到过同样的问题。就我而言,我已经更新了数据库中的令牌,但没有更新内存中的 everywhere(特别是在 $dataService 对象中)。因此,继续使用 $dataService 对象进行 API 调用就是使用旧令牌。哦!

    虽然我认为它仍然可以工作,但您不需要在每次 API 调用时都刷新令牌(正如 David 指出的那样)。我的解决方案是进行 API 调用,如果失败,我会刷新令牌并再次进行 API 调用。这是我的代码的简化版本:

    $user        = ...; // get from database
    $dataService = getDataServiceObject();
    
    $response = $dataService->Add(...); // hit the QBO API
    $error    = $dataService->getLastError();
    
    if ($error) {
      refreshTokens();
      $response = $dataService->Add(...); // try the API call again
    }
    
    // ... "Add" complete, onto the next thing
    
    ////////////////////////////////
    
    function getDataServiceObject() {
      global $user;
    
      return DataService::Configure(array(
        'auth_mode'       => 'oauth2',
        'ClientID'        => '...',
        'ClientSecret'    => '...',
        'accessTokenKey'  => $user->getQbAccessToken(),
        'refreshTokenKey' => $user->getQbRefreshToken(),
        'QBORealmID'      => $user->getQbRealmId(),
        'baseUrl'         => '...',
      ));
    }
    
    function refreshTokens() {
      global $dataService;
      global $user;
    
      $OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
      $obj               = $OAuth2LoginHelper->refreshAccessTokenWithRefreshToken($user->getQbRefreshToken());
      $newAccessToken    = $obj->getAccessToken();
      $newRefreshToken   = $obj->getRefreshToken();
    
      // update $user and store in database
      $user->setQbAccessToken($newAccessToken);
      $user->setQbRefreshToken($newRefreshToken);
      $user->save();
    
      // update $dataService object
      $dataService = getDataServiceObject(); 
    }
    

    【讨论】:

      【解决方案2】:

      https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/faq

      为什么我的刷新令牌会在 24 小时后过期?

      过时的刷新令牌会在 24 小时后过期。每次刷新 access_token 时,都会返回一个新的 refresh_token,有效期为 100 天。之前的 refresh_token 现在已过时,并在 24 小时后过期。刷新 access_token 时,请始终使用返回给您的最新 refresh_token。

      您确定使用的是最新的刷新令牌吗?

      【讨论】:

      • 是的,每次我的代码运行时,我都会调用这个函数来刷新我的令牌并将新的令牌保存到我的数据库中
      • @AJ47 也许其他人也使用了那个保存的刷新令牌,所以你保存的那个已经过时了。
      • 谢谢,但理论上上面的代码应该可以连续工作而无需手动刷新令牌?假设应用在 100 天内使用,因此 refreshToken 保持有效
      • @AJ47 理论上,这是对您问题的明确解释。我没有你的代码和基础设施,所以我不知道谁/在用保存的令牌做什么
      【解决方案3】:

      如您所见,在每个 API 调用中,我都使用 refreshAccessTokenWithRefreshToken($qbRefreshToken) 方法来获取新的刷新和访问令牌并将它们保存到我的数据库以供下次使用...

      为什么每次发出请求时都请求新的访问令牌和刷新令牌?为什么不检查旧的访问令牌是否仍然有效?

      如上所述,您甚至存储了访问令牌的到期时间。所以你应该知道它是否仍然有效。

      因此,当您发出 API 请求并且访问令牌已过期时,您将收到一条错误消息。作为回报,您现在可以申请新的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-25
        • 1970-01-01
        • 1970-01-01
        • 2017-12-20
        • 2014-07-15
        • 2016-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多