Can t upload reports from QBO - python-3.x

I m trying to fetch QBO reports with python I have this error:
intuitlib.exceptions.AuthClientError: HTTP status 400, error message: b'{"error_description":"The token is not an authorization code: actualTokenType=RefreshToken","error":"invalid_grant"}',
I tried to change auth code to refresh token and it is not working. I was able to connect to QBO for objects like invoices,...
from intuitlib.client import AuthClient
from intuitlib.enums import Scopes
import requests
import QBOConnector
REDIRECT_URI = 'https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl'
auth_client = AuthClient(QBOConnector.CLIENT_ID, QBOConnector.CLIENT_SECRET, REDIRECT_URI, QBOConnector.environment )
url = auth_client.get_authorization_url([Scopes.ACCOUNTING])
auth_client.get_bearer_token(QBOConnector.TOKEN, realm_id=QBOConnector.CLIENT_ID)
auth_header = 'Bearer {0}'.format(auth_client.access_token)
headers = {
'Authorization': auth_header,
'Accept': 'application/json'
}
base_url = 'https://sandbox-quickbooks.api.intuit.com'
url = '{0}//v3/company/{1}/query?query=ProfitAndLoss?&minorversion=4'.format(base_url,auth_client.realm_id)
print('Url')
print(url)
response = requests.get(url, headers=headers)
print profil and loss report for a specific period of time

REDIRECT_URI = 'https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl' # not using the redirection at the moment
ENV = QBOConnector.PROD_environment
REFRESH_TOKEN = QBOConnector.PROD_TOKEN # Refresh token needs to be added here (which will be generated from https://developer.intuit.com/app/developer/playground)
COMPANY_ID = QBOConnector.PROD_COMPANY_ID #id of the company that we use in the example
# auth credentials to connect to the QBO account
auth_client = AuthClient(
client_id = QBOConnector.PROD_CLIENT_ID,
client_secret = QBOConnector.PROD_CLIENT_SECRET,
environment = ENV,
redirect_uri = REDIRECT_URI,
)
# creating the client object to access the QBO account
client = QuickBooks(
auth_client= auth_client,
refresh_token= REFRESH_TOKEN,
company_id= COMPANY_ID,
)
# retrieving all customers for the above client object
customers = Customer.all(qb=client)
# printing all customer names on the console/shell
for customer in customers:
print (customer)
# request authorization
auth_header = 'Bearer {0}'.format(auth_client.access_token)
headers = {
'Authorization': auth_header,
'Accept': 'application/json'
}
base_url = 'https://quickbooks.api.intuit.com'
# --- trial Balance
url = '{0}//v3/company/{1}/reports/TrialBalance?end_date=2019-09-30&minorversion=4'.format(base_url,
QBOConnector.PROD_COMPANY_ID)
response = requests.get(url, headers=headers)

Related

API in python Error 400 "invalid input parameters" - how to fix

I am programming an API in python to query a server if it has endpoint agents in it. The server and the endpoint belong to Apex central SaaS trend micro.
The error I get is that I'm putting the wrong parameters but I don't think the problem is there.
The code I have for the query is as follows:
import base64
import jwt
import hashlib
import requests
import time
import json
import urllib.parse
def create_checksum(http_method, raw_url, headers, request_body):
string_to_hash = http_method.upper() + '|' + raw_url.lower() + '|' + headers + '|' + request_body
base64_string = base64.b64encode(hashlib.sha256(str.encode(string_to_hash)).digest()).decode('utf-8')
return base64_string
def create_jwt_token(appication_id, api_key, http_method, raw_url, headers, request_body,
iat=time.time(), algorithm='HS256', version='V1'):
payload = {'appid': appication_id,
'iat': iat,
'version': version,
'checksum': create_checksum(http_method, raw_url, headers, request_body)}
token = jwt.encode(payload, api_key, algorithm=algorithm)
return token
# Use this region to setup the call info of the Apex Central server (server url, application id, api key)
# server info
use_url_base = 'https://arct3w.manage.trendmicro.com'
use_application_id = '52EB0005-B6DA-4249-9764-62AE3BFCDBB1'
use_api_key = 'B3FE1D91-5D05-490C-B45C-26A9EFF6C363'
productAgentAPIPath = '/WebApp/API/AgentResource/ProductAgents'
canonicalRequestHeaders = ''
useQueryString=''
payload = {
'computerId':'e34a13a1-1d0f-47bc-96e0-ae4db4288940'
}
useRequestBody = json.dumps(payload)
jwt_token = create_jwt_token(use_application_id, use_api_key, 'POST',
productAgentAPIPath + useQueryString,
canonicalRequestHeaders, useRequestBody, iat=time.time())
headers = {'Authorization': 'Bearer ' + jwt_token , 'Content-Type': 'application/json;charset=utf-8'}
#Choose by call type.
r = requests.post(use_url_base + productAgentAPIPath + useQueryString, data=useRequestBody, headers=headers, verify=False)
print(r.status_code)
if 'application/json' in r.headers.get('Content-Type', '') and len(r.content):
print(json.dumps(r.json(), indent=4))
else:
print(r.text)
I tried to do something similar to an api belonging to Vision One but it didn't work:
https://automation.trendmicro.com/xdr/api-v2#tag/Search/paths/~1v2.0~1xdr~1eiqs~1query~1endpointInfo/post
the original code of the query is :
https://automation.trendmicro.com/apex-central/api#tag/Security-Agents/operation/AgentResource_GetProductAgentsV2

