I have been using stripe checkout in my react application for about a week now. However, I now receive an error that says "Stripe Checkout can't communicate with our payment processor because the API key is invalid. Please contact the website owner or support#stripe.com." I have no idea why this is happening now. I just want to be able to send my total into the stripe modal.
stripe.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import { connect } from "react-redux";
import { purchase } from "../actions/StoreActions";
import { toast } from "react-toastify";
import StripeCheckout from "react-stripe-checkout";
const mapStateToProps = (state) => {
return {
cart: state.cart,
total: state.total
};
};
const mapDispatchToProps = (dispatch) => {
return {
purchase: (order) => {
dispatch(purchase(order));
}
};
};
function Stripe(props) {
console.log(props);
const [product] = React.useState({
name: `$${props.total}`,
price: props.total
});
async function handleToken(token, address) {
props.startLoading();
const response = await axios.post(
"https://storebe.herokuapp.com/checkout",
{
token,
product
}
);
const { status } = response.data;
if (status === "success") {
props.stopLoading();
console.log(address);
purchaseCartItems(address);
} else {
props.stopLoading();
toast("Failed, please try again", { type: "error" });
}
console.log(response.data);
}
return (
<div className="container">
<StripeCheckout
stripeKey="pk_test_51HF9J6FriexrfnPAT0b3P1wDiKx1YQzONJrB5F4ksTidko10JKZOTgo7zuPjj9NWquykYNnMz1GRyQ5LDI2HvrEF00U49BhKdn"
token={handleToken}
amount={props.total * 100}
billingAddress
shippingAddress
name={product.name}
/>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Stripe);
There isn't a way to validate if an API key is actually a valid Stripe API key.
The issue on your end is most likely because the publishable key in your code has a typo in it.
You just have to make sure that the API keys you copy from https://dashboard.stripe.com/test/apikeys are correct and don't have any copy paste errors like extra white space, etc.
Related
Expected type 'pa', but it was: a custom Promise object
Hello everyone, I am new on asking questions on Stack overflow so,
i need a guide to solve this issue here. Here in this code, I am trying to implement the Stripe checkout functionality to redirect the user to the stripe checkout page. But, when i click on the loadCheckout() button this error keeps coming. Can anybody help me fix this error ?
import { collection, getDocs, where, query, addDoc } from 'firebase/firestore/lite';
import { onSnapshot } from 'firebase/firestore';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { selectUser } from '../features/userSlice';
import db from '../firebase';
import './Plans.css';
import { loadStripe } from '#stripe/stripe-js';
const Plans = () => {
const [products, setProducts] = useState([]);
const user = useSelector(selectUser);
useEffect(() => {
if(collection) {
getDocs(query(collection(db, 'products'), where('active', "==", true)))
.then((querySnapshot) => {
const products = {}
querySnapshot.forEach(async (productDoc) => {
products[productDoc.id] = productDoc.data();
const priceSnap = await getDocs(query(collection(db, `products/${productDoc.id}/prices`)));
priceSnap.docs.forEach((price) => {
products[productDoc.id].prices = {
priceId: price.id,
...price.data(),
};
});
setProducts(products);
});
return querySnapshot;
});
}
}, []);
const loadCheckout = async (priceId) => {
const firstQ = collection(db, `customers/${user.uid}/checkout_sessions`);
const secondQ = query(
addDoc(firstQ, {
price: priceId,
success_url: window.location.origin,
cancel_url: window.location.origin,
})
);
onSnapshot(secondQ, async (snap) => {
const { error, sessionId } = snap.data();
if(error) {
// show error to the customer
// inspect the cloud function logs in the firebase console.
alert(`An error occurred: ${error.message}`);
}
if (sessionId) {
// we have a stripe checkout url, let's redirect
const stripe = await loadStripe(
'pk_test_51LnQj5K41BCUjAV1QSW7AAeX3XMzWJZLUNPNPKPKtHojs4wj9ECSky68tcluQQkCGMsgrA6wMQ58C0uYEWdUALja00CNIYgnnb');
stripe.redirectToCheckout({ sessionId });
}
});
}
return (
<div className='plans'>
{Object.entries(products).map(([productId, productData], index) => {
// add some logic to check if the user's subscription is active...
return (
<div key={index} className='plans__plan'>
<div className='plans__info'>
<h5>{productData.name}</h5>
<h6>{productData.description}</h6>
</div>
<button onClick={() => loadCheckout(productData.prices.priceId)}>
Subscribe
</button>
</div>
);
})}
</div>
)
}
export default Plans;
Error shown image
I am trying to write a function that will handle getting data to and from a server. This function takes the url to contact and uses the token to authorize itself against the server. This function is quite long. I would therefore want every other page in my react app to call this function with the needed url and then let this function handle everything else. I therefore need each page to await this function but I get "Error: Invalid hook call" no matter what I try.
This is the function that handles post requests to the server:
import React, { useEffect, useState, createRef, lazy, useContext } from "react";
import { UserContext } from "./UserContext";
import jwt_decode from "jwt-decode";
import axios from "axios";
export async function getProtectedAsset(url) {
const { user, setUser } = useContext(UserContext);
//If we do not have a token
if (user["userID"] == -1) {
return "Error: No token";
} else {
try {
//Get user data
const token = {
accessToken: user["accessToken"],
email: user["email"],
userID: user["userID"],
};
//Check if accessToken is about to expire (60s mairgain)
if (
Date.now() >=
jwt_decode(token["accessToken"])["exp"] * 1000 - 60000
) {
//Get new token
const res = await axios
.post("http://127.0.0.1:5002/refreshtoken", {
token: user["refreshToken"],
})
.then((res) => {
setUser({
userID: user["userID"],
email: user["email"],
accessToken: res.data["accessToken"],
refreshToken: user["refreshToken"],
accountType: user["accountType"],
});
})
.catch((err) => {
console.error(err);
});
}
//Our token is fresh
else {
const res = await axios
.post(url, token)
.then((promise) => {
return promise.data;
})
.catch((err) => {
console.error(err);
});
}
} catch (error) {
console.log(error);
throw err;
}
}
}
This is the page/component that I try to call this function from:
import React, { useState, useContext, useEffect, useCallback } from "react";
import { UserContext } from "../../UserContext";
import { getProtectedAsset } from "../../getProtectedAsset";
const Settings = () => {
const { user, setUser } = useContext(UserContext);
useEffect(async () => {
try {
let data = await getProtectedAsset("http://127.0.0.1:5002/mypage");
console.log(data);
} catch (error) {
console.error(error.message);
}
}, []);
return <></>;
};
export default Settings;
This gives me the error:
Invalid hook call. Hooks can only be called inside of the body of a
function component. This could happen for one of the following
reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug
and fix this problem.
I have tried everything I can imagine and read different tutorials/guides/docs but still cannot figure out the problem. Usually it is the lack of knowledge, or some thinking mistakes, but I really need help with this one!
Thank you for your help
Its because you are using useContext() hook inside getProtectedAsset() function.
Instead of using useContext inside getProtectedAsset try to pass user as parameter like url to the function.
let data = await getProtectedAsset(url, user);
// Want to show spinner while posting and then success/error message using react-toastify
Is it possible?
axios.post("/orders.json", order)
.then((response) => {
console.log(response.status);
})
.catch((error) => {
console.log(error);
});
import { toast } from "react-toastify";
const promise=axios.post("/orders.json", order)
const res = await toast.promise(promise, {
pending: "Posting",
success: "Posted",
error: "error message",
});
Yes it is possible. You can have a state called isLoading and you can set it to true when you submit a post request and you can check for isLoading before rendering your component like below.
if(isLoading) {
return (<Spinner />)
}
And you can use toast to show success/error message after post method is executed.
Like below
toast.error('Sorry request failed')
or
toast.success('Request successfull')
But before use toast you have wrap your App component in toast container like below.
import React from 'react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
function App(){
const notify = () => toast("Wow so easy!");
return (
<div>
<button onClick={notify}>Notify!</button>
<ToastContainer />
</div>
);
}
This will solve your question.
import React, { useEffect, useState } from "react";
import axios from "axios";
import { toast } from "react-toastify";
import 'react-toastify/dist/ReactToastify.css';
toast.configure({
position: toast.POSITION.BOTTOM_RIGHT
});
export default function App() {
const [state, setState] = useState({
loading: true,
dataArray: []
});
const myRequest = async () => {
try {
const request = await axios.get(`/generic_data/search_skills`);
const { error, msg, data } = request.data;
if (error) throw new Error(msg);
setState({ ...state, loading: false, dataArray: data });
toast.success("All good, we have the data");
} catch (e) {
toast.error("Upps, someting went wrong");
}
};
useEffect(()=>{
myRequest()
},[])
if (state.loading) {
return "Loading data from server.. this will take long time...";
}
return <div>The request has ended. We have the data</div>;
}
I am building a web application in which i need to verify the user's email sent via the client side (React.js and Next.js) and i'm following this youtube tutorial. However, the mentor is using create-react-app CLI and React-Router-Dom for the routing system which doesn't really go with my current needs.
Moreover, I found this method online using HOC :
import React from 'react';
import Router from 'next/router';
const login = '/register?redirected=true'; // Define your login route address.
const checkUserAuthentication = () => {
return { auth: null }; // change null to { isAdmin: true } for test it.
};
export default WrappedComponent => {
const hocComponent = ({ ...props }) => <WrappedComponent {...props} />;
hocComponent.getInitialProps = async (context) => {
const userAuth = await checkUserAuthentication();
// Are you an authorized user or not?
if (!userAuth?.auth) {
// Handle server-side and client-side rendering.
if (context.res) {
context.res?.writeHead(302, {
Location: login,
});
context.res?.end();
} else {
Router.replace(login);
}
} else if (WrappedComponent.getInitialProps) {
const wrappedProps = await WrappedComponent.getInitialProps({...context, auth: userAuth});
return { ...wrappedProps, userAuth };
}
return { userAuth };
};
return hocComponent;
};
The code above helps me to have a private route that the user cannot access unless he's authenticated (currently no programming included), but on the other hand i still need a page in the following route :
'pages/user/activate/[token].js' // the link sent via email from express back end.
What i need now is to create this page using Next routing system in order to get the token and decode it to move forward with the back end and save the user into MongoDB, and in order to accomplish that, i have created my [token].js page with the following code :
import React, {useState, useEffect} from 'react'
import { ToastContainer, toast } from 'react-toastify';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import { authenticate, isAuth } from '../helpers/auth';
import { Link, Redirect } from 'react-router-dom';
const Activate = ({ match }) => {
const [formData, setFormData] = useState({
email: '',
token: '',
show: true
});
const { email, token, show } = formData;
useEffect(() => {
let token = match.params.token;
let { email } = jwt.decode(token);
if (token) {
setFormData({ ...formData, email, token });
}
console.log(token, email);
}, [match.params.token]);
return (
<>
{isAuth() ? <Redirect to="/" /> : null}
<p>Account activated, please log in</p>
</>
)
};
export default Activate;
However, i keep getting this error :
TypeError: Cannot read property 'params' of undefined
at Activate (C:\Users\Hp\Desktop\SMP\client\.next\server\pages\user\activate\[token].js:245:13)
at processChild (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3353:14)
at resolve (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-
dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:3690:29)
at renderToString (C:\Users\Hp\Desktop\SMP\client\node_modules\react-dom\cjs\react-dom-
server.node.development.js:4298:27)
at Object.renderPage (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\server\render.js:53:851)
at Function.getInitialProps (C:\Users\Hp\Desktop\SMP\client\.next\server\pages\_document.js:293:19)
at loadGetInitialProps (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\lib\utils.js:5:101)
at renderToHTML (C:\Users\Hp\Desktop\SMP\client\node_modules\next\dist\next-
server\server\render.js:53:1142)
I couldn't find a solution because i believe that i'm doing something wrong whether in my code or in the logic implemented.
Is there any way that i can do this properly ?
Thank you in advance !
i'm french, sorry for my little english.
I've a problem with Reactjs and Firebase, an error when i want connect with Facebook. I look tutorial in Udemy platform. This is a video for learn React
REBASE: The Firebase endpoint you are trying to listen to must be a string. Instead, got undefined
Parts of code Admin.js :
import React, { Component } from 'react'
import AjouterRecette from './AjouterRecette'
import AdminForm from './AdminForm'
import Login from './Login'
import firebase from 'firebase/app'
import 'firebase/auth'
import base, { firebaseApp } from '../base'
class Admin extends Component {
state = {
uid: null,
chef: null
}
componentDidMount () {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.handleAuth({ user })
}
})
}
handleAuth = async authData => {
console.log(authData)
const box = await base.fetch(this.props.pseudo, { context: this })
if (!box.chef) {
await base.post(`${this.props.pseudo}/chef`, {
data: authData.user.uid
})
}
this.setState({
uid: authData.user.uid,
chef: box.chef || authData.user.uid
})
}
authenticate = () => {
const authProvider = new firebase.auth.FacebookAuthProvider()
firebaseApp
.auth()
.signInWithPopup(authProvider)
.then(this.handleAuth)
}
...
export default Admin
Thank's
Have a good day.
......................................................................................................................................................................................................................................................................................................................................................................................................
I've got exactly the same problem, probably because I follow the same training as you.
Your error is here :
const box = await base.fetch(this.props.pseudo, { context: this })
because this.props.pseudo is null.
in app.js, in the admin component, write
pseudo={this.props.match.params.pseudo}
and not
pseudo={this.state.pseudo}
and that shoudl work.
regards