GithubHelp home page GithubHelp logo

stripe-archive / react-stripe-elements Goto Github PK

View Code? Open in Web Editor NEW
3.0K 3.0K 319.0 2.08 MB

Moved to stripe/react-stripe-js.

Home Page: https://github.com/stripe/react-stripe-js

License: MIT License

JavaScript 100.00%

react-stripe-elements's Introduction

We’ve moved to @stripe/react-stripe-js!

We have decided to rename, rework, and move this project. We have no plans for any additional major releases of react-stripe-elements. If you have an issue with this package, please open it on the react-stripe-js repo.

If you are starting a new Stripe integration or are looking to update your existing integration, use React Stripe.js.


react-stripe-elements

build status npm version

React components for Stripe.js and Stripe Elements

This project is a thin React wrapper around Stripe.js and Stripe Elements. It allows you to add Elements to any React app, and manages the state and lifecycle of Elements for you.

The Stripe.js / Stripe Elements API reference goes into more detail on the various customization options for Elements (e.g. styles, fonts).

Table of Contents

Demo

The fastest way to start playing around with react-stripe-elements is with this JSFiddle: https://jsfiddle.net/f5wxprnc/.

You can also play around with the demo locally. The source code is in demo/. To run it:

git clone https://github.com/stripe/react-stripe-elements
cd react-stripe-elements

# (make sure you have yarn installed: https://yarnpkg.com/)

yarn install
yarn run demo

Now go to http://localhost:8080/ to try it out!

⚠️ PaymentRequestButtonElement will not render unless the page is served over HTTPS. To demo PaymentRequestButtonElement, you can tunnel over HTTPS to the local server using ngrok or a similar service.

Screenshot of the demo running

Installation

First, install react-stripe-elements.

Install with yarn:

yarn add react-stripe-elements

OR with npm:

npm install --save react-stripe-elements

OR using UMD build (exports a global ReactStripeElements object);

<script src="https://unpkg.com/react-stripe-elements@latest/dist/react-stripe-elements.min.js"></script>

Then, load Stripe.js in your application:

<script src="https://js.stripe.com/v3/"></script>

Getting started

The Stripe context (StripeProvider)

In order for your application to have access to the Stripe object, let's add StripeProvider to our root React App component:

// index.js
import React from 'react';
import {render} from 'react-dom';
import {StripeProvider} from 'react-stripe-elements';

import MyStoreCheckout from './MyStoreCheckout';

const App = () => {
  return (
    <StripeProvider apiKey="pk_test_12345">
      <MyStoreCheckout />
    </StripeProvider>
  );
};

render(<App />, document.getElementById('root'));

Element groups (Elements)

Next, when you're building components for your checkout form, you'll want to wrap the Elements component around your form. This groups the set of Stripe Elements you're using together, so that we're able to pull data from groups of Elements when you're tokenizing.

// MyStoreCheckout.js
import React from 'react';
import {Elements} from 'react-stripe-elements';

import InjectedCheckoutForm from './CheckoutForm';

class MyStoreCheckout extends React.Component {
  render() {
    return (
      <Elements>
        <InjectedCheckoutForm />
      </Elements>
    );
  }
}

export default MyStoreCheckout;

Setting up your payment form (injectStripe)

Use the injectStripe Higher-Order Component (HOC) to build your payment form components in the Elements tree. The Higher-Order Component pattern in React can be unfamiliar to those who've never seen it before, so consider reading up before continuing. The injectStripe HOC provides the this.props.stripe and this.props.elements properties that manage your Elements groups. Within an injected component, you can call any of the methods on the Stripe or Elements objects.

⚠️ NOTE injectStripe cannot be used on the same element that renders the Elements component; it must be used on the child component of Elements. injectStripe returns a wrapped component that needs to sit under <Elements> but above any code where you'd like to access this.props.stripe.

// CheckoutForm.js
import React from 'react';
import {injectStripe} from 'react-stripe-elements';

import AddressSection from './AddressSection';
import CardSection from './CardSection';

