Sanjeev_gupta2812
Sanjeev_gupta2812

Reputation: 236

Stripe card details auto fill not wokring

I am using stripe for the pyament methods but unable to pre fill the fields although I am providing the payment_method_ID in the intent being created.

//Creating customer if does not exist 
customer = await stripe.customers.create({
                        email : user.email || null,
                        description : 'Helpaas Offer',
                        name : user.name || null
                    });
//Creating Payment Intent

const paymentIntent = await stripe.paymentIntents.create({
                    amount: amount || 100,
                    currency: "Eur",
                    customer : 'cus_L89XOh7b8Z3aCt',
                    payment_method : 'card_1KTnI8Hbhjmc0b01rYAY7YfC', // for now static
                    automatic_payment_methods: {
                        enabled: true,
                      },
                });
                resolve({clientSecret:  paymentIntent }) // sending back to FrontEnd

This is how I am handling the Payment Intent in my Reactjs.

{ cartDetails && cartDetails.length > 0 && Object.values(clientSecret).length > 0 ?
                        <Elements stripe={stripePromise} options={{'clientSecret' : clientSecret}}>
                            <InjectedCheckoutForm items={cartDetails} />
                        </Elements> : ''
                      }

Here is my Component.

export default function InjectedCheckoutForm(props) {
const [succeeded, setSucceeded] = useState(false);
const [error, setError] = useState(null);
const [processing, setProcessing] = useState(false);
const [disabled, setDisabled] = useState(true);
const [saveCard, setSaveCard] = useState(false)
const [clientSecret, setClientSecret] = useState('');
const stripe = useStripe();
const elements = useElements();

const [appearance,SetAppearance] = useState({theme: 'night'}) 


useEffect(()=>{

  if (!stripe) {
    return;
  }
  // Retrieve the "payment_intent_client_secret" query parameter appended to
  // your return_url by Stripe.js
  const clientSecret = new URLSearchParams(window.location.search).get(
    'payment_intent_client_secret'
  );

  // Retrieve the PaymentIntent
  if(clientSecret){
    setProcessing(true)
    stripe
    .retrievePaymentIntent(clientSecret)
    .then(({paymentIntent}) => {
      // Inspect the PaymentIntent `status` to indicate the status of the payment
      // to your customer.
      //
      // Some payment methods will [immediately succeed or fail][0] upon
      // confirmation, while others will first enter a `processing` state.
      //
      // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification
      // alert(paymentIntent.status);
      console.log(paymentIntent,"CHEKC T?E PAYMENT INTENT RECIEVED...")
      switch (paymentIntent.status) {
        case 'succeeded':
          saveOrder(paymentIntent,props['items']);
          break;
        case 'processing':
          toastr.info("Payment processing..." ,"We'll update you when payment is received.");
          window.history.pushState({},'','/order');
          window.location.reload();
          break;

        case 'requires_payment_method':
          // Redirect your user back to your payment page to attempt collecting
          // payment again
          toastr.error('Payment failed.','Please try another payment method.');
          break;

        default:
          toastr.error('','Something went wrong.');
          break;
      }
    });
  }
  
},[stripe]);

const saveOrder = async (paymentIntent,orderDetails)=>{
  if (paymentIntent['status'] === "succeeded" || paymentIntent['status'] === "pending") {
    // save the order in the database
    orderService.saveOrder({
      ClientID: store.get('userDetails')?.ClientID,
      OrderDetails: orderDetails,
      PaymentDetails: paymentIntent,
      status : paymentIntent['status'],
      OfferID : orderDetails[0].OfferID,
      PriceTotal : paymentIntent['amount'],
      OrderedBy : store.get('userDetails').displayName,
      Buyer : store.get('userDetails').mail,
      Seller : orderDetails[0].DisplayName ,
      ItemDetails : orderDetails,
      StripePaymentMethod : paymentIntent['payment_method'],
      Quantity : orderDetails.length || 1,
      stripePaymentID : paymentIntent['id']

    })
      .then(data => data.json())
      .then(response => {
        if (response['statusCode'] === 200) {
          toastr.success('Thank You!', 'Your order has been successfull.Please check your orders.');
          window.history.pushState({},'','/order');
          window.location.reload();
        }
      })
  } else {
    toastr.error('',this.props?.t(`GenericMessage.Error`))
  }
  setProcessing(false)
}
const handleChange = async (event) => {
  // Listen for changes in the CardElement
  // and display any errors as the customer types their card details
  setDisabled(event.empty);
  setError(event.error ? event.error.message : "");
};

const saveCardForFuture = async (ev,{checked,value})=>{
  console.log(checked,value);
  setSaveCard(checked)
}
const handleSubmit = async ev => {
  ev.preventDefault();
  setProcessing(true);
  if (!stripe || !elements) {
    // Stripe.js has not yet loaded.
    // Make sure to disable form submission until Stripe.js has loaded.
    return;
  }

  const {error} = await stripe.confirmPayment({
    //`Elements` instance that was used to create the Payment Element
    elements,
    confirmParams: {
      return_url: 'http://localhost:3050/ordersummary?cartITems=1',
    },
  });
  
};
return (
  <form id="payment-form" onSubmit={handleSubmit}>
    {stripe && <PaymentElement />}
      {elements &&
        <Checkbox label="Save card for Future payments." checked={saveCard} onChange={saveCardForFuture}/>
      }
      <Button type='submit' disabled={!stripe} size='small' style={{marginTop: '15px'}} className='full-width'>Pay with Card</Button>

  </form>
);
}
type propTypes = {
  items :any
}

Basically I want to provide end-user a way to prefill the information in the PaymentElement of Stripe except the mandatory thing i.e CVV. I tried with the Stripe support but as per them passing just the customerID to the payment intent will work and stripe will automatically handle all things. But When Card Elements are rendering the customer details are not coming auto filled.

Upvotes: 1

Views: 3940

Answers (1)

Jonathan Steele
Jonathan Steele

Reputation: 1938

Fields of any Elements component (including Payment Element) cannot be prefilled. If you already have a Payment Method object (pm_xxx), then you'd simply pass that to the the relevant Stripe.js function to confirm (i.e. confirmCardPayment). This does not work with the Payment Element however, which requires an Elements instance by passed.

Upvotes: 3

Related Questions