stripe-archive / react-stripe-elements

Moved to stripe/react-stripe-js.
https://github.com/stripe/react-stripe-js
MIT License
3.03k stars 319 forks source link

Proper way to validate CardElement information #528

Closed zamirkhan closed 3 years ago

zamirkhan commented 4 years ago

We have a rarely-occurring (at least, based on user reports) issue where our React payment form, which uses a CardElement, does not allow the user to proceed to the next step. We don't currently have a lot of evidence (other than communications from a couple of users) and are currently unable to reproduce the issue but are hoping to get a second set of eyes on this and ensure we're doing things correctly.

Basically, on our form, there are input fields to fill out the information (name, address, country, region, and the CardElement) and there is a "Review" button that takes the user to the next step. In instances where this bug happens, the Button appears disabled (confirmed with a screenshot from the user), despite all of the information being filled out on the screen (again, confirmed with a screenshot). As far as the user reports, they are not using auto-fill or autocomplete; they are entering the information manually. This has happened to desktop-based users on Chrome and Safari. When these users try it on their mobile devices, it works for them.

The button's code looks as follows:

          <Button
            color="success"
            size="lg"
            onClick={this.handleSubmit}
            disabled={!this.canProceed()}
          >
            Review
          </Button>

And canProceed looks like this:

  canProceed() {
    return (
      this.state.cardInfoComplete &&
      this.state.name &&
      this.state.address &&
      this.state.city &&
      this.state.country &&
      this.state.region &&
      !this.state.error
    );
  } 

We have no reason to believe that this.state.error is at play, because error can only be set after the Review button is clicked (e.g. if there is an error encountered during token generation), so the other options are the likely source of the bug. Only the cardInfoComplete state value is affected by the CardElement and is set as follows:

                    <CardElement
                      id="card-element"
                      onChange={(el) =>
                        this.stripeElementChange(el, "card_number")
                      }
                    />

and

  stripeElementChange = (el, name) => {
    this.setState({
      cardInfoComplete: !el.empty && el.complete,
      postalCode: el.value.postalCode,
    });
  };

The handlers for the other state values are fairly simple onChange handlers that also call setState. Like this:

  handleChange = (event) => {
    this.setState({
      [event.target.id]: event.target.value,
    });
  };

Again, we don't believe this to necessarily be an issue with this package, but are looking for confirmation that we're doing things the right way when it comes to React and this particular package. Thank you.

fred-stripe commented 4 years ago

Hi @zamirkhan, that sounds like a very unexpected issue. Based on what you've shared I don't see any obvious patterns that would cause this: you're properly calling setState() to notify the component of the state change, so canProceed() will always have the correct button state on render.

One thought would be to also check on the error property of the event but I'm guessing that your screenshots are showing no errors on the CardNumber field.

Beyond that I'd contact Stripe Support so that you can provide screenshots and a link to your site for testing. Any other information you have about the users' specific browser(s) & platform(s) would be very helpful as well. I wish I had an answer here for you.

zamirkhan commented 4 years ago

One thought would be to also check on the error property of the event but I'm guessing that your screenshots are showing no errors on the CardNumber field.

We don't currently inspect the error property of the event, but as you noted, there was no error being displayed in the screenshot.

Thank you for taking a look at this. We'll keep investigating.

craigpullar commented 4 years ago

@zamirkhan Did you find anything? We had a similar report and we are using a very similar pattern to yourself

zamirkhan commented 4 years ago

@craigpullar Unfortunately, no. And while we hadn't heard of this issue in a while (it seems quite rare) is was just reported again today (user sends a screenshot of everything filled out, but still cannot proceed). If you find a solution, please let us know.

zamirkhan commented 4 years ago

For what it's worth, that same user switched browsers (desktop Chrome to Safari, on a Mac) and it worked for them, so it's unlikely to be anything to do with their card, specifically. They also said that they tried both auto-fill and entering all the values manually.

If I recall correctly, most of the time this has happened, it has been in a desktop Chrome browser. The issue is so rare and because of the setting it's happening in, it makes me wonder if there is some Chrome extension or something that is interfering with the Stripe element.

In what kind of situations are you seeing it @craigpullar?

gabberr commented 3 years ago

We have a very similar case as well with one customer and we are having trouble reproducing it. @zamirkhan Since switching browsers sometimes helped, could it be maybe related to the browser locale/language setting? Some of the stripe error messages are translated.

zamirkhan commented 3 years ago

We have a very similar case as well with one customer and we are having trouble reproducing it. @zamirkhan Since switching browsers sometimes helped, could it be maybe related to the browser locale/language setting? Some of the stripe error messages are translated.

That's an interesting thought. However, our application displays any such error messages to the user (regardless of language) and none of these users have reported an error message (and some have provided screenshots proving this).

craigpullar commented 3 years ago

@zamirkhan The switching browsers is good to know thanks. We've only had this issue come up once and it was on Chrome Desktop also.

What was interesting was that one of our sales associates tried to process the payment for the customer using the same information but on a different machine and in doing so ran into the same issue. Which implies the error is linked to the card information entered.

sashko-stripe commented 3 years ago

Hi, sounds like we haven't been able to find a reproduction for this issue. If anyone does find a reproduction, please file a new issue on the new repository for this project: React Stripe.js