class CheckoutForm extends React.Component {
  handleSubmit = (ev) => {
    // We don't want to let default form submission happen here, which would refresh the page.
    ev.preventDefault();

    // Use Elements to get a reference to the Card Element mounted somewhere
    // in your <Elements> tree. Elements will know how to find your Card Element
    // because only one is allowed.
    // See our getElement documentation for more:
    // https://stripe.com/docs/stripe-js/reference#elements-get-element
    const cardElement = this.props.elements.getElement('card');

    // From here we can call createPaymentMethod to create a PaymentMethod
    // See our createPaymentMethod documentation for more:
    // https://stripe.com/docs/stripe-js/reference#stripe-create-payment-method
    this.props.stripe
      .createPaymentMethod({
        type: 'card',
        card: cardElement,
        billing_details: {name: 'Jenny Rosen'},
      })
      .then(({paymentMethod}) => {
        console.log('Received Stripe PaymentMethod:', paymentMethod);
      });

    // You can also use confirmCardPayment with the PaymentIntents API automatic confirmation flow.
    // See our confirmCardPayment documentation for more:
    // https://stripe.com/docs/stripe-js/reference#stripe-confirm-card-payment
    this.props.stripe.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
      payment_method: {
        card: cardElement,
      },
    });

    // You can also use confirmCardSetup with the SetupIntents API.
    // See our confirmCardSetup documentation for more:
    // https://stripe.com/docs/stripe-js/reference#stripe-confirm-card-setup
    this.props.stripe.confirmCardSetup('{PAYMENT_INTENT_CLIENT_SECRET}', {
      payment_method: {
        card: cardElement,
      },
    });

    // You can also use createToken to create tokens.
    // See our tokens documentation for more:
    // https://stripe.com/docs/stripe-js/reference#stripe-create-token
    // With createToken, you will not need to pass in the reference to
    // the Element. It will be inferred automatically.
    this.props.stripe.createToken({type: 'card', name: 'Jenny Rosen'});
    // token type can optionally be inferred if there is only one Element
    // with which to create tokens
    // this.props.stripe.createToken({name: 'Jenny Rosen'});

    // You can also use createSource to create Sources.
    // See our Sources documentation for more:
    // https://stripe.com/docs/stripe-js/reference#stripe-create-source
    // With createSource, you will not need to pass in the reference to
    // the Element. It will be inferred automatically.
    this.props.stripe.createSource({
      type: 'card',
      owner: {
        name: 'Jenny Rosen',
      },
    });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <AddressSection />
        <CardSection />
        <button>Confirm order</button>
      </form>
    );
  }
}

export default injectStripe(CheckoutForm);

Using individual *Element components

Now, you can use individual *Element components, such as CardElement, to build your form.

// CardSection.js
import React from 'react';
import {CardElement} from 'react-stripe-elements';

class CardSection extends React.Component {
  render() {
    return (
      <label>
        Card details
        <CardElement style={{base: {fontSize: '18px'}}} />
      </label>
    );
  }
}

export default CardSection;

Using the PaymentRequestButtonElement

The Payment Request Button lets you collect payment and address information from your customers using Apple Pay and the Payment Request API.

To use the PaymentRequestButtonElement you need to first create a PaymentRequest object. You can then conditionally render the PaymentRequestButtonElement based on the result of paymentRequest.canMakePayment and pass the PaymentRequest Object as a prop.

class PaymentRequestForm extends React.Component {
  constructor(props) {
    super(props);

    // For full documentation of the available paymentRequest options, see:
    // https://stripe.com/docs/stripe.js#the-payment-request-object
    const paymentRequest = props.stripe.paymentRequest({
      country: 'US',
      currency: 'usd',
      total: {
        label: 'Demo total',
        amount: 1000,
      },
    });

    paymentRequest.on('token', ({complete, token, ...data}) => {
      console.log('Received Stripe token: ', token);
      console.log('Received customer information: ', data);
      complete('success');
    });

    paymentRequest.canMakePayment().then((result) => {
      this.setState({canMakePayment: !!result});
    });

    this.state = {
      canMakePayment: false,
      paymentRequest,
    };
  }

  render() {
    return this.state.canMakePayment ? (
      <PaymentRequestButtonElement
        paymentRequest={this.state.paymentRequest}
        className="PaymentRequestButton"
        style={{
          // For more details on how to style the Payment Request Button, see:
          // https://stripe.com/docs/elements/payment-request-button#styling-the-element
          paymentRequestButton: {
            theme: 'light',
            height: '64px',
          },
        }}
      />
    ) : null;
  }
}
export default injectStripe(PaymentRequestForm);

Advanced integrations

The above Getting started section outlines the most common integration, which makes the following assumptions:

  • The Stripe.js script is loaded before your application's code.
  • Your code is only run in a browser environment.
  • You don't need fine-grained control over the Stripe instance that react-stripe-elements uses under the hood.

When all of these assumptions are true, you can pass the apiKey prop to <StripeProvider> and let react-stripe-elements handle the rest.

When one or more of these assumptions doesn't hold true for your integration, you have another option: pass a Stripe instance as the stripe prop to <StripeProvider> directly. The stripe prop can be either null or the result of using Stripe(apiKey, options) to construct a [Stripe instance].

We'll now cover a couple of use cases which break at least one of the assumptions listed above.

Loading Stripe.js asynchronously

Loading Stripe.js asynchronously can speed up your initial page load, especially if you don't show the payment form until the user interacts with your application in some way.

<html>
  <head>
    <!-- ... -->

    <!-- Note the 'id' and 'async' attributes:                         -->
    <!--    ┌────────────┐                                 ┌───┐       -->
    <script id="stripe-js" src="https://js.stripe.com/v3/" async></script>

    <!-- ... -->
  </head>
  <!-- ... -->
