Authentication Error with Paypal Sandbox and Google App Engine - python

I'm having trouble getting the Paypal Adaptive Payments API to work with GAE - I'm specifically going to be using Implicit Payments.
The error returned is that my api credentials are incorrect, but from what i've read I should be suspicious of the header format as well.
Here's the snippet of code - I'm using the urlfetch module in GAE:
headers = {
"X-PAYPAL-USERID" : "xxxx_123456789_biz_api1.xxxx.com",
"X-PAYPAL-SECURITY-PASSWORD" : "1234567890",
"X-PAYPAL-SECURITY-SIGNATURE" : "Ahg-XXXXXXXXXXXXXXXXXXXXXX",
"X-PAYPAL-REQUEST-DATA-FORMAT" : "JSON",
"X-PAYPAL-RESPONSE-DATA-FORMAT" : "JSON",
"X-PAYPAL-APPLICATION-ID" : "APP-80W284485P519543T"
}
request_body = {
"actionType" : "PAY",
"senderEmail" : "xxxx_123456789_biz_api1#xxxx.com",
"receiverList.receiver(0).email" : "xxxx_123456789_per#xxxx.com",
"receiverList.receiver(0).amount" : 100.00,
"currencyCode" : "USD",
"cancelUrl" : "some_url.com",
"returnUrl" : "some_url.com",
"requestEnvelope.errorLanguage" : "en_US"
}
url = "https://svcs.sandbox.paypal.com/AdaptivePayments/Pay"
result = urlfetch.fetch(url=url,payload=request_body,headers=headers)
I've Xed out some values, but everything I'm using is coming from the sandbox "API Credentials" section.
Is there a problem with the header format? Am I using the wrong set of credentials? Can I even use the sandbox to test Implicit Payments?
Any help is much appreciated.
Thanks!
For any of those having similar problems, follow the excellent tutorial located here:
Awesome Paypal Adaptive Payments Tutorial
The headers do tend to cause authentication errors if not formed correctly. I was pretty far off :)

go to your headers, and make a change like this
the key
'X-PAYPAL-USERID'
should become
'X-PAYPAL-SECURITY-USERID'.

You forgot to set the POST method inside the urlfetch.fetch call; without it, the payload data is ignored.
result = urlfetch.fetch(url=url,
payload=request_body,
method=urlfetch.POST,
headers=headers)
The urllib2.Request used in the Tutorial instead switches automatically from GET to POST when the request data is set.
req = urllib2.Request(self.request_url,paypal_request_data,header_data)

Related

Sending a POST request from Python to Wix?

I'm currently trying to send a POST request from a python tkinter GUI to a wix free website. I already sent several GET requests and were successful. But regardless of anything I do, the POST request yields a 500 internal server error. Here are the code of the http-functions.js in the backend of my wix.
export function post_posFunc(request) {
let options = {
"headers":{
"Content-Type":"application/json"
}
};
return request.body.text()
.then((body) =>{
return wixData.insert("vidinfo", JSON.parse(body));
})
.then((results)=> {
options.body={
"inserted":results
};
return created(options)
})
.catch((error) =>{
options.body = {
"error":error
};
return serverError(options)
});
}
and on my tkinter app, I pass a video's name, size, and class alongside a userId and the code is as follows
def runPost(a,b,c,d,e,f):
url = 'https://###.wixsite.com/###/_functions/posFunc/'
myobj = {
"vidUserId":a,
"videoName":b,
"videoSize":c,
"videoClass":d
}
z = requests.post(url, data=myobj)
print(json.dumps(data, indent=2, sort_keys=True))
print("done with post")
I have already tried it with postman and It worked successfully. The fields that are in vidinfo are displayed above as you can see. I have censored the website's name as someone told me it's against the rules to release private information but If I am allowed to post it please do let me know. What is wrong with my code?
UPDATE
managed to catch and print the error. Updated the code above and adding the error below
{
"error": {
"errorGroup": "User",
"name": "JsonSyntaxError"
}
}
UPDATE#2
Using json.dumps did the trick!
It might be helpful to find out what the actual error message is. In your python script, you are only printing the status code. Knowing the error response which is caught with .catch((error) => { ... }) and is sent with options.body = { error: error }
might give you (and us) some more clues as to what is going on.
Also note that it doesn't always make sense to send a 'server error', namely when the issue is really with the request and not server side. Knowing the error message (and thus, potentially what is causing the error) will help you send the appropriate response and status code.
Without knowing any further error message information, I wonder if how you are handling the request is causing the issue. Are you sure that you can parse the request by using request.body.text() and/or JSON.parse from the python-sent request? It's possible that the python requests module does not serialize data in the same way that Postman does.
Hopefully what I've said can be helpful. I will keep following if you happen to make any updates to what you've posted above. Good luck!!
UPDATE:
After seeing your response error, it looks to me like you might be handling the request incorrectly. As I stated above, Postman may serialize the object differently from python requests.
Try using request.post(url, data=json.dumps(data)).
Again, are you sure that the data can be retrieved from the request.body.text() method? I am not sure what http framework is being used server-side, but if request.body.text() isn't actually able to return any data, it is likely passing undefined to your first promise handler .then((body) => { ... }). Since your error is a JsonSyntaxError, it is likely that JSON.parse cannot actually parse what it is trying to parse, whether that be undefined or an invalid JSON string.

