I am trying to work through some code to connect to merchantos.com's rest API via Python.
With some research, I have managed to get the GET access working, using the following urllib2 code:
# NOTE: This api key has been made bogus
lcMOS_APIKey = '07203c82fab495xxxxxxxxxxxxxxxxxxxc2a499c'
# also bogus...
lcMOS_Acct = '98765'
lcBaseURL = 'https://api.merchantos.com/API/Account/' + lcMOS_Acct + '/'
# create a password manager
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None, lcBaseURL, lcMOS_APIKey, 'apikey')
# create "opener" (OpenerDirector instance)
handler = urllib2.HTTPBasicAuthHandler(password_mgr)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
# use the opener to fetch a URL
#loReturn = opener.open(lcBaseURL + lcURLEnd)
loReturn = opener.open(lcBaseURL + 'Customer.xml?firstName=Alex')
lcResponse = loReturn.read()
So, the above successfully pulls data back. I get an XML of the customer record.
Now, what I need to do is change the method so that I can do a PUT (for an update) and a POST (for a create/new).
MerchantOS requires the following for an update:
UPDATE / HTTP PUT
To update an existing record/object you do an HTTP PUT request. The put/post data should be an XML block defining the updates to the object. For example to update an Item you would PUT to API/Account/1/Item/2 with an block (1 is the account number and 2 the itemID in this example).
So, for example, I want to do a PUT to update customer ID = 2
I would provide a data reference to an XML block for the
<Customer>
..contents omitted here...
</Customer>
And, I am to point it to theURL.
The problems I am facing here are..
I do not know where/how to change the method to PUT
I need top know how to attach my data block and post it
So, can someone please show me how to adapt the above code for a GET to make a PUT .. as well as a POST (for creating a new record)
Thanks, in advance, for any assistance in this regard.
Scott.
You might try cURL instead of urllib. cURL is extremely flexible and addresses your needs:
http://pycurl.sourceforge.net/
Here are two of the options you can set with cURL:
CURLOPT_POST: A parameter set to 1 tells the library to do a regular HTTP post...
CURLOPT_POSTFIELDS: The full data to post in a HTTP POST operation...
Related
I have made a flask/python website which can create and edit events on a user's google calendar. Obviously the user has to give their permission via OAuth2 (which I struggled to understand but managed to make work in the end). Currently I am forcing the user to register and login to my site and I store various user settings and the refresh token attached to whatever username they select when they register with my site.... But now I want the user to be able to allow the user the use my site without having to register. I still want to store user settings and a refresh token but now I need to have some sort of label to identify the user so I know it's them when they come back (perhaps they will access my site from a different PC). Is there some string that I will have access to as part of the OAuth2 process that would serve to uniquely identify the user or do I need to do some additional step to grab such a string...
EDIT: looking at the comment made by shox and looking at the most upvoted answer to this SO question it seems that at the end of the oauth process I should...
send a GET to https://www.googleapis.com/oauth2/v3/userinfo, using the
OAuth2 bearer token you just received, and you will get a response
with some information about the user (id, name, etc.).
Unfortunately I'm not quite sure what that means nor how to code it in python. My best guess was as follows:
r = requests.get( "https://www.googleapis.com/oauth2/v3/userinfo",
params = {'token': credentials.token } )
data = r.json()
But data turns out to be {'error': 'invalid_request', 'error_description': 'Invalid Credentials'}
SOLVED: ... seems I needed to use the string "access_token" instead of "token" and now data contains an email address and a few other bits and bobs.
r = requests.get( "https://www.googleapis.com/oauth2/v3/userinfo",
params = {'access_token': credentials.token } )
data = r.json()
One way to uniquely identify a Google user via OAuth 2.0 is to record the user's unique identifier. That identifier is known as the id property of the Source object.
To read that identifier you'll need to make a call to People.get() with people/me as the resourceName and metadata as personFields. The first value will identify the authorized account as the one that we are interested in. In the second parameter, personFields, we are indicating that we want metadata about the target account. The latter isn't needed per se, but because we need to fill a valid value in personFields. In summary, the request should look like this (if done with cURL):
curl \
'https://people.googleapis.com/v1/people/me?personFields=metadata&key={API KEY}' \
--header 'Authorization: Bearer {ACCESS TOKEN}' \
--header 'Accept: application/json' \
--compressed`
With that request you'll get a JSON response which first lines will read:
{
"resourceName": "people/{ID HERE}",
…
That would be the id that you want to use for user identification. Please, ask me any question if you need more help.
I am a beginner to the Django framework and I am building a Django app that uses the Slack RTM API.
I have a coded a program in python that performs the OAuth authentication process like so :
def initialize():
url="https://slack.com/api/rtm.connect"
payload={"token":"xxx"}
r=requests.post(url,payload)
res=json.loads(r.text)
url1=res['url']
ws = create_connection(url1)
return ws
My Requirement:
The stream of events I receive (from my slack channel that my slack app is added to) is processed to filter out events of the type - message ,then match the message with a regex pattern and then store the matched string in a database.
As a stand alone python program I am receiving the stream of events from my channel.
My questions:
How do I successfully integrate this code to Django so that I can
fulfill my requirement?
Do I put the code in templates/views? What is the
recommended method to process this stream of data?
def initialize():
url = "https://slack.com/api/rtm.connect"
r = requests.get(url, params={'token': '<YOUR TOKEN>'})
res = r.json()
url1=res['url']
ws = create_connection(url1) #Note: There is no function called create_connnection() so it will raise an error
return ws
if you read the API web methods, you see :
Preferred HTTP method: GET
See here: Slack rtm.connect method
look at the comment, and thats the right code, see the differences between this code and yours.
basically to get JSON from a request don't use json.loads because this search your local computer not the request
use r.json() so it call the json you got from r.
Note that r.text will return raw text output so when you want to get url it will not be identified, with r.json you can call the object url as stated about
Hope this help.
and please could you tell us more what you wanna do with this in view ? because template is a directory which contains all the HTML files which you don't need to work with.
but why views.py ?
I'm working on a Rails 4 / mongoid application which needs to expose APIs for other applications and scripts. I need to be able to update documents in one of the models through an API with Python 3 script. I'm a bit fresh with Python hence asking for help here.
I already found out how to query Rails APIs with Python 3 and urllib but struggling with updates. I was trying to go through Python 3.5 docs for urllib2 but struggling to apply this to my script.
What goes to data and how to add authentication token to headers, which in curl would look something like this
-H 'Authorization:Token token="xxxxxxxxxxxxxxxx"'
-X POST -d "name=A60E001&status=changed"
I would greatly appreciate if somebody explained how to, for example, update status based on name (name is not unique yet but will be). My biggest challenge is the Python side. Once I have the data in params on Rails side I think I can handle it. I think.
I included my model and update action from the controller below.
app/models/experiment.rb
class Experiment
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :status, type:String
end
app/controllers/api/v1/experiments_controller.rb
module Api
module V1
class ExperimentsController < ActionController::Base
before_filter :restrict_access
...
def update
respond_to do |format|
if #expt_proc.update(expt_proc_params)
format.json { render :show, status: :ok, location: #expt_proc }
else
format.json { render json: #expt_proc.errors, status: :unprocessable_entity }
end
end
end
...
private
def restrict_access
authenticate_or_request_with_http_token do |token, options|
ApiKey.where(access_token: token).exists?
end
end
...
I figured out who to send a PATCH request with Python 3 and update the the record's status by name.
Thanks to this post found out about requests module. I used requests.patch to update the record and it works great.
python code
import requests
import json
url = 'http://0.0.0.0:3000/api/v1/update_expt_queue.json'
payload = {'expt_name' : 'myExperiment1', 'status' : 'finished' }
r = requests.patch(url, payload)
There are two problems remaining:
How to add headers to this request which would allow me to go through token based authentication. At the moment it's disabled. request.patch only takes 2 parameters, it doesn't take headers parameter.
How to access the JSON which is sent in response by Rails API.
I am trying to create a set on Quizlet.com, using its API found here: https://quizlet.com/api/2.0/docs/sets#add
Here is my code of a set I am trying to create:
import requests
quizkey = my_client_id
authcode = my_secret_code # I'm not sure if I need this or not
data = {"client_id":quizkey, "whitespace":1, "title":"my-api-set",
"lang_terms":"it", "lang_definitions":"en",
"terms":['uno','due'], "definitions":["one","two"]}
apiPrefix = "https://api.quizlet.com/2.0/sets"
r = requests.post(url=apiPrefix, params=data)
print r.text
The response is:
{
"http_code": 401,
"error": "invalid_scope",
"error_title": "Not Allowed",
"error_description": "You do not have sufficient permissions to perform the requested action."
}
I also tried "access_token":authcode instead of "client_id":quizkey, but this resulted in the error: "You do not have sufficient permissions to perform the requested action."
How can I fix this and not get a 401 error?
Alright so 3 and a half years later (!!) I've looked into this again and here's what I've discovered.
To add a set you need an access token - this is different to the client_id (what I call quizkey in my code), and to be quite honest I don't remember what authcode in my code is.
This token is obtained by going through the user authentication flow. To summarise it:
Send a POST request to https://quizlet.com/authorize like so:
https://quizlet.com/authorize?response_type=code&client_id=MY_CLIENT_ID&scope=read&state=RANDOM_STRING
Keep the response_type as code, replace client_id with your client_id, keep the scope as read, and state can be anything
I believe this requires human intervention because you're literally authorising your own account? Not sure of another way...
You'll receive a response back with a code
Let's call this RESPONSE_CODE for now
Send a POST request to https://api.quizlet.com/oauth/token, specifying 4 mandatory parameters:
grant_type="authorization_code" (this never changes)
code=RESPONSE_CODE
redirect_uri=https://yourredirecturi.com (this can be found at your personal API dashboard)
client ID and secret token separated by a colon and then base64-encoded (the user authentication flow link above tells you what this is if you don't want to do any of the encoding)
You'll receive the access_token from this API call
Now you can use that access_token in your call to create a set like I've done above (just replace "client_id":quizkey with "access_token":access_token)
You will need to authenticate in order to make sets. This link gives an overview:
https://quizlet.com/api/2.0/docs/making_api_calls
And this one provides details about the authentication process:
https://quizlet.com/api/2.0/docs/authorization_code_flow
I'm interested in writing a python script to log into Facebook and then request some data (mainly checking the inbox). There are few nice examples out there on how to do this. One interesting script i found over here and there is some nice example on stackoverflow itself.
Now i could just copy-paste some of the code i need and get to do what i want, but that wouldn't be a good way to learn. So i am trying to understand what i am actually coding and can't understand some elements of the script in the first example, namely: what is a post_form_id?
Here is the section of the code which refers to "post_form_id" (line 56-72):
# Initialize the cookies and get the post_form_data
print 'Initializing..'
res = browser.open('http://m.facebook.com/index.php')
mxt = re.search('name="post_form_id" value="(\w+)"', res.read())
pfi = mxt.group(1)
print 'Using PFI: %s' % pfi
res.close()
# Initialize the POST data
data = urllib.urlencode({
'lsd' : '',
'post_form_id' : pfi,
'charset_test' : urllib.unquote_plus('%E2%82%AC%2C%C2%B4%2C%E2%82%AC%2C%C2%B4%2C%E6%B0%B4%2C%D0%94%2C%D0%84'),
'email' : user,
'pass' : passw,
'login' : 'Login'
})
Would you be so kind to tell me what a post_form_id is? And accessorily: would you know what the lsd key/value stands for?
Thanks.
I don't understand why you are trying to "hack" this ...
There is an official api from facebook to read the mailbox of a user, and you need to ask the "read_mailbox" permission for this.
So I advice you to check my post here on how to use facebook and python/django together, and how to login to facebook from python.
And then I would recommend you to read the facebook doc about the messages/inbox.
Basically you need an access_token then you can do http://graph.facebook.com/me/inbox/?access_token=XXX
You can also ask for the "offline_access" permission so you'll need only to get an access token once and you will be able to use it "forever"
And the you can do http://graph.facebook.com/MESSAGE_ID?access_token=XXX to get the details about a particular message.
Or using the api I use in the other thread :
f = Facebook()
res = f.get_object("me/inbox")
...
Feel free to comment if you have any question about this ?