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:
- Implement webhook to listen to the latest events from Stripe (you are already doing it) and save them to your database.
- 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