send data to create incident to Dynamics 365 with Python Requests post() Method

I try to writing code to send data to create incident to Dynamics 365 with Python Requests post() Method but I have issue.
I use python 3.6,
I use this code but it give me this error
{'error': {'code': '', 'message': "The requested resource does not support http method 'POST'."}}
the code:
import requests
import json
#set these values to retrieve the oauth token
crmorg = 'https://xxxxxx.crm4.dynamics.com/' #base url for crm org
clientid = 'xxxxxxxxxxx' #application client id
tokenendpoint = 'https://login.microsoftonline.com/xxxxxxxxxx/oauth2/token' #oauth token endpoint
secret = 'xxxxxxxxxxxxxxxxx'
#set these values to query your crm data
crmwebapi = 'https://xxxxxx.api.crm4.dynamics.com/api/data/v9.1/Incident' #full path to web api endpoint
#crmwebapiquery = 'contacts?$select=fullname,contactid' #web api query (include leading /)
#build the authorization token request
tokenpost = {
'client_id':clientid,
'resource':crmorg,
'client_secret' : secret,
'grant_type':'client_credentials',
}
#make the token request
tokenres = requests.post(tokenendpoint, data=tokenpost)
#set accesstoken variable to empty string
accesstoken = ''
#extract the access token
try:
accesstoken = tokenres.json()['access_token']
except(KeyError):
#handle any missing key errors
print('Could not get access token')
#if we have an accesstoken
if(accesstoken!=''):
#prepare the crm request headers
crmrequestheaders = {
'Authorization': 'Bearer ' + accesstoken,
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8',
'Prefer': 'odata.maxpagesize=500',
'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
}
incidentdata={
"title": "test",
"customerid_account": "xxxxxxxxxxxxxxx",
"forte_casetypeid": "xxxxxxxxxxxxx",
"forte_casecategoryid": "xxxxxxxxxxxxxxxxxxx",
"primarycontactid": "xxxxxxxxxxxxxxxxx",
"entitlementid": "xxxxxxxxxxxxxxxxxxxxx",
}
#make the crm request
crmres = requests.post(crmwebapi, headers=crmrequestheaders, data=json.dumps(incidentdata))
try:
#get the response json
crmresults = crmres.json()
print(crmresults)
except KeyError:
#handle any missing key errors
print('Could not parse CRM results')
Let me suggest few things to fix and test the code.
Entity name should be corrected
Both of the below endpoints should work, but incidents is the right entity name.
crmwebapi = 'https://xxxxxx.api.crm4.dynamics.com/api/data/v9.1/incidents'
crmwebapi = 'https://xxxxxx.crm4.dynamics.com/api/data/v9.1/incidents'
Remove Prefer headers, as they are only needed for GET requests
Try the below headers.
crmrequestheaders = {
'Authorization': 'Bearer ' + accesstoken,
'OData-MaxVersion': '4.0',
'OData-Version': '4.0',
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8',
}
While assigning lookup/navigation properties - use #odata.bind
Check below and adjust accordingly.
incidentdata={
"title": "test",
"customerid_account#odata.bind": "/accounts(xxxxxxxxxxxxxxx)",
"forte_casetypeid": "xxxxxxxxxxxxx",
"forte_casecategoryid": "xxxxxxxxxxxxxxxxxxx",
"primarycontactid#odata.bind": "/contacts(xxxxxxxxxxxxxxxxx)",
"entitlementid#odata.bind": "/entitlements(xxxxxxxxxxxxxxxxxxxxx)",
}

