diff --git a/config.json.example b/config.json.example index aa70349d0a..a9e7d5f4ac 100644 --- a/config.json.example +++ b/config.json.example @@ -31,6 +31,7 @@ "secretAccessKey":"secretAccessKey" }, "PAYPAL":{ + "billing_plan_id":"billing_plan_id", "mode":"sandbox", "client_id":"client_id", "client_secret":"client_secret" diff --git a/src/controllers/payments/paypal.js b/src/controllers/payments/paypal.js index e46a7e4940..536f959ef9 100644 --- a/src/controllers/payments/paypal.js +++ b/src/controllers/payments/paypal.js @@ -9,6 +9,11 @@ var logger = require('../../logging'); var ipn = require('paypal-ipn'); var paypal = require('paypal-rest-sdk'); +// This is the plan.id for paypal subscriptions. You have to set up billing plans via their REST sdk (they don't have +// a web interface for billing-plan creation), see ./paypalBillingSetup.js for how. After the billing plan is created +// there, get it's plan.id and store it in config.json +var billingPlanID = nconf.get('PAYPAL:billing_plan_id'); + paypal.configure({ 'mode': nconf.get("PAYPAL:mode"), //sandbox or live 'client_id': nconf.get("PAYPAL:client_id"), @@ -19,64 +24,8 @@ var parseErr = function(err){ return (err.response && err.response.message || err.response.details[0].issue) || err; } -// Initialize Billing Plans -var billingPlanID; -var billingPlanTitle ="HabitRPG subscription ($5 month-to-month)"; -(function(){ - var billingPlanAttributes = { - // https://developer.paypal.com/docs/api/#billing-plans-and-agreements - "name": billingPlanTitle, - "description": billingPlanTitle, - "type": "INFINITE", - "merchant_preferences": { - "auto_bill_amount": "yes", - "cancel_url": nconf.get("BASE_URL"), - "return_url": nconf.get('BASE_URL') + '/paypal/subscribe/success' - }, - "payment_definitions": [{ - "name": billingPlanTitle, - "type": "REGULAR", - "frequency_interval": "1", - "frequency": "MONTH", - "cycles": "0", - "amount": { - "currency": "USD", - "value": "5" - } - }] - }; - - async.waterfall([ - function(cb) { - paypal.billingPlan.list({status: 'ACTIVE'}, cb); - }, - function(plans, cb){ - var plan = _.find(plans.plans, {name:billingPlanTitle}); - if (plan) return cb(null, plan); - paypal.billingPlan.create(billingPlanAttributes, cb); - }, - function(plan, cb){ - if (plan.state == "ACTIVE") return cb(null, plan); - // Super obvious this stuff, right? *sigh* - var billingPlanUpdateAttributes = [{ - "op": "replace", - "path": "/", - "value": { - "state": "ACTIVE" - } - }]; - // Activate the plan by changing status to Active - paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, function(err, response){ - if (err) return cb(err); - cb(null, plan); - }); - }, - ],function(err, plan){ - billingPlanID = plan && plan.id || "none"; - }) -})(); - exports.createBillingAgreement = function(req,res,next){ + var billingPlanTitle ="HabitRPG subscription ($5 month-to-month)"; var billingAgreementAttributes = { "name": billingPlanTitle, "description": billingPlanTitle, diff --git a/src/controllers/payments/paypalBillingSetup.js b/src/controllers/payments/paypalBillingSetup.js new file mode 100644 index 0000000000..d4d7f8e167 --- /dev/null +++ b/src/controllers/payments/paypalBillingSetup.js @@ -0,0 +1,68 @@ +// This file is used for creating paypal billing plans. PayPal doesn't have a web interface for setting up recurring +// payment plan definitions, instead you have to create it via their REST SDK and keep it updated the same way. So this +// file will be used once for initing your billing plan (then you get the resultant plan.id to store in config.json), +// and once for any time you need to edit the plan thereafter + +var path = require('path'); +var nconf = require('nconf'); +nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../../../config.json'))); +var paypal = require('paypal-rest-sdk'); +var OP = "list"; // list create update remove + +paypal.configure({ + 'mode': nconf.get("PAYPAL:mode"), //sandbox or live + 'client_id': nconf.get("PAYPAL:client_id"), + 'client_secret': nconf.get("PAYPAL:client_secret") +}); + +var billingPlanTitle ="HabitRPG subscription ($5 month-to-month)"; +// https://developer.paypal.com/docs/api/#billing-plans-and-agreements +var billingPlanAttributes = { + "name": billingPlanTitle, + "description": billingPlanTitle, + "type": "INFINITE", + "merchant_preferences": { + "auto_bill_amount": "yes", + "cancel_url": nconf.get("BASE_URL"), + "return_url": nconf.get('BASE_URL') + '/paypal/subscribe/success' + }, + "payment_definitions": [{ + "name": billingPlanTitle, + "type": "REGULAR", + "frequency_interval": "1", + "frequency": "MONTH", + "cycles": "0", + "amount": { + "currency": "USD", + "value": "5" + } + }] +}; + +switch(OP) { + case "list": + paypal.billingPlan.list({status: 'ACTIVE'}, function(err, plans){ + console.log({err:err, plans:plans}); + }); + break; + case "update": + break; + case "create": + paypal.billingPlan.create(billingPlanAttributes, function(err,plan){ + if (plan.state == "ACTIVE") + return console.log({err:err, plan:plan}); + var billingPlanUpdateAttributes = [{ + "op": "replace", + "path": "/", + "value": { + "state": "ACTIVE" + } + }]; + // Activate the plan by changing status to Active + paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, function(err, response){ + console.log({err:err, response:response}); + }); + }); + case "remove": + break; +} \ No newline at end of file