3

Apologies if this seems rudimental as I am new to Python. The task I am trying to complete is to send a json object from an iPhone app to a python script that will process a stripe payment. The problem I have is I cannot figure out how to get Python to recognise the incoming json object to extract data from it and pass onto Stripe.

I have taken a step back to simplify the problem. I have a python script that attempts to post a json object with four value pairs to another function that should extract the values, create a new json object and return that object. I cannot get it to work and any help would be greatly appreciated as I've been stuck on this for a while. I am using Flask:

`
import json
import stripe
import smtplib
import requests

from flask import Flask, request, jsonify

@application.route('/run_post')
def run_post():
    url = 'http://xxx.pythonanywhere.com/stripetest'
    data = {'stripeAmount': '199', 'stripeCurrency': 'USD', 'stripeToken': '122', 'stripeDescription': 'Test post'}
    headers = {'Content-Type' : 'application/json'}

    r = requests.post(url, data, headers=headers)

    #return json.dumps(r.json(), indent=4)
    return r.text

@application.route('/stripetest', methods=["POST"])
def stripeTest():

    if request.method == "POST":

        json_dict = json.loads(request.body.raw)

        stripeAmount = json_dict['stripeAmount']
        stripeCurrency = json_dict['stripeCurrency']
        stripeToken = json_dict['stripeToken']
        stripeDescription = json_dict['stripeDescription']

        data = "{'stripeAmountRet': " +  stripeAmount + ", 'stripeCurrencyRet': " + stripeCurrency + ", 'stripeTokenRet': " + stripeToken + ", 'stripeDescriptionRet': " + stripeDescription + "}"

        return jsonify(data)
    else:

        return """<html><body>
        Something went horribly wrong
        </body></html>"""

`

I get the following returned in the error log when I run this:

`

2015-03-19 21:07:47,148 :Starting new HTTP connection (1): xxx.pythonanywhere.com
    2015-03-19 21:07:47,151 :Exception on /stripetest [POST]
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1687, in wsgi_app
        response = self.full_dispatch_request()
      File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1360, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1358, in full_dispatch_request
        rv = self.dispatch_request()
      File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1344, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/var/www/xxx_pythonanywhere_com_wsgi.py", line 156, in stripeTest
        json_dict = json.loads(request.body.raw)
      File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 336, in __getattr__
        return getattr(self._get_current_object(), name)
    AttributeError: 'Request' object has no attribute 'body'

`

dickiebow
  • 92
  • 1
  • 1
  • 12

2 Answers2

15

You have a couple of issues with the code. First of all, you need to properly define the json data when you make the request from the requests library. You can do this as follows:

@application.route('/run_post')
def run_post():
    url = 'http://xxx.pythonanywhere.com/stripetest'
    data = {'stripeAmount': '199', 'stripeCurrency': 'USD', 'stripeToken': '122', 'stripeDescription': 'Test post'}
    headers = {'Content-Type' : 'application/json'}

    r = requests.post(url, data=json.dumps(data), headers=headers)

    #return json.dumps(r.json(), indent=4)
    return r.text

Notice that we call json.dumps instead of just passing the data directly. Otherwise, the incoming request is not interpreted as json data.

Next, in your receiving function, we change it as follows:

@application.route('/stripetest', methods=["POST"])
def stripeTest():

    if request.method == "POST":
        json_dict = request.get_json()

        stripeAmount = json_dict['stripeAmount']
        stripeCurrency = json_dict['stripeCurrency']
        stripeToken = json_dict['stripeToken']
        stripeDescription = json_dict['stripeDescription']


        data = {'stripeAmountRet': stripeAmount, 'stripeCurrencyRet': stripeCurrency, 'stripeTokenRet': stripeToken, 'stripeDescriptionRet': stripeDescription}
        return jsonify(data)
    else:

        return """<html><body>
        Something went horribly wrong
        </body></html>"""

A couple of things are changed. First, we read in the data by calling request.get_json(), which properly parses the incoming json data. Note from above that we needed to change how we actually made the request for it to parse the data properly. The next issue was how you returned the data. To properly jsonify the data to return, we put the data into a python dictionary rather than into a string.

If you're calling your function to process the stripe payment from somewhere else (i.e. not using the python requests library), another issue is that you may not be defining the json request properly for Flask to later interpret. If the issue still persists after making the above change to the processing function, post how you're making the json request elsewhere and I can take a look.

Let me know if this fixes your problems!

Jason B
  • 7,097
  • 8
  • 38
  • 49
  • 1
    Hi Jason, thanks for taking the time to reply. The above solution worked and it's allowed me to move forward. Now I can read an incoming json object I should be able to link it successfully to my app. – dickiebow Mar 20 '15 at 15:21
0

You should check the document Flask requests

It does not define a body, instead you should try with

request.get_json()

You just need to make sure you are specifying the correct mimetype which would be "application/json".

See request.get_json() method for more info

ryentzer
  • 168
  • 2
  • 11
Zyber
  • 1,034
  • 8
  • 19