HTTP Triggering Cloud Function with Cloud Scheduler

I have a problem with a job in the Cloud Scheduler for my cloud function. I created the job with next parameters:
Target: HTTP
URL: my trigger url for cloud function
HTTP method: POST
Body:
{
"expertsender": {
"apiKey": "ExprtSender API key",
"apiAddress": "ExpertSender APIv2 address",
"date": "YYYY-MM-DD",
"entities": [
{
"entity": "Messages"
},
{
"entity": "Activities",
"types":[
"Subscriptions"
]
}
]
},
"bq": {
"project_id": "YOUR GCP PROJECT",
"dataset_id": "YOUR DATASET NAME",
"location": "US"
}
}
The real values has been changed in this body.
When I run this job I got an error. The reason is caused by processing body from POST request.
However, when I take this body and use it as Triggering event in Testing I don't get any errors. So I think, that problem in body representation for my job but I havn't any idea how fix it. I'll be very happy for any idea.
Disclaimer:
I have tried to solve the same issue using NodeJS and I'm able to get a solution
I understand that this is an old question. But I felt like its worth to answer this question as I have spent almost 2 hours figuring out the answer for this issue.
Scenario - 1: Trigger the Cloud Function via Cloud Scheduler
Function fails to read the message in request body.
Scenario - 2: Trigger the Cloud Function via Test tab in Cloud Function interface
Function call always executes fine with no errors.
What did I find?
When the GCF routine is executed via Cloud Scheduler, it sends the header content-type as application/octet-stream. This makes express js unable to parse the data in request body when Cloud scheduler POSTs the data.
But when the exact same request body is used to test the function via the Cloud Function interface, everything works fine because the Testing feature on the interface sends the header content-type as application/json and express js is able to read the request body and parses the data as a JSON object.
Solution
I had to manually parse the request body as JSON (explicitly using if condition based on the content-type header) to get hold of data in the request body.
/**
* Responds to any HTTP request.
*
* #param {!express:Request} req HTTP request context.
* #param {!express:Response} res HTTP response context.
*/
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
console.log('Headers from request: ' + JSON.stringify(req.headers));
let parsedBody;
if(req.header('content-type') === 'application/json') {
console.log('request header content-type is application/json and auto parsing the req body as json');
parsedBody = req.body;
} else {
console.log('request header content-type is NOT application/json and MANUALLY parsing the req body as json');
parsedBody = JSON.parse(req.body);
}
console.log('Message from parsed json body is:' + parsedBody.message);
res.status(200).send(message);
};
It is truly a feature issue which Google has to address and hopefully Google fixes it soon.
Cloud Scheduler - Content Type header issue
Another way to solve the problem is this:
request.get_json(force=True)
It forces the parser to treat the payload as json, ingoring the Mimetype.
Reference to the flask documentation is here
I think this is a bit more concise then the other solutions proposed.
Thank you #Dinesh for pointing towards the request headers as a solution! For all those who still wander and are lost, the code in python 3.7.4:
import json
raw_request_data = request.data
# Luckily it's at least UTF-8 encoded...
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
Totally agree, this is sub-par from a usability perspective. Having the testing utility pass a JSON and the cloud scheduler posting an "application/octet-stream" is incredibly irresponsibly designed.
You should, however, create a request handler, if you want to invoke the function in a different way:
def request_handler(request):
# This works if the request comes in from
# requests.post("cloud-function-etc", json={"key":"value"})
# or if the Cloud Function test was used
request_json = request.get_json()
if request_json:
return request_json
# That's the hard way, i.e. Google Cloud Scheduler sending its JSON payload as octet-stream
if not request_json and request.headers.get("Content-Type") == "application/octet-stream":
raw_request_data = request.data
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
if request_json:
return request_json
# Error code is obviously up to you
else:
return "500"
One of the workarounds that you can use is to provide a header "Content-Type" set to "application/json". You can see a setup here.

How to store complex meta data using Asana's external data feature

