1

I am struggled with Stripe payment api. When I click the button after filled data and card number, It goes to the paymentSuccess page, but there are errors on the console. It said that Invalid API Key provided: undefined

enter image description here

Also, when I checked the stripe dashboard It said that no payment method. enter image description here

enter image description here

Stripe suggest me to make payment method , but on my code there is payment method. I don't know what is the problem.

This is my code

import React from 'react';
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';

//make the card elements 
const stripePromise = loadStripe(`${process.env.PUBLISHABLE_KEY}`);
console.log(stripePromise);
const CheckoutFormWrap = ({ children }) => {
  return (
    <div>
      <Elements stripe={stripePromise}>{children}</Elements>
    </div>
  );
};

CheckoutForm.js 
import React, { useState } from 'react';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
import BillingDetailsFields from './BillingDetailForm';
import axios from 'axios';
import styled from 'styled-components';

const CheckoutForm = ({ price, onSuccessfulCheckout }) => {
  const [isProcessing, setProcessingTo] = useState(false);
  const [checkoutError, setCheckoutError] = useState();

  const stripe = useStripe();
  const elements = useElements();

  const handleCardDetailsChange = ev => {
    ev.error ? setCheckoutError(ev.error.message) : setCheckoutError();
  };
  const handleFormSubmit = async e => {
    e.preventDefault();
    const billingDetails = {
      name: e.target.name.value,
      email: e.target.email.value,
      };

    setProcessingTo(true);
    const cardElement = elements.getElement(CardElement);

 
    const { data: clientSecret } = await axios.post("http://localhost:5000/pay",
      {amount: price}
    );
    console.log(clientSecret);

    const paymentMethodReq =  await stripe.createPaymentMethod({
      type: 'card',
      card: cardElement,
      billing_details: billingDetails,
    });
    
    const confirmCardPayment = await stripe.confirmCardPayment(clientSecret,{
      payment_method: paymentMethodReq.paymentMethod,
    })
    onSuccessfulCheckout();
    console.log(confirmCardPayment);
    if (paymentMethodReq.error) {
      setCheckoutError(paymentMethodReq.error.message);
      setProcessingTo(false);
      return;
    }


  };
  return (
    <form  onSubmit={handleFormSubmit}>
      <div>
        <CheckoutTitle>Pay with</CheckoutTitle>
        <BillingDetailsFields />
      </div>
      <div>
        <CardElementContainer>
          <CardElement
            onChange={handleCardDetailsChange}
          />
        </CardElementContainer>
      </div>
      <div>
        <PayBtn disabled={isProcessing || !stripe}>
          {isProcessing ? 'Processing...' : `Confirm and Pay`}
        </PayBtn>
      </div>
    </form>
  );
};
export default CheckoutForm;

server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const path = require('path');
if (process.env.NODE_ENV !== 'production') require('dotenv').config();
const stripe = require('stripe')(process.env.SECRET_KEY);

const app = express();
const port = process.env.PORT || 5000;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(cors());

if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, 'client/build')));

  app.get('*', function (req, res) {
    res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
  });
}
app.listen(port, error => {
  if (error) throw error;
  console.log('server running on port' + port);
});

app.post('/pay', async (req, res) => {
  if (req.method === 'POST') {
    try {
      const { amount } = req.body;
      const paymentIntent = await stripe.paymentIntents.create({
        amount,
        currency: 'usd',
        payment_method_types: ['card_present'],
      });
      res.status(200).send(paymentIntent.client_secret);
    } catch (err) {
      res.status(500).json({ statusCode: 500, message: err.message });
    }
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
});

Any ideas?

4
  • Are you sure you are using the right key, check you have TEST or LIVE key based on your environment, I would guess your passing the wrong key. Commented Jul 24, 2021 at 4:40
  • Hmm.. I get the key from the Stripe Developers API Keys. So I think the key is okay. What's the mean of TEST or LIVE key?!! Commented Jul 24, 2021 at 6:26
  • In stripe you can set developer mode - test or live mode. You would need to make sure you are using the right key, based on what mode you are in. The intent needs to be created with the same key as your request/client request for payment. Commented Jul 24, 2021 at 16:16
  • Thx! I am so stupied.. key was okay the problem was when I get the key from const stripePromise = loadStripe('${process.env.PUBLISHABLE_KEY}'); I think this cause the issue. Now When I just copy and paste key on cord directly it works! Commented Jul 26, 2021 at 3:13

1 Answer 1

1

I see two problems:

  1. Are you initializing Stripe.js using loadStripe and your publishable key, and setting the Elements provider like the docs say?
  2. In your call to confirmCardPayment you likely need to use paymentMethodReq.paymentMethod.id because createPaymentMethod returns an object.

Note that you don't need to make two calls. You could combine the payment method creation and payment intent confirmation into a single step, as shown here:

const result = await stripe.confirmCardPayment('{CLIENT_SECRET}', {
  payment_method: {
    card: cardElement,
    billing_details: billingDetails,
  }
});
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for you reply! 1) I have loadStripe on the other components (I updated on my question ) 2) I remove id becuase, when I put the paymentMethodReq.paymentMethod.id , Console said that 'Unhandled Rejection (TypeError): Cannot read property 'id' of undefined'
Also, you said that I dont need to make two call. That's means , I have two call on server.js and CheckForm.js?? So I should remove one of them?!
The first issue likely because an error is returned, instead of the paymentMethod you expect, which might also be related to the API key error. Are you sure Stripe.js is initialized as needed for react? Are you seeing any successful requests from your client app?
I meant just in the client code where you call createPaymentMethod then confirmCardPayment can be combined into a since request within confirmCardPayment with the appropriate payment method params included.
Thx ! I solve it it was key problem. I mean, when I save the key on the .env there were problem. Also I remove the duplicated code base on your saying. Now code looks more clear!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.