2018-02-14 22:21:56 +09:00
import { debug , debugGroup , debugGroupEnd , getSetting , registerSetting , newMutation , editMutation , Collections , registerCallback , runCallbacks , runCallbacksAsync } from 'meteor/vulcan:core' ;
2017-10-18 20:05:51 +09:00
import express from 'express' ;
2017-05-31 10:25:13 +09:00
import Stripe from 'stripe' ;
import Charges from '../../modules/charges/collection.js' ;
import Users from 'meteor/vulcan:users' ;
import { Products } from '../../modules/products.js' ;
2017-10-26 11:27:22 +09:00
import { webAppConnectHandlersUse } from 'meteor/vulcan:core' ;
2018-02-03 13:17:04 -06:00
import { Promise } from 'meteor/promise' ;
2017-05-31 10:25:13 +09:00
2017-09-22 12:24:15 +02:00
registerSetting ( 'stripe' , null , 'Stripe settings' ) ;
2018-02-05 10:44:56 +09:00
registerSetting ( 'stripe.publishableKey' , null , 'Publishable key' , true ) ;
registerSetting ( 'stripe.publishableKeyTest' , null , 'Publishable key (test)' , true ) ;
registerSetting ( 'stripe.secretKey' , null , 'Secret key' ) ;
registerSetting ( 'stripe.secretKeyTest' , null , 'Secret key (test)' ) ;
registerSetting ( 'stripe.endpointSecret' , null , 'Endpoint secret for webhook' ) ;
2018-02-05 10:19:44 -06:00
registerSetting ( 'stripe.alwaysUseTest' , false , 'Always use test keys in all environments' , true ) ;
2017-09-22 12:24:15 +02:00
2017-05-31 10:25:13 +09:00
const stripeSettings = getSetting ( 'stripe' ) ;
2017-10-18 20:05:51 +09:00
// initialize Stripe
2018-02-05 10:19:44 -06:00
const keySecret = Meteor . isDevelopment || stripeSettings . alwaysUseTest ? stripeSettings . secretKeyTest : stripeSettings . secretKey ;
2018-02-03 13:24:57 -06:00
export const stripe = new Stripe ( keySecret ) ;
2017-10-18 20:05:51 +09:00
2017-05-31 10:25:13 +09:00
const sampleProduct = {
amount : 10000 ,
name : 'My Cool Product' ,
description : 'This product is awesome.' ,
currency : 'USD' ,
2018-02-03 13:17:04 -06:00
} ;
2017-05-31 10:25:13 +09:00
2017-10-18 20:05:51 +09:00
/ *
Create new Stripe charge
( returns a promise )
* /
export const performAction = async ( args ) => {
2017-05-31 10:25:13 +09:00
2017-06-04 13:56:40 +09:00
let collection , document , returnDocument = { } ;
2017-05-31 10:25:13 +09:00
2017-10-18 20:05:51 +09:00
const { token , userId , productKey , associatedCollection , associatedId , properties } = args ;
2017-05-31 10:25:13 +09:00
if ( ! stripeSettings ) {
throw new Error ( 'Please fill in your Stripe settings' ) ;
}
// if an associated collection name and document id have been provided,
// get the associated collection and document
if ( associatedCollection && associatedId ) {
collection = _ . findWhere ( Collections , { _name : associatedCollection } ) ;
document = collection . findOne ( associatedId ) ;
}
// get the product from Products (either object or function applied to doc)
// or default to sample product
const definedProduct = Products [ productKey ] ;
const product = typeof definedProduct === 'function' ? definedProduct ( document ) : definedProduct || sampleProduct ;
// get the user performing the transaction
const user = Users . findOne ( userId ) ;
2017-07-24 16:06:04 +09:00
// create metadata object
2018-02-16 12:07:55 +09:00
let metadata = {
2017-07-24 16:06:04 +09:00
userId : userId ,
userName : Users . getDisplayName ( user ) ,
userProfile : Users . getProfileUrl ( user , true ) ,
2017-10-18 20:05:51 +09:00
productKey ,
2017-07-24 16:06:04 +09:00
... properties
}
2017-10-18 20:05:51 +09:00
if ( associatedCollection && associatedId ) {
metadata . associatedCollection = associatedCollection ;
metadata . associatedId = associatedId ;
}
2018-02-16 12:07:55 +09:00
metadata = await runCallbacks ( 'stripe.charge.sync' , metadata , user , product , collection , document , args ) ;
2017-10-18 20:05:51 +09:00
if ( product . plan ) {
// if product has a plan, subscribe user to it
2018-02-16 12:07:55 +09:00
returnDocument = await subscribeUser ( { user , product , collection , document , metadata , args } ) ;
2017-10-18 20:05:51 +09:00
} else {
// else, perform charge
2018-02-16 12:07:55 +09:00
returnDocument = await createCharge ( { user , product , collection , document , metadata , args } ) ;
2017-10-18 20:05:51 +09:00
}
return returnDocument ;
}
/ *
2017-10-31 10:18:16 +09:00
Retrieve or create a Stripe customer
* /
export const getCustomer = async ( user , id ) => {
let customer ;
try {
// try retrieving customer from Stripe
customer = await stripe . customers . retrieve ( user . stripeCustomerId ) ;
} catch ( error ) {
// if user doesn't have a stripeCustomerId; or if id doesn't match up with Stripe
// create new customer object
const customerOptions = { email : user . email } ;
if ( id ) { customerOptions . source = id ; }
customer = await stripe . customers . create ( customerOptions ) ;
// add stripe customer id to user object
await editMutation ( {
collection : Users ,
documentId : user . _id ,
set : { stripeCustomerId : customer . id } ,
validate : false
} ) ;
}
return customer ;
}
/ *
2017-10-18 20:05:51 +09:00
Create one - time charge .
* /
2018-02-05 15:18:57 -06:00
export const createCharge = async ( { user , product , collection , document , metadata , args } ) => {
const { token , /* userId, productKey, associatedId, properties, */ coupon } = args ;
2018-01-25 15:03:03 -06:00
2018-02-05 15:18:57 -06:00
const customer = await getCustomer ( user , token ) ;
2017-10-18 20:05:51 +09:00
let amount = product . amount ;
2017-07-24 16:06:04 +09:00
// apply discount coupon and add it to metadata, if there is one
if ( coupon && product . coupons && product . coupons [ coupon ] ) {
amount -= product . coupons [ coupon ] ;
metadata . coupon = coupon ;
metadata . discountAmount = product . coupons [ coupon ] ;
}
2017-07-23 16:29:21 +09:00
// gather charge data
const chargeData = {
amount ,
2017-05-31 10:25:13 +09:00
description : product . description ,
currency : product . currency ,
customer : customer . id ,
2017-07-24 16:06:04 +09:00
metadata
2018-02-13 11:22:41 -06:00
} ;
2017-07-23 16:29:21 +09:00
// create Stripe charge
const charge = await stripe . charges . create ( chargeData ) ;
2017-05-31 10:25:13 +09:00
2018-02-05 15:18:57 -06:00
runCallbacksAsync ( 'stripe.charge.async' , charge , collection , document , args , user ) ;
2017-12-26 11:17:44 +09:00
return processCharge ( { collection , document , charge , args , user } )
2017-10-18 20:05:51 +09:00
2018-02-13 11:22:41 -06:00
} ;
2017-10-18 20:05:51 +09:00
/ *
Process charge on Vulcan ' s side
* /
2017-12-26 11:17:44 +09:00
export const processCharge = async ( { collection , document , charge , args , user } ) => {
2017-10-18 20:05:51 +09:00
2018-02-14 22:21:56 +09:00
debug ( '' ) ;
debugGroup ( ` --------------- start \x 1b[35m processCharge \x 1b[0m --------------- ` ) ;
debug ( ` Collection: ${ collection . options . collectionName } ` ) ;
debug ( ` documentId: ${ document . _id } ` ) ;
debug ( ` Charge: ${ charge } ` ) ;
2017-10-18 20:05:51 +09:00
let returnDocument = { } ;
2018-02-06 09:16:42 +09:00
// make sure charge hasn't already been processed
// (could happen with multiple endpoints listening)
const existingCharge = Charges . findOne ( { 'data.id' : charge . id } ) ;
if ( existingCharge ) {
// eslint-disable-next-line no-console
console . log ( ` // Charge with Stripe id ${ charge . id } already exists in db; aborting processCharge ` ) ;
return collection && document ? document : { } ;
}
2017-10-18 20:05:51 +09:00
const { token , userId , productKey , associatedCollection , associatedId , properties , livemode } = args ;
2017-05-31 10:25:13 +09:00
// create charge document for storing in our own Charges collection
const chargeDoc = {
createdAt : new Date ( ) ,
userId ,
type : 'stripe' ,
2017-10-18 20:05:51 +09:00
test : ! livemode ,
2017-05-31 10:25:13 +09:00
data : charge ,
2017-10-18 20:05:51 +09:00
associatedCollection ,
associatedId ,
2017-05-31 10:25:13 +09:00
properties ,
productKey ,
2018-02-13 11:22:41 -06:00
} ;
2017-05-31 10:25:13 +09:00
2017-10-18 20:05:51 +09:00
if ( token ) {
chargeDoc . tokenId = token . id ;
chargeDoc . test = ! token . livemode ; // get livemode from token if provided
chargeDoc . ip = token . client _ip ;
}
2017-05-31 10:25:13 +09:00
// insert
2018-02-13 11:22:41 -06:00
const chargeSaved = await newMutation ( {
2017-05-31 10:25:13 +09:00
collection : Charges ,
document : chargeDoc ,
validate : false ,
} ) ;
// if an associated collection and id have been provided,
// update the associated document
if ( collection && document ) {
2017-10-18 20:05:51 +09:00
// note: assume a single document can have multiple successive charges associated to it
2017-05-31 10:25:13 +09:00
const chargeIds = document . chargeIds ? [ ... document . chargeIds , chargeSaved . _id ] : [ chargeSaved . _id ] ;
let modifier = {
$set : { chargeIds } ,
$unset : { }
}
2017-10-18 20:05:51 +09:00
2017-05-31 10:25:13 +09:00
// run collection.charge.sync callbacks
2017-12-26 11:17:44 +09:00
modifier = runCallbacks ( ` ${ collection . _name } .charge.sync ` , modifier , document , chargeDoc , user ) ;
2017-05-31 10:25:13 +09:00
2017-08-07 16:02:29 +09:00
returnDocument = await editMutation ( {
2017-05-31 10:25:13 +09:00
collection ,
documentId : associatedId ,
set : modifier . $set ,
unset : modifier . $unset ,
validate : false
} ) ;
2017-06-04 13:56:40 +09:00
returnDocument . _ _typename = collection . typeName ;
2017-05-31 10:25:13 +09:00
}
2017-12-26 11:17:44 +09:00
runCallbacksAsync ( ` ${ collection . _name } .charge.async ` , returnDocument , chargeDoc , user ) ;
2017-06-04 13:56:40 +09:00
2018-02-14 22:21:56 +09:00
debugGroupEnd ( ) ;
debug ( ` --------------- end \x 1b[35m processCharge \x 1b[0m --------------- ` ) ;
debug ( '' ) ;
2017-06-04 13:56:40 +09:00
return returnDocument ;
2017-05-31 10:25:13 +09:00
}
/ *
2017-10-18 20:05:51 +09:00
Subscribe a user to a Stripe plan
2017-05-31 10:25:13 +09:00
* /
2018-02-05 15:18:57 -06:00
export const subscribeUser = async ( { user , product , collection , document , metadata , args } ) => {
2018-02-16 12:07:55 +09:00
let returnDocument = document ;
2017-10-18 20:05:51 +09:00
try {
2018-02-05 15:18:57 -06:00
const customer = await getCustomer ( user , args . token . id ) ;
2017-10-31 10:18:16 +09:00
// if product has an initial cost,
// create an invoice item and attach it to the customer first
// see https://stripe.com/docs/subscriptions/invoices#adding-invoice-items
if ( product . initialAmount ) {
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-unused-vars
2017-10-31 10:18:16 +09:00
const initialInvoiceItem = await stripe . invoiceItems . create ( {
customer : customer . id ,
amount : product . initialAmount ,
currency : product . currency ,
description : product . initialAmountDescription ,
} ) ;
}
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-unused-vars
2017-10-18 20:05:51 +09:00
const subscription = await stripe . subscriptions . create ( {
customer : customer . id ,
items : [
{ plan : product . plan } ,
] ,
metadata ,
} ) ;
2017-10-31 10:18:16 +09:00
2018-02-16 12:07:55 +09:00
// if an associated collection and id have been provided,
// update the associated document
if ( collection && document ) {
let modifier = {
$set : { } ,
$unset : { }
}
// run collection.subscribe.sync callbacks
modifier = runCallbacks ( ` ${ collection . _name } .subscribe.sync ` , modifier , document , subscription , user ) ;
returnDocument = await editMutation ( {
collection ,
documentId : document . _id ,
set : modifier . $set ,
unset : modifier . $unset ,
validate : false
} ) ;
returnDocument . _ _typename = collection . typeName ;
}
runCallbacksAsync ( 'stripe.subscribe.async' , subscription , collection , returnDocument , args , user ) ;
return returnDocument ;
2018-02-05 15:18:57 -06:00
2017-10-18 20:05:51 +09:00
} catch ( error ) {
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '// Stripe subscribeUser error' ) ;
// eslint-disable-next-line no-console
console . log ( error ) ;
2017-10-18 20:05:51 +09:00
}
2018-02-03 13:17:04 -06:00
} ;
// create a stripe plan
// plan is used as the unique ID and is not needed for creating a plan
2018-02-05 10:19:44 -06:00
const createPlan = async ( {
2018-02-03 13:17:04 -06:00
// Extract all the known properties for the stripe api
// Evertying else goes in the metadata field
plan : id ,
currency ,
interval ,
name ,
amount ,
interval _count ,
statement _descriptor ,
... metadata
} ) => stripe . plans . create ( {
id ,
currency ,
interval ,
name ,
amount ,
interval _count ,
statement _descriptor ,
... metadata
} ) ;
2018-02-05 10:19:44 -06:00
export const createSubscriptionPlan = async ( maybePlanObject ) => typeof maybePlanObject === 'object' && createPlan ( maybePlanObject ) ;
const retrievePlan = async ( planObject ) => stripe . plans . retrieve ( planObject . plan ) ;
export const retrieveSubscriptionPlan = async ( maybePlanObject ) => typeof maybePlanObject === 'object' && retrievePlan ( maybePlanObject ) ;
const createOrRetrievePlan = async ( planObject ) => {
2018-02-03 13:17:04 -06:00
return retrievePlan ( planObject )
. catch ( error => {
// Plan does not exist, create it
if ( error . statusCode === 404 ) {
// eslint-disable-next-line no-console
2018-02-05 10:19:44 -06:00
console . log ( ` Creating subscription plan ${ planObject . plan } for ${ ( planObject . amount && ( planObject . amount / 100 ) . toLocaleString ( 'en-US' , { style : 'currency' , currency : planObject . currency } )) || 'free'} ` ) ;
2018-02-03 13:17:04 -06:00
return createPlan ( planObject ) ;
}
// Something else went wrong
// eslint-disable-next-line no-console
console . error ( error ) ;
throw error ;
} ) ;
} ;
2018-02-05 10:19:44 -06:00
export const createOrRetrieveSubscriptionPlan = async ( maybePlanObject ) => typeof maybePlanObject === 'object' && createOrRetrievePlan ( maybePlanObject ) ;
2017-10-18 20:05:51 +09:00
/ *
2017-10-26 11:27:22 +09:00
Webhooks with Express
2017-05-31 10:25:13 +09:00
2017-10-18 20:05:51 +09:00
* /
2017-05-31 10:25:13 +09:00
2017-10-26 11:27:22 +09:00
// see https://github.com/stripe/stripe-node/blob/master/examples/webhook-signing/express.js
2017-05-31 10:25:13 +09:00
2018-02-03 13:17:04 -06:00
const app = express ( ) ;
2017-05-31 10:25:13 +09:00
2017-10-26 11:27:22 +09:00
// Add the raw text body of the request to the `request` object
function addRawBody ( req , res , next ) {
req . setEncoding ( 'utf8' ) ;
2017-05-31 10:25:13 +09:00
2017-10-26 11:27:22 +09:00
var data = '' ;
2017-05-31 10:25:13 +09:00
2017-10-26 11:27:22 +09:00
req . on ( 'data' , function ( chunk ) {
data += chunk ;
} ) ;
2017-05-31 10:25:13 +09:00
2017-10-26 11:27:22 +09:00
req . on ( 'end' , function ( ) {
req . rawBody = data ;
next ( ) ;
} ) ;
}
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
app . use ( addRawBody ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
app . post ( '/stripe' , async function ( req , res ) {
2017-10-18 20:05:51 +09:00
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '////////////// stripe webhook' ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
const sig = req . headers [ 'stripe-signature' ] ;
try {
const event = stripe . webhooks . constructEvent ( req . rawBody , sig , stripeSettings . endpointSecret ) ;
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( 'event ///////////////////' ) ;
// eslint-disable-next-line no-console
console . log ( event ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
switch ( event . type ) {
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
case 'charge.succeeded' :
2017-10-18 20:05:51 +09:00
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '////// charge succeeded' ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
const charge = event . data . object ;
2017-10-18 20:05:51 +09:00
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( charge ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
try {
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
// look up corresponding invoice
const invoice = await stripe . invoices . retrieve ( charge . invoice ) ;
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '////// invoice' ) ;
// eslint-disable-next-line no-console
console . log ( invoice ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
// look up corresponding subscription
const subscription = await stripe . subscriptions . retrieve ( invoice . subscription ) ;
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '////// subscription' ) ;
// eslint-disable-next-line no-console
console . log ( subscription ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
const { userId , productKey , associatedCollection , associatedId } = subscription . metadata ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
if ( associatedCollection && associatedId ) {
const collection = _ . findWhere ( Collections , { _name : associatedCollection } ) ;
const document = collection . findOne ( associatedId ) ;
2017-10-18 20:05:51 +09:00
2018-02-06 09:16:42 +09:00
// make sure document actually exists
if ( ! document ) {
throw new Error ( ` Could not find ${ associatedCollection } document with id ${ associatedId } associated with subscription id ${ subscription . id } ; Not processing charge. ` )
}
2017-10-26 11:27:22 +09:00
const args = {
userId ,
productKey ,
associatedCollection ,
associatedId ,
livemode : subscription . livemode ,
}
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
processCharge ( { collection , document , charge , args } ) ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
}
} catch ( error ) {
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '// Stripe webhook error' ) ;
// eslint-disable-next-line no-console
console . log ( error ) ;
2017-10-26 11:27:22 +09:00
}
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
break ;
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
}
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
} catch ( error ) {
2018-01-25 15:03:03 -06:00
// eslint-disable-next-line no-console
console . log ( '///// Stripe webhook error' ) ;
// eslint-disable-next-line no-console
console . log ( error ) ;
2017-10-26 11:27:22 +09:00
}
2017-10-18 20:05:51 +09:00
2017-10-26 11:27:22 +09:00
res . sendStatus ( 200 ) ;
2017-10-18 20:05:51 +09:00
} ) ;
2017-10-26 11:27:22 +09:00
webAppConnectHandlersUse ( Meteor . bindEnvironment ( app ) , { name : 'stripe_endpoint' , order : 100 } ) ;
// Picker.middleware(bodyParser.json());
// Picker.route('/stripe', async function(params, req, res, next) {
// console.log('////////////// stripe webhook')
// console.log(req)
// const sig = req.headers['stripe-signature'];
// const body = req.body;
// console.log('sig ///////////////////')
// console.log(sig)
// console.log('body ///////////////////')
// console.log(body)
// console.log('rawBody ///////////////////')
// console.log(req.rawBody)
// try {
// const event = stripe.webhooks.constructEvent(req.rawBody, sig, stripeSettings.endpointSecret);
// console.log('event ///////////////////')
// console.log(event)
// } catch (error) {
// console.log('///// Stripe webhook error')
// console.log(error)
// }
// // Retrieve the request's body and parse it as JSON
// switch (body.type) {
// case 'charge.succeeded':
// console.log('////// charge succeeded')
// // console.log(body)
// const charge = body.data.object;
// try {
// // look up corresponding invoice
// const invoice = await stripe.invoices.retrieve(body.data.object.invoice);
// console.log('////// invoice')
// // look up corresponding subscription
// const subscription = await stripe.subscriptions.retrieve(invoice.subscription);
// console.log('////// subscription')
// console.log(subscription)
// const { userId, productKey, associatedCollection, associatedId } = subscription.metadata;
// if (associatedCollection && associatedId) {
// const collection = _.findWhere(Collections, {_name: associatedCollection});
// const document = collection.findOne(associatedId);
// const args = {
// userId,
// productKey,
// associatedCollection,
// associatedId,
// livemode: subscription.livemode,
// }
// processCharge({ collection, document, charge, args});
// }
// } catch (error) {
// console.log('// Stripe webhook error')
// console.log(error)
// }
// break;
// }
// res.statusCode = 200;
// res.end();
// });
2017-12-26 11:17:44 +09:00
Meteor . startup ( ( ) => {
Collections . forEach ( c => {
2018-01-25 15:03:03 -06:00
const collectionName = c . _name . toLowerCase ( ) ;
2017-12-26 11:17:44 +09:00
registerCallback ( {
name : ` ${ collectionName } .charge.sync ` ,
description : ` Modify the modifier used to add charge ids to the charge's associated document. ` ,
arguments : [ { modifier : 'The modifier' } , { document : 'The associated document' } , { charge : 'The charge' } , { currentUser : 'The current user' } ] ,
runs : 'sync' ,
returns : 'modifier' ,
} ) ;
registerCallback ( {
2018-02-05 13:31:53 -06:00
name : ` ${ collectionName } .charge.async ` ,
2017-12-26 11:17:44 +09:00
description : ` Perform operations after the charge has succeeded. ` ,
arguments : [ { document : 'The associated document' } , { charge : 'The charge' } , { currentUser : 'The current user' } ] ,
runs : 'async' ,
} ) ;
2018-02-16 12:07:55 +09:00
registerCallback ( {
name : ` ${ collectionName } .subscribe.sync ` ,
description : ` Modify the modifier used to modify the subscription's associated document. ` ,
arguments : [ { modifier : 'The modifier' } , { document : 'The associated document' } , { subscription : 'The subscription' } , { currentUser : 'The current user' } ] ,
runs : 'sync' ,
returns : 'modifier' ,
} ) ;
registerCallback ( {
name : ` ${ collectionName } .subscribe.async ` ,
description : ` Perform operations after the subscription has succeeded. ` ,
arguments : [ { subscription : 'The subscription' } , { collection : 'The associated collection' } , { document : 'The associated document' } , { args : 'The arguments' } , { currentUser : 'The current user' } ] ,
runs : 'async' ,
} ) ;
2018-02-04 10:41:00 +09:00
2018-02-03 13:17:04 -06:00
} ) ;
2018-02-05 15:18:57 -06:00
registerCallback ( {
name : 'stripe.charge.sync' ,
2018-02-16 12:07:55 +09:00
description : 'Modify any metadata before sending the charge to stripe' ,
arguments : [ { metadata : 'Metadata about the charge' } , { user : 'The user' } , { product : 'Product created with addProduct' } , { collection : 'Associated collection of the charge' } , { document : 'Associated document in collection to the charge' } , { args : 'Original mutation arguments' } ] ,
2018-02-05 15:18:57 -06:00
runs : 'sync' ,
returns : 'The modified arguments to be sent to stripe' ,
} ) ;
registerCallback ( {
name : 'stripe.charge.async' ,
description : 'Perform operations immediately after the stripe charge has completed' ,
arguments : [ { charge : 'Charge object returning from stripe' } , { collection : 'Associated collection of the charge' } , { document : 'Associated document in collection to the charge' } , { args : 'Original mutation arguments' } , { user : 'The user' } ] ,
runs : 'async' ,
} ) ;
2018-02-03 13:17:04 -06:00
// Create plans if they don't exist
if ( stripeSettings . createPlans ) {
// eslint-disable-next-line no-console
console . log ( 'Creating stripe plans...' ) ;
Promise . awaitAll ( Object . keys ( Products )
2018-02-05 10:19:44 -06:00
// Filter out function type products and those without a plan defined (non-subscription)
. filter ( productKey => typeof Products [ productKey ] === 'object' && Products [ productKey ] . plan )
. map ( productKey => createOrRetrievePlan ( Products [ productKey ] ) ) ) ;
2018-02-03 13:17:04 -06:00
// eslint-disable-next-line no-console
console . log ( 'Finished creating stripe plans.' ) ;
}
2018-02-04 10:41:00 +09:00
} ) ;