Python Forum
How to create Flask-Stripe Checkout and Charge for the multiple items
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to create Flask-Stripe Checkout and Charge for the multiple items
#1
I am building an integration with Stripe by following the examples in its documentation, but I can't understand the part of creating a Charge for more than one product.

I was looking all over Stripe's docs and was searching for any articles / forums about the similar issue but was unable to find anything. I'd be very grateful to either some links to the articles on this matter or any tips to help me to understand how to solve it.

Here's a server side code:

@app.route("/checkout", methods=["GET", "POST"])
def checkout():
    if request.method == "POST":
        # Process a JSON string with a checkout information:
        # { item_id: item_quantity, ... }
        # Build the SQL query based on it
        items = {}
        shopping_cart = request.form["cart_checkout"]
        shopping_cart = shopping_cart.lstrip("{")
        shopping_cart = shopping_cart.rstrip("}")
        shopping_cart = shopping_cart.split(",")
        sqlQuery = "SELECT * FROM Items WHERE item_id IN ("
        for KeyValPair in shopping_cart:
            Key = KeyValPair.split(":")[0]
            Key = Key.strip('"')
            sqlQuery = sqlQuery + Key + ","
            Value = KeyValPair.split(":")[1]
            items[Key] = Value
        sqlQuery = sqlQuery.rstrip(",")
        sqlQuery = sqlQuery + ") ORDER BY item_id ASC"
        cart_items = sql_select(sqlQuery)

        # Add a column about the quantity of items
        for item in cart_items:
            item["quantity"] = items[item["item_id"]]

        # Build a Stripe checkout list
        line_items_list = []
        for item in cart_items:
            line_item = {}
            line_item["name"] = item["item_name"]
            line_item["description"] = item["item_description"]
            line_item["amount"] = item["price"]
            line_item["currency"] = "usd"
            line_item["quantity"] = item["quantity"]
            line_items_list.append(dict(line_item))

        stripe_session = stripe.checkout.Session.create(
            submit_type="pay",
            payment_method_types=["card"],
            line_items=line_items_list,
            success_url='https://example.com/success',
            cancel_url='https://example.com/cancel',
        )

        return render_template("checkout.html",
            stripe_id=stripe_session.id,
            stripe_pk=stripe_keys["PUBLIC_KEY"])

    return redirect("/")
And here's a part of HTML template:

<form action="/checkout" method="post" id="form_checkout" onsubmit="return cart_info()"
    ...
    <input type="hidden" name="cart_checkout" id="checkout_info" value="{{ cart_checkout }}">
    <script
        src="https://checkout.stripe.com/checkout.js" class="stripe-button"
        data-key="{{ stripe_pk }}"
        data-name="Company Name"
        data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
        data-description="A description of the product or service being purchased"
        data-amount="999"
        data-shipping-address="true"
        data-zip-code="true"
        data-allow-remember-me="true"
        data-panel-label="Pay"
        data-label="Checkout"
        data-locale="auto">
    </script>
</form>
If I do a simple example of Charge from Stripe docs, like this:

@app.route('/charge', methods=['POST'])
def charge():
    # Amount in cents
    amount = 500

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

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

    return render_template('charge.html', amount=amount)
Then I can create without any issues a successful test Charge, it displays with the success label in my Stripe's dashboard. But it just a charge for a single product. The issue is, if I use
stripe.checkout.Session.create()
, Stripe dashboard properly creates a record of an incomplete transaction from this Checkout session with the selected list of items, but I've no idea how to proceed from there to finalise the Charge for them.

If there are some more code details you require to help me to solve this issue, please ask, I'll update my post.
Reply
#2
I think you're on the right track with the Session. https://stripe.com/docs/payments/checkout/server

It looks like you create the session on the server side (flask), but the actual checkout is all client-side with javascript. Which makes sense, since the user will have to sign and whatnot. When you create the session, you should have a session id, which you then pass to the template so the javascript has access to it.

So in your template, something like the following should exist:
<script src="https://js.stripe.com/v3/"></script>

