feat(subscriptions): add paypal recurring cancelation. refactor stripe & paypal code to use auth.authWithUrl.

This commit is contained in:
Tyler Renelle
2014-03-24 20:00:11 -06:00
parent b686b56282
commit 0f430e102e
11 changed files with 65 additions and 43 deletions
+9 -4
View File
@@ -16,10 +16,6 @@ var NO_TOKEN_OR_UID = { err: "You must include a token and uid (user id) in your
var NO_USER_FOUND = {err: "No user found."};
var NO_SESSION_FOUND = { err: "You must be logged in." };
/*
beforeEach auth interceptor
*/
api.auth = function(req, res, next) {
var uid = req.headers['x-api-user'];
var token = req.headers['x-api-key'];
@@ -47,6 +43,15 @@ api.authWithSession = function(req, res, next) { //[todo] there is probably a mo
});
};
api.authWithUrl = function(req, res, next) {
User.findOne({_id:req.query._id, apiToken:req.query.apiToken}, function(err,user){
if (err) return next(err);
if (_.isEmpty(user)) return res.json(401, NO_USER_FOUND);
res.locals.user = user;
next();
})
}
api.registerUser = function(req, res, next) {
var confirmPassword, e, email, password, username, _ref;
_ref = req.body, email = _ref.email, username = _ref.username, password = _ref.password, confirmPassword = _ref.confirmPassword;
+36 -13
View File
@@ -312,7 +312,8 @@ function createSubscription(user, data) {
planId:'basic_earned',
customerId: data.customerId,
dateUpdated: new Date,
gemsBought: 0
gemsBought: 0,
paymentMethod: data.paymentMethod
})
.defaults({ // allow non-override if a plan was previously used
dateCreated: new Date,
@@ -324,6 +325,12 @@ function createSubscription(user, data) {
ga.transaction(data.customerId, 5).item(5, 1, data.paymentMethod.toLowerCase() + '-subscription', data.paymentMethod + " > Stripe").send();
}
function cancelSubscription(user, data){
_.merge(user.purchased.plan, {planId:null, customerId:null, paymentMethod:null});
user.markModified('purchased.plan');
ga.event('unsubscribe', 'Stripe').send();
}
function buyGems(user, data) {
user.balance += 5;
user.purchased.txnCount++;
@@ -334,7 +341,7 @@ function buyGems(user, data) {
/*
Setup Stripe response when posting payment
*/
api.buyGems = function(req, res, next) {
api.stripeCheckout = function(req, res, next) {
var api_key = nconf.get('STRIPE_API_KEY');
var stripe = require("stripe")(api_key);
var token = req.body.id;
@@ -367,13 +374,12 @@ api.buyGems = function(req, res, next) {
}
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
res.send(200, saved);
res.send(200);
});
};
api.cancelSubscription = function(req, res, next) {
var api_key = nconf.get('STRIPE_API_KEY');
var stripe = require("stripe")(api_key);
api.stripeSubscribeCancel = function(req, res, next) {
var stripe = require("stripe")(nconf.get('STRIPE_API_KEY'));
var user = res.locals.user;
if (!user.purchased.plan.customerId)
return res.json(401, {err: "User does not have a plan subscription"});
@@ -383,20 +389,17 @@ api.cancelSubscription = function(req, res, next) {
stripe.customers.del(user.purchased.plan.customerId, cb);
},
function(response, cb) {
_.merge(user.purchased.plan, {planId:null, customerId:null});
user.markModified('purchased.plan');
cancelSubscription(user);
user.save(cb);
}
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
res.send(200, saved);
ga.event('unsubscribe', 'Stripe').send()
res.redirect('/');
});
}
api.paypalSubscribe = function(req,res,next) {
var uuid = req.query.uuid;
if (!uuid) return next("UUID required");
var uuid = res.locals.user._id;
// Authenticate a future subscription of ~5 USD
paypalRecurring.authenticate({
RETURNURL: nconf.get('BASE_URL') + '/paypal/subscribe/success?uuid=' + uuid,
@@ -432,8 +435,28 @@ api.paypalSubscribeSuccess = function(req,res,next) {
});
}
api.paypalSubscribeCancel = function(req, res, next) {
var user = res.locals.user;
if (!user.purchased.plan.customerId)
return res.json(401, {err: "User does not have a plan subscription"});
async.waterfall([
function(cb) {
paypalRecurring.modifySubscription(user.purchased.plan.customerId, 'cancel', cb);
},
function(response, cb) {
cancelSubscription(user);
user.save(cb);
}
], function(err, saved){
if (err) return next(err);
res.redirect('/');
});
}
api.paypalCheckout = function(req, res, next) {
var opts = {RETURNURL:nconf.get('BASE_URL') + '/paypal/checkout/success?uuid=' + req.query.uuid};
var uuid = res.locals.user._id;
var opts = {RETURNURL:nconf.get('BASE_URL') + '/paypal/checkout/success?uuid=' + uuid};
paypalCheckout.pay(+new Date, 5, 'HabitRPG Gems', 'USD', opts, function(err, url) {
if (err) return next(err);
res.redirect(url);
-1
View File
@@ -234,7 +234,6 @@ module.exports.locals = function(req, res, next) {
res.locals.habitrpg = {
NODE_ENV: nconf.get('NODE_ENV'),
BASE_URL: nconf.get('BASE_URL'),
PAYPAL_MERCHANT: nconf.get('PAYPAL_MERCHANT'),
GA_ID: nconf.get("GA_ID"),
IS_MOBILE: /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')),
STRIPE_PUB_KEY: nconf.get('STRIPE_PUB_KEY'),
+1
View File
@@ -85,6 +85,7 @@ var UserSchema = new Schema({
mobileChat: Boolean,
plan: {
planId: String,
paymentMethod: String, //enum: ['Paypal','Stripe', '']}
customerId: String,
dateCreated: Date,
dateUpdated: Date,
-10
View File
@@ -299,16 +299,6 @@ module.exports = (swagger, v2) ->
]
action: user.unlock
"/user/buy-gems":
spec: method: 'POST', description: "Do not use this route"
middleware: auth.auth
action:user.buyGems
"/user/cancel-subscription":
spec: method: 'POST', description: "Do not use this route"
middleware: auth.auth
action:user.cancelSubscription
"/user/batch-update":
spec:
method: 'POST'
+7 -2
View File
@@ -59,9 +59,14 @@ router.get('/static/extensions', function(req, res) {
// --------- PayPal --------
router.get('/paypal/checkout', user.paypalCheckout);
router.get('/paypal/checkout', auth.authWithUrl, user.paypalCheckout);
router.get('/paypal/checkout/success', user.paypalCheckoutSuccess);
router.get('/paypal/subscribe', user.paypalSubscribe);
router.get('/paypal/subscribe', auth.authWithUrl, user.paypalSubscribe);
router.get('/paypal/subscribe/success', user.paypalSubscribeSuccess);
router.get('/paypal/subscribe/cancel', auth.authWithUrl, user.paypalSubscribeCancel);
router.post("/stripe/checkout", auth.auth, user.stripeCheckout);
//router.get("/stripe/subscribe", auth.authWithUrl, user.stripeSubscribe); // checkout route is used (above) with ?plan= instead
router.get("/stripe/subscribe/cancel", auth.authWithUrl, user.stripeSubscribeCancel);
module.exports = router;