</html>

Initialize this.state.stripe to null in the constructor, then update it in componentDidMount when the script tag has loaded.

class App extends React.Component {
  constructor() {
    super();
    this.state = {stripe: null};
  }
  componentDidMount() {
    if (window.Stripe) {
      this.setState({stripe: window.Stripe('pk_test_12345')});
    } else {
      document.querySelector('#stripe-js').addEventListener('load', () => {
        // Create Stripe instance once Stripe.js loads
        this.setState({stripe: window.Stripe('pk_test_12345')});
      });
    }
  }
  render() {
    // this.state.stripe will either be null or a Stripe instance
    // depending on whether Stripe.js has loaded.
    return (
      <StripeProvider stripe={this.state.stripe}>
        <Elements>
          <InjectedCheckoutForm />
        </Elements>
      </StripeProvider>
    );
  }
}

When loading Stripe.js asynchronously, the stripe prop provided by injectStripe will initially be null, and will update to the Stripe instance once you pass it in to your StripeProvider. You can find a working demo of this strategy in async.js. If you run the demo locally, you can view it at http://localhost:8080/async/.

For alternatives to calling setStatein componentDidMount, consider using a setTimeout(), moving the if/else statement to the constructor, or dynamically injecting a script tag in componentDidMount. For more information, see stripe/react-stripe-elements.

Server-side rendering (SSR)

If you're using react-stripe-elements in a non-browser environment (React.renderToString, etc.), Stripe.js is not available. To use react-stripe-elements with SSR frameworks, use the following instructions.

The general idea is similar to the async loading snippet from the previous section (initialize this.state.stripe to null in constructor, update in componentDidMount), but this time we don't have to wait for the script tag to load in componentDidMount; we can use window.Stripe directly.

class App extends React.Component {
  constructor() {
    super();
    this.state = {stripe: null};
  }
  componentDidMount() {
    // Create Stripe instance in componentDidMount
    // (componentDidMount only fires in browser/DOM environment)
    this.setState({stripe: window.Stripe('pk_test_12345')});
  }
  render() {
    return (
      <StripeProvider stripe={this.state.stripe}>
        <Elements>
          <InjectedCheckoutForm />
        </Elements>
      </StripeProvider>
    );
  }
}

Inside your form, <InjectedCheckoutForm />, this.props.stripe will either be null or a valid Stripe instance. This means that it will be null when rendered server-side, but set when rendered in a browser.

Using an existing Stripe instance

In some projects, part of the project uses React, while another part doesn't. For example, maybe you have business logic and view logic separate. Or maybe you use react-stripe-elements for your credit card form, but use Stripe.js APIs directly for tokenizing bank account information.

You can use the stripe prop to get more fine-grained control over the Stripe instance that <StripeProvider> uses. For example, if you have a stripe instance in a Redux store that you pass to your <App /> as a prop, you can pass that instance directly into <StripeProvider>:

class App extends React.Component {
  render() {
    return (
      <StripeProvider stripe={this.props.stripe}>
        <Elements>
          <InjectedCheckoutForm />
        </Elements>
      </StripeProvider>
    );
  }
}

As long as <App /> is provided a non-null stripe prop, this.props.stripe will always be available within your InjectedCheckoutForm.

Component reference

<StripeProvider>

All applications using react-stripe-elements must use the <StripeProvider> component, which sets up the Stripe context for a component tree. react-stripe-elements uses the provider pattern (which is also adopted by tools like react-redux and react-intl) to scope a Stripe context to a tree of components.

This allows configuration like your API key to be provided at the root of a component tree. This context is then made available to the <Elements> component and individual <*Element> components that we provide.

An integration usually wraps the <StripeProvider> around the application’s root component. This way, your entire application has the configured Stripe context.

Props shape

There are two distinct props shapes you can pass to <StripeProvider>.

type StripeProviderProps =
  | {apiKey: string, ...}
  | {stripe: StripeObject | null};

See Advanced integrations for more information on when to use each.

The ... above represents that this component accepts props for any option that can be passed into Stripe(apiKey, options). For example, if you are using Stripe Connect and want to act on behalf of a connected account, you can pass stripeAccount="acct_123" as a property to <StripeProvider>. This will get used just like passing stripeAccount in the options of the Stripe constructor or like using stripe_account when your backend calls the Stripe API directly

<Elements>

The Elements component wraps groups of Elements that belong together. In most cases, you want to wrap this around your checkout form.

Props shape

This component accepts all options that can be passed into stripe.elements(options) as props.

type ElementsProps = {
  locale?: string,
  fonts?: Array<Object>,
  // The full specification for `elements()` options is here: https://stripe.com/docs/elements/reference#elements-options
};

