Fiddled around with python-oauth2 and flattr

[UPDATE] This entry is not really valid any more, since flattr is switching to a rewritten api v2 . I will write a few words about v2 when I know how it works... And so I did :) [/UPDATE]

Because I like the idea of Flattr , I just fiddled around a little bit with python-oauth2 and Flattr's API .

This are the first steps of allowing your webapp to create a new thing on Flattr . This is very useful if you are running a podcast or blogging software, and you want to create a thing for each new entry or episode. So it's possible to flattr each of them separately, instead of the entire podcast/blog. E.g. there is a flattr plugin for Wordpress .

Remember this code is far away from being ready to use.

There are libraries for PHP , Ruby , as well as a community library for Java .

My entry point was the developer wiki of Flattr and the python-oauth2 documentation . It's also useful if you know the basics about oauth .

First of all, you need an account on Flattr , and register your webapp to retrieve the customer_keyand customer_secret. You have to choose browseras application type. At this point, you already have to know a callback_url.

You also have to install python-oauth2 into your python environment.

So let's play:

Let's create the customer:

>>> key='YOUR_CUSTOMER_KEY'

>>> secret='YOUR_CUSTOMER_SECRET'
>>> consumer = oauth.Consumer(key, secret)
>>> method = oauth.SignatureMethod_HMAC_SHA1()

Get the request token:

>>> params = {'oauth_consumer_key': key,

... 'oauth_timestamp': oauth.Request.make_timestamp(),
... 'oauth_nonce': oauth.Request.make_nonce(),
... 'oauth_version': oauth.Request.version,
... 'oauth_callback': 'YOUR_REGISTERED_CALLBACK_URL'}
>>> req = oauth.Request(url='https://api.flattr.com/oauth/request_token',
... parameters=params)
>>> req.sign_request(method, consumer, None)
>>> http = httplib2.Http(disable_ssl_certificate_validation=True)
>>> ret = http.request(req.to_url())
>>> ret
({'-content-encoding': 'gzip',
 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0',
 'connection': 'close',
 'content-length': '158',
 'content-location': u'https://api.flattr.com/oauth/request_token?oauth_body_hash=SOME_HASH&oauth_nonce=75294181&oauth_timestamp=1318517637&oauth_consumer_key=YOUR_KEY&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=SIG&oauth_callback=http%3A%2F%2FYOUR_CALLBACK_URL',
 'content-type': 'application/x-www-form-urlencoded',
 'date': 'Thu, 13 Oct 2011 14:54:22 GMT',
 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT',
 'pragma': 'no-cache',
 'server': 'lighttpd',
 'set-cookie': 'PHPSESSID=GENERATED_SESSION_ID; path=/; domain=.flattr.com; HttpOnly',
 'status': '200',
 'strict-transport-security': 'max-age=500',
 'vary': 'Accept-Encoding'},
 'oauth_token=NEW_REQUEST_TOKEN&oauth_token_secret=NEW_REQUEST_TOKEN_SECRET&oauth_callback=http://YOUR_CALLBACK_URL&oauth_callback_confirmed=true')

Unfortunately, in this code we are not able to use buildin clientof python-oauth2, because it is not possible to pass the callback_urlto client. However, we are able to fetch the request token with oauth2's Requestand httplib2.

In a real application, you have to store the request token and the secret permanently (of course, you only need it to get the access token).

>>> parse_ret = parse_qs(ret[1])

>>> request_token = parse_ret['oauth_token'][0]
>>> request_token_secret = parse_ret['oauth_token_secret'][0]

Once you have the request token, you must send the user (yourself) to Flattr, to authorize your webapp. Here, you only request permissions for readand publish. However, have a look at https://developers.flattr.net/doku.php/user_authentication for further information:

>>> 'https://api.flattr.com/oauth/authenticate?access_scope=read,publish&%s' % ret[1]