Background
My organization uses the Asana platform to coordinate our work efforts. I have been leveraging Asana's API to automate a number of our daily operations and as well integrate Asana's platform with other external services we use. I interact with Asana's API using python and the requests library to make GET, POST, and PUT requests.
Often times I need to GET or POST to a specific task within Asana, I can often achieve this using Asana's auto-generated task ID.
result = requests.get("https://app.asana.com/api/1.0/tasks/task_id", headers)
However there are times where it is useful for me to be able to identify a task by specific information stored within it. I have been able to successfully do so by storing the specific information in question within task's meta data, referred to as "external data" by Asana.
result = requests.get("https://app.asana.com/api/1.0/tasks/external_id", headers)
Both of these methods have served me well. However I am having trouble storing specific data within a task's external data which I outline in the section below.
Problem
Currently when I store meta data in a task external data my PUT/POST request is as follows:
header = {
"Authorization" : "Bearer " + AUTH_TOKEN
}
data = {
"data" : {
"name" : "Burgers",
"external" : {
"id" : "external_id",
"data" : "data_value"
}
}
}
url = "https://app.asana.com/api/1.0/tasks/task_id"
result = requests.put(url, headers=header, json=data)
return result
The important thing to note here is that the "data_value" is a single string. However according to Asana's documentation here the "data_value" can actually store a dictionary of keys and values. I have attempted to pass a dictionary object by doing the following:
data = {
"data" : {
"name" : "Burgers",
"external" : {
"id" : "external_id",
"data" : {
"data_value" : "some_data",
"data_value_2" : "some_data"
}
}
}
}
But I continue to receive an error stating:
"{"errors":[{"message":"external: data: Value is not a string: [object Object]","help":"For more information on API status codes and how to handle them, read the docs on errors: https://asana.com/developers/documentation/getting-started/errors"}]}"
Any ideas where I am going wrong? Has anyone had success with this?

How to consume the Github GraphQL API using Python?

I want to access details from Github using Github GraphQl v4 API. I found Graphene library, but I'm not sure how to authenticate with a personal access token in Python.
I tried to search on Google but couldn't found any example. It's Python library that can create graphical schema's and are not for consuming them, I tried with `requests' but failed. How can i authenticate and can find list of repositories?
I have used Github GraphQl explorer to find list of repositories via this code:
viewer {
repositories(first: 30) {
totalCount
pageInfo {
hasNextPage
endCursor
}
edges {
node {
name
}
}
}
Unlike rest, graphql has only one end point. You just need to do a POST with your query as a json object. You should provide your api_token you get from github as part of the headers.
import requests
url = 'https://api.github.com/graphql'
json = { 'query' : '{ viewer { repositories(first: 30) { totalCount pageInfo { hasNextPage endCursor } edges { node { name } } } } }' }
api_token = "your api token here..."
headers = {'Authorization': 'token %s' % api_token}
r = requests.post(url=url, json=json, headers=headers)
print (r.text)
Graphene is for building GraphQL APIs not for consuming them.
Did you see that: https://github.com/graphql-python/gql ?
It's a GraphQL client for Python.
Hope that's helpful.
As previous answers mentioned, calling GraphQL is as simple has making a POST request with the query string.
However, if you're on Python3 want something more advanced that'll also verify your queries during build and generate typed data-class response classes for you check out the new GQL library:
https://github.com/ekampf/gql
Exactly for GitHub, there is an example on using the Github GraphQL API with Python 3
https://gist.github.com/gbaman/b3137e18c739e0cf98539bf4ec4366ad
(check link as it has a lot of comments including better code for authentication)
# An example to get the remaining rate limit using the Github GraphQL API.
import requests
headers = {"Authorization": "Bearer YOUR API KEY"}
def run_query(query): # A simple function to use requests.post to make the API call. Note the json= section.
request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers)
if request.status_code == 200:
return request.json()
else:
raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))
# The GraphQL query (with a few aditional bits included) itself defined as a multi-line string.
query = """
{
viewer {
login
}
rateLimit {
limit
cost
remaining
resetAt
}
}
"""
result = run_query(query) # Execute the query
remaining_rate_limit = result["data"]["rateLimit"]["remaining"] # Drill down the dictionary
print("Remaining rate limit - {}".format(remaining_rate_limit))
And there are many Python GraphQL client libraries:
https://github.com/graphql-python/gql (aka https://github.com/ekampf/gql)
https://github.com/graphql-python/gql-next
https://github.com/prodigyeducation/python-graphql-client
Official list is at https://graphql.org/code/#python
(just scroll down, client libraries are after server libraries)

Sending a json object from extjs page to backend

I am new to Extjs. I wanted to know how can I send a json object to the backend from an extjs page. I am using python to connect to the databse. What I wanted to do was, if an user enters data on the form, that data to be transfered to the database. I am not getting any good tutorials online. Can someone please help??
Thanks in advance.
There are two ways to send Json Object from a form to the Server side for processing and saving in database.
1st way:
Ext.Ajax.request({
url : 'your-server-url-to-post-to',
method : 'POST', //or GET, PUT, DELETE.. case sensitive
jsonData : your-json-object
params : {
//your-request-parameters
},
success : function(response){ //callback function },
failure : function(response) { //callback failure function}
});
For direct form submission:
Ext.form.action.submit({
form : your-form-instance,
method : 'POST',
url : 'url-to-post-to',
params : {
//your request params
}
});
or another way of doing it is :
your-form.submit({
//same config options as above, except form : your-form-instance
});
Read the docs for more config options to suit your needs.. Documentation is pretty good. For learning a good coding style for ext js check out the examples that are part of the download package.

Categories