timotheus / ebaysdk-python

eBay API SDK for Python
https://developer.ebay.com/tools/sdks
Other
809 stars 326 forks source link

Shopping API is gonna be deprecated #347

Open Ajakhongir opened 3 years ago

Ajakhongir commented 3 years ago

Hi, I am using Shopping API and APP ID for authorization, Recently, I received an email from ebay support, that I am not gonna be able to use Shopping API, using APP ID. Question is, Possible to use OAUTH2 Authorization to Shopping API? if yes, How am I gonna do that? Or should I have to change everything?

thank you for your answers !!!

ffeist-ccg commented 3 years ago

I had this issue. I believe the current eBay sdk is no longer compatible with shopping API because it uses APP ID instead of Auth token to authenticate. My a-few-months-old eBay sdk code didn't work so I had to change a few lines in connection.py as a little hack.

If you want to do the same:

  1. go here to see how to get your auth credentials: https://developer.ebay.com/api-docs/static/oauth-credentials.html
  2. go here to see what you need in your POST http request to mint an authentication token. these are valid for 2 hours: https://developer.ebay.com/api-docs/static/oauth-client-credentials-grant.html
  3. having done all the steps in (2), including encoding your credentials in base 64, you can edit connection.py in the ebaysdk as follows:

At the top of connection.py just after imports I added import requests from requests.structures import CaseInsensitiveDict import json import datetime time_of_last_token = datetime.datetime.min previous_access_token = ""

...and then within build_request function, just after the line request = Request(self.method, ... files=files,), I added the following: time_now = datetime.datetime.now() time_difference_last_token = time_now - time_of_last_token if time_difference_last_token.total_seconds() > 3600: url = "https://api.ebay.com/identity/v1/oauth2/token" # CHANGE THIS BASED ON LINK IN STEP (2) headers = CaseInsensitiveDict() headers["Content-Type"] = "application/x-www-form-urlencoded" headers["Authorization"] = "Basic YOURAUTHENTICATIONDETAILSHERE" # CHANGE BASED ON STEP 2 data = "grant_type=client_credentials&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope" response = requests.post(url, headers=headers, data=data) response_dict = json.loads(response.text) access_token = response_dict['access_token'] previous_access_token = access_token request.headers['X-EBAY-API-IAF-TOKEN'] = access_token

now the access token will be added to the POST request headers so the authentication works. At least for me. This is a hack and not intended to be a permanent solution so it might not be the best possible way to do things but it worked for me.

xjxckk commented 2 years ago

I made some further changes to @ffeist-ccg's answer as I am using multiple developer accounts.

In /python/lib/site-packages/ebaysdk/connection.py:

At the top of the file after the first imports under from ebaysdk.exception import ConnectionError, ConnectionResponseError (above HTTP_SSL = {) I added this:

## Added this / https://github.com/timotheus/ebaysdk-python/issues/347

from ebaysdk.config import Config
from base64 import b64encode

from requests.structures import CaseInsensitiveDict
import json
import datetime
time_of_last_token = datetime.datetime.min
previous_access_token = ""

## End of changes

In def init(...) of the BaseConnection class under set_stream_logger() (above self.response = None) I added this:

## Added this / https://github.com/timotheus/ebaysdk-python/issues/347

self.config = Config(domain=kwargs.get('domain', 'open.api.ebay.com'), connection_kwargs=kwargs, config_file=kwargs.get('config_file', 'ebay.yaml'))

# Building OAuth token
client_id = self.config.get('appid', '')
client_secret = self.config.get('certid', '')
token_string = f'{client_id}:{client_secret}'
token_bytes = token_string.encode('ascii')
token_base64 = b64encode(token_bytes)
self.final_token = token_base64.decode('ascii')

## End of changes

Under this line request = Request(self.method, (above the line self.request = request.prepare()) I added this:

## Added this / https://github.com/timotheus/ebaysdk-python/issues/347

time_now = datetime.datetime.now()
time_difference_last_token = time_now - time_of_last_token
if time_difference_last_token.total_seconds() > 3600:
    url = "https://api.ebay.com/identity/v1/oauth2/token" # If you want to use sandbox you will need to change this URL
    headers = CaseInsensitiveDict()
    headers["Content-Type"] = "application/x-www-form-urlencoded"
    headers["Authorization"] = f"Basic {self.final_token}"
    data = "grant_type=client_credentials&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope"
    response = post(url, headers=headers, data=data)
    response_dict = json.loads(response.text)
    access_token = response_dict['access_token']
    previous_access_token = access_token
    request.headers['X-EBAY-API-IAF-TOKEN'] = access_token

## End of changes

Final connection.py file: https://gist.github.com/xjxckk/805147238c64836648f2e0bd094aca68