<*Element> components

These components display the UI for Elements, and must be used within StripeProvider and Elements.

Available components

(More to come!)

  • CardElement
  • CardNumberElement
  • CardExpiryElement
  • CardCvcElement
  • PaymentRequestButtonElement
  • IbanElement
  • IdealBankElement

Props shape

These components accept all options that can be passed into elements.create(type, options) as props.

type ElementProps = {
  id?: string,
  className?: string,

  // For full documentation on the events and payloads below, see:
  // https://stripe.com/docs/elements/reference#element-on
  onBlur?: () => void,
  onChange?: (changeObject: Object) => void,
  onFocus?: () => void,
  onReady?: (StripeElement) => void,
};

The props for the PaymentRequestButtonElement are:

type PaymentRequestButtonProps = {
  id?: string,
  className?: string,

  paymentRequest: StripePaymentRequest,

  onBlur?: () => void,
  onClick?: () => void,
  onFocus?: () => void,
  onReady?: (StripeElement) => void,
};

Using onReady

Note that the onReady callback gives you access to the underlying Element created with Stripe.js. You can use this to get access to all the underlying methods that a Stripe Element supports.

For example, you can use onReady to force your element to focus:

// CardSection.js
import React from 'react';
import {CardElement} from 'react-stripe-elements';

class CardSection extends React.Component {
  render = () => {
    return (
      <label>
        Card details
        <CardElement onReady={(el) => el.focus()} />
      </label>
    );
  };
}

export default CardSection;

(Note that this functionality is new as of react-stripe-elements v1.6.0.)

injectStripe HOC

function injectStripe(
  WrappedComponent: ReactClass,
  options?: {
    withRef?: boolean = false,
  }
): ReactClass;

Use injectStripe to wrap a component that needs to interact with Stripe.js to create sources or tokens.

  1. First, create a component that accepts the stripe prop and calls one of the Stripe or Elements methods when necessary.
  2. Wrap that component by passing it to injectStripe so that it actually receives the stripe and elements props.
  3. Render the component that injectStripe returns.

Example

// 1. Create a component that uses this.props.stripe:
class CheckoutForm extends React.Component {
  render() {
    /* ... */
  }
  onCompleteCheckout() {
    this.props.stripe
      .createPaymentMethod({
        type: 'card',
        card: this.props.stripe.getElement('card'),
      })
      .then(/* ... */);
  }
}

// 2. Wrap it in a higher-order component that provides the `stripe` prop:
const InjectedCheckoutForm = injectStripe(CheckoutForm);

// 3. Render the wrapped component in your app:
const CheckoutRoute = (props) => (
  <div>
    <InjectedCheckoutForm />
  </div>
);

injectStripe will work with any method of providing the actual Stripe instance with StripeProvider, whether you just give it an api key, load Stripe.js asynchronously, or pass in an existing instance.

Within the context of Elements, stripe.createToken and stripe.createSource wrap methods of the same name in Stripe.js. Calls to them automatically infer and pass the Element object as the first argument.

If the withRef option is set to true, the wrapped component instance will be available with the getWrappedInstance() method of the wrapper component. This feature can not be used if the wrapped component is a stateless function component.

Within the wrapped component, the stripe and elements props have the type:

type FactoryProps = {
  elements: null | {
    getElement: (type: string) => Element | null,
    // For more detail and documentation on other methods available on
    // the `elements` object, please refer to our official documentation:
    // https://stripe.com/docs/elements/reference#the-elements-object
  },
  stripe: null | {
    createToken: (tokenData: {type?: string}) => Promise<{
      token?: Object,
      error?: Object,
    }>,
    createSource: (sourceData: {type: string}) => Promise<{
      source?: Object,
      error?: Object,
    }>,
    createPaymentMethod: (
      paymentMethodData: Object
    ) => Promise<{
      paymentMethod?: Object,
      error?: Object,
    }>,
    confirmCardPayment: (
      clientSecret: string,
      paymentIntentData?: Object
    ) => Promise<{
      paymentIntent?: Object,
      error?: Object,
    }>,
    confirmCardSetup: (
      clientSecret: string,
      paymentIntentData?: Object
    ) => Promise<{
      setupIntent?: Object,
      error?: Object,
    }>,
    // For more detail and documentation on other methods available on
    // the `stripe` object, please refer to our official documentation:
    // https://stripe.com/docs/elements/reference#the-stripe-object
  },
};

The stripe and elements props can only be null if you are using one of the Advanced integrations mentioned above, like loading Stripe.js asynchronously or providing an existing instance. If you are using a basic integration where you pass in an api key to <StripeProvider/>, they will always be present.

Troubleshooting

react-stripe-elements may not work properly when used with components that implement shouldComponentUpdate. react-stripe-elements relies heavily on React's context feature and shouldComponentUpdate does not provide a way to take context updates into account when deciding whether to allow a re-render. These components can block context updates from reaching react-stripe-element components in the tree.

