cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Github python code is very outdated?

I just downloaded the github python code, as I was attempting to acquire a class to allow me to acquire the IAF token from ebay, so that I can get a new token each time I run my application. After debugging the code and bringing it up to speed to work with the current classes, the testing script is looking for "code" in the url after signing in. Presently, when signing into the sandbox url, it redirects you to "https://www.sandbox.ebay.com/" which now no longer contains the code in the url to parse using regex.

 

I feel like this is much more complicated than it should be to just get an up to date IAF token. I was trying to look through the other documentation to make a simple XML call using the API to get a new token/refresh the existing token.

 

I keep getting the following response

 

{'error': 'invalid_client', 'error_description': 'client authentication failed'}

 

with me performing the following call

 

tempString = api_settings['client_id'] + ':' + api_settings['client_secret'];

b64_encoded_credential = base64.b64encode(str.encode(tempString))
print('b64_encoded_credential - '+str(b64_encoded_credential))
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + str(b64_encoded_credential)
}



body = {
"grant_type" : "client_credentials",
"redirect_uri" : api_settings['redirecturi'],
"scope" : app_scopes,
}

and then making the call to the system via the following

data = urllib.parse.urlencode(body)

response = requests.post("https://api.ebay.com/identity/v1/oauth2/token", headers=headers, data=data)

 

But as I said before, for whatever reason, it just keeps telling me that the authentication failed

 

Message 1 of 12
latest reply
11 REPLIES 11

Github python code is very outdated?

@fillersfulfillment 

 

I am certainly going to claim ignorance, but perhaps you can pull some sense out of this. I use PHP to fetch application tokens in production mode (haven't tried sandbox) and last month asked ChatGPT to give me a Python version of an OAuth application token for the Browse API. This has not been tested as Python code, although I then fed this back to Chat and requested a PHP version, which worked fine.

 

I have three credential files on my server, listed in the global at the top of the procedure.

Look at the funny encode() .decode() in the headers.

I'm surprised the scope is not encoded, but perhaps the "requests.post" handles that. 

import os
import time
import base64
import requests

# Set up file paths
oauth_clientIdfile = os.path.join(oauth_root, "ebay_apiuser.txt")
oauth_secretIdfile = os.path.join(oauth_root, "ebay_apisecret.txt")
oauth_basictokenfile = os.path.join(oauth_root, "ebay_token_basic.txt")

def get_basic_oauth_token():
    global oauth_basictokenfile
    # Look at timestamp to see if it has expired
    now = time.time()
    duration = 7200  # Life of the token, 2 hours
    margin = 60  # Remaining time before we request a new token, 1 minute
    if os.path.exists(oauth_basictokenfile):
        tstamp = os.path.getmtime(oauth_basictokenfile)
        if tstamp + duration - now > margin:  # Some time remains on token
            with open(oauth_basictokenfile, 'r') as f:
                return f.read().strip()
        else:
            return create_basic_oauth_token()
    else:
        return create_basic_oauth_token()

def create_basic_oauth_token():
    global oauth_clientIdfile, oauth_secretIdfile, oauth_basictokenfile

    url = 'https://api.ebay.com/identity/v1/oauth2/token'
    clientID = open(oauth_clientIdfile, 'r').read().strip()
    clientSecret = open(oauth_secretIdfile, 'r').read().strip()

    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Basic ' + base64.b64encode((clientID + ':' + clientSecret).encode()).decode()
    }

    body = {
        'grant_type': 'client_credentials',
        'scope': 'https://api.ebay.com/oauth/api_scope'
    }

    response = requests.post(url, headers=headers, data=body)
    
    if response.ok:
        token = response.json()
        if 'access_token' in token:
            with open(oauth_basictokenfile, 'w') as f:
                f.write(token['access_token'])
            return token['access_token']
    else:
        response.raise_for_status()

# Example usage:
# token = get_basic_oauth_token()
# print(token)

 

You may also find some Python code examples (snippets actually) on other threads here, and in some of eBay's API pages. 

 

ShipScript has been an eBay Community volunteer since 2003, specializing in HTML, CSS, Scripts, Photos, Active Content, Technical Solutions, and online Seller Tools.
Message 2 of 12
latest reply

Github python code is very outdated?

Yeah, I originally asked ChatGPT to provide me a python script to perform this task. I can go ahead and make use this to make a python version. If Base64 encode/decode works similarly to what I have been working with, it is because

 

base64.b64encode

 

