Troubleshooting Stripe Payment Gateway using react and flask

16 views Asked by At

I am trying to implement a sample Stripe payment gateway using React.js in the frontend and Flask in the backend. The backend is designed such that it returns the client payment secret after getting my stripe api secret and an email. The frontend uses Stripe CardNumberElement, CardCvcElement and CardExpiry element, as shown in the code. however, when the pay button is triggered, i dont see anything in the console, except the console refreshing itself 2-3 times. As you can see that I also tried to log the fetched client secret to the console, but nothing is logged there as well, not even a log saying something like 'undefined'. I can confirm the backend is working fine as I used thunderclient to hit the request and it successfully fetched me the client secret. Would really appreciate if anyone helps me find the issue and correct my code accordingly. Here is the backend contoller code:

Also, please note that the stripe_api_key defined in the backend code is actually my stripe secret key.

# Payment route
@app.route("/pay", methods=['POST'])
def pay():
    
    stripe.api_key = stripe_api_key
    
    email= request.json.get("email", None)
    
    if not email:
        return "You need to send an email", 400
    
    intent = stripe.PaymentIntent.create(
        amount=90000,
        currency='inr',
        receipt_email=email
    )
    
    return {"client_secret":intent['client_secret']},200

and here is the react code in the frontend payment route page:

import React, { useEffect, useRef, useState } from 'react'
import {
    CardNumberElement,
    CardCvcElement,
    CardExpiryElement,
    useStripe,
    useElements,
} from "@stripe/react-stripe-js"
import CreditCardIcon from '@mui/icons-material/CreditCard';
import EventIcon from '@mui/icons-material/Event';
import VpnKeyIcon from '@mui/icons-material/VpnKey';
import { useNavigate } from 'react-router-dom';
import { collapseToast, toast } from "react-toastify"

import axios from "axios"

import './payment.css'



const Payment = () => {

    const stripe = useStripe()
    const elements = useElements()
    const payBtn = useRef(null)
    const navigate = useNavigate()

    const userEmail = '[email protected]'

    const submitHandler = async (e) => {
        if (!stripe || !elements) {
            return;
        }

        const res = await axios.post('http://localhost:5000/pay', {
            // email: userEmail,
        })

        const clientSecret = res.data['client_secret'];
        console.log(clientSecret)

        const result = await stripe.confirmCardPayment(clientSecret, {
            payment_method: {
                card:
                    elements.getElement(CardNumberElement),
                billing_details: {
                    email: userEmail,
                }
            }
        })

        if (result.error) {
            console.log('Payment failed:', result.error.message);
        } else {
            if (result.paymentIntent.status === 'succeeded') {
                console.log('Payment Successful')
            }
        }

    }

    return (
        <>
            <div className="paymentContainer">
                <form onSubmit={(e) => submitHandler(e)} className="paymentForm">
                    <span>Card Info</span>
                    <div>
                        <CreditCardIcon />
                        <CardNumberElement className='paymentInput' />
                    </div>
                    <div>
                        <EventIcon />
                        <CardExpiryElement className='paymentInput' />
                    </div>
                    <div>
                        <VpnKeyIcon />
                        <CardCvcElement className='paymentInput' />
                    </div>

                    <input type="submit"
                        value={`Pay - ₹500`}
                        ref={payBtn}
                        className='paymentFormBtn'
                    />


                </form>
            </div>
        </>
    )
}

export default Payment

Just in case you need it, I am also sending a part of my app.js where I imported the stripe elements and loadstripe

import React from 'react';
import {
  BrowserRouter as Router,
  Routes,
  Route,
} from 'react-router-dom'
import './App.css';
import Home from './components/Home';
import NotFound from './components/NotFound';
import LoginPage from './components/LoginPage';
import RegisterPage from './components/RegisterPage';
import Payment from './components/Payment';
//stripe imports
import { Elements } from "@stripe/react-stripe-js"
import { loadStripe } from '@stripe/stripe-js';
import CardInput from './components/CardInput';




const stripeApiKey = 'pk_test_51OsdA9SGDmMGS51Otr1bx9FEAGWmdZ44PRxEtsjGfYTKksgSLNp0aFtVmu3jQXUqWeAU00MYNcoCoo1fx92Phvmy00SMzMJu4r'


function App() {

  return (
    <>
      <Router>
        <Routes>
          {/* Other routes */}
          <Route exact path='/payment' element={
            <Elements stripe={loadStripe(stripeApiKey)}>
              <Payment />
            </Elements>
          } />

        </Routes>
      </Router>
    </>
  );
}

export default App;

0

There are 0 answers