<script type="text/javascript">
var stripe = Stripe('your_api_key');

stripe.redirectToCheckout({
  // Make the id field from the Checkout Session creation API response
  // available to this file, so you can provide it as parameter here
  // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
  sessionId: '{{CHECKOUT_SESSION_ID}}'
}).then(function (result) {
  // If `redirectToCheckout` fails due to a browser or network
  // error, display the localized error message to your customer
  // using `result.error.message`.
});
</script>
Reply
#3
This is so typical of me Big Grin ! I have a "checkout.html" template with that code, but it didn't work, I was clicking on the button and there was literally 0 effect with no errors. So I assumed that I was missing something else and was looking for some more code that would be required.

The answer is, I've simply missed "" in
var stripe = Stripe({{ stripe_pk }});
Now it's all working perfectly! Here's my "checkout.html" template:

{% extends "layout.html" %}

{% block title %}Checkout{% endblock %}

{% block head %}
    <script src="https://js.stripe.com/v3/"></script>
{% endblock %}

{% block main %}

    <!-- Main content -->
    <div class="wrapper main-content">

        {% with messages = get_flashed_messages(with_categories=true) %}
            {% for category, message in messages %}
                <div class="alert alert-{{ category }}">{{ message }}</div>
            {% endfor %}
        {% endwith %}

        <h2 class="section-header">Checkout</h2>

        <p id="result_msg"></p>

        <button onclick="checkout()">Checkout</button>

    </div>

    <script type="text/javascript">
        function checkout() {
            var stripe = Stripe("{{ stripe_pk }}");

            stripe.redirectToCheckout({
                // Make the id field from the Checkout Session creation API response
                // available to this file, so you can provide it as parameter here
                // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
                sessionId: "{{CHECKOUT_SESSION_ID}}"
            }).then(function (result) {
                // If `redirectToCheckout` fails due to a browser or network
                // error, display the localized error message to your customer
                // using `result.error.message`.
                document.getElementById("result_msg").innerHTML = result.error.message;
            });
        }
    </script>

{% endblock %}
Reply
#4
Hi,

except the actual problem: the way JSON is "processed" and the way the SQL query is build is terrible.

Python's json module can convert strings containing JSON into a Python data structure. Formatting SQL queries is describe in the Python DB API 2.0.

I suggest to get a better understanding of Python first prior to building an online shopping system...

Regards, noisefloor
Reply
#5
Thanks for pointing that out. Yes, I knew that part should be modified, I wasn't going to leave it like this. I've started a new question, if you could take a look at it please. When I rebuilt that part of code I'm having an issue with getting SQL query to work with the variable amount of parameters.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Populating list items to html code and create individualized html code files ChainyDaisy 0 1,560 Sep-21-2022, 07:18 PM
Last Post: ChainyDaisy
  Flask Create global response function to be called from every where in the web app umen 2 2,255 Apr-14-2020, 09:54 PM
Last Post: umen
  Flask, Posgresql - Multiple requests are not working bmaganti 5 2,671 Feb-20-2020, 03:02 PM
Last Post: bmaganti
  Pass multiple items from one parse to another using Scrapy nazmulfinance 2 4,556 Jan-23-2020, 06:44 PM
Last Post: nazmulfinance
  Create .exe file for Python flask website. vintysaw 4 18,943 Nov-18-2019, 07:56 AM
Last Post: tonycstech
  display multiple sensors on webpage python flask jinja pascale 6 5,191 Jan-29-2019, 10:10 AM
Last Post: pascale
  Uploading multiple pdfs to Flask ( Sql alchmey) with additional variables KirkmanJ 10 9,374 Jul-27-2018, 09:49 AM
Last Post: KirkmanJ
  As a Free Lancer What Should I Charge? MIPython 0 1,994 Apr-12-2018, 06:41 PM
Last Post: MIPython
  Scrape Multiple items from a webpage Prince_Bhatia 2 3,292 Sep-12-2017, 06:08 AM
Last Post: Prince_Bhatia

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020