├── .gitignore
├── README.md
├── config
└── template.js
├── lib
└── server.js
├── package.json
├── public
└── global.css
├── server.js
└── views
├── connected.pug
├── index.pug
└── partials
├── footer.pug
├── head.pug
└── nav.pug
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | config/index.js
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A simple Stripe Connect Node demo app
2 |
3 | This is a simple Stripe Connect application written in Node.js with Express. At this point it doesn't do a whole lot, and the intention is primarily to provide a general example to help you get up and running with [Stripe Connect](https://stripe.com/docs/connect). It ~~was totally stolen from~~ is heavily inspired by [A simple PHP Stripe Connect example using OAuth 2]( https://github.com/adamjstevenson/oauth-stripe-connect-php).
4 |
5 |
6 |
7 |
8 | ## Some important things you should know right off the bat
9 |
10 | * This isn't, by any means, ready for production.
11 | * You should read over [Stripe's Connect documentation](https://stripe.com/docs/connect/standalone-accounts) as a first step.
12 | * This example uses [Express](https://expressjs.com/) and [Pug](https://pugjs.org/) to try to keep the actual logic as clear as possible. In theory I could've chosen any framework, but I'm most familiar with Express, so that's what you got.
13 | * This application uses an OAuth 2.0 client library provided by the [Mulesoft](https://github.com/mulesoft/js-client-oauth2). Though [it's possible](https://stripe.com/docs/connect/standalone-accounts#sample-code) to build the OAuth flow out yourself, it's recommended that you use an OAuth library like this one.
14 | * Since the goal here is just to show the connection process, this application doesn't make use of any database. IRL, you'll want to save at least the account ID to your database when your user connects so you can [do things on their behalf](https://stripe.com/docs/connect/authentication#authentication-via-the-stripe-account-header) later.
15 | * This integration uses [standalone accounts](https://stripe.com/docs/connect/standalone-accounts), so you can either create a new test account using [some test data](https://stripe.com/docs/testing), or connect an existing account.
16 |
17 | ## Getting started
18 |
19 | Clone this repository:
20 |
21 | ```
22 | git clone https://github.com/floatingLomas/stripe-connect-node.git
23 | ```
24 |
25 | Log in to your Stripe account (or create one) and register your application as a platform. Set a redirect URI in Stripe that points to https://localhost:3000/connected (or whatever you want to set below).
26 |
27 | Copy `config/template.js` to `config/index.js` and add your test secret key, development client ID, redirect URL and the port you want to listen on there.
28 |
29 | Run `npm install` from the project's root directory to install dependencies, then `npm start` to get rolling.
30 |
--------------------------------------------------------------------------------
/config/template.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Save this file as `index.js` in this folder with your account's IDs.
4 | // `index.js` is .gitignored so it won't accidentally end up somewhere
5 | // it shouldn't.
6 |
7 | module.exports = exports = {
8 | clientId: 'ca_YOUR_CLIENT_ID', // Your client ID: https://dashboard.stripe.com/account/applications/settings
9 | secretKey: 'sk_YOUR_SECRET_KEY', // Your secret API KEY: https://dashboard.stripe.com/account/apikeys
10 | redirectUri: 'http://localhost:3000/connected', // https://dashboard.stripe.com/account/applications/settings
11 |
12 | port: 3000
13 | };
14 |
--------------------------------------------------------------------------------
/lib/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var express = require('express');
4 | var app = express();
5 |
6 | app.set('views', './views');
7 | app.set('view engine', 'pug');
8 | app.use(express.static('public'));
9 |
10 | module.exports = exports = app;
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stripe-connect-node",
3 | "version": "0.0.1",
4 | "description": "A simple Node.js Stripe Connect example using OAuth 2",
5 | "private": true,
6 | "scripts": {},
7 | "repository": {
8 | "type": "git",
9 | "url": "git+https://github.com/floatingLomas/stripe-connect-node.git"
10 | },
11 | "keywords": [
12 | "stripe",
13 | "stripe-connect",
14 | "oauth"
15 | ],
16 | "author": "Jonathan Lomas ",
17 | "bugs": {
18 | "url": "https://github.com/floatingLomas/stripe-connect-node/issues"
19 | },
20 | "homepage": "https://github.com/floatingLomas/stripe-connect-node",
21 | "dependencies": {
22 | "client-oauth2": "^2.2.0",
23 | "express": "^4.14.0",
24 | "pug": "^2.0.0-beta6",
25 | "stripe": "^4.10.0"
26 | },
27 | "devDependencies": {}
28 | }
29 |
--------------------------------------------------------------------------------
/public/global.css:
--------------------------------------------------------------------------------
1 | html {
2 | position: relative;
3 | min-height: 100%;
4 | }
5 | body {
6 | /* Margin bottom by footer height */
7 | margin-bottom: 60px;
8 | background-color: #fafafa;
9 | }
10 | body > .container {
11 | padding: 60px 15px 0;
12 | }
13 | .navbar-default {
14 | background-color:#fff;
15 | }
16 | .footer {
17 | position: absolute;
18 | bottom: 0;
19 | width: 100%;
20 | height: 60px;
21 | background-color: #fff;
22 | }
23 | .space-top {
24 | margin-top:20px;
25 | }
26 | dt {
27 | color: #777;
28 | }
29 | .shadow-sm {
30 | webkit-box-shadow: 0 2px 0 rgba(37,46,53,0.06);
31 | -moz-box-shadow: 0 2px 0 rgba(37,46,53,0.06);
32 | box-shadow: 0 2px 0 rgba(37,46,53,0.06);
33 | }
34 | .btn-xl {
35 | font-size:28px;
36 | padding:10px;
37 | font-weight: 300;
38 | }
39 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var CONFIG = require('./config');
4 |
5 | var app = require('./lib/server');
6 | var stripe = require('stripe')(CONFIG.secretKey);
7 | var OAuth = require('client-oauth2');
8 |
9 | // Configure the OAuth 2.0 Client
10 | var oauth = new OAuth({
11 | clientId: CONFIG.clientId,
12 | clientSecret: CONFIG.secretKey,
13 |
14 | scopes: ['read_write'],
15 |
16 | redirectUri: CONFIG.redirectUri,
17 | authorizationUri: 'https://connect.stripe.com/oauth/authorize',
18 | accessTokenUri: 'https://connect.stripe.com/oauth/token'
19 | });
20 |
21 | // Get the home page:
22 | app.get('/', function(req, res) {
23 | res.render('index', {
24 | redirectUri: oauth.code.getUri()
25 | });
26 | });
27 |
28 | // Handle the redirect - this should match your CONFIG redirect's path:
29 | app.get('/connected', function(req, res) {
30 | if (req.query.error) return response.render('connected', {
31 | error: req.query.error
32 | });
33 |
34 | // Use the Authorization Code to get a Token
35 | oauth.code.getToken(req.url).then(handleToken);
36 |
37 | // Go fetch the Account from the Token
38 | function handleToken(token) {
39 | stripe.account.retrieve(token.data.stripe_user_id, onAccount);
40 | }
41 |
42 | // Render the Account information
43 | function onAccount(error, account) {
44 | res.render('connected', {
45 | error: error,
46 | account: account
47 | });
48 | }
49 | });
50 |
51 | app.listen(CONFIG.port, function() {
52 | console.log('Listening on port', CONFIG.port);
53 | });
54 |
--------------------------------------------------------------------------------
/views/connected.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include partials/head.pug
4 |
5 | body
6 | include partials/nav.pug
7 |
8 | .container
9 | if error
10 | .alert.alert-danger: strong #{error.error}: #{error.error_description}
11 | else
12 | .alert.alert-success: strong Successfully connected your Account!
13 |
14 | if account
15 | h2.page-header About your account
16 |
17 | .panel.panel-default.shadow-sm: .panel-body: .dl-horizontal
18 | dt #[i.fa.fa-cc-stripe] Account ID
19 | dd #{account.id}
20 |
21 | dt #[i.fa.fa-envelope] Email
22 | dd #{account.email}
23 |
24 | dt #[i.fa.fa-briefcase] Business Name
25 | dd #{account.business_name}
26 |
27 | dt #[i.fa.fa-globe] Country
28 | dd #{account.country}
29 |
30 | dt #[i.fa.fa-envelope] Email
31 | dd #{account.id}
32 |
33 | dt #[i.fa.fa-usd] Default Currency
34 | dd #{account.default_currency}
35 |
36 | dt #[i.fa.fa-briefcase] Display Name
37 | dd #{account.display_name}
38 |
39 | dt #[i.fa.fa-file-text] Statement Descriptor
40 | dd #{account.statement_descriptor}
41 |
42 | dt #[i.fa.fa-question-circle] Charges Enabled
43 | dd #{account.charges_enabled.toString()}
44 |
45 | dt #[i.fa.fa-question-circle] Transfers Enabled
46 | dd #{account.transfers_enabled.toString()}
47 |
48 | dt #[i.fa.fa-link] Website
49 | dd #{account.business_url}
50 |
51 | include partials/footer.pug
52 |
--------------------------------------------------------------------------------
/views/index.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include partials/head.pug
4 |
5 | body
6 | include partials/nav.pug
7 |
8 | .container
9 | .page-header: h1 A Simple Stripe Connect PHP example
10 |
11 | p.lead This is a basic Stripe Connect example app built with Node.js, Express and an #[a( href="https://github.com/lelylan/simple-oauth2") OAuth 2.0 client].
12 |
13 | p.lead This integration uses #[a(href="https://stripe.com/docs/connect/standalone-accounts") standalone accounts], so you can either create a new test account using #[a(href="https://stripe.com/docs/testing") some test data], or connect an existing account (in test mode).
14 |
15 | p: a.btn.btn-primary.btn-block.btn-xl(
16 | data-loading-text='Connecting...'
17 | href=redirectUri
18 | ) Connect to Stripe
19 |
20 | include partials/footer.pug
21 |
--------------------------------------------------------------------------------
/views/partials/footer.pug:
--------------------------------------------------------------------------------
1 | footer.footer
2 | .container
3 | p.text-muted.text-center.space-top
4 | a(href='https://stripe.com/docs/connect') View Stripe Connect docs
5 |
6 | script(type='text/javascript').
7 | $('.btn').on('click', function () {
8 | var $btn = $(this).button('loading')
9 | });
10 |
--------------------------------------------------------------------------------
/views/partials/head.pug:
--------------------------------------------------------------------------------
1 | head
2 | meta(charset='utf-8')
3 | meta(http-equiv='X-UA-Compatible', content='IE=edge')
4 | meta(name='viewport', content='width=device-width, initial-scale=1')
5 | meta(name='description', content='')
6 | meta(name='author', content='')
7 | link(rel='icon', href='../../favicon.ico')
8 | title Simple Connect Node.js example
9 | script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js')
10 | script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js', integrity='sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS', crossorigin='anonymous')
11 | link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css', integrity='sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7', crossorigin='anonymous')
12 | link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css')
13 | link(rel='stylesheet', href='/global.css')
14 | // HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries
15 | //if lt IE 9
16 | script(src='https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js')
17 | script(src='https://oss.maxcdn.com/respond/1.4.2/respond.min.js')
18 |
--------------------------------------------------------------------------------
/views/partials/nav.pug:
--------------------------------------------------------------------------------
1 | nav.navbar.navbar-default.navbar-fixed-top
2 | .container
3 | .navbar-header
4 | button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#navbar', aria-expanded='false', aria-controls='navbar')
5 | span.sr-only Toggle navigation
6 | span.icon-bar
7 | span.icon-bar
8 | span.icon-bar
9 | a.navbar-brand(href='/') Simple Connect Node.js
10 | #navbar.collapse.navbar-collapse.pull-right
11 | ul.nav.navbar-nav
12 | li
13 | a(href='/') Home
14 | li
15 | a(href='https://github.com/floatingLomas/stripe-connect-node') View on Github
16 | // /.nav-collapse
17 |
--------------------------------------------------------------------------------