2017-10-10 123 views
1

The docs python-fitbit API建议将'refresh_cb'函数作为参数传递,因此我们不必每次都需要手动检索访问令牌,刷新令牌和expires_at变量Fitbit API。我已将这些值放入环境变量中,每次手动检索值时,都可以成功访问我的Fitbit信息。但是,我不明白refresh_cb函数应该做什么或返回。我知道这是为了保存新的令牌,但我只是试图将环境变量更改为新值,但当我尝试执行任何操作时,这些错误仍然会触发一个(Invalid grant)错误。这里是我到目前为止的代码:python-fitbit API更新令牌

from fitbit import Fitbit 
import os 

CLIENT_ID = os.environ['client_id'] 
SECRET = os.environ['secret'] 
ACCESS_TOKEN = os.environ['access_token'] 
EXPIRES_AT = os.environ['expires_in'] 
REFRESH_TOKEN = os.environ['refresh_token'] 
USER_ID = os.environ['user_id'] 


def refresh_cb(token_dict): 
    """Function for refreshing access_token, refresh_token, and expires_at.""" 
    os.environ['access_token'] = token_dict['access_token'] 
    os.environ['expires_at'] = str(token_dict['expires_at']) 
    os.environ['refresh_token'] = token_dict['refresh_token'] 

    return token_dict 

kurt = Fitbit(
    CLIENT_ID, 
    SECRET, 
    access_token=ACCESS_TOKEN, 
    refresh_token=REFRESH_TOKEN, 
    expires_at=EXPIRES_AT, 
    refresh_cb=refresh_cb 
) 

这里的文档说什么:

我们也强烈建议传递一个refresh_cb关键字参数, 这应该是采取一个参数的函数:令牌字典。当 该参数存在时,我们将在需要时自动刷新访问令牌并调用此函数,以便您可以保存 已更新的令牌数据。如果您不保存更新的信息,那么您最终可能会得到无效的访问和刷新令牌,并且唯一可以从中恢复的方式是重新授权用户。如果您有一个 工作示例或可以指向正确的方向,我真的 欣赏它。

编辑:

这里是完整的回溯我越来越:

TokenExpiredError       Traceback (most recent call last) 
~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in request(self, method, url, data, headers, withhold_token, client_id, client_secret, **kwargs) 
    329     url, headers, data = self._client.add_token(url, 
--> 330       http_method=method, body=data, headers=headers) 
    331    # Attempt to retrieve and save new access token if expired 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/clients/base.py in add_token(self, uri, http_method, body, headers, token_placement, **kwargs) 
    192   if self._expires_at and self._expires_at < time.time(): 
--> 193    raise TokenExpiredError() 
    194 

TokenExpiredError: (token_expired) 

During handling of the above exception, another exception occurred: 

InvalidGrantError       Traceback (most recent call last) 
<ipython-input-3-c92ce9c67530> in <module>() 
----> 1 sleep = kurt.sleep() 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/utils.py in _curried(*moreargs, **morekwargs) 
    36 def curry(_curried_func, *args, **kwargs): 
    37  def _curried(*moreargs, **morekwargs): 
---> 38   return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) 
    39  return _curried 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in _COLLECTION_RESOURCE(self, resource, date, user_id, data) 
    313    base_url = "{0}/{1}/user/{2}/{resource}.json" 
    314   url = base_url.format(*self._get_common_args(user_id), **kwargs) 
--> 315   return self.make_request(url, data) 
    316 
    317  def _DELETE_COLLECTION_RESOURCE(self, resource, log_id): 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in make_request(self, *args, **kwargs) 
    221 
    222   method = kwargs.get('method', 'POST' if 'data' in kwargs else 'GET') 
--> 223   response = self.client.make_request(*args, **kwargs) 
    224 
    225   if response.status_code == 202: 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in make_request(self, url, data, method, **kwargs) 
    94    client_id=self.client_id, 
    95    client_secret=self.client_secret, 
---> 96    **kwargs 
    97  ) 
    98 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/fitbit/api.py in _request(self, method, url, **kwargs) 
    66 
    67   try: 
---> 68    response = self.session.request(method, url, **kwargs) 
    69 
    70    # If our current token has no expires_at, or something manages to slip 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in request(self, method, url, data, headers, withhold_token, client_id, client_secret, **kwargs) 
    341       auth = requests.auth.HTTPBasicAuth(client_id, client_secret) 
    342      token = self.refresh_token(
--> 343       self.auto_refresh_url, auth=auth, **kwargs 
    344     ) 
    345      if self.token_updater: 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py in refresh_token(self, token_url, refresh_token, body, auth, timeout, headers, verify, proxies, **kwargs) 
    307    r = hook(r) 
    308 
--> 309   self.token = self._client.parse_request_body_response(r.text, scope=self.scope) 
    310   if not 'refresh_token' in self.token: 
    311    log.debug('No new refresh token given. Re-using old.') 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/clients/base.py in parse_request_body_response(self, body, scope, **kwargs) 
    406   .. _`Section 7.1`: http://tools.ietf.org/html/rfc6749#section-7.1 
    407   """ 
--> 408   self.token = parse_token_response(body, scope=scope) 
    409   self._populate_attributes(self.token) 
    410   return self.token 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/parameters.py in parse_token_response(body, scope) 
    377 
    378  params = OAuth2Token(params, old_scope=scope) 
--> 379  validate_token_parameters(params) 
    380  return params 
    381 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/parameters.py in validate_token_parameters(params) 
    384  """Ensures token precence, token type, expiration and scope in params.""" 
    385  if 'error' in params: 
--> 386   raise_from_error(params.get('error'), params) 
    387 
    388  if not 'access_token' in params: 

~/Projects/kurt_data/ENV/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/errors.py in raise_from_error(error, params) 
    404  for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): 
    405   if cls.error == error: 
--> 406    raise cls(**kwargs) 

InvalidGrantError: (invalid_grant) 

回答

0

据我了解,你需要刷新全球蟒蛇变量(不是环境变量)这样

def refresh_cb(token_dict): 
    """Function for refreshing access_token, refresh_token, and expires_at.""" 
    global ACCESS_TOKEN 
    global EXPIRES_AT 
    global REFRESH_TOKEN 
    ACCESS_TOKEN = token_dict['access_token'] 
    EXPIRES_AT = str(token_dict['expires_at']) 
    REFRESH_TOKEN = token_dict['refresh_token'] 

    return token_dict 
+0

我尝试了你的建议,但我仍然收到同样的错误。我基本上只是将'Fitbit'类实例化到变量'kurt'中,然后尝试获取一些数据。根据我的理解,如果'refresh_cb'函数是正确的,那么它将得到新的令牌并使用提供的函数来保存它们。 –