For example, when using react-stripe-elements together with react-redux doing the following will not work:

const Component = connect()(injectStripe(_Component));

In this case, the context updates originating from the StripeProvider are not reaching the components wrapped inside the connect function. Therefore, react-stripe-elements components deeper in the tree break. The reason is that the connect function of react-redux implements shouldComponentUpdate and blocks re-renders that are triggered by context changes outside of the connected component.

There are two ways to prevent this issue:

  1. Change the order of the functions to have injectStripe be the outermost one:

    const Component = injectStripe(connect()(_CardForm));

This works, because injectStripe does not implement shouldComponentUpdate itself, so context updates originating from the redux Provider will still reach all components.

  1. You can use the pure: false option for redux-connect:

    const Component = connect(
      mapStateToProps,
      mapDispatchToProps,
      mergeProps,
      {
        pure: false,
      }
    )(injectStripe(_CardForm));

Development

Install dependencies:

yarn install

Run the demo:

yarn run demo

Run the tests:

yarn run test

Build:

yarn run build

We use prettier for code formatting:

yarn run prettier

To update the ToC in the README if any of the headers changed:

yarn run doctoc

Checks:

yarn test
yarn run lint
yarn run flow

react-stripe-elements's People

Contributors

asolove-stripe avatar atty-stripe avatar chris-erickson avatar christopher-stripe avatar cweiss-stripe avatar dependabot[bot] avatar dweedon-stripe avatar egdbear avatar indiesquidge avatar jenan-stripe avatar jez avatar jul-sh avatar mbarrett-stripe avatar michelle avatar michelle-stripe avatar mikiest avatar oliver-stripe avatar oscar-21 avatar rlk-stripe avatar romainhuet avatar sashko-stripe avatar shaneosullivan avatar shaun-stripe avatar shengwei-stripe avatar stephen avatar thchia avatar thorsten-stripe avatar tuxrace avatar tylersmith-stripe avatar zabicki-stripe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-stripe-elements's Issues

Demo Split Form security Issue?

StripeProvider for specific components with Redux and Router

I am using Redux and React router with my application.
I want to use component to the specific components. Not all components. Currently my implementation is like below,

ReactDOM.render(
  <Provider store={store}>
    <StripeProvider apiKey="pk_test_pub_key">
      <Router history={history}>
        {routes}
      </Router>
    </StripeProvider>
  </Provider>
  , container
);

But all components will be under StripeProvider. Is there a way to separate it and use it for specific components?

CardElement intermittently doesn't appear on Safari Mobile

I received a report from a user that the CardElement never rendered on Safari (up to date, new iPhone). This was using version 0.0.2 of the library. This occurred on this page: https://www.themarshallproject.org/support-us.

From the user: "I could not enter information on the line under “credit card” It simply would not make the keyboard available or allow me to click on/place a cursor/etc. on the space under “credit card” when that was selected. It was totally blank. After a couple of attempts poking around on the screen, Safari just crashed. Twice."

This sounds possibly related to #35. I was not able to reproduce, as with that bug. This is now the third report I've had of something similar though.

Accessing Error state of <CardElement>

The <CardElement> component obviously has some internal method of determining error state, as it will highlight red certain values that are invalid.

How can I access this state, (maybe through the StripeProvider) so that I can disable the form submission if the values are invalid?

any way to use stripe 3 without all the ui of this library? with just simple fields like in v2

This library adds quite a bit of overhead to a react app - but I do still want to use Stripe directly in React app. Documentation on stripe.com is not clear and refers a lot to various css styling issues to create a 'card' before creating a token.

In other words, I'd like something like the following:

  1. npm install stripe --save
  2. import stripe;
  3. stripe(mykey).createToken({cc:ccVal,exp:expVal,cvc:cvcVal}).then(...)

how do I do this? (without reverting to stripe v2)

*Element items should accept className property

According to the Stripe.js documentation, it is possible to add a class to the div container for the element to allow styling. Currently this doesn't appear to have any affect on the UI elements.

Error message: You did not specify the type of Source or Token to create.

I have a basic setup like it is documented, when I call the createToken method, I get this error:

Uncaught Error: You did not specify the type of Source or Token to create. We could not infer which Element you want to use for this operation.

Would appreciate any ideas on how I could tackle this issue.

Add testContext

Hi, It would be great if you extended this project with a mock Stripe object so that it is possible to write tests using these components without loading the Stripe API.

Protocols, domains, and ports must match.

I'm seeing this issue when viewing on Google Chrome browser on iOS:

Blocked a frame with origin "https://www.mycoolwebsite.com" from accessing a frame with origin "https://js.stripe.com". Protocols, domains, and ports must match.

Any suggestions. Here's where I'm adding the StripeProvider

