2014-12-02 20:01:35 -08:00
# Not paired with a document in the DB, just handles coordinating between
# the stripe property in the user with what's being stored in Stripe.
Handler = require ' ../commons/Handler '
2014-12-04 17:41:17 -08:00
discountHandler = require ' ./discount_handler '
2014-12-02 20:01:35 -08:00
subscriptions = {
basic: {
gems: 3500
}
}
class SubscriptionHandler extends Handler
2014-12-05 15:49:38 -08:00
logSubscriptionError: (user, msg) ->
console . warn " Subscription Error: #{ user . get ( ' slug ' ) } ( #{ user . _id } ): ' #{ msg } ' "
2014-12-02 20:01:35 -08:00
subscribeUser: (req, user, done) ->
2014-12-05 15:49:38 -08:00
if ( not req . user ) or req . user . isAnonymous ( ) or user . isAnonymous ( )
2014-12-04 13:07:00 -08:00
return done ( { res: ' You must be signed in to subscribe. ' , code: 403 } )
2014-12-05 14:11:38 -08:00
token = req . body . stripe . token
2014-12-04 17:41:17 -08:00
customerID = user . get ( ' stripe ' ) ? . customerID
if not ( token or customerID )
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Missing stripe token or customer ID. ' )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Missing stripe token or customer ID. ' , code: 422 } )
2014-12-04 17:41:17 -08:00
if token
if customerID
stripe . customers . update customerID , { card: token } , (err, customer) =>
2014-12-05 14:11:38 -08:00
if err or not customer
# should not happen outside of test and production polluting each other
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Cannot find customer: ' , + customer . id + ' \n \n ' + err )
2014-12-05 14:11:38 -08:00
return done ( { res: ' Cannot find customer. ' , code: 404 } )
2014-12-04 17:41:17 -08:00
@ checkForExistingSubscription ( req , user , customer , done )
else
newCustomer = {
card: token
2014-12-05 15:49:38 -08:00
email: user . get ( ' email ' )
metadata: { id: user . _id + ' ' , slug: user . get ( ' slug ' ) }
2014-12-03 16:35:53 -08:00
}
2014-12-04 17:41:17 -08:00
stripe . customers . create newCustomer , (err, customer) =>
if err
if err . type in [ ' StripeCardError ' , ' StripeInvalidRequestError ' ]
return done ( { res: ' Card error ' , code: 402 } )
else
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe customer creation error. ' + err )
2014-12-04 17:41:17 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-05 15:49:38 -08:00
stripeInfo = _ . cloneDeep ( user . get ( ' stripe ' ) ? { } )
2014-12-02 20:01:35 -08:00
stripeInfo.customerID = customer . id
2014-12-05 15:49:38 -08:00
user . set ( ' stripe ' , stripeInfo )
user . save (err) =>
2014-12-02 20:01:35 -08:00
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe customer id save db error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
@ checkForExistingSubscription ( req , user , customer , done )
else
2014-12-04 17:41:17 -08:00
stripe . customers . retrieve ( customerID , (err, customer) =>
2014-12-02 20:01:35 -08:00
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe customer creation error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-04 17:41:17 -08:00
@ checkForExistingSubscription ( req , user , customer , done )
2014-12-02 20:01:35 -08:00
)
2014-12-03 09:13:51 -08:00
2014-12-02 20:01:35 -08:00
checkForExistingSubscription: (req, user, customer, done) ->
2014-12-04 17:41:17 -08:00
couponID = user . get ( ' stripe ' ) ? . couponID
2014-12-06 12:37:54 -08:00
# SALE LOGIC
# overwrite couponID with another for everyone-sales
# couponID = 'hoc_bonanza' if not couponID
2014-12-02 20:01:35 -08:00
if subscription = customer . subscriptions ? . data ? [ 0 ]
2014-12-03 09:13:51 -08:00
2014-12-02 20:01:35 -08:00
if subscription . cancel_at_period_end
# Things are a little tricky here. Can't re-enable a cancelled subscription,
# so it needs to be deleted, but also don't want to charge for the new subscription immediately.
# So delete the cancelled subscription (no at_period_end given here) and give the new
# subscription a trial period that ends when the cancelled subscription would have ended.
stripe . customers . cancelSubscription subscription . customer , subscription . id , (err) =>
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe cancel subscription error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
options = { plan: ' basic ' , trial_end: subscription . current_period_end }
2014-12-04 17:41:17 -08:00
options.coupon = couponID if couponID
2014-12-05 15:49:38 -08:00
stripe . customers . update user . get ( ' stripe ' ) . customerID , options , (err, customer) =>
2014-12-02 20:01:35 -08:00
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe customer plan setting error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-03 09:13:51 -08:00
2014-12-04 17:41:17 -08:00
@ updateUser ( req , user , customer , false , done )
2014-12-02 20:01:35 -08:00
else
# can skip creating the subscription
2014-12-04 17:41:17 -08:00
return @ updateUser ( req , user , customer , false , done )
2014-12-03 09:13:51 -08:00
2014-12-02 20:01:35 -08:00
else
2014-12-04 17:41:17 -08:00
options = { plan: ' basic ' }
options.coupon = couponID if couponID
2014-12-05 15:49:38 -08:00
stripe . customers . update user . get ( ' stripe ' ) . customerID , options , (err, customer) =>
2014-12-02 20:01:35 -08:00
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe customer plan setting error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-03 09:13:51 -08:00
2014-12-04 17:41:17 -08:00
@ updateUser ( req , user , customer , true , done )
2014-12-03 09:13:51 -08:00
2014-12-04 17:41:17 -08:00
updateUser: (req, user, customer, increment, done) ->
subscription = customer . subscriptions . data [ 0 ]
2014-12-02 20:01:35 -08:00
stripeInfo = _ . cloneDeep ( user . get ( ' stripe ' ) ? { } )
stripeInfo.planID = ' basic '
stripeInfo.subscriptionID = subscription . id
2014-12-04 17:41:17 -08:00
stripeInfo.customerID = customer . id
2014-12-02 20:01:35 -08:00
req.body.stripe = stripeInfo # to make sure things work for admins, who are mad with power
user . set ( ' stripe ' , stripeInfo )
if increment
purchased = _ . clone ( user . get ( ' purchased ' ) )
purchased ? = { }
purchased . gems ? = 0
purchased . gems += subscriptions . basic . gems # TODO: Put actual subscription amount here
user . set ( ' purchased ' , purchased )
user . save (err) =>
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe user plan saving error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-05 15:49:38 -08:00
user ? . saveActiveUser ' subscribe '
2014-12-02 20:01:35 -08:00
return done ( )
2014-12-03 09:13:51 -08:00
2014-12-02 20:01:35 -08:00
unsubscribeUser: (req, user, done) ->
stripeInfo = _ . cloneDeep ( user . get ( ' stripe ' ) )
stripe . customers . cancelSubscription stripeInfo . customerID , stripeInfo . subscriptionID , { at_period_end: true } , (err) =>
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' Stripe cancel subscription error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
delete stripeInfo . planID
user . set ( ' stripe ' , stripeInfo )
req.body.stripe = stripeInfo
user . save (err) =>
if err
2014-12-05 15:49:38 -08:00
@ logSubscriptionError ( user , ' User save unsubscribe error. ' + err )
2014-12-02 20:01:35 -08:00
return done ( { res: ' Database error. ' , code: 500 } )
2014-12-05 15:49:38 -08:00
user ? . saveActiveUser ' unsubscribe '
2014-12-02 20:01:35 -08:00
return done ( )
2014-12-03 09:13:51 -08:00
module.exports = new SubscriptionHandler ( )