Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove sync Stripe wrapper #1

Merged
merged 3 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 15 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,22 @@ function provided by the Stripe.js script as an ES module.

[![npm version](https://img.shields.io/npm/v/@stripe/stripe-js.svg?style=flat-square)](https://www.npmjs.com/package/@stripe/stripe-js)

## Usage

### `Stripe`

To use the exported `Stripe` function, first include the Stripe.js script on
each page of your site.

```html
<script src="https://js.stripe.com/v3/"></script>
```
## Installation

Then import and use Stripe.js as you would any other module.

```js
import {Stripe} from '@stripe/stripe-js';
Use `npm` to install the Stripe.js module:

const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
```sh
npm install @stripe/stripe-js
```

We’ve placed a random API key in this example. Replace it with your
[actual publishable API keys](https://dashboard.stripe.com/account/apikeys) to
test this code through your Stripe account.

For more information on how to use Stripe.js, please refer to the
[Stripe.js API reference](https://stripe.com/docs/js) or learn to
[accept a payment](https://stripe.com/docs/payments/accept-a-payment) with
Stripe.
## Usage

### `loadStripe`

This function returns a `Promise` that resolves with a newly created `Stripe`
object once Stripe.js has loaded. If necessary, it will load Stripe.js for you
by inserting the Stripe.js script tag.
by inserting the Stripe.js script tag. If you call `loadStripe` in a server
environment it will resolve to `null`.

```js
import {loadStripe} from '@stripe/stripe-js';
Expand All @@ -66,11 +49,12 @@ loaded on every page, not just your checkout page. This allows Stripe to detect
anomalous behavior that may be indicative of fraud as customers browse your
website.

If you are adding the `<script>` tag manually, make sure you do so on every
page. If you are relying on the script insertion that this module provides, and
you utilize code splitting or only include your JavaScript app on your checkout
page, you will need to take extra steps to ensure Stripe.js is available
everywhere.
By default, this module will insert a `<script>` tag that loads Stripe.js from
`https://js.stripe.com`. This happens as a side effect immediately upon
importing this module. If you utilize code splitting or only include your
JavaScript app on your checkout page, the Stripe.js script will only be
available in parts of your site. To ensure Stripe.js is available everywhere,
you can perform either of the following steps:

### Import as a side effect

Expand All @@ -85,8 +69,8 @@ import '@stripe/stripe-js';
### Manually include the script tag

Manually add the Stripe.js script tag to the `<head>` of each page on your site.
If you use `loadStripe`, it will use this script tag rather than inserting a new
one.
If an existing script tag is already present, this module will not insert a new
one. When you call `loadStripe`, it will use the existing script tag.

```html
<!-- Somewhere in your site's <head> -->
Expand Down
41 changes: 2 additions & 39 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
const V3_URL = 'https://js.stripe.com/v3';

let hasInjectedScript = false;

// Execute our own script injection after a tick to give users time to
// do their own script injection.
const stripePromise = Promise.resolve().then(() => {
Expand All @@ -18,7 +16,6 @@ const stripePromise = Promise.resolve().then(() => {
let script = document.querySelector(`script[src="${V3_URL}"]`);

if (!script) {
hasInjectedScript = true;
script = document.createElement('script');
script.src = V3_URL;

Expand Down Expand Up @@ -48,41 +45,7 @@ const stripePromise = Promise.resolve().then(() => {
});
});

let hasCalledLoadStripe = false;
export const loadStripe = (...args) => {
hasCalledLoadStripe = true;
return stripePromise.then((maybeStripe) =>
export const loadStripe = (...args) =>
stripePromise.then((maybeStripe) =>
maybeStripe ? maybeStripe(...args) : null
);
};

const STRIPE_NOT_LOADED_ERROR_TEXT = `Stripe.js has not yet loaded. Instead of calling \`Stripe\` directly, try using the \`loadStripe\` utility from this package.

See https://stripe.com/docs/js/including for more information.
`;

const STRIPE_UNAVAILABLE_ERROR_TEXT = `window.Stripe is not defined. Did you include Stripe.js on your page?

For compliance reasons, Stripe.js must be loaded directly from https://js.stripe.com, and cannot be included in a bundle or hosted yourself. This npm module exists as a convenience, but delegates to window.Stripe.

You can load Stripe.js by using the \`loadStripe\` utility from this package, or by including the following <script> tag on your page:

<script src="${V3_URL}"></script>

See https://stripe.com/docs/js/including for more information.
`;

const hasUserIncludedScript = () =>
document.querySelector(`script[src="${V3_URL}"]`) && !hasInjectedScript;

export const Stripe = (...args) => {
if (window && window.Stripe) {
return window.Stripe(...args);
}

if (hasCalledLoadStripe || hasUserIncludedScript()) {
throw new Error(STRIPE_NOT_LOADED_ERROR_TEXT);
}

throw new Error(STRIPE_UNAVAILABLE_ERROR_TEXT);
};
42 changes: 0 additions & 42 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,46 +96,4 @@ describe('Stripe module loader', () => {
});
});
});

describe('Stripe proxy', () => {
it('proxies to window.Stripe when present', () => {
const {Stripe} = require('./index');
window.Stripe = jest.fn((key) => ({key}));

expect(Stripe('pk_test_foo')).toEqual({key: 'pk_test_foo'});
});

it('throws when Stripe.js has not yet loaded from a user injected script', () => {
const {Stripe} = require('./index');
const script = document.createElement('script');
script.src = 'https://js.stripe.com/v3';
document.body.appendChild(script);

expect(() => Stripe('pk_test_foo')).toThrow(
'Stripe.js has not yet loaded.'
);
});

it('throws when Stripe.js has not yet loaded after calling loadStripe', () => {
const {loadStripe, Stripe} = require('./index');

loadStripe();

expect(() => Stripe('pk_test_foo')).toThrow(
'Stripe.js has not yet loaded.'
);
});

it('throws when Stripe.js has not been included', () => {
const {Stripe} = require('./index');

return Promise.resolve(() => {
// Wait for next tick to validate this error is thrown
// even after our own script has been added.
expect(() => Stripe('pk_test_foo')).toThrow(
'window.Stripe.js is not defined.'
);
});
});
});
});