ReactDOM.render(
  <Provider store={store}>
    <StripeProvider apiKey={STRIPE_KEY}>
      <div>
        <Router history={history} routes={routes} onUpdate={routerOnUpdate} />
      </div>
    </StripeProvider>
  </Provider>,
  document.getElementById('app')
);

Confused about createToken argument(s?)

I'm a bit confused about how to work with the arguments in stripe.createToken.

I can see in the source code that createToken is a bit strange for legacy reasons, and I'd love it if we could perhaps shed a bit more light on that.

For context, here is the signature

createToken: (
  type: string | ElementShape,
  options: mixed
) => Promise<{token?: MixedObject, error?: MixedObject}>

What string values are applicable to type? The README example shows 'card', I assume this is because the example is using the CardElement component. So if I were to be using individual *Element components, what type would I specify? cardNumber perhaps? Is this what is being set implicitly if I pass in no arguments?

I think most of my confusion is surrounding the disparities between this function's API and the official documentation. Seems like the point of my confusion has been mentioned before, but didn't seem to result in a discussion.

Just curious about the best way to make use of createToken without it feeling like a blackbox (i.e. no arguments).

Generalized way of displaying error messages on *Element items

Maybe it's just a documentation issue, but there doesn't seem to be a generalized way of adding and error messages on the page when using multiple *Element components. Errors are definitely coming back to onChange, but there doesn't seem to be a good way of determining which field on the page generated the error.

Generally I like to display the error message with the associated field, instead of just having a block of error messages at the top of the form. I would like a relatively straightforward to determine which field to attach an error to.

Support className for styling elements

I've seen closed PR #14 and want to express interest in adding styles via className

I'm testing the waters with these elements in an SSR app and have not been successful applying styles the old fashioned way

React Native intergration

Can there be a guide for integrating with React Native? Assuming it's possible without major amounts of changes.

Input for Card Element squished

Trying to implement this into my react app the input from the cardElement is all squished together, is that how it comes out of the box? Do I need to apply extra styling from the get go to get it to appear correctly? Thanks.
screen shot 2017-08-16 at 9 03 30 am

Clear the element in the handler

Is there a way to clear the element in the handler?

I know in stripe.js the element object has a clear function but I'm not sure how it can be called in using this module,

Redux Form

I got this error message when I run this.props.stripe.createToken on redux form.

inject.js:53 Uncaught Error: You did not specify the type of Source or Token to create.
        We could not infer which Element you want to use for this operation.

Usage with stripe connect

I was reading documentation about connect (store-builder recipe) and saw mention that I could use Elements or Checkout for collecting the payment details.

So ended up trying to set this up but run into a small hiccup... if I understood correctly I should be creating the token with connected user’s API key which means I should be changing the apiKey to StripeProvider based on the seller/user. While checking on how to do this I found this:
https://github.com/stripe/react-stripe-elements/blob/master/src/components/Provider.js#L45

Does this mean that this is not supported? or is the some better way of doing this?

Create source for SEPA

Hi there;

I'm using this component to create source for cards.

Could I use the injectStripe to get configured Stripe and create source for SEPA Debits ?

Right now; I'm getting the following error :

You did not specify the type of Source or Token to create.
We could not infer which Element you want to use for this operation.

Using multiple payment forms at the same time on one page.

I want to use a setup like this:

<StripeProvider>
  <App>
    <Elements>
       <CheckoutForm1 />
    </Elements>
    <Elements>
       <CheckoutForm2 />
    </Elements>
  </App>
</StripeProvide>

I basically want to have two independent forms mounted and used at the same time. The error I get is the following:

You did not specify the type of Source or Token to create. We could not infer which Element you want to use for this operation.

Is this setup technically possible, where could this error come from?

Invalid token creation param after calling createToken

I'm getting this error:

Invalid token creation param: exp_month should be used in Elements instead

after calling createToken, it was working few days ago and suddenly I'm getting this error without any code changes and I don't have any clue what could be the problem

Form submission after token creation

We're preventing form submission with ev.preventDefault(); to not refresh the page before we get the token from Stripe.

I'm stumbling a bit on how to subsequently (programmatically?) submit the form to our server with all values (including the token) after the Stripe response?

Passing options to the stripe createToken

I am trying to pass additional information of the card like name , address as mentioned here, https://stripe.com/docs/stripe.js#stripe-create-token

this.props.stripe.createToken({
	name: 'Name',
	address_line1: 'Address 1',
	address_line2: 'Address 2'
	address_city: 'Address C'
	address_state: 'Address S'
	address_zip: 'Address Z'
	address_country: 'Address C',

}).then(({token}) => {
    console.log('Received Stripe token:', token);
});

When I try to retrieve the card information with the token generated, the extra options weren't set. What could be the issue?

Library does do not allow Stripe SDK to be loaded async

