2014-12-02 23:01:35 -05: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'
|
|
|
|
config = require '../../server_config'
|
|
|
|
stripe = require('stripe')(config.stripe.secretKey)
|
2014-12-04 20:41:17 -05:00
|
|
|
discountHandler = require './discount_handler'
|
2014-12-02 23:01:35 -05:00
|
|
|
|
|
|
|
subscriptions = {
|
|
|
|
basic: {
|
|
|
|
gems: 3500
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SubscriptionHandler extends Handler
|
|
|
|
logSubscriptionError: (req, msg) ->
|
|
|
|
console.warn "Subscription Error: #{req.user.get('slug')} (#{req.user._id}): '#{msg}'"
|
|
|
|
|
|
|
|
subscribeUser: (req, user, done) ->
|
2014-12-04 16:07:00 -05:00
|
|
|
if (not req.user) or req.user.isAnonymous()
|
|
|
|
return done({res: 'You must be signed in to subscribe.', code: 403})
|
|
|
|
|
2014-12-04 20:41:17 -05:00
|
|
|
token = req.body.stripe?.token
|
|
|
|
customerID = user.get('stripe')?.customerID
|
|
|
|
if not (token or customerID)
|
2014-12-02 23:01:35 -05:00
|
|
|
@logSubscriptionError(req, 'Missing stripe token or customer ID.')
|
|
|
|
return done({res: 'Missing stripe token or customer ID.', code: 422})
|
|
|
|
|
2014-12-04 20:41:17 -05:00
|
|
|
if token
|
|
|
|
if customerID
|
|
|
|
stripe.customers.update customerID, { card: token }, (err, customer) =>
|
|
|
|
@checkForExistingSubscription(req, user, customer, done)
|
|
|
|
|
|
|
|
else
|
|
|
|
newCustomer = {
|
|
|
|
card: token
|
|
|
|
email: req.user.get('email')
|
|
|
|
metadata: { id: req.user._id + '', slug: req.user.get('slug') }
|
2014-12-03 19:35:53 -05:00
|
|
|
}
|
2014-12-04 20:41:17 -05:00
|
|
|
|
|
|
|
stripe.customers.create newCustomer, (err, customer) =>
|
|
|
|
if err
|
|
|
|
if err.type in ['StripeCardError', 'StripeInvalidRequestError']
|
|
|
|
return done({res: 'Card error', code: 402})
|
|
|
|
else
|
|
|
|
@logSubscriptionError(req, 'Stripe customer creation error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
|
|
|
|
2014-12-02 23:01:35 -05:00
|
|
|
stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
|
|
|
|
stripeInfo.customerID = customer.id
|
|
|
|
req.user.set('stripe', stripeInfo)
|
2014-12-04 20:41:17 -05:00
|
|
|
req.user.save (err) =>
|
2014-12-02 23:01:35 -05:00
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'Stripe customer id save db error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
|
|
|
@checkForExistingSubscription(req, user, customer, done)
|
|
|
|
|
|
|
|
else
|
2014-12-04 20:41:17 -05:00
|
|
|
stripe.customers.retrieve(customerID, (err, customer) =>
|
2014-12-02 23:01:35 -05:00
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'Stripe customer creation error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
2014-12-04 20:41:17 -05:00
|
|
|
@checkForExistingSubscription(req, user, customer, done)
|
2014-12-02 23:01:35 -05:00
|
|
|
)
|
|
|
|
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-02 23:01:35 -05:00
|
|
|
checkForExistingSubscription: (req, user, customer, done) ->
|
2014-12-04 20:41:17 -05:00
|
|
|
couponID = user.get('stripe')?.couponID
|
2014-12-02 23:01:35 -05:00
|
|
|
if subscription = customer.subscriptions?.data?[0]
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-02 23:01:35 -05: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
|
|
|
|
@logSubscriptionError(req, 'Stripe cancel subscription error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
|
|
|
|
|
|
|
options = { plan: 'basic', trial_end: subscription.current_period_end }
|
2014-12-04 20:41:17 -05:00
|
|
|
options.coupon = couponID if couponID
|
2014-12-02 23:01:35 -05:00
|
|
|
stripe.customers.update req.user.get('stripe').customerID, options, (err, customer) =>
|
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'Stripe customer plan setting error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-04 20:41:17 -05:00
|
|
|
@updateUser(req, user, customer, false, done)
|
2014-12-02 23:01:35 -05:00
|
|
|
|
|
|
|
else
|
|
|
|
# can skip creating the subscription
|
2014-12-04 20:41:17 -05:00
|
|
|
return @updateUser(req, user, customer, false, done)
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-02 23:01:35 -05:00
|
|
|
else
|
2014-12-04 20:41:17 -05:00
|
|
|
options = { plan: 'basic' }
|
|
|
|
options.coupon = couponID if couponID
|
|
|
|
stripe.customers.update req.user.get('stripe').customerID, options, (err, customer) =>
|
2014-12-02 23:01:35 -05:00
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'Stripe customer plan setting error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-04 20:41:17 -05:00
|
|
|
@updateUser(req, user, customer, true, done)
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-04 20:41:17 -05:00
|
|
|
updateUser: (req, user, customer, increment, done) ->
|
|
|
|
subscription = customer.subscriptions.data[0]
|
2014-12-02 23:01:35 -05:00
|
|
|
stripeInfo = _.cloneDeep(user.get('stripe') ? {})
|
|
|
|
stripeInfo.planID = 'basic'
|
|
|
|
stripeInfo.subscriptionID = subscription.id
|
2014-12-04 20:41:17 -05:00
|
|
|
stripeInfo.customerID = customer.id
|
2014-12-02 23:01:35 -05: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
|
|
|
|
@logSubscriptionError(req, 'Stripe user plan saving error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
2014-12-04 15:57:57 -05:00
|
|
|
req.user?.saveActiveUser 'subscribe'
|
2014-12-02 23:01:35 -05:00
|
|
|
return done()
|
2014-12-03 12:13:51 -05:00
|
|
|
|
2014-12-02 23:01:35 -05:00
|
|
|
unsubscribeUser: (req, user, done) ->
|
|
|
|
stripeInfo = _.cloneDeep(user.get('stripe'))
|
|
|
|
stripe.customers.cancelSubscription stripeInfo.customerID, stripeInfo.subscriptionID, { at_period_end: true }, (err) =>
|
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'Stripe cancel subscription error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
|
|
|
delete stripeInfo.planID
|
|
|
|
user.set('stripe', stripeInfo)
|
|
|
|
req.body.stripe = stripeInfo
|
|
|
|
user.save (err) =>
|
|
|
|
if err
|
|
|
|
@logSubscriptionError(req, 'User save unsubscribe error. '+err)
|
|
|
|
return done({res: 'Database error.', code: 500})
|
2014-12-04 15:57:57 -05:00
|
|
|
req.user?.saveActiveUser 'unsubscribe'
|
2014-12-02 23:01:35 -05:00
|
|
|
return done()
|
|
|
|
|
2014-12-03 12:13:51 -05:00
|
|
|
module.exports = new SubscriptionHandler()
|