'https://api.flattr.com/oauth/authenticate?access_scope=read,publish&oauth_token=NEW_REQUEST_TOKEN&oauth_token_secret=NEW_REQUEST_TOKEN_SECRET&oauth_callback=http://YOUR_CALLBACK_URL&oauth_callback_confirmed=true'

The user (yourself) permits the webapp, and will be redirected to the configured callback_url. After that, you will find the oauth_verifierin the redirected url.

e.g. if you configured http://example.com/flattras callback_url, you will be redirected to http://example.com/flattr?oauth_token=NEW_REQUEST_TOKEN&oauth_verifier=VERIFIER_NUMBER

With your request token and the obtained oauth_verifier, you can fetch the access token. From this point python-oauth2 works fine, and we do not need to work around.

Create a token with the oauth_verifier:

>>> oauth_verifier=843099

>>> token = oauth.Token(request_token, request_token_secret)
>>> token.set_verifier(oauth_verifier)

Now you can use your consumerand the new tokento create a python-oauth2 client:

>>> client = oauth.Client(consumer, token)

The creation and signing of the request is now done by client. You do not have take care on it. You just have to pass the correct api url:

>>> ret = client.request('http://api.flattr.com/oauth/access_token', 'POST')

>>> ret
({'-content-encoding': 'gzip',
 'cache-control': 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0',
 'connection': 'close',
 'content-length': '96',
 'content-type': 'application/x-www-form-urlencoded',
 'date': 'Thu, 13 Oct 2011 14:55:38 GMT',
 'expires': 'Thu, 19 Nov 1981 08:52:00 GMT',
 'pragma': 'no-cache',
 'server': 'lighttpd',
 'set-cookie': 'PHPSESSID=i6md2vqg8t84hri1hk4r7448c3; path=/; domain=.flattr.com; HttpOnly',
 'status': '200',
 'vary': 'Accept-Encoding'},
 'oauth_token=NEW_ACCESS_TOKEN&oauth_token_secret=NEW_ACCESS_TOKEN_SECRET')
>>> parse_ret = parse_qs(ret[1])
>>> access_token = parse_ret['oauth_token'][0]
>>> access_token_secret = parse_ret['oauth_token_secret'][0]

You have to store the access token and the secret permanently. It is valid, till the user (yourself) rejects the permission on Flattr (Settings -> Tab Application). Now you can delete the request token and secret (request not the access token!!!)

Your application is registered now, and you granted the necessary permissions. In this case readand publish. Use the consumer and the access token to speak with Flattr API .

E.g. request your user information. It is again very easy to use python-oauth2 without work arounds:

>>> token = oauth.Token(access_token, access_token_secret)

>>> client = oauth.Client(consumer, token)
>>> ret = client.request('http://api.flattr.com/rest/0.0.1/user/me', 'GET')
>>> ret
({'-content-encoding': 'gzip',
 'connection': 'close',
 'content-length': '276',
 'content-location': u'http://api.flattr.com/rest/0.0.1/user/me?oauth_body_hash=SOME_HASH&oauth_nonce=55948733&oauth_timestamp=1318518733&oauth_consumer_key=APPS_KEY&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=YOUR_ACCESS_TOKEN&oauth_signature=SOME_SIG',
 'content-type': 'text/xml',
 'date': 'Thu, 13 Oct 2011 15:12:13 GMT',
 'server': 'lighttpd',
 'status': '200',
 'vary': 'Accept-Encoding'},
 '<?xml version="1.0" encoding="utf-8"?>\n
  <flattr>
   <version>0.0.1</version>
   <user><id>YOUR ID</id>
    <username>YOUR USERNAME</username>
    <firstname>YOUR NAME</firstname>
    <lastname>YOUR LAST NAME</lastname>
    <description></description>
    <thingcount>2</thingcount>
    <language>en_GB</language>
   </user>
  </flattr>\n')

For a ... hmm, not really complete ... documentation of what you can do, have a look at the Flattr API documentation .

Hoping to give some inspiration.