The provider expects window.Stripe to be set in its constructor. This forces the user to load the script synchronously (which is bad practice) before they load their app JS (which is even worse).

Are there plans to rearchitect this library to support this?

I have a server-side rendered app, which does not include the Stripe SDK (since it's not needed on every page) -- on pages that require the SDK, we inject it & assume (perhaps slightly unsafely) that it has loaded by the time the user has entered their payment details.

Even ignoring the safety aspects, this approach is not possible with this library as it will throw an exception if the Stripe SDK is not present at first instantiation.

Installation issue with npm and v0.0.3

If I try to install the latest version using npm 3.10.10, I get the following error

npm ERR! cb() never called!

I installed 0.0.2 and it worked fine.

Error integrating react-stripe-elements to project

Hi, I'm encountering a react.createElement type is invalid error while integrating react-stripe-elements to a project (in this step)

Dependencies used:
[email protected]
[email protected]
[email protected]

fragment of the relevant code:

const store = rehydrate();

const renderApp = Component => {
	render(
		<AppContainer>
			<StripeProvider apiKey="[key_hidden]">
				<Router>
					<Provider store={isProduction ? store : hotRehydrate()}>
						<App />
					</Provider>
				</Router>
			</StripeProvider>
		</AppContainer>,
		document.getElementById("root")
	);
};

renderApp(App);

if (module.hot) {
	module.hot.accept(() => renderApp(App));
}

full error details:

warning.js:36 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.
printWarning @ warning.js:36
warning @ warning.js:60
createElement @ ReactElementValidator.js:171
patchedCreateElement @ patch.dev.js:164
renderApp @ index.js:39
(anonymous) @ index.js:55
./src/index.js @ app.e2c0fc4dfb8973baf072.js:7439
__webpack_require__ @ app.e2c0fc4dfb8973baf072.js:687
fn @ app.e2c0fc4dfb8973baf072.js:110
(anonymous) @ client:8
0 @ app.e2c0fc4dfb8973baf072.js:7486
__webpack_require__ @ app.e2c0fc4dfb8973baf072.js:687
(anonymous) @ app.e2c0fc4dfb8973baf072.js:787
(anonymous) @ app.e2c0fc4dfb8973baf072.js:790
ReactCompositeComponent.js:327 Uncaught TypeError: Cannot read property 'unmountComponent' of null
    at ReactCompositeComponentWrapper.performInitialMountWithErrorHandling (ReactCompositeComponent.js:327)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:256)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at mountComponentIntoNode (ReactMount.js:104)
    at ReactReconcileTransaction.perform (Transaction.js:140)
    at batchedMountComponentIntoNode (ReactMount.js:126)
    at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)

The injected stripe property loses track of components added or created after initial render

I have a component mounted inside in the Element with a nested CardElement. When the component initially renders the CardElement is not in the tree because it instead shows a "Loading" state. After loading is finished the render function of the component includes the CardElement in the tree.

After the loading is finished, when a button is clicked to call this.props.stripe.createToken() the following error shows in the console:

inject.js:53 Uncaught Error: You did not specify the type of Source or Token to create.
        We could not infer which Element you want to use for this operation.

In another example, I have a form that can switch between an editable and non-editable state. The editable state includes a CardElement, the non-editable state doesn't. If I set it to initially render the editable state, then click I button to exit the editable state, and click another button to go back into the editable state, then click another button to call this.props.stripe.createToken() I get this rejected promise:

stack: "IntegrationError: We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted. at new t (https://js.stripe.com/v3/:1:1784) at e.value (https://js.stripe.com/v3/:1:5928) at https://js.stripe.com/v3/:1:5201"
message: "We could not retrieve data from the specified Element. Please make sure the Element you are attempting to use is still mounted."
name: "IntegrationError"

Client-side source creation of 3D Secure Source object gives Error: You did not specify the type of Source or Token to create. We could not infer which Element you want to use for this operation.

https://stripe.com/docs/sources/three-d-secure#client-side-source-creation

stripe.createSource({
  type: 'three_d_secure',
  amount: 1099,
  currency: "eur",
  three_d_secure: {
    card: "src_19YP2AAHEMiOZZp1Di4rt1K6"
  },
  redirect: {
    return_url: "https://shop.example.com/crtA6B28E1"
  }
}).then(function(result) {
  // handle result.error or result.source
});

Gives :

Uncaught (in promise) Error: You did not specify the type of Source or Token to create.
        We could not infer which Element you want to use for this operation.
    at ProxyComponent._this.findElement (inject.js:61)

no information on AddressSection in doc

Hi,

in the README.md file you provide some sample code which mentions AddressSection but there seems to be no implementation/sample for that code (yet).

Do you plan to support the extraFields also via this package? If so is there a timeline?

Best,
Gerwin

Too complicated

Hi team;