Yahoo API - Unable to request new access token once previous access token has expired

I am attempting to use Yahoo's API for fantasy football. I am able to receive an access token and refresh token initially, but once that access token has expired, I am unable to get another one.
My code is as follows:
from requests import Request, get, post
import webbrowser
import base64
baseURL = 'https://api.login.yahoo.com/'
oauthENDPOINT = "https://api.login.yahoo.com/oauth2/request_auth"
## Generate a url using the endpoint and parameters above
params = {'client_id' : client_id,
'redirect_uri' : "oob",
'response_type' : 'code'}
p = Request('GET', oauthENDPOINT, params=params).prepare()
webbrowser.open(p.url)
The last line sends me to the Yahoo website where I allow myself access and receive authCode.
encoded = base64.b64encode((client_id + ':' + client_secret).encode("utf-8"))
headers = {
'Authorization': f'Basic {encoded.decode("utf-8")}',
'Content-Type': 'application/x-www-form-urlencoded'
}
data = {
'grant_type': 'authorization_code',
'redirect_uri': 'oob',
'code': authCode}
tokenResponse = post(baseURL + 'oauth2/get_token', headers=headers, data=data)
tokenResponseJSON = tokenResponse.json()
access_token = tokenResponseJSON['access_token']
refresh_token = tokenResponseJSON['refresh_token']
I now have all the information necessary to examine the settings of my league (for example).
fbURL = 'https://fantasysports.yahooapis.com/fantasy/v2'
leagueURL1 = f'{fbURL}/leagues;league_keys=nfl.l.{leagueID}/settings'
headers = {
'Authorization': f'Bearer {access_token}',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response2 = get(leagueURL1, headers=headers,params={'format': 'json'})
The above works as expected. However, the access_token lasts for 3600 seconds and once that time has expired I am unable to request a new one, using my refresh_token. My attempt:
accessTokenData = {
'grant_type': 'refresh_token',
'redirect_uri': 'oob',
'code': authCode,
'refresh_token': refresh_token
}
accessTokenResponse = post(baseURL + 'oauth2/get_token', headers=headers, data=accessTokenData)
accessTokenJSON = accessTokenResponse.json()
In the above, I am hoping to receive a new access_token, but instead accessTokenJSON is this:
{'error': {'localizedMessage': 'client request is not acceptable or not supported',
'errorId': 'INVALID_INPUT',
'message': 'client request is not acceptable or not supported'}}
Up to this point I have been following these steps, which worked well up to this point. What am I doing wrong? I understand many Python users use yahoo_oauth or rauth for authentication, but that involves saving the client_id and client_secret in a .json file separately and I'm looking to load those in dynamically. I don't think I'm very far away from succeeding, but I'm just missing something when it comes to generating a new refresh_token. All help much appreciated!
Thanks to referring back to our guide.
Managed to reproduce your error and it's really simple to solve.
You are redefining the headers variable in your request to the fantasyspot url.
The headers variable should be the same in the call for requesting a new access_token using the refresh_token as it was when initially getting both tokens using the auth_code.
So just define header before making requesting a new access_token. Should look like the the following:
headers = {
'Authorization': f'Basic {encoded.decode("utf-8")}',
'Content-Type': 'application/x-www-form-urlencoded'
}
response = post(base_url + 'oauth2/get_token', headers=headers, data=data)
Should work now.
Recommend using different variable names for the headers used for getting an access_token and the one used to the fantasy sport url.

How to get access_token from fyers API?

I'm looking to get access_token from fyers API
I'm able to get authorization_code and build authorization_url to open it in browser to enter user credentials. access_token is displayed in browser's address when user enters credentials but my program is unable to retrieve the access_code.
Your help is much appreciable.
My code is as follows:
from fyers_api import accessToken
from fyers_api import fyersModel
import requests
import webbrowser
import urllib.request as ur
app_id = "XXXXXXXXX"
app_secret = "XXXXXXXXX"
app_session = accessToken.SessionModel(app_id, app_secret)
response = app_session.auth()
if response['code'] != 200:
print('CODE=' + str(response['code']))
print('MESSAGE=' + str(response['message']))
print('Exiting program...')
exit(0)
authorization_code = response['data']['authorization_code']
app_session.set_token(authorization_code)
authorization_url=app_session.generate_token('XXXXXX')
token = webbrowser.open(authorization_url)
#Following authorization url is opened in browser:
#https://api.fyers.in/api/v1/genrateToken?authorization_code=xxxxxxxxxxxxx&appId=xxxxxxxxx&user_id=xxxxxx
#User is redirected to following url after successful log-in:
#https://trade.fyers.in/?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=&user_id=xxxxxx
print(token)
#token=”your_access_token”
#is_async = False #(By default False, Change to True for asnyc API calls.)
#fyers = fyersModel.FyersModel(is_async)
#fyers. get_profile(token = token)
Instead of writing the mentioned code, it is better to directly call Fyers Api.
import requests
url = 'https://api.fyers.in/api/v1/token'
requestParams = {
"fyers_id":"Your Client ID",
"password":"Your Password",
"pan_dob":"Your PAN card or DOB(DD-MM-YYYY)",
"appId":"YOur APP ID",
"create_cookie":False}
response = requests.post(url, json = requestParams )
print (response.text)
from fyers_api import accessToken
from fyers_api import fyersModel
app_id = "xxxxxxxxxx"
app_secret = "xxxxxxxxxx"
app_session = accessToken.SessionModel(app_id, app_secret)
response = app_session.auth()
print(app_session)
print(response)
authorization_code = response['data']['authorization_code']
app_session.set_token(authorization_code)
gen_token = app_session.generate_token()
print("token url is copy paste this url in browser and copy access
token excluding your id at Last ")
print(gen_token)
print("tokent printed thanks")
token="gAAAAABeTWk7AnufuuQQx0D0NkgABinWk7AnufuuQQx0DQ3ctAFWk7AnufuuQQx0DMQQwacJ-
_xUVnrTu2Pk5K5QCLF0SZmw7nlpaWk7AnufuuQQx0DG4_3EGCYw92-iAh8="
is_async = False
fyers = fyersModel.FyersModel(is_async)
print(fyers. get_profile(token = token))
fyers.funds(token = token)
print(fyers.funds(token = token))

Paylocity API Access Token

I have been trying to retreive the access token for the paylocity API. I am able to get it through postman with the client id and client secret however when I try and retrieve it with Python I get the message {"error":"invalid_client"}. This is the code that I am using
import json
import base64
import requests
url = "https://api.paylocity.com/IdentityServer/connect/token"
client_id = ''
client_secret = ''
auth = (f'{client_id}:{client_secret}')
headers = {
'content-type': "application/x-www-form-urlencoded",
'Authorization': f"Basic {auth}"
}
body = "grant_type=client_credentials&scope=WebLinkAPI"
response = requests.request("POST", url, data=body, headers=headers)
print (response.text)
In case someone else stumbles on this response, since there are not many search hits for this:
To get the token from Paylocity and call their API:
client_id = {your client id string}
client_secret = {your client secret}
company_id = {your company id from Paylocity dashboard, without leading 'CS'}
prod_auth_url = 'https://api.paylocity.com/IdentityServer/connect/token'
body_params = urllib.parse.urlencode({'grant_type': 'client_credentials','scope':'WebLinkAPI'})
# Requests can use auth= for basic authentication
auth_response = requests.post(prod_auth_url,auth=(client_id, client_secret), data=urllib.parse.urlencode(body_params))
response = json.loads(auth_response.content)
api_call_headers = {'Authorization': 'Bearer ' + response['access_token']}
# Get all employees for a company
empl_response = requests.get(f"https://api.paylocity.com/api/v2/companies/{company_id}/employees/",headers=api_call_headers, verify=False)
pd.DataFrame(json.loads(empl_response.text))
Make sure you're using the client_id and client_secret for your token call, not the company id. It is not necessary to use any OAuth2 libraries to access the API.
for only the token I do:
import requests, json
token_url = "https://apisandbox.paylocity.com/IdentityServer/connect/token"
#client credentials
client_id = 'XXXX'
client_secret = 'XXXXXX'
#step A, B - single call with client credentials as the basic auth header - will return access_token
data = {'grant_type': 'client_credentials', 'scope':'WebLinkAPI'}
access_token_response = requests.post(token_url, data=data, verify=False, allow_redirects=False, auth=(client_id, client_secret))
print(access_token_response.headers)
print (access_token_response.text)
And after that code I recived the Token the same as the PostMan.
you can check: https://developer.byu.edu/docs/consume-api/use-api/oauth-20/oauth-20-python-sample-code
for more information/options.
Try the following with the same variables:
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=url, client_id=client_id, client_secret=client_secret, body=body, headers=headers)

Resources