Home > database >  React (frontend) Express (backend) Stripe integration
React (frontend) Express (backend) Stripe integration

Time:09-27

I'm trying to implement stripe to my web app. I have integrated stripe checkout already and it works but I need to handle some logic in the frontend. I have done it with the previous version of Stripe but that seems to be deprecated now.

Basically what I need is if payment successful, do something else don't do it.(I know how to implement this logic)

What I don't know is how to send a response from backend to frontend after a successful payment.

I read about web sockets or something like that but I'm not too familiar and I have limited time. I rather avoid them if possible.

This is how I did it for the deprecated version, but now I can't do it with the newest stripe checkout version.

I'm a beginner sorry if it's not clear.

Thanks

async function handleToken(token, addresses) {
    const response = await axios.post(
        "https://btycwse.codesandbox.io/checkout",
      { token, product }
    );
    const { status } = response.data;
    
    console.log("Response:", response.data);
    if (status === "success") {
      console.log("Success! Check email for details");
      handleSubmit();
    } else {
      console.log("Something went wrong");
    }
  }

Backend (express.js)

// This is your test secret API key.
const stripe = require('stripe')('sk_test');
const express = require('express');
const app = express();

app.use(express.json())

const cors = require("cors")
app.use(
  cors({
    origin: "http://localhost:3000",
    
  })
)

const storeItems = new Map([
  [1, { priceInCents: 10000, name: "JavaScript Tutorial" }],
  [2, { priceInCents: 15000, name: "Ultimate CSS tutorial" }],
])

app.get("/", (req, res) => {
  res.send("Add your Stripe Secret Key to the .require('stripe') statement!");
});

app.post("/checkout", async (req, res) => {
  try {
    // Create a checkout session with Stripe
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ["card"],
      mode: "payment",
      // For each item use the id to get it's details
      // Take that information and convert it to Stripe's format
      line_items: req.body.items.map(({ id, quantity }) => {
        const storeItem = storeItems.get(id)
        return {
            price_data: {
            currency: "usd",
            product_data: {
              name: storeItem.name,
            },
            unit_amount: storeItem.priceInCents,
          },
          quantity: quantity,
        }
      }),
      // Set a success and cancel URL we will send customers to
      // They are complete urls
      success_url: "http://localhost:3000/success.html",
      cancel_url: "http://localhost:3000//cancel.html",
    })

    res.json({ url: session.url })

  } catch (e) {
    // If there is an error send it to the client
    res.status(500).json({ error: e.message })
   
  }
})

const bodyParser = require('body-parser');

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
  const event = request.body;

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      // Then define and call a method to handle the successful payment intent.
      // handlePaymentIntentSucceeded(paymentIntent);
      break;
    case 'payment_method.attached':
      const paymentMethod = event.data.object;
      // Then define and call a method to handle the successful attachment of a PaymentMethod.
      // handlePaymentMethodAttached(paymentMethod);
      break;
    // ... handle other event types
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  // Return a response to acknowledge receipt of the event
  response.json({received: true});
});


app.listen(4242, () => console.log('Running on port 4242'));

Frontend(ReactJS)

import React from "react";
import "./App.css";


export default function App() {



const handleCheckout = () => {
  fetch("http://localhost:4242/checkout", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    // Send along all the information about the items
    body: JSON.stringify({
      items: [
        {
          id: 1,
          quantity: 5,
        },
        {
          id: 2,
          quantity: 2,
        },
      ],
    }),
  })
   .then(res => {
      if (res.ok) return res.json()
      // If there is an error then make sure we catch that
      return res.json().then(json => Promise.reject
        (json))
    })
    .then(({ url }) => {
    
      // On success redirect the customer to the returned URL
      window.location = url
    })
    .catch(e => {
      console.log(e.error)
      
    })
  }

  return (
    <>
    
     <button type="submit" onClick={handleCheckout}>Checkout</button>
 
    </>

  );
}

CodePudding user response:

Per your assumption, there is no way to send a request from backend to frontend unless you use some WebSocket. The most closed approach is:

  1. Implement webhook to listen to the latest events from Stripe (you are already doing it) and save them to your database.
  2. In your redirected sucess_url (http://localhost:3000/success.html), send an AJAX request from frontend to backend and retrieve the latest data from your database in step 1.

CodePudding user response:

my suggestion is implement a webhook here

switch($payload){
  case 'invoice.paid':

  $a = $event->data->object;
    // do stuff e.g. 'talk' to your db, emails
  break;
  default:
       $body['eventDefaulted'] = 'Received unknown event type ' . $event->type;
  break;
 }

add (to make sure it doesn't timeout and stripe will throw an error at the beginning of the script)

// respond to stripe otherwise timeout
// Buffer all upcoming output...

// Send your response.

echo "recieved $event->type";

// // Get the size of the output.

$size = ob_get_length();

// // // Disable compression (in case content length is compressed).

header("Content-Encoding: none");

// // Set the content length of the response.

header("Content-Length: {$size}");
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("HTTP/1.1 200 OK");
http_response_code(200);

// // Close the connection.

header("Connection: close");

// // // Flush all output.

ob_end_flush();
ob_flush();
flush();

see api docs

then talk to you db with apis for invoice details

  • Related