I'm using React with Redux; I'm used to separate component and container.
I think this component is too complicated to use.

What I was expected was very simple :

<StripeSourceElement onSourceCreated={::this.handleSourceCreated} publicKey="pk_test" type="card" />
<StripeTokenElement onTokenCreated={::this.handleTokenCreated} publicKey="pk_test" type="card"/>

Regards.

Getting context injection error when using injectStripe HoC

I'm willing to assume this is just my ignorance on how context works in React, but I'm confused why I am receiving this error

It looks like you are trying to inject Stripe context outside of an Elements context.
Please be sure the component that calls createSource or createToken is within an 
<Elements> component.

This is what my code looks like (here's a running example).

class _CardForm extends React.Component {
  render () {
    return (
      <div className="Checkout">
        <h1>Available Elements</h1>
        <Elements>
          <form onSubmit={this.props.stripe.createToken()}>
            <label>
              Card details
              <CardElement />
            </label>
            <button>Pay</button>
          </form>
        </Elements>
      </div>
    )
  }
}

const CardForm = injectStripe(_CardForm)

const App = () => 
  <StripeProvider apiKey="pk_RXwtgk4Z5VR82S94vtwmam6P8qMXQ">
    <CardForm />
  </StripeProvider>

ReactDOM.render(<App />, document.querySelector('.App'))

AFAICT, I am definitely trying to "inject Stripe context inside of an Elements context", not outside. I can't see what I'm doing that is breaking the code 😕.

Any help would be greatly appreciated!

CardElement intermittently doesn't appear on Safari

I've had multiple reports (with screenshots) from users of CardElement not rendering (just never appears) on Safari (one of them Version 10.1.1 (11603.2.5)). There were no errors in the console. The problem did not persist after a refresh, and I was not able to reproduce it.

I know this is not a terribly helpful bug report, but I thought you should know that I have seen this happen.

"You did not specify the type of source or token to create"

Hello, in my payment form, many cards from visa, mastercard, and amex have processed fine. But intermittently, a customer encounters this error:

"You did not specify the type of source or token to create"

This doesn't quite make sense given that I don't see type as an option inside of the react stripe elements configuration, so I assume this is an error encountered in the script that isn't passed quite up the react chain. My boss fired this earlier when he used 1password autofill in elements.

Does anybody have tips regarding this error during tokenization, and what I can do to catch it and communicate errors to customers better? I am unable to share source due to proprietary nature of code.

Change Object in Card Element has only zipcode prop

I tried to extract data from the form by accessing the change object inside a handleChange function but only value that is available is the zip code.

Am I doing something wrong? how should I extract Card number and other inputs from CardElement?

CardElement: when card number is invalid user focus cannot go to other form inputs

Hello!

When using CardElement in a form that contains also other input fields unrelated to Stripe, if I insert an invalid card number and then try to click another input field the cursor is always brought back to the CardElement input field.
If the card number is empty or valid this doesn't happen. How is that? Thanks :)

PS: I'm using redux-form

Promise from stripe.createToken never resolves

I'm trying to create a simple checkout form with a <CardElement>, like in the Readme example. However, after I make the call to stripe.createToken, I never get a response.

My main component is wrapped with <StripeProvider>:

      <StripeProvider apiKey={process.env.REACT_APP_STRIPE_KEY}>
        <div className="app">
           ....
        </div>
      </StripeProvider>

My form is wrapped with <Elements>:

  render() {
    return (
        <Elements>
          <Form />
        </Elements>
    )
  }

and I inject the HOC and make the stripe call in my handleSubmit:

/Form.js
class Form extends Component {

  handleSubmit = () => {
    console.log("trying to get stripe token");  // This prints
    const { form, stripe, } = this.props

    console.log(stripe);  // This shows the stripe object (so I know it's being injected)
    stripe.createToken({name: form.card_name.value})
    .then(({token}) => {
      console.log('Received Stripe token:', token);  // This never prints
    })
    .catch((e) => {
      console.log('got error', e);  // Nor does this
    });
  }


  render() {
    ...
    return (
      <div>
        ...
        <BillingSection />
        ...
      </div>
    )
}
export default injectStripe(withRouter(connect(mapStateToProps)(Form)))

Lastly, inside <BillingSection>, I render the card element:

  render() {
    ...
    return (
          <label>
            Card details
            <CardElement style={cardStyle} />
          </label>
    )
}

As you can see from this code, the submit gets called properly, and stripe is loaded correctly, but neither the .then or .catch blocks get called. What's going on here? Is the call being made at all, and if so, why are there no error messages that trigger the .catch block?

Edit:
I noticed in the Stripe control panel that no new customer accounts are being created. So this call never even makes it to Stripe?

Display issues on mobile

If you switch browser to a mobile format the base CardElement has a rough time with everything overlapping and looking quite ugly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.