| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | import Stripe from 'stripe'; | 
					
						
							| 
									
										
										
										
											2018-08-31 16:04:04 +01:00
										 |  |  | import keys from '../../../config/secrets'; | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  | export default function donateBoot(app, done) { | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |   let stripe = false; | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  |   const { User } = app.models; | 
					
						
							|  |  |  |   const api = app.loopback.Router(); | 
					
						
							|  |  |  |   const donateRouter = app.loopback.Router(); | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |   const subscriptionPlans = [500, 1000, 3500, 5000, 25000].reduce( | 
					
						
							|  |  |  |     (accu, current) => ({ | 
					
						
							|  |  |  |       ...accu, | 
					
						
							|  |  |  |       [current]: { | 
					
						
							|  |  |  |         amount: current, | 
					
						
							|  |  |  |         interval: 'month', | 
					
						
							|  |  |  |         product: { | 
					
						
							|  |  |  |           name: | 
					
						
							|  |  |  |             'Monthly Donation to freeCodeCamp.org - ' + | 
					
						
							|  |  |  |             `Thank you ($${current / 100})` | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           currency: 'usd', | 
					
						
							|  |  |  |           id: `monthly-donation-${current}` | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }), {} | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function connectToStripe() { | 
					
						
							|  |  |  |     return new Promise(function(resolve) { | 
					
						
							|  |  |  |       // connect to stripe API
 | 
					
						
							|  |  |  |       stripe = Stripe(keys.stripe.secret); | 
					
						
							|  |  |  |       // parse stripe plans
 | 
					
						
							|  |  |  |       stripe.plans.list({}, function(err, plans) { | 
					
						
							|  |  |  |         if (err) { | 
					
						
							|  |  |  |           throw err; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const requiredPlans = Object.keys(subscriptionPlans).map( | 
					
						
							|  |  |  |           key => subscriptionPlans[key].id | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         const availablePlans = plans.data.map(plan => plan.id); | 
					
						
							|  |  |  |         requiredPlans.forEach(planId => { | 
					
						
							|  |  |  |           if (!availablePlans.includes(planId)) { | 
					
						
							|  |  |  |             const key = planId.split('-').slice(-1)[0]; | 
					
						
							|  |  |  |             createStripePlan(subscriptionPlans[key]); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       resolve(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function createStripePlan(plan) { | 
					
						
							|  |  |  |     stripe.plans.create(plan, function(err) { | 
					
						
							|  |  |  |       if (err) { | 
					
						
							|  |  |  |         console.log(err); | 
					
						
							|  |  |  |         throw err; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       console.log(`${plan.id} created`); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   function createStripeDonation(req, res) { | 
					
						
							|  |  |  |     const { user, body } = req; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!body || !body.amount) { | 
					
						
							|  |  |  |       return res.status(400).send({ error: 'Amount Required' }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const { amount, token: {email, id} } = body; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const fccUser = user ? | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |             Promise.resolve(user) : | 
					
						
							|  |  |  |             User.create$({ email }).toPromise(); | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let donatingUser = {}; | 
					
						
							|  |  |  |     let donation = { | 
					
						
							|  |  |  |       email, | 
					
						
							|  |  |  |       amount, | 
					
						
							|  |  |  |       provider: 'stripe', | 
					
						
							|  |  |  |       startDate: new Date(Date.now()).toISOString() | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return fccUser.then( | 
					
						
							|  |  |  |       user => { | 
					
						
							|  |  |  |         donatingUser = user; | 
					
						
							|  |  |  |         return stripe.customers | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |           .create({ | 
					
						
							|  |  |  |             email, | 
					
						
							|  |  |  |             card: id | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |     }) | 
					
						
							|  |  |  |     .then(customer => { | 
					
						
							|  |  |  |       donation.customerId = customer.id; | 
					
						
							|  |  |  |       return stripe.subscriptions.create({ | 
					
						
							|  |  |  |         customer: customer.id, | 
					
						
							|  |  |  |         items: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             plan: `monthly-donation-${amount}` | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |     }) | 
					
						
							|  |  |  |     .then(subscription => { | 
					
						
							|  |  |  |       donation.subscriptionId = subscription.id; | 
					
						
							|  |  |  |       return res.send(subscription); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .then(() => { | 
					
						
							|  |  |  |       donatingUser.createDonation(donation).toPromise() | 
					
						
							|  |  |  |         .catch(err => { | 
					
						
							|  |  |  |           throw new Error(err); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     .catch(err => { | 
					
						
							|  |  |  |       if (err.type === 'StripeCardError') { | 
					
						
							|  |  |  |         return res.status(402).send({ error: err.message }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return res.status(500).send({ error: 'Donation Failed' }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |   const pubKey = keys.stripe.public; | 
					
						
							|  |  |  |   const secKey = keys.stripe.secret; | 
					
						
							|  |  |  |   const secretInvalid = !secKey || secKey === 'sk_from_stipe_dashboard'; | 
					
						
							|  |  |  |   const publicInvalid = !pubKey || pubKey === 'pk_from_stipe_dashboard'; | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 08:47:10 -06:00
										 |  |  |   if (secretInvalid || publicInvalid) { | 
					
						
							|  |  |  |     if (process.env.NODE_ENV === 'production') { | 
					
						
							|  |  |  |       throw new Error('Stripe API keys are required to boot the server!'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     console.info('No Stripe API keys were found, moving on...'); | 
					
						
							|  |  |  |     done(); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     api.post('/charge-stripe', createStripeDonation); | 
					
						
							|  |  |  |     donateRouter.use('/donate', api); | 
					
						
							|  |  |  |     app.use(donateRouter); | 
					
						
							|  |  |  |     app.use('/external', donateRouter); | 
					
						
							|  |  |  |     connectToStripe().then(done); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-07 22:35:06 +01:00
										 |  |  | } |