243 lines
6.5 KiB
Markdown
243 lines
6.5 KiB
Markdown
# React Stripe.js
|
|
|
|
React components for
|
|
[Stripe.js and Elements](https://stripe.com/docs/stripe-js).
|
|
|
|
[](https://www.npmjs.com/package/@stripe/react-stripe-js)
|
|
|
|
## Requirements
|
|
|
|
The minimum supported version of React is v16.8. If you use an older version,
|
|
upgrade React to use this library. If you prefer not to upgrade your React
|
|
version, we recommend using legacy
|
|
[`react-stripe-elements`](https://github.com/stripe/react-stripe-elements).
|
|
|
|
## Getting started
|
|
|
|
- [Learn how to accept a payment](https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements)
|
|
- [Add React Stripe.js to your React app](https://stripe.com/docs/stripe-js/react#setup)
|
|
- [Try it out using CodeSandbox](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark)
|
|
|
|
## Documentation
|
|
|
|
- [React Stripe.js reference](https://stripe.com/docs/stripe-js/react)
|
|
- [Migrate from `react-stripe-elements`](docs/migrating.md)
|
|
- [Legacy `react-stripe-elements` docs](https://github.com/stripe/react-stripe-elements/#react-stripe-elements)
|
|
- [Examples](examples)
|
|
|
|
### Minimal example
|
|
|
|
First, install React Stripe.js and
|
|
[Stripe.js](https://github.com/stripe/stripe-js).
|
|
|
|
```sh
|
|
npm install @stripe/react-stripe-js @stripe/stripe-js
|
|
```
|
|
|
|
#### Using hooks
|
|
|
|
```jsx
|
|
import React, {useState} from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
import {loadStripe} from '@stripe/stripe-js';
|
|
import {
|
|
PaymentElement,
|
|
Elements,
|
|
useStripe,
|
|
useElements,
|
|
} from '@stripe/react-stripe-js';
|
|
|
|
const CheckoutForm = () => {
|
|
const stripe = useStripe();
|
|
const elements = useElements();
|
|
|
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
|
|
const handleSubmit = async (event) => {
|
|
event.preventDefault();
|
|
|
|
if (elements == null) {
|
|
return;
|
|
}
|
|
|
|
// Trigger form validation and wallet collection
|
|
const {error: submitError} = await elements.submit();
|
|
if (submitError) {
|
|
// Show error to your customer
|
|
setErrorMessage(submitError.message);
|
|
return;
|
|
}
|
|
|
|
// Create the PaymentIntent and obtain clientSecret from your server endpoint
|
|
const res = await fetch('/create-intent', {
|
|
method: 'POST',
|
|
});
|
|
|
|
const {client_secret: clientSecret} = await res.json();
|
|
|
|
const {error} = await stripe.confirmPayment({
|
|
//`Elements` instance that was used to create the Payment Element
|
|
elements,
|
|
clientSecret,
|
|
confirmParams: {
|
|
return_url: 'https://example.com/order/123/complete',
|
|
},
|
|
});
|
|
|
|
if (error) {
|
|
// This point will only be reached if there is an immediate error when
|
|
// confirming the payment. Show error to your customer (for example, payment
|
|
// details incomplete)
|
|
setErrorMessage(error.message);
|
|
} else {
|
|
// Your customer will be redirected to your `return_url`. For some payment
|
|
// methods like iDEAL, your customer will be redirected to an intermediate
|
|
// site first to authorize the payment, then redirected to the `return_url`.
|
|
}
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit}>
|
|
<PaymentElement />
|
|
<button type="submit" disabled={!stripe || !elements}>
|
|
Pay
|
|
</button>
|
|
{/* Show error message to your customers */}
|
|
{errorMessage && <div>{errorMessage}</div>}
|
|
</form>
|
|
);
|
|
};
|
|
|
|
const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
|
|
|
|
const options = {
|
|
mode: 'payment',
|
|
amount: 1099,
|
|
currency: 'usd',
|
|
// Fully customizable with appearance API.
|
|
appearance: {
|
|
/*...*/
|
|
},
|
|
};
|
|
|
|
const App = () => (
|
|
<Elements stripe={stripePromise} options={options}>
|
|
<CheckoutForm />
|
|
</Elements>
|
|
);
|
|
|
|
ReactDOM.render(<App />, document.body);
|
|
```
|
|
|
|
#### Using class components
|
|
|
|
```jsx
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
import {loadStripe} from '@stripe/stripe-js';
|
|
import {
|
|
PaymentElement,
|
|
Elements,
|
|
ElementsConsumer,
|
|
} from '@stripe/react-stripe-js';
|
|
|
|
class CheckoutForm extends React.Component {
|
|
handleSubmit = async (event) => {
|
|
event.preventDefault();
|
|
const {stripe, elements} = this.props;
|
|
|
|
if (elements == null) {
|
|
return;
|
|
}
|
|
|
|
// Trigger form validation and wallet collection
|
|
const {error: submitError} = await elements.submit();
|
|
if (submitError) {
|
|
// Show error to your customer
|
|
return;
|
|
}
|
|
|
|
// Create the PaymentIntent and obtain clientSecret
|
|
const res = await fetch('/create-intent', {
|
|
method: 'POST',
|
|
});
|
|
|
|
const {client_secret: clientSecret} = await res.json();
|
|
|
|
const {error} = await stripe.confirmPayment({
|
|
//`Elements` instance that was used to create the Payment Element
|
|
elements,
|
|
clientSecret,
|
|
confirmParams: {
|
|
return_url: 'https://example.com/order/123/complete',
|
|
},
|
|
});
|
|
|
|
if (error) {
|
|
// This point will only be reached if there is an immediate error when
|
|
// confirming the payment. Show error to your customer (for example, payment
|
|
// details incomplete)
|
|
} else {
|
|
// Your customer will be redirected to your `return_url`. For some payment
|
|
// methods like iDEAL, your customer will be redirected to an intermediate
|
|
// site first to authorize the payment, then redirected to the `return_url`.
|
|
}
|
|
};
|
|
|
|
render() {
|
|
const {stripe} = this.props;
|
|
return (
|
|
<form onSubmit={this.handleSubmit}>
|
|
<PaymentElement />
|
|
<button type="submit" disabled={!stripe}>
|
|
Pay
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|
|
}
|
|
|
|
const InjectedCheckoutForm = () => (
|
|
<ElementsConsumer>
|
|
{({stripe, elements}) => (
|
|
<CheckoutForm stripe={stripe} elements={elements} />
|
|
)}
|
|
</ElementsConsumer>
|
|
);
|
|
|
|
const stripePromise = loadStripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');
|
|
|
|
const options = {
|
|
mode: 'payment',
|
|
amount: 1099,
|
|
currency: 'usd',
|
|
// Fully customizable with appearance API.
|
|
appearance: {
|
|
/*...*/
|
|
},
|
|
};
|
|
|
|
const App = () => (
|
|
<Elements stripe={stripePromise} options={options}>
|
|
<InjectedCheckoutForm />
|
|
</Elements>
|
|
);
|
|
|
|
ReactDOM.render(<App />, document.body);
|
|
```
|
|
|
|
### TypeScript support
|
|
|
|
React Stripe.js is packaged with TypeScript declarations. Some types are pulled
|
|
from [`@stripe/stripe-js`](https://github.com/stripe/stripe-js)—be sure to add
|
|
`@stripe/stripe-js` as a dependency to your project for full TypeScript support.
|
|
|
|
Typings in React Stripe.js follow the same
|
|
[versioning policy](https://github.com/stripe/stripe-js#typescript-support) as
|
|
`@stripe/stripe-js`.
|
|
|
|
### Contributing
|
|
|
|
If you would like to contribute to React Stripe.js, please make sure to read our
|
|
[contributor guidelines](CONTRIBUTING.md).
|