diff --git a/README.md b/README.md index 309c56f..7c7be37 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,71 @@ To demo how to implement stripe SCA using react and node. > [MIRROR ON GITHUB](https://github.com/mfbx9da4/stripe-sca-subscription-react) ![edAUunAs5S](https://user-images.githubusercontent.com/1690659/65525116-e8bc2700-dee6-11e9-814f-96ece40653cd.gif) + +### Aim + +- A step by step guide for integrating Stripe in an SCA compliant way for subscriptions. +- If you just want a template project to copy, [you can see a live demo and fork the code here](https://glitch.com/edit/#!/stripe-sca-subscription-react). +- Stripe React Elements github repository also has some [demo code](https://github.com/stripe/react-stripe-elements/tree/master/demo/intents) +which I made into a [working example here](https://glitch.com/edit/#!/stripe-react-elements-express). + +### Overview + +Prerequisites +1. Upgrade stripe +2. Upgrade stripejs (server) +3. Upgrade stripe-react-elements +4. Upgrade stripejs (web) +5. Create subscriptions in dashboard + +Integrate Stripe +1. Setup the intent +2. Authenticate with 3D secure +3. Attach payment method to customer +4. Start subscription + +### Prerequisites + +1. Upgrade to latest version of stripe in the dashboard. `2019-09-09` or later. + +![Upgraded stripe version](https://user-images.githubusercontent.com/1690659/65693247-e6370a00-e06b-11e9-96b5-53c9e5c129f0.png) + + +2. Use the latest version of `stripe` nodejs library. + +``` +npm uninstall stripe -S ; npm install stripe -S +# or if you use yarn +yarn remove stripe ; yarn add stripe +``` + +3. Use latest version of `react-stripe-elements`. + +``` +npm uninstall react-stripe-elements -S ; npm install react-stripe-elements -S +# or if you use yarn +yarn remove react-stripe-elements ; yarn add react-stripe-elements +``` + +4. Use latest version of client side stripe. If you are already using stripe make sure to update it. If you are starting fresh, we'll include it later in the tutorial, so don't worry about including it now! + +``` + +``` + +5. In the dashboard, [create a subscription plan](https://stripe.com/docs/billing/subscriptions/creating) or [do it programmatically](https://stripe.com/docs/api/subscriptions). +If you have a subscription it should look a bit like this in the dashboard. Jot down the `ID` shown in the image for later. + +![dashboard subscription](https://user-images.githubusercontent.com/1690659/65694524-e9cb9080-e06d-11e9-8433-8a42407ce361.png) + + +### Activate SCA + + +1. Setup the intent + +2. Authenticate with 3D secure +3. Attach payment method to customer +4. Start subscription + + diff --git a/config/env.js b/_#config/env.js similarity index 100% rename from config/env.js rename to _#config/env.js diff --git a/config/jest/cssTransform.js b/_#config/jest/cssTransform.js similarity index 100% rename from config/jest/cssTransform.js rename to _#config/jest/cssTransform.js diff --git a/config/jest/fileTransform.js b/_#config/jest/fileTransform.js similarity index 100% rename from config/jest/fileTransform.js rename to _#config/jest/fileTransform.js diff --git a/config/paths.js b/_#config/paths.js similarity index 100% rename from config/paths.js rename to _#config/paths.js diff --git a/config/polyfills.js b/_#config/polyfills.js similarity index 100% rename from config/polyfills.js rename to _#config/polyfills.js diff --git a/config/webpack.config.dev.js b/_#config/webpack.config.dev.js similarity index 100% rename from config/webpack.config.dev.js rename to _#config/webpack.config.dev.js diff --git a/config/webpack.config.prod.js b/_#config/webpack.config.prod.js similarity index 100% rename from config/webpack.config.prod.js rename to _#config/webpack.config.prod.js diff --git a/scripts/build.js b/_scripts/build.js similarity index 100% rename from scripts/build.js rename to _scripts/build.js diff --git a/scripts/start.js b/_scripts/start.js similarity index 100% rename from scripts/start.js rename to _scripts/start.js diff --git a/scripts/test.js b/_scripts/test.js similarity index 100% rename from scripts/test.js rename to _scripts/test.js diff --git a/package-lock.json b/package-lock.json index c1fd003..30bc20b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "app", + "name": "stripe-sca-subscription-react", "version": "0.1.0", "lockfileVersion": 1, "requires": true, @@ -3145,7 +3145,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -3166,12 +3167,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3186,17 +3189,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3313,7 +3319,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3325,6 +3332,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3339,6 +3347,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3346,12 +3355,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3370,6 +3381,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3450,7 +3462,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3462,6 +3475,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3547,7 +3561,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3583,6 +3598,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3602,6 +3618,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3645,12 +3662,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -9210,9 +9229,9 @@ } }, "loadjs": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-3.6.1.tgz", - "integrity": "sha512-AZEBw2GWdJk2IzBgQ+Wohoao5j+t0rajqK8dJu8jQqgYxDTxhmCt0ayMo/vCa0ZAMvZxnJcam6uLICfnVd8KAw==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/loadjs/-/loadjs-4.0.1.tgz", + "integrity": "sha512-ArFeJEd5TFXjcO1YqT5uSgSMBq+NHWdoew7o6sLqb1KZBg06UIyk/PMT8ftN9T5vT20q3QbzsKdp2N8XhdYysQ==" }, "locate-path": { "version": "3.0.0", diff --git a/package.json b/package.json index 71b63ed..a9e1fea 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "app", + "name": "stripe-sca-subscription-react", "version": "0.1.0", "private": true, "dependencies": { @@ -10,7 +10,7 @@ "body-parser": "^1.19.0", "stripe": "^7.9.1", "react-stripe-elements": "^5.0.0", - "loadjs": "^3.6.1" + "loadjs": "^4.0.1" }, "devDependencies": { "react-scripts": "^3.1.2" diff --git a/src/index.js b/src/index.js index 94ab758..9f3675f 100644 --- a/src/index.js +++ b/src/index.js @@ -66,19 +66,7 @@ class _CardForm extends React.Component { const paymentMethod = await this.getPaymentMethod() return this.attachPaymentMethod(paymentMethod) } - - attachPaymentMethod = async paymentMethod => { - const attached = await api.attachPaymentMethod({ - paymentMethod, - email: 'david@crowdform.co.uk' - }) - console.log('attache', attached) - this.setState({ - succeeded: true, - message: `Subscription started!` - }) - } - + getPaymentMethod = async () => { const payload = await this.props.stripe.handleCardSetup(this.state.clientSecret) if (payload.error) { @@ -96,6 +84,18 @@ class _CardForm extends React.Component { return payload.setupIntent.payment_method } + attachPaymentMethod = async paymentMethod => { + const attached = await api.attachPaymentMethod({ + paymentMethod, + email: 'david@crowdform.co.uk' + }) + console.log('attache', attached) + this.setState({ + succeeded: true, + message: `Subscription started!` + }) + } + render() { return (