├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── APIDOCS.md ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Stripe_Connect_Workflow_1.jpg ├── Stripe_Connect_Workflow_2.jpg ├── TODO ├── index.js ├── package-lock.json ├── package.json └── test ├── _stripe.stub.js ├── add-customer-card.test.js ├── capture-payment.test.js ├── customer-create.test.js ├── customer-delete.test.js ├── delete-customer-card.test.js ├── fetch-customer-cards.test.js ├── get-default-customer-card.test.js ├── initiate-payment.test.js ├── refund-create.test.js ├── set-default-customer-card.test.js ├── set-vendor-bank-account.test.js ├── vendor-accept-toc.test.js ├── vendor-create.test.js ├── vendor-delete.test.js └── vendor-kyc.test.js /.eslintignore: -------------------------------------------------------------------------------- 1 | .nyc_output/ 2 | .vscode/ 3 | coverage/ 4 | node_modules/ 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true, 5 | "mocha": true 6 | }, 7 | "extends": "airbnb-base", 8 | "rules": { 9 | "func-names": [ 10 | "error", 11 | "never" 12 | ], 13 | "comma-dangle": [ 14 | "error", 15 | "only-multiline" 16 | ], 17 | "semi": [ 18 | "warn", 19 | "never" 20 | ], 21 | "quotes": [ 22 | "warn", 23 | "double" 24 | ], 25 | "max-len": [ 26 | "warn", 27 | { 28 | "ignoreComments": true, 29 | "ignoreTrailingComments": true, 30 | "ignoreUrls": true, 31 | "ignoreStrings": true, 32 | "ignoreTemplateLiterals": true, 33 | "ignoreRegExpLiterals": true 34 | } 35 | ], 36 | "no-console": 1, 37 | "no-unused-vars": 1, 38 | "prefer-const": 1, 39 | "no-var": 1, 40 | "eol-last": 1, 41 | "padded-blocks": 1, 42 | "import/newline-after-import": 0, 43 | "no-underscore-dangle": 0, 44 | "camelcase": 1 45 | } 46 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | ## Editors 61 | .vscode/ 62 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.jpg 2 | TODO 3 | .nyc_output/ 4 | coverage/ 5 | .vscode/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - stable 5 | 6 | install: 7 | - npm install 8 | 9 | script: 10 | - npm run lint 11 | - npm test 12 | 13 | # Send coverage data to Coveralls 14 | after_script: npm run coveralls -------------------------------------------------------------------------------- /APIDOCS.md: -------------------------------------------------------------------------------- 1 | ## Functions 2 | 3 |
Promise
Create a Customer on Stripe
6 |Promise
Delete a Customer on Stripe
9 |Promise
Create a Vendor (Custom Account on Stripe)
12 |Promise
Delete a Vendor (Custom Account on Stripe)
15 |Promise
Fetch all the Cards (or other sources) associated with the Customer with the provided id. The default card is marked as such.
18 |Promise
Add a Card to a Customer
21 |Promise
Delete a Customer's Card
24 |Promise
Get a Customer's default Card. Note that, this info is already available implicitly from fetchCustomerCards()
Promise
Set an existing Customer Card as the default payment source
30 |Promise
Set the default Bank A/c for a Vendor (Custom Account on Stripe)
33 |Promise
Update KYC details for a Vendor (Stripe Custom Account). These are mandatory to be able to receive payments and payouts.
36 |Promise
ToS acceptance of a Vendor (Stripe Custom Account)
39 |Promise
Initiate a Payment (Stripe Charge creation)
42 |Promise
Capture an existing Payment (Stripe Charge)
45 |Promise
Refund a previously captured (but unrefunded) Charge
48 |Promise
54 | Create a Customer on Stripe
55 |
56 | **Kind**: global function
57 |
58 | | Param | Type | Default |
59 | | --- | --- | --- |
60 | | [email] | string
| null
|
61 |
62 |
63 |
64 | ## customerDelete(stripeCustomerId) ⇒ Promise
65 | Delete a Customer on Stripe
66 |
67 | **Kind**: global function
68 |
69 | | Param | Type | Description |
70 | | --- | --- | --- |
71 | | stripeCustomerId | string
| Customer ID to delete (begins with "cus_") |
72 |
73 |
74 |
75 | ## vendorCreate([email], [country]) ⇒ Promise
76 | Create a Vendor (Custom Account on Stripe)
77 |
78 | **Kind**: global function
79 |
80 | | Param | Type | Default |
81 | | --- | --- | --- |
82 | | [email] | string
| null
|
83 | | [country] | string
| "US"
|
84 |
85 |
86 |
87 | ## vendorDelete(stripeAccountId) ⇒ Promise
88 | Delete a Vendor (Custom Account on Stripe)
89 |
90 | **Kind**: global function
91 |
92 | | Param | Type | Description |
93 | | --- | --- | --- |
94 | | stripeAccountId | string
| Vendor ID (Custom Account on Stripe) to delete (begins with "acct_") |
95 |
96 |
97 |
98 | ## fetchCustomerCards(stripeCustomerId) ⇒ Promise
99 | Fetch all the Cards (or other sources) associated with the Customer with the provided id. The default card is marked as such.
100 |
101 | **Kind**: global function
102 |
103 | | Param | Type | Description |
104 | | --- | --- | --- |
105 | | stripeCustomerId | string
| Customer Id (begins with "cus_") |
106 |
107 |
108 |
109 | ## addCustomerCard(stripeCustomerId, stripeToken) ⇒ Promise
110 | Add a Card to a Customer
111 |
112 | **Kind**: global function
113 |
114 | | Param | Type | Description |
115 | | --- | --- | --- |
116 | | stripeCustomerId | string
| Id of the Customer to whom the Card is to be added (begins with "cus_") |
117 | | stripeToken | string
| The token representing the Card to add, genetrated client-side using Stripe.js, etc. |
118 |
119 |
120 |
121 | ## deleteCustomerCard(stripeCustomerId, cardId) ⇒ Promise
122 | Delete a Customer's Card
123 |
124 | **Kind**: global function
125 |
126 | | Param | Type | Description |
127 | | --- | --- | --- |
128 | | stripeCustomerId | string
| Id of the Customer for whom the Card is to be deleted (begins with "cus_") |
129 | | cardId | string
| Id of the Card to be deleted |
130 |
131 |
132 |
133 | ## getDefaultCustomerCard(stripeCustomerId) ⇒ Promise
134 | Get a Customer's default Card. Note that, this info is already available implicitly from `fetchCustomerCards()`
135 |
136 | **Kind**: global function
137 |
138 | | Param | Type | Description |
139 | | --- | --- | --- |
140 | | stripeCustomerId | string
| Customer Id (begins with "cus_") |
141 |
142 |
143 |
144 | ## setDefaultCustomerCard(stripeCustomerId, stripeCardId) ⇒ Promise
145 | Set an existing Customer Card as the default payment source
146 |
147 | **Kind**: global function
148 |
149 | | Param | Type | Description |
150 | | --- | --- | --- |
151 | | stripeCustomerId | string
| Customer Id (begins with "cus_") |
152 | | stripeCardId | string
| The id of the Card to be set as default. Must be one of the Customer's existing Cards. |
153 |
154 |
155 |
156 | ## setVendorBankAccount(stripeAccountId, _) ⇒ Promise
157 | Set the default Bank A/c for a Vendor (Custom Account on Stripe)
158 |
159 | **Kind**: global function
160 |
161 | | Param | Type | Default | Description |
162 | | --- | --- | --- | --- |
163 | | stripeAccountId | string
| | Vendor Id (begins with "acct_") |
164 | | _ | object
| | The Bank A/c details |
165 | | _.routingNo | string
| | |
166 | | _.accountNo | string
| | |
167 | | [_.accountHolderName] | string
| null
| |
168 | | [_.country] | string
| "US"
| |
169 | | [_.currency] | string
| "usd"
| |
170 |
171 |
172 |
173 | ## vendorKyc(stripeAccountId, _) ⇒ Promise
174 | Update KYC details for a Vendor (Stripe Custom Account). These are mandatory to be able to receive payments and payouts.
175 |
176 | **Kind**: global function
177 |
178 | | Param | Type | Description |
179 | | --- | --- | --- |
180 | | stripeAccountId | string
| Vendor Id (begins with "acct_") |
181 | | _ | object
| The KYC details |
182 | | _.address | object
| Address details |
183 | | _.address.city | string
| City |
184 | | _.address.line1 | string
| Address Line 1 |
185 | | _.address.line2 | string
| Address Line 2 |
186 | | _.address.postal_code | string
| ZIP/Postal Code |
187 | | _.address.state | string
| State/County/Province/Region |
188 | | _.address.country | string
| 2-letter Country Code |
189 | | _.dob | object
| Date of Birth |
190 | | _.dob.day | string
| Day of Birth |
191 | | _.dob.month | string
| Month of Birth |
192 | | _.dob.year | string
| Year of Birth |
193 | | _.name | object
| Name |
194 | | _.name.first | string
| First Name |
195 | | _.name.last | string
| Last Name |
196 | | _.email | string
| Email Id |
197 | | _.phone | string
| Phone Number |
198 | | _.businessUrl | string
| Business url |
199 | | _.personalIdNumber | string
| Personal ID Number (For some Non US Countries) |
200 | | _.ssnLastFour | string
| Last 4 digits of the SSN |
201 | | _.mcc | string
| Stripe Merchant Category Code (Ref: https://stripe.com/docs/connect/setting-mcc) |
202 |
203 |
204 |
205 | ## vendorAcceptTos(stripeAccountId, _) ⇒ Promise
206 | ToS acceptance of a Vendor (Stripe Custom Account)
207 |
208 | **Kind**: global function
209 |
210 | | Param | Type | Default | Description |
211 | | --- | --- | --- | --- |
212 | | stripeAccountId | string
| | Vendor Id (begins with "acct_") |
213 | | _ | object
| | ToS Acceptance details |
214 | | _.tosAcceptanceDate | number
| | Date (in UNIX timestamp format) of ToS acceptance |
215 | | _.tosAcceptanceIp | string
| | IP address from where the ToS was accepted |
216 | | [_.tosUserAgent] | string
| null
| User Agent string of the browser using which the ToS was accepted |
217 |
218 |
219 |
220 | ## initiatePayment(_) ⇒ Promise
221 | Initiate a Payment (Stripe Charge creation)
222 |
223 | **Kind**: global function
224 |
225 | | Param | Type | Default | Description |
226 | | --- | --- | --- | --- |
227 | | _ | object
| | Payment (Stripe Charge) parameters |
228 | | [_.capture] | boolean
| false
| Whether to capture this charge later or immediately. By default, it is set to false, signifying later capture. Note that such charges need to be captured manually within 7 days, beyond which it is automatically reveresed/refunded by Stripe. |
229 | | _.customer | string
| | Id of the Customer (Stripe Customer) making the payment (begins with "cus_") |
230 | | _.vendor | string
| | Id of the Vendor (Stripe Custom Account) to receive the payment (begins with "acct_") |
231 | | _.amount | number
| | Amount to deduct from Customer |
232 | | _.vendorAmount | number
| | Amount payable to the Vendor. Must be less than or equal to `amount`. Ideally, the difference between `amount` & `vendorAmount`, minus the Stripe fees, is what the Marketplace retains as profit. |
233 | | _.currency | string
| | Currency code |
234 | | [_.receiptEmail] | string
| null
| Email to mail the receipt from Stripe |
235 | | [_.description] | string
| | Optional description |
236 | | [_.statementDescriptor] | string
| | Text appearing on Bank/Card statements |
237 |
238 |
239 |
240 | ## capturePayment(transactionId, [vendorAmount], [statementDescriptor]) ⇒ Promise
241 | Capture an existing Payment (Stripe Charge)
242 |
243 | **Kind**: global function
244 |
245 | | Param | Type | Default | Description |
246 | | --- | --- | --- | --- |
247 | | transactionId | string
| | Id of the Stripe Charge to capture (begins with "ch_") |
248 | | [vendorAmount] | number
|
| Optionally update the amount payable to Vendor. If not mentioned, the amount in original charge is used. |
249 | | [statementDescriptor] | string
| | Text appearing on Bank/Card statements (overrides the one mentioned in original charge) |
250 |
251 |
252 |
253 | ## refund(transactionId, amount, [reason]) ⇒ Promise
254 | Refund a previously captured (but unrefunded) Charge
255 |
256 | **Kind**: global function
257 |
258 | | Param | Type | Default | Description |
259 | | --- | --- | --- | --- |
260 | | transactionId | string
| | The Stripe Charge Id to Refund |
261 | | amount | string
| | Amount to refund |
262 | | [reason] | string
| null
| Reason for refund |
263 |
264 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [0.2.2](https://github.com/sayanriju/stripe-connect-functions/compare/v0.2.1...v0.2.2) (2018-05-23)
3 |
4 |
5 |
6 |
7 | ## [0.2.1](https://github.com/sayanriju/stripe-connect-functions/compare/v0.2.0...v0.2.1) (2018-05-15)
8 |
9 |
10 |
11 |
12 | # [0.2.0](https://github.com/sayanriju/stripe-connect-functions/compare/v0.1.2...v0.2.0) (2018-05-06)
13 |
14 |
15 |
16 |
17 | ## [0.1.2](https://github.com/sayanriju/stripe-connect-functions/compare/v0.1.1...v0.1.2) (2018-05-01)
18 |
19 |
20 |
21 |
22 | ## [0.1.1](https://github.com/sayanriju/stripe-connect-functions/compare/v0.1.0...v0.1.1) (2018-05-01)
23 |
24 |
25 |
26 |
27 | # 0.1.0 (2018-04-30)
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Sayan "Riju" Chakrabarti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # stripe-connect-functions 
2 |
3 |   
4 |
5 | [](https://nodei.co/npm/stripe-connect-functions/)
6 |
7 | This package provides a collection of functions to help with a _Customers -> Marketplace -> Vendors_ Workflow using [Stripe Connect](https://stripe.com/connect).
8 |
9 | All the provided functions internally uses the [official NodeJS library for Stripe](https://www.npmjs.com/package/stripe).
10 |
11 | ## Example Workflow
12 |
13 | The following activity diagrams try to elucidate a rudimentary workflow. The various stages are labelled with the librarry function names to use in each case.
14 |
15 | 
16 |
17 | 
18 |
19 | ## Installation & Basic Usage
20 |
21 | 0. Set up a Stripe Connect Account and obtain the _Secret key_, which is in the form `sk_myapp_k9DHwQESw7ntTGzdjS7vFsHs`
22 |
23 | 1. Install:
24 |
25 | ```shell
26 | npm install stripe-connect-functions
27 | ```
28 |
29 |
30 |
31 | 2. Initialize:
32 |
33 | ```javascript
34 | const stripeConnect = require("stripe-connect-functions")("sk_myapp_k9DHwQESw7ntTGzdjS7vFsHs")
35 | // ^^ Remember to replace with your own key!
36 | ```
37 |
38 | 3. Use:
39 |
40 | ```javascript
41 | stripeConnect.fetchCustomerCards("cus_Ckc6NCwnBdzDCb")
42 | .then(console.log, console.log) // returns a Promise!
43 | ```
44 |
45 | For details, check the Api Docs [HERE](./APIDOCS.md).
46 |
47 | ## Testing
48 |
49 | For Unit Tests, [Ava](https://github.com/avajs/ava) is being used. Code Coverage is provided by nyc/istanbul. All calls to the Stripe API are stubbed.
50 |
51 | To run the included tests:
52 |
53 | ```shell
54 | npm run test
55 | ## Or, if you don't want code coverage:
56 | npm run test:nocoverage
57 | ```
58 |
59 | ## License
60 |
61 | [MIT](https://github.com/sayanriju/stripe-connect-functions/blob/master/LICENSE)
62 |
--------------------------------------------------------------------------------
/Stripe_Connect_Workflow_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sayanriju/stripe-connect-functions/5b2cf68ab1967b763e1d9622b2768ef3c7e0da32/Stripe_Connect_Workflow_1.jpg
--------------------------------------------------------------------------------
/Stripe_Connect_Workflow_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sayanriju/stripe-connect-functions/5b2cf68ab1967b763e1d9622b2768ef3c7e0da32/Stripe_Connect_Workflow_2.jpg
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 |
2 | Todo:
3 | ✔ Coding: @done(18-04-29 14:00)
4 | ✔ Mark default card in list cards function itself @done(18-04-29 14:00)
5 | ✔ Documentation: @done(18-05-01 18:15)
6 | ✔ Draw Activity Diagrams @done(18-04-29 20:21)
7 | ✔ Write README.md (link Diagrams) @done(18-05-01 18:15)
8 | ✔ Complete documenting code @done(18-05-01 18:15)
9 | ✔ Generate Docs using DocumentationJS @done(18-05-01 18:15)
10 | ✔ Testing, Coverage & CI: @done(18-05-01 01:00)
11 | ✔ Write Tests using AVA. Stub using Sinon (Read up!). Add Code Coverage using nyc/istanbul. @done(18-05-01 01:00)
12 | ✔ Set up CI (Ref: https://codeburst.io/how-to-create-and-publish-your-first-node-js-module-444e7585b738), Travis & Coveralls. @done(18-05-01 01:00)
13 | ✔ Publish npm package @done(18-05-01 01:00)
14 | ✔ Get some Badges (shields.io & nodei.co) and add them to README.md @done(18-05-01 01:00)
15 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const Stripe = require("stripe")
2 | module.exports = (stripeSecretKey) => {
3 | const stripe = Stripe(stripeSecretKey)
4 | return {
5 | /**
6 | * Create a Customer on Stripe
7 | * @param {string} [email=null]
8 | * @returns {Promise}
9 | */
10 | async customerCreate(email = null) {
11 | try {
12 | return await stripe.customers.create({ email })
13 | } catch (err) {
14 | // istanbul ignore next
15 | throw err
16 | }
17 | },
18 |
19 | /**
20 | * Delete a Customer on Stripe
21 | * @param {string} stripeCustomerId Customer ID to delete (begins with "cus_")
22 | * @returns {Promise}
23 | */
24 | async customerDelete(stripeCustomerId) {
25 | try {
26 | return await stripe.customers.del(stripeCustomerId)
27 | } catch (err) {
28 | // istanbul ignore next
29 | throw err
30 | }
31 | },
32 |
33 | /**
34 | * Create a Vendor (Custom Account on Stripe)
35 | * @param {string} [email=null]
36 | * @param {string} [country=US]
37 | * @returns {Promise}
38 | */
39 | async vendorCreate(email = null, country = "US") {
40 | try {
41 | return await stripe.accounts.create({
42 | country,
43 | business_type: "individual",
44 | requested_capabilities: ["transfers"],
45 | type: "custom",
46 | email,
47 | })
48 | } catch (err) {
49 | // istanbul ignore next
50 | throw err
51 | }
52 | },
53 |
54 | /**
55 | * Delete a Vendor (Custom Account on Stripe)
56 | * @param {string} stripeAccountId Vendor ID (Custom Account on Stripe) to delete (begins with "acct_")
57 | * @returns {Promise}
58 | */
59 | async vendorDelete(stripeAccountId) {
60 | try {
61 | return await stripe.accounts.del(stripeAccountId)
62 | } catch (err) {
63 | // istanbul ignore next
64 | throw err
65 | }
66 | },
67 |
68 | /**
69 | * Fetch all the Cards (or other sources) associated with the Customer with the provided id. The default card is marked as such.
70 | * @param {string} stripeCustomerId Customer Id (begins with "cus_")
71 | * @returns {Promise}
72 | */
73 | async fetchCustomerCards(stripeCustomerId) {
74 | try {
75 | const result = await Promise.all([
76 | await stripe.customers.listSources(stripeCustomerId),
77 | await stripe.customers.retrieve(stripeCustomerId)
78 | ])
79 | const { data } = result[0]
80 | const { default_source } = result[1] // eslint-disable-line camelcase
81 | return data.map(card => Object.assign(card, {
82 | isDefault: (card.id === default_source) // eslint-disable-line camelcase
83 | }))
84 | } catch (err) {
85 | // istanbul ignore next
86 | throw err
87 | }
88 | },
89 |
90 | /**
91 | * Add a Card to a Customer
92 | * @param {string} stripeCustomerId Id of the Customer to whom the Card is to be added (begins with "cus_")
93 | * @param {string} stripeToken The token representing the Card to add, genetrated client-side using Stripe.js, etc.
94 | * @returns {Promise}
95 | */
96 | async addCustomerCard(stripeCustomerId, stripeToken) {
97 | try {
98 | return await stripe.customers.createSource(stripeCustomerId, {
99 | source: stripeToken
100 | })
101 | } catch (err) {
102 | // istanbul ignore next
103 | throw err
104 | }
105 | },
106 |
107 | /**
108 | * Delete a Customer's Card
109 | * @param {string} stripeCustomerId Id of the Customer for whom the Card is to be deleted (begins with "cus_")
110 | * @param {string} cardId Id of the Card to be deleted
111 | * @returns {Promise}
112 | */
113 | async deleteCustomerCard(stripeCustomerId, cardId) {
114 | try {
115 | return await stripe
116 | .customers
117 | .deleteSource(stripeCustomerId, cardId)
118 | } catch (err) {
119 | // istanbul ignore next
120 | throw err
121 | }
122 | },
123 |
124 | /**
125 | * Get a Customer's default Card. Note that, this info is already available implicitly from `fetchCustomerCards()`
126 | * @param {string} stripeCustomerId Customer Id (begins with "cus_")
127 | * @returns {Promise}
128 | */
129 | async getDefaultCustomerCard(stripeCustomerId) {
130 | try {
131 | const {
132 | default_source // eslint-disable-line camelcase
133 | } = await stripe.customers.retrieve(stripeCustomerId)
134 | return default_source // eslint-disable-line camelcase
135 | } catch (err) {
136 | // istanbul ignore next
137 | throw err
138 | }
139 | },
140 |
141 | /**
142 | * Set an existing Customer Card as the default payment source
143 | * @param {string} stripeCustomerId Customer Id (begins with "cus_")
144 | * @param {string} stripeCardId The id of the Card to be set as default. Must be one of the Customer's existing Cards.
145 | * @returns {Promise}
146 | */
147 | async setDefaultCustomerCard(stripeCustomerId, stripeCardId) {
148 | try {
149 | const {
150 | default_source // eslint-disable-line camelcase
151 | } = await stripe.customers.update(stripeCustomerId, { // eslint-disable-line camelcase
152 | default_source: stripeCardId
153 | })
154 | return default_source // eslint-disable-line camelcase
155 | } catch (err) {
156 | // istanbul ignore next
157 | throw err
158 | }
159 | },
160 |
161 | /**
162 | * Set the default Bank A/c for a Vendor (Custom Account on Stripe)
163 | * @param {string} stripeAccountId Vendor Id (begins with "acct_")
164 | * @param {object} _ The Bank A/c details
165 | * @param {string} _.routingNo
166 | * @param {string} _.accountNo
167 | * @param {string} [_.accountHolderName=null]
168 | * @param {string} [_.country=US]
169 | * @param {string} [_.currency=usd]
170 | * @returns {Promise}
171 | */
172 | async setVendorBankAccount(stripeAccountId, {
173 | routingNo,
174 | accountNo,
175 | accountHolderName = null,
176 | country = "US",
177 | currency = "usd"
178 | }) {
179 | try {
180 | const accountObj = {
181 | object: "bank_account",
182 | country,
183 | currency,
184 | account_number: accountNo,
185 | routing_number: routingNo,
186 | }
187 | if (accountHolderName !== null) {
188 | accountObj.account_holder_name = accountHolderName
189 | }
190 | return await stripe.accounts.update(stripeAccountId, {
191 | external_account: accountObj
192 | })
193 | } catch (err) {
194 | // istanbul ignore next
195 | throw err
196 | }
197 | },
198 |
199 | /**
200 | * Update KYC details for a Vendor (Stripe Custom Account). These are mandatory to be able to receive payments and payouts.
201 | * @param {string} stripeAccountId Vendor Id (begins with "acct_")
202 | * @param {object} _ The KYC details
203 | * @param {object} _.address Address details
204 | * @param {string} _.address.city City
205 | * @param {string} _.address.line1 Address Line 1
206 | * @param {string} _.address.line2 Address Line 2
207 | * @param {string} _.address.postal_code ZIP/Postal Code
208 | * @param {string} _.address.state State/County/Province/Region
209 | * @param {string} _.address.country 2-letter Country Code
210 | * @param {object} _.dob Date of Birth
211 | * @param {string} _.dob.day Day of Birth
212 | * @param {string} _.dob.month Month of Birth
213 | * @param {string} _.dob.year Year of Birth
214 | * @param {object} _.name Name
215 | * @param {string} _.name.first First Name
216 | * @param {string} _.name.last Last Name
217 | * @param {string} _.email Email Id
218 | * @param {string} _.phone Phone Number
219 | * @param {string} _.businessUrl Business url
220 | * @param {string} _.personalIdNumber Personal ID Number (For some Non US Countries)
221 | * @param {string} _.ssnLastFour Last 4 digits of the SSN
222 | * @param {string} _.mcc Stripe Merchant Category Code (Ref: https://stripe.com/docs/connect/setting-mcc)
223 | * @returns {Promise}
224 | */
225 | async vendorKyc(stripeAccountId, {
226 | address = {},
227 | dob = {},
228 | name = {},
229 | email = null,
230 | phone = null,
231 | businessUrl = null,
232 | ssnLastFour = null,
233 | personalIdNumber = null,
234 | mcc = null
235 | }) {
236 | try {
237 | const entityObj = {
238 | individual: {
239 | address,
240 | dob,
241 | first_name: name.first,
242 | last_name: name.last,
243 | id_number: personalIdNumber,
244 | ssn_last_4: ssnLastFour,
245 | email,
246 | phone
247 | },
248 | business_type: "individual",
249 | business_profile: {
250 | mcc,
251 | url: businessUrl
252 | }
253 | }
254 | if (ssnLastFour !== null && personalIdNumber !== null) {
255 | entityObj.individual.ssn_last_4 = ssnLastFour
256 | entityObj.individual.id_number = personalIdNumber
257 | }
258 | return await stripe.accounts.update(stripeAccountId, entityObj)
259 | } catch (err) {
260 | // istanbul ignore next
261 | throw err
262 | }
263 | },
264 |
265 | /**
266 | * ToS acceptance of a Vendor (Stripe Custom Account)
267 | * @param {string} stripeAccountId Vendor Id (begins with "acct_")
268 | * @param {object} _ ToS Acceptance details
269 | * @param {number} _.tosAcceptanceDate Date (in UNIX timestamp format) of ToS acceptance
270 | * @param {string} _.tosAcceptanceIp IP address from where the ToS was accepted
271 | * @param {string} [_.tosUserAgent=null] User Agent string of the browser using which the ToS was accepted
272 | * @returns {Promise}
273 | */
274 | async vendorAcceptTos(stripeAccountId, {
275 | tosAcceptanceDate,
276 | tosAcceptanceIp,
277 | tosUserAgent = null
278 | }) {
279 | try {
280 | const tosObj = {
281 | date: tosAcceptanceDate,
282 | ip: tosAcceptanceIp,
283 | }
284 | if (tosUserAgent !== null) tosObj.user_agent = tosUserAgent
285 | return await stripe.accounts.update(stripeAccountId, {
286 | tos_acceptance: tosObj
287 | })
288 | } catch (err) {
289 | // istanbul ignore next
290 | throw err
291 | }
292 | },
293 |
294 | /**
295 | * Initiate a Payment (Stripe Charge creation)
296 | * @param {object} _ Payment (Stripe Charge) parameters
297 | * @param {boolean} [_.capture=false] Whether to capture this charge later or immediately. By default, it is set to false, signifying later capture. Note that such charges need to be captured manually within 7 days, beyond which it is automatically reveresed/refunded by Stripe.
298 | * @param {string} _.customer Id of the Customer (Stripe Customer) making the payment (begins with "cus_")
299 | * @param {string} _.vendor Id of the Vendor (Stripe Custom Account) to receive the payment (begins with "acct_")
300 | * @param {number} _.amount Amount to deduct from Customer
301 | * @param {number} _.vendorAmount Amount payable to the Vendor. Must be less than or equal to `amount`. Ideally, the difference between `amount` & `vendorAmount`, minus the Stripe fees, is what the Marketplace retains as profit.
302 | * @param {string} _.currency Currency code
303 | * @param {string} [_.receiptEmail=null] Email to mail the receipt from Stripe
304 | * @param {string} [_.description] Optional description
305 | * @param {string} [_.statementDescriptor] Text appearing on Bank/Card statements
306 | * @returns {Promise}
307 | */
308 | async initiatePayment({
309 | customer,
310 | vendor,
311 | amount,
312 | vendorAmount,
313 | currency,
314 | receiptEmail = null,
315 | description = null,
316 | statementDescriptor = null,
317 | capture = false
318 | }) {
319 | try {
320 | const opts = {
321 | capture,
322 | customer,
323 | amount: amount * 100, // convert to cents from dollar
324 | currency,
325 | description,
326 | destination: {
327 | amount: vendorAmount * 100,
328 | account: vendor,
329 | }
330 | }
331 | if (receiptEmail !== null) opts.receipt_email = receiptEmail
332 | if (statementDescriptor !== null) opts.statement_descriptor = statementDescriptor
333 | return await stripe.charges.create(opts)
334 | } catch (err) {
335 | // istanbul ignore next
336 | throw err
337 | }
338 | },
339 |
340 | /**
341 | * Capture an existing Payment (Stripe Charge)
342 | * @param {string} transactionId Id of the Stripe Charge to capture (begins with "ch_")
343 | * @param {number} [vendorAmount=null] Optionally update the amount payable to Vendor. If not mentioned, the amount in original charge is used.
344 | * @param {string} [statementDescriptor] Text appearing on Bank/Card statements (overrides the one mentioned in original charge)
345 | * @returns {Promise}
346 | */
347 | async capturePayment(
348 | transactionId,
349 | vendorAmount = null,
350 | statementDescriptor = null
351 | ) {
352 | try {
353 | const objToCapture = {}
354 | if (statementDescriptor !== null) {
355 | objToCapture.statement_descriptor = statementDescriptor
356 | }
357 | if (vendorAmount !== null) { // Update amount payable to Vendor; otherwise send the initiated amount
358 | objToCapture.destination = {
359 | amount: vendorAmount * 100, // convert to cents from dollar
360 | }
361 | }
362 | return await stripe.charges.capture(transactionId, objToCapture)
363 | } catch (err) {
364 | // istanbul ignore next
365 | throw err
366 | }
367 | },
368 |
369 | /**
370 | * Refund a previously captured (but unrefunded) Charge
371 | * @param {string} transactionId The Stripe Charge Id to Refund
372 | * @param {string} amount Amount to refund
373 | * @param {string} [reason=null] Reason for refund
374 | * @returns {Promise}
375 | */
376 | async refund(transactionId, amount, reason = null) {
377 | try {
378 | const refundObj = {
379 | charge: transactionId,
380 | amount: amount * 100
381 | }
382 | if (reason !== null) {
383 | refundObj.reason = reason
384 | }
385 | return await stripe.refunds.create(refundObj)
386 | } catch (err) {
387 | // istanbul ignore next
388 | throw err
389 | }
390 | }
391 | }
392 | }
393 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stripe-connect-functions",
3 | "version": "1.0.0",
4 | "description": "A collection of functions to help with a Customers -> Marketplace -> Vendors Workflow using Stripe Connect",
5 | "main": "index.js",
6 | "engines": {
7 | "node": ">=10"
8 | },
9 | "scripts": {
10 | "test:nocoverage": "ava",
11 | "test:withcoverage": "nyc ava",
12 | "test": "npm run test:withcoverage",
13 | "coveralls": "nyc report --reporter=text-lcov | coveralls",
14 | "lint": "npm run lint:quiet",
15 | "lint:quiet": "eslint --quiet './**/*.js'",
16 | "lint:all": "eslint './**/*.js'",
17 | "lint:fix": "eslint './**/*.js' --quiet --fix"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/sayanriju/stripe-connect-functions.git"
22 | },
23 | "author": "Sayan \"Riju\" Chakrabarti