0

I'm using Stripe API using Flask. I'm wondering how I can pass an arguments when switching the page as I do using redirect(url_for('')).

For example,

@app.route('/charge', methods=['POST'])
def charge():

    amount= #Amount in cents

    customer = stripe.Customer.create(
        email='customer@example.com',
        source=request.form['stripeToken']
        )

    charge = stripe.Charge.create(
         customer=customer.id,
         amount=amount,
         currency='usd',
         description='Test'
         )

When I finished inputting card info, the page is switched to other page and create token. Now I want to get the amount of the money from the previous page as an argument. But I don't know how to do it when using Stripe API.

Usually, I can do it like this answer does redirect while passing arguments

How can I do this?

I tried the first guy's way but it didn't work.

The previous page is like this On this page, users will input their card info using Stripe checkout window and after inputting, it redirect to charge page.

@app.route('/checkout', methods=['GET'])
def checkout():
    item_id = request.args['item_id']
    item = Item.query.filter_by(id=item_id).first()
    return redirect(url_for('charge', item_id=item_id), code=307)
    return render_template('checkout.html', title='Check Out',key=stripe_keys['publishable_key'], item=item)

When I entered this page, this error message appeared on the page:

Bad Request
The browser (or proxy) sent a request that this server could not understand

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

2

The solutions are the followings:

from flask import Flask, request 

@app.route('/previouspage/', methods=['GET'])
def previous_page():
   item = Item.query.filter_by(id=item_id).first()
   redirect(url_for('charge', amount=item.price), code=307)


@app.route('/charge/<amount>', methods=['GET', 'POST'])
def charge(amount):

    customer = stripe.Customer.create(
        email='customer@example.com',
        source=request.form['stripeToken']
        )

    charge = stripe.Charge.create(
        customer=customer.id,
        amount=amount,
        currency='usd',
        description='Test'
        )

But the more correct way to avoid passing path variables in URls is to use query strings instead (eg. charge?amount=10.0). Like this:

@app.route('/previouspage/', methods=['GET'])
def previous_page():
    item = Item.query.filter_by(id=item_id).first()
    return redirect(url_for('charge', amount=item.price), code=307)


@app.route('/charge', methods=['GET', 'POST'])
def charge():
    amount = request.args.get('amount')
    customer = stripe.Customer.create(
            email='customer@example.com',
            source=request.form['stripeToken']
            )

    charge = stripe.Charge.create(
        customer=customer.id,
        amount=amount,
        currency='usd',
        description='Test'
    )

Keep in mind that both approaches are not that safe because someone can change the price in url. So even better you should pass only the Item ID and fetch the item in /charge. Like this:

@app.route('/previouspage/', methods=['GET'])
def previous_page():
    return redirect(url_for('charge', item_id=item_id), code=307)


@app.route('/charge', methods=['GET', 'POST'])
def charge():
    amount = request.args.get('item_id')
    item = Item.query.filter_by(id=item_id).first()
    if not item:
        return '....some kind of error'

    customer = stripe.Customer.create(
            email='customer@example.com',
            source=request.form['stripeToken']
            )

    charge = stripe.Charge.create(
        customer=customer.id,
        amount=item.price,
        currency='usd',
        description='Test'
    )
  • Actually what I want to pass isn't part of form so I cannot do this. –  Apr 16 '18 at 06:30
  • what kind of data you want to pass? JSON? even if it's json you can do request.get_json() – Spiros I. Economakis Apr 16 '18 at 06:44
  • It's not form. It's just on of the columns in a datatable and set as a variable. like on the previous page, `item = Item.query.filter_by(id=item_id).first()` Item is defined like this and one of the column representing the price. I want to get it from the specific item –  Apr 16 '18 at 06:45
  • So usually I can pass a variable using `url_for`. –  Apr 16 '18 at 06:49
  • First the redirect `url_for` will return 302 and will move to `GET`. So what you need is this `redirect(url_for('charge', amount=item.price), code=307)`. updating also the code – Spiros I. Economakis Apr 16 '18 at 07:07
  • Isn't it redirect to `charge` right after I enter the previous page? Sorry I didn't know what `code=307` means but I will try your way anyway. Thanks a lot! –  Apr 16 '18 at 08:52
  • 307 is an http status code which tells to the browser to preserve the http post method because `redirect` in flask returns 302 so it will redirect without having the proper behavior you want – Spiros I. Economakis Apr 16 '18 at 09:41