requires the content to be in bytes, while the response method requires it all to be in a string, so you are converting the client_id and secret_id into a bytes variable, encoding it into b64, and then throwing it back as a string. I am doing a similar thing in my code, but I have it broken up into numerous lines so that I can print it out and see what it is spitting out.

 

Regardless, I'll go ahead and give this a try. The fact that this code works for you is immensely helpful, as I have not been able to find a working example anywhere from my searches, and Ebay's existing code is VERY outdated, sadly.

 

I'll retrofit my code to match this and try it, and report back with a working example so that whoever else that is running into a similar situation can have a working copy to use.

Message 3 of 12
latest reply

Github python code is very outdated?

@fillersfulfillment 

 

I'll definitely be interested in what you can come up with. There are many who would like a token script, and Python appears to be an ever more popular language.

 

The PHP source code from which ChatGPT derived the Python version can be found here, so if something doesn't work in Python, you can at least see the working PHP version:

https://community.ebay.com/t5/Token-Messaging-Sandbox-related/Sample-PHP-for-generating-and-renewing... 

 

The PHP curl prep is split into two formats to show two different mechanisms - there is no requirement for doing it that way.

 

Additionally, my PHP OAuth code queries the age of the token file. eBay recommends actually testing whether the token has expired and then minting a new token if that is the case.

 

 

ShipScript has been an eBay Community volunteer since 2003, specializing in HTML, CSS, Scripts, Photos, Active Content, Technical Solutions, and online Seller Tools.
Message 4 of 12
latest reply

Github python code is very outdated?

It's amazing how simple this is once you have a working example. I made small modifications based on your code, and got it working in about 15 minutes, and spent a few minutes removing all of the print comments to get access to it. I tried it on both SANDBOX and PRODUCTION, and both work fine. I have a variable at the top which allows you to switch between the two, depending on what you are looking for.

 

Thanks again for your example code. That saved me a ton of headache, and I think it all boiled down to potentially having a more complicated scope, being unsure of the correct tokenUrl to call, and the encode/decode method, which I swapped my own code around to get working. Without further ado, for all those out there looking for a code snippet, enjoy.

 

import requests, urllib, base64, gc
from requests.auth import HTTPBasicAuth
import xml.etree.ElementTree as ET
import xml.sax.saxutils

def getAuthToken():
    sandbox = True  # Set to False for production
    #default settings that apply for both live and testing
    api_settings = {
        'sandbox': sandbox,  # Set to False for production
        'siteid': '0',  # US eBay site
    }

    if (sandbox == True):
        # eBay Dev API credentials
        api_settings.update({
            'appid' : 'SANDBOX-APP-ID',
            'devid' : 'SANDBOX-DEV-ID',
            'certid': 'SANDBOX-CLIENT-ID',
            'redirecturi': 'NOT-USED',
            'token' : 'NOT-USED',
            'url'   : 'https://api.sandbox.ebay.com/identity/v1/oauth2/token',
        })
    else:
        # eBay : Production API credentials
        api_settings.update({
            'appid' : 'PRODUCTION-APP-ID',
            'devid' : 'PRODUCTION-DEV-ID',
            'certid' : 'PRODUCTION-CLIENT-ID',
            'redirecturi' : 'NOT-USED',
            'token' : 'NOT-USED',
            'url'   : 'https://api.ebay.com/identity/v1/oauth2/token',
        })
    
    tempString = api_settings['appid'] + ':' + api_settings['certid'];

    headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': 'Basic ' + base64.b64encode((api_settings['appid'] + ':' + api_settings['certid']).encode()).decode(),
    }
    
    body = {
        "grant_type" : "client_credentials",
        "scope" : "https://api.ebay.com/oauth/api_scope",
    }
    
    data = urllib.parse.urlencode(body)
    
    #tokenURL = "https://api.ebay.com/identity/v1/oauth2/token"

    response = requests.post(api_settings['url'], headers=headers, data=data) 

    return response.json()


response_json = getAuthToken()

if('access_token' in response_json):
    print(response_json['access_token']) #access keys as required
if ('error_description' in response_json):
    print(response_json['error_description']) #if errors
Message 5 of 12
latest reply

Github python code is very outdated?

@fillersfulfillment   Wonderful!! 

I would recommend that you hurry and edit (down arrow at top right of post) to use the </> code tool so that the indents show. Use the ellipsis to open more on the toolbar and then select the </> tool.  If too late to edit, then perhaps you can repost the code. 

 

 

 

