I am following a Amazon clone guide to get me started with React JS. While being 4 days in im getting stuck after processing my Orders. I am using Stripe, Firebase, Axios and Express to do this. After clicking the Buy now button im getting the error:
Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client_secret string. You specified: true.
Tried every possible solution and the videoguide doesnt get this error or discuss this error in anyway.
Thanks in advance!
I wouldnt mind sharing my github so youre getting a full look at all my codes if need be.
This is my payment page code:
import React, { useEffect, useState } from "react";
import { Link, useHistory } from "react-router-dom";
import CheckoutProduct from "./CheckoutProduct";
import "./Payment.css";
import { useStateValue } from "./StateProvider";
import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
import CurrencyFormat from "react-currency-format";
import { getBasketTotal } from "./reducer";
import axios from "./axios";
import {db} from "./firebase";
function Payment() {
const [{ basket, user }, dispatch] = useStateValue();
const history = useHistory();
const stripe = useStripe();
const elements = useElements();
const [processing, setProcessing] = useState(false);
const [succeeded, setSucceeded] = useState("");
const [error, setError] = useState(null);
const [disabled, setDisabled] = useState(true);
const [clientSecret, setClientSecret] = useState(true);
useEffect(() => {
//zorgt ervoor dat ik betalingen kan aannemen
const getClientSecret = async () => {
const response = await axios({
method: "post",
url: `/payments/create?total=${getBasketTotal(basket) * 100}`
});
setClientSecret(response.data.clientSecret);
};
getClientSecret();
}, [basket]);
console.log("Mijn geheim is >>>>", clientSecret);
const handleSubmit = async (event) => {
// Stripe betalingen
event.preventDefault();
setProcessing(true);
const payload = await stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
},
})
.then(({ paymentIntent }) => {
// betalingconfirmatie
// bestelhistorie uit mijn database halen
db.collection('users')
.doc(user?.id)
.collection('orders')
.doc(paymentIntent.id)
.set({
basket: basket,
amount: paymentIntent.amount,
created: paymentIntent.created
})
setSucceeded(true);
setError(null);
setProcessing(false);
dispatch({
type: "EMPTY_BASKET",
});
history.replace("/orders");
});
};
const handleChange = (event) => {
// Kijkt naar veranderingen in de Cardelement
// geeft errors aan wanneer de bezoeker zijn kaartgegevens niet goed intypt
setDisabled(event.emtpy);
setError(event.error ? event.error.message : "");
};
return (
<div className="payment">
<div className="paymentcontainer">
<h1>
Checkout (<Link to="/checkout">{basket?.length} items</Link>)
</h1>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Bezorgadres</h3>
</div>
<div className="paymentaddress">
<p>{user?.email}</p>
<p>Melkdistel</p>
<p>Almere, FL</p>
</div>
</div>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Artikelen</h3>
</div>
<div className="paymentitems">
{basket.map((item) => (
<CheckoutProduct
id={item.id}
title={item.title}
image={item.image}
price={item.price}
rating={item.rating}
/>
))}
</div>
</div>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Betalingsmethode</h3>
</div>
<div className="paymentdetails">
{/* Stripe */}
<form onSubmit={handleSubmit}>
<CardElement onChange={handleChange} />
<div className="paymentpriceContainer">
<CurrencyFormat
renderText={(value) => <h3>Order Totaal:{value}</h3>}
decimalScale={2}
value={getBasketTotal(basket)}
displayType={"text"}
thousandSeparator={true}
prefix={"$"}
/>
<button disabled={processing || disabled || succeeded}>
<span>{processing ? <p>Processing</p> : "Buy Now"}</span>
</button>
</div>
{/*Errors */}
{error && <div>{error}</div>}
</form>
</div>
</div>
</div>
</div>
);
}
export default Payment;
This is my index.js code or my server:
/* eslint-disable max-len */
const functions = require("firebase-functions");
const express = require("express");
const cors = require("cors");
const stripe = require("stripe")("sk_xxx");
// API
// App config
const app = express();
// Middlewares
app.use(cors({origin: true}));
app.use(express.json());
// API Routes
app.get("/", (request, response) => response.status(200).send("hello world"));
app.post("/payments/create", async (request, response) => {
const total = request.query.total;
console.log("Payment request received", total);
const paymentIntent = await stripe.paymentIntents.create({
amount: total,
currency: "usd",
});
// Good
response.status(201).send({
clientSecret: paymentIntent.client_secret,
});
});
// Listen mand
exports.api = functions.https.onRequest(app);
// http://localhost:5001/flowerpower-7c9f1/us-central1/api
I am following a Amazon clone guide to get me started with React JS. While being 4 days in im getting stuck after processing my Orders. I am using Stripe, Firebase, Axios and Express to do this. After clicking the Buy now button im getting the error:
Uncaught (in promise) IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client_secret string. You specified: true.
Tried every possible solution and the videoguide doesnt get this error or discuss this error in anyway.
Thanks in advance!
I wouldnt mind sharing my github so youre getting a full look at all my codes if need be.
This is my payment page code:
import React, { useEffect, useState } from "react";
import { Link, useHistory } from "react-router-dom";
import CheckoutProduct from "./CheckoutProduct";
import "./Payment.css";
import { useStateValue } from "./StateProvider";
import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
import CurrencyFormat from "react-currency-format";
import { getBasketTotal } from "./reducer";
import axios from "./axios";
import {db} from "./firebase";
function Payment() {
const [{ basket, user }, dispatch] = useStateValue();
const history = useHistory();
const stripe = useStripe();
const elements = useElements();
const [processing, setProcessing] = useState(false);
const [succeeded, setSucceeded] = useState("");
const [error, setError] = useState(null);
const [disabled, setDisabled] = useState(true);
const [clientSecret, setClientSecret] = useState(true);
useEffect(() => {
//zorgt ervoor dat ik betalingen kan aannemen
const getClientSecret = async () => {
const response = await axios({
method: "post",
url: `/payments/create?total=${getBasketTotal(basket) * 100}`
});
setClientSecret(response.data.clientSecret);
};
getClientSecret();
}, [basket]);
console.log("Mijn geheim is >>>>", clientSecret);
const handleSubmit = async (event) => {
// Stripe betalingen
event.preventDefault();
setProcessing(true);
const payload = await stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
},
})
.then(({ paymentIntent }) => {
// betalingconfirmatie
// bestelhistorie uit mijn database halen
db.collection('users')
.doc(user?.id)
.collection('orders')
.doc(paymentIntent.id)
.set({
basket: basket,
amount: paymentIntent.amount,
created: paymentIntent.created
})
setSucceeded(true);
setError(null);
setProcessing(false);
dispatch({
type: "EMPTY_BASKET",
});
history.replace("/orders");
});
};
const handleChange = (event) => {
// Kijkt naar veranderingen in de Cardelement
// geeft errors aan wanneer de bezoeker zijn kaartgegevens niet goed intypt
setDisabled(event.emtpy);
setError(event.error ? event.error.message : "");
};
return (
<div className="payment">
<div className="paymentcontainer">
<h1>
Checkout (<Link to="/checkout">{basket?.length} items</Link>)
</h1>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Bezorgadres</h3>
</div>
<div className="paymentaddress">
<p>{user?.email}</p>
<p>Melkdistel</p>
<p>Almere, FL</p>
</div>
</div>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Artikelen</h3>
</div>
<div className="paymentitems">
{basket.map((item) => (
<CheckoutProduct
id={item.id}
title={item.title}
image={item.image}
price={item.price}
rating={item.rating}
/>
))}
</div>
</div>
{/* payment*/}
<div className="paymentsection">
<div className="paymenttitle">
<h3>Betalingsmethode</h3>
</div>
<div className="paymentdetails">
{/* Stripe */}
<form onSubmit={handleSubmit}>
<CardElement onChange={handleChange} />
<div className="paymentpriceContainer">
<CurrencyFormat
renderText={(value) => <h3>Order Totaal:{value}</h3>}
decimalScale={2}
value={getBasketTotal(basket)}
displayType={"text"}
thousandSeparator={true}
prefix={"$"}
/>
<button disabled={processing || disabled || succeeded}>
<span>{processing ? <p>Processing</p> : "Buy Now"}</span>
</button>
</div>
{/*Errors */}
{error && <div>{error}</div>}
</form>
</div>
</div>
</div>
</div>
);
}
export default Payment;
This is my index.js code or my server:
/* eslint-disable max-len */
const functions = require("firebase-functions");
const express = require("express");
const cors = require("cors");
const stripe = require("stripe")("sk_xxx");
// API
// App config
const app = express();
// Middlewares
app.use(cors({origin: true}));
app.use(express.json());
// API Routes
app.get("/", (request, response) => response.status(200).send("hello world"));
app.post("/payments/create", async (request, response) => {
const total = request.query.total;
console.log("Payment request received", total);
const paymentIntent = await stripe.paymentIntents.create({
amount: total,
currency: "usd",
});
// Good
response.status(201).send({
clientSecret: paymentIntent.client_secret,
});
});
// Listen mand
exports.api = functions.https.onRequest(app);
// http://localhost:5001/flowerpower-7c9f1/us-central1/api
Share
Improve this question
edited May 21, 2021 at 20:49
Hicham Harmaz
asked May 21, 2021 at 1:08
Hicham HarmazHicham Harmaz
511 silver badge8 bronze badges
1 Answer
Reset to default 3Firstly, please don't share your Stripe secret keys!
The issue is that you're passing clientSecret: true
to the confirmCardPayment
method, which instead expects the client_secret
of a created PaymentIntent.
I note from the code you've provided that true
is the default value of your clientSecret
local React variable used in the confirmCardPayment
call. The error you're seeing likely indicates that this value is not updated (via setClientSecret
) following your API call to /payments/create
.
My remendation to you would be verify that the /payments/create
API does indeed create and return a PaymentIntent
object and introduce error handling to your sever function to throw if/when that Stripe API call fails.