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

Very awkward API Design #226

Closed iMerica closed 6 years ago

iMerica commented 6 years ago

Hey guys,

My use case is very simple: I have a checkout form that is designed consistently with the rest of my site. I just need to create a token with stripe, then on success, record that token in my system.

Why do I need 4 layers of indirection just to call createToken? Am I misunderstanding something?

Thanks in advance,

Michael

jez commented 6 years ago

👋 Hey there @iMerica! Thanks for the feedback. We're all sort of used to the complexity here at Stripe, so it's always refreshing to hear people challenge us to do better.

In the case of this particular API: React and iframes don't really play well. Iframes are intimately connected to the DOM, and the DOM is one big mutable object. This is why jQuery was so popular at first: it presented nice abstractions around those mutable DOM APIs.

Over time, people realized that mutation was Not Good, and Facebook built React with the idea that UI should be declarative: if the data didn't change, then we shouldn't need to re-render.

But Stripe.js needs to make heavy use of iframes to sandbox payment information from residing on the top-level page. This lets our users avoid a lot of compliance and regulatory overhead.

So we have this problem: how do we get iframes (super mutable) to play nicely with React (immutable)? That's where a lot of the complexity comes from.

The rest comes from the fact that we wanted to provide a Redux-like interface, where the stripe instance shows up as a property on all children components. This is not strictly necessary; you can call the Stripe constructor yourself, and avoid one layer of indirection (so now there's only 3):

https://jsfiddle.net/xux7qzch/729/

Arguably, the remaining three are the bare minimum needed. In order to create a <CardElement /> component for you, we'll need both the stripe instance (provided by the StripeProvider) and an Elements instance (provided by <Elements>). We could require that these be threaded through the entire hierarchy, but it's nice to just be able to have them automatically show up where needed.

But as a last option, you don't have to use react-stripe-elements if you don't want to! You can follow all the normal steps in the Card Element Quickstart for the form with the minimal amount of boilerplate.

iMerica commented 6 years ago

Thanks for your response @jez. I didn't realize there was so much sandboxing going on with IFrames. That definitely explains it.

Last question:

Overriding the styles of a <CardElement/>, is not enough to make the Stripe payment form look consistent with the rest of my site.

To achieve a 100% consistent UI that looks native to my site, I would need to have control over the actual markup as well including the input masks, labels, error markup etc. Is that possible or am I wasting my time trying to achieve that?

I'm using Semantic UI, which is a very popular UI framework with over 40 thousands stars on Github.

jez commented 6 years ago

You might want to look at this issue:

https://github.com/stripe/react-stripe-elements/issues/116

which explains how to do something similar with Bootstrap for the UI library. (look for the JSFiddle link).

The key idea is: the CardElement itself should just be the inside part of the input. All the chrome and decorations on the input should outside.

So you don't need to override all the card element styles: only the ones that are strictly within the input (for stuff like fonts, text weight, etc.) Everything else you can build up by styling the wrapper div around the element.

jez commented 6 years ago

Unfortunately, we don't like to provide support over GitHub issues (it makes it harder to track for us internally). I'm going to close this issue, but if you have any follow up questions, you should definitely reach out to our support team:

https://support.stripe.com

They take on questions like this all the time, and are happy to help.

Thanks again for using Stripe!

hakunin commented 4 years ago

Thanks for your response @jez. I didn't realize there was so much sandboxing going on with IFrames. That definitely explains it.

Last question:

Overriding the styles of a <CardElement/>, is not enough to make the Stripe payment form look consistent with the rest of my site.

To achieve a 100% consistent UI that looks native to my site, I would need to have control over the actual markup as well including the input masks, labels, error markup etc. Is that possible or am I wasting my time trying to achieve that?

I'm using Semantic UI, which is a very popular UI framework with over 40 thousands stars on Github.

The bootstrap issue has been locked so I'll comment here.

Just adding form-control to the react elements make them look better so that's great but then I focus one and no box shadow is happening.

Given industry wide adoption of bootstrap, it would be nice to have an example of using it, as the components seem to make it hard to just plug it in.