Programmer
Programmer

Reputation: 1294

Error implementing stripe payment in deployment (Heroku)

I am trying to implement Stripe payment system in my Heroku web application. Below you can see a html file which has a 'Purchase' button, which calls the javascript function 'MyFunction()' when clicked. After this happens, the javascript function calls the create_checkout_session() function in Flask (the Python file), which returns a session checkout ID to the javascript function, which redirects to the payment page. For some reason, the below process works perfectly on localhost, but fails when I deploy to Heroku. I get an error 500 in Heroku for some reason.

enter image description here

html file

  <section class="section">
    <div class="container">
      <button class="btn btn-outline-info" onclick="myFunction()" id="stripePay">Purchase!</button>
    </div>
  </section>


  <script>
    function myFunction() {


    //stripe
    // Get Stripe publishable key
      // Initialize Stripe.js
      const stripe = Stripe('pk_test_zcqqggPiGsbFA49H0BE4Mxj200AyZDDWnN');

      // new
      // Event handler
        // Get Checkout Session ID
        fetch("/create-checkout-session")
        .then((result) => { return result.json(); })
        .then((data) => {
          console.log(data);
          // Redirect to Stripe Checkout
          return stripe.redirectToCheckout(data)
        })
    };
</script>

Python file

@app.route("/create-checkout-session")
def create_checkout_session():
    domain_url = "http://localhost:5000/"
    stripe.api_key = stripe_keys["secret_key"]

        # Create new Checkout Session for the order
        # Other optional params include:
        # [billing_address_collection] - to display billing address details on the page
        # [customer] - if you have an existing Stripe Customer ID
        # [payment_intent_data] - capture the payment later
        # [customer_email] - prefill the email input in the form
        # For full details see https://stripe.com/docs/api/checkout/sessions/create

        # ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
        checkout_session = stripe.checkout.Session.create(
            success_url=domain_url + "success?session_id={CHECKOUT_SESSION_ID}",
            cancel_url=domain_url + "cancelled",
            payment_method_types=["card"],
            mode="payment",
            line_items=[
                {
                    "name": "T-shirt",
                    "quantity": 1,
                    "currency": "usd",
                    "amount": "2000",
                }
            ]
        )
        return jsonify({"sessionId": checkout_session["id"]})

EDIT:

Here is the error I get when clicking the 'Purchase' button on my deployed Heroku app. enter image description here

Upvotes: 3

Views: 1058

Answers (1)

Kebby
Kebby

Reputation: 329

From the logs screenshot, I am guessing this is because the processing time of your application is too long. Check that the service time is 383 ms

service=383ms

But Heroku does a timeout for the connection if it exceeds 300ms (link). That's why your application works locally but not on Heroku. In other words, you have to return some response before the timeout kicks in.

You can try these methods:

  1. Add a --timeout 400 option in the Procfile. Eg: web: gunicorn app:app --timeout 400
  2. Try to implement streaming response. For example, in Flask, you can use this code: https://flask.palletsprojects.com/en/1.1.x/patterns/streaming/ . You can find a similar one for your use case of the first option does not work.

Upvotes: 3

Related Questions