From 123f8192f4be1e52fc2b3283794d380b9a0b8260 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Mon, 24 Mar 2014 21:51:49 -0600 Subject: [PATCH] feat(subscriptions): add misc. IPN handler. For this case, it will catch off-site cancelled subscriptions --- src/controllers/payments.js | 25 +++++++++++++++++++++++++ src/routes/payments.js | 1 + 2 files changed, 26 insertions(+) diff --git a/src/controllers/payments.js b/src/controllers/payments.js index a5c69f3116..7956a7db8c 100644 --- a/src/controllers/payments.js +++ b/src/controllers/payments.js @@ -212,4 +212,29 @@ api.paypalCheckoutSuccess = function(req,res,next) { }); }); }); +} + +/** + * General IPN handler. We could use this for all paypal transaction handling (instead of the above functions), but I've + * found it extremely unreliable. Instead, here we'll cancel HabitRPG subscriptions for users who manually cancel their + * recurring paypal payments. + */ +api.paypalIPN = function(req, res, next) { + // Must respond to PayPal IPN request with an empty 200 first, if using Express uncomment the following: + res.send(200); + ipn.verify(req.body, function callback(err, msg) { + if (err) return logger.error(msg); + switch (req.body.txn_type) { + // TODO what's the diff b/w the two data.txn_types below? The docs recommend subscr_cancel, but I'm getting the other one instead... + case 'recurring_payment_profile_cancel': + case 'subscr_cancel': + User.findOne({'purchased.plan.customerId':req.body.recurring_payment_id},function(err, user){ + if (err) return logger.error(err); + if (_.isEmpty(user)) return; // looks like the cancellation was already handled properly above (see api.paypalSubscribeCancel) + cancelSubscription(user); + user.save(); + }); + break; + } + }); } \ No newline at end of file diff --git a/src/routes/payments.js b/src/routes/payments.js index 1109f85c5c..bc10df5f84 100644 --- a/src/routes/payments.js +++ b/src/routes/payments.js @@ -9,6 +9,7 @@ router.get('/paypal/checkout/success', payments.paypalCheckoutSuccess); router.get('/paypal/subscribe', auth.authWithUrl, payments.paypalSubscribe); router.get('/paypal/subscribe/success', payments.paypalSubscribeSuccess); router.get('/paypal/subscribe/cancel', auth.authWithUrl, payments.paypalSubscribeCancel); +router.post('/paypal/ipn', payments.paypalIPN); // misc ipn handling router.post("/stripe/checkout", auth.auth, payments.stripeCheckout); //router.get("/stripe/subscribe", auth.authWithUrl, payments.stripeSubscribe); // checkout route is used (above) with ?plan= instead