ShipScript has been an eBay Community volunteer since 2003, specializing in HTML, CSS, Scripts, Photos, Active Content, Technical Solutions, and online Seller Tools.
Message 6 of 12
latest reply

Github python code is very outdated?

Good call. I went ahead and went back and edited it and was able to make the modification to display code. Good tip on that, and thanks again for the help you provided to get this up and running so that I can move onto more important code

Message 7 of 12
latest reply

Github python code is very outdated?

Very strange. The system returns a token to me using the "grant_type" of "client_credentials", which I pass into a method for "AddFixedPriceItem", both in sandbox mode, and it is returning

 

'AddFixedPriceItem: Class: RequestError, Severity: Error, Code: 21916984, Invalid IAF token. IAF token supplied is invalid.'

 

Comparing the token that I receive from the ebay developer website that works when I hardcode it, the token length is 2660 characters long, but the length of the token returned from calling the api is 1924 characters long. Perhaps I am not making a call for the correct api scopes?

Message 8 of 12
latest reply

Github python code is very outdated?

@fillersfulfillment 

 

Client_credentials (for public data) is the wrong type of OAuth token for the Trading API (private data) . 

https://developer.ebay.com/api-docs/static/oauth-client-credentials-grant.html

 

While Auth-n-auth supported a single 18-month token for private data, the Oauth process for private data is three parts:

  • The 5-minute authorization from the account owner.
  • Trading that in for a 2-hour access token and an 18 month refresh token.
  • And then updating the 2-hour access token with the refresh token as needed.

https://developer.ebay.com/api-docs/static/oauth-authorization-code-grant.html 

 

 

ShipScript has been an eBay Community volunteer since 2003, specializing in HTML, CSS, Scripts, Photos, Active Content, Technical Solutions, and online Seller Tools.
Message 9 of 12
latest reply

Github python code is very outdated?

Okay, so based on what I am reading, I need to make the original grant call for "client_credentials" and then following it up with a grant call to "authorization_code" which includes the "redirecturi" to obtain the complete IAF token. Does that sound about right?

Message 10 of 12
latest reply

Github python code is very outdated?

@fillersfulfillment 

 

If working with private data, start out with the authorization process.

https://developer.ebay.com/api-docs/static/oauth-authorization-code-grant.html 

This asks the user to log in and grant permission. The user's acceptance redirects to the URL you have provided (either on the developer screen or programmatically) and includes a query string with the 5-minute authorization code.

https://developer.ebay.com/api-docs/static/oauth-consent-request.html

 

That authorization code is then fed into a token request, which returns the access token and the refresh token. 

https://developer.ebay.com/api-docs/static/oauth-auth-code-grant-request.html

 

If you are doing this for your own account, you can simply request the 5-minute authorization on the developer screen and then hurriedly feed it into the token request. Pick up the 18-month refresh token and use that for the next 18 months to request a two-hour access token.

https://developer.ebay.com/api-docs/static/oauth-refresh-token-request.html 

 

Minting the 2-hour token should be quite similar to what you are doing to mint a token for client_credentials (which accesses public data).

 

You will notice that you must pass a scope list when getting user authorization. However, it is not necessary to pass the scope list when minting a token unless you want to use only a subset of what the user authorized. (Or at least, that is my understanding from reading the last paragraph on the scopes page.)

https://developer.ebay.com/api-docs/static/oauth-scopes.html 

 

 

ShipScript has been an eBay Community volunteer since 2003, specializing in HTML, CSS, Scripts, Photos, Active Content, Technical Solutions, and online Seller Tools.
Message 11 of 12
latest reply

Github python code is very outdated?

That sounds about right. I re-read it numerous times, and after doing a combination of manually requesting the content, and getting the user code by sending the request directly into the browse, copying, hardcoding it to verify that it works as expected, and then adding in some functionality so that I can input certain information in directly, I finally obtained the token I was looking for that I am able to submit and not get an error. Currently, the sandbox api is down again, sadly, so I cannot continue working on my code, but I believe I have the correct information that I am looking for.

 

And yes, this code is for my own personal use, so I do not need to create a robust setup so that can handle additional users. Just need to understand the workflow, and connect them all up so that I can utilize the api for convenient listing from a spreadsheet.

 

All in all, I believe I am on the right track, and should be able to perform my task.

 

Once again, thanks for your assistance.

Message 12 of 12
latest reply