feat(discount) google discount & use sub.key instead of sub.months

This commit is contained in:
Tyler Renelle
2014-12-20 20:47:16 -07:00
parent 303d30a270
commit edf66cbb59
15 changed files with 114 additions and 68 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ api.sendMessage = function(user, member, data){
msg = data.message
} else {
msg = "`Hello " + member.profile.name + ", " + user.profile.name + " has sent you ";
msg += (data.type=='gems') ? data.gems.amount + " gems!`" : data.subscription.months + " months of subscription!`";
msg += (data.type=='gems') ? data.gems.amount + " gems!`" : shared.content.subscriptionBlocks[data.subscription.key].months + " months of subscription!`";
msg += data.message;
}
shared.refPush(member.inbox.messages, groups.chatDefaults(msg, user));
+13 -3
View File
@@ -10,6 +10,8 @@ var paypal = require('./paypal');
var members = require('../members')
var async = require('async');
var iap = require('./iap');
var mongoose= require('mongoose');
var cc = require('coupon-code');
function revealMysteryItems(user) {
_.each(shared.content.gear.flat, function(item) {
@@ -29,8 +31,8 @@ exports.createSubscription = function(data, cb) {
var recipient = data.gift ? data.gift.member : data.user;
//if (!recipient.purchased.plan) recipient.purchased.plan = {}; // FIXME double-check, this should never be the case
var p = recipient.purchased.plan;
var months = +(data.gift ? data.gift.subscription.months : data.sub.months);
var block = shared.content.subscriptionBlocks[months];
var block = shared.content.subscriptionBlocks[data.gift ? data.gift.subscription.key : data.sub.key];
var months = +block.months;
if (data.gift) {
if (p.customerId && !p.dateTerminated) { // User has active plan
@@ -114,6 +116,14 @@ exports.buyGems = function(data, cb) {
], cb);
}
exports.validCoupon = function(req, res, next){
mongoose.model('Coupon').findOne({_id:cc.validate(req.params.code), event:'google_6mo'}, function(err, coupon){
if (err) return next(err);
if (!coupon) return res.json(401, {err:"Invalid coupon code"});
return res.send(200);
});
}
exports.stripeCheckout = stripe.checkout;
exports.stripeSubscribeCancel = stripe.subscribeCancel;
exports.stripeSubscribeEdit = stripe.subscribeEdit;
@@ -126,4 +136,4 @@ exports.paypalCheckoutSuccess = paypal.executePayment;
exports.paypalIPN = paypal.ipn;
exports.iapAndroidVerify = iap.androidVerify;
exports.iapIosVerify = iap.iosVerify;
exports.iapIosVerify = iap.iosVerify;
+28 -16
View File
@@ -9,12 +9,14 @@ var logger = require('../../logging');
var ipn = require('paypal-ipn');
var paypal = require('paypal-rest-sdk');
var shared = require('habitrpg-shared');
var mongoose = require('mongoose');
var cc = require('coupon-code');
// 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
_.each(shared.content.subscriptionBlocks, function(block){
block.paypalKey = nconf.get("PAYPAL:billing_plans:"+block.months);
block.paypalKey = nconf.get("PAYPAL:billing_plans:"+block.key);
});
paypal.configure({
@@ -30,23 +32,33 @@ var parseErr = function(res, err){
}
exports.createBillingAgreement = function(req,res,next){
req.session.paypalBlock = req.query.sub;
var block = shared.content.subscriptionBlocks[req.query.sub];
var billingPlanTitle = "HabitRPG Subscription" + ' ($'+block.price+' every '+block.months+' months, recurring)';
var billingAgreementAttributes = {
"name": billingPlanTitle,
"description": billingPlanTitle,
"start_date": moment().add({minutes:5}).format(),
"plan": {
"id": block.paypalKey
var sub = shared.content.subscriptionBlocks[req.query.sub];
async.waterfall([
function(cb){
if (!sub.discount) return cb(null, null);
if (!req.query.coupon) return cb('Please provide a coupon code for this plan.');
mongoose.model('Coupon').findOne({_id:cc.validate(req.query.coupon), event:sub.key}, cb);
},
"payer": {
"payment_method": "paypal"
function(coupon, cb){
if (sub.discount && !coupon) return cb('Invalid coupon code.');
var billingPlanTitle = "HabitRPG Subscription" + ' ($'+sub.price+' every '+sub.months+' months, recurring)';
var billingAgreementAttributes = {
"name": billingPlanTitle,
"description": billingPlanTitle,
"start_date": moment().add({minutes:5}).format(),
"plan": {
"id": sub.paypalKey
},
"payer": {
"payment_method": "paypal"
}
};
paypal.billingAgreement.create(billingAgreementAttributes, cb);
}
};
paypal.billingAgreement.create(billingAgreementAttributes, function (err, billingAgreement) {
], function(err, billingAgreement){
if (err) return parseErr(res, err);
// For approving subscription via Paypal, first redirect user to: approval_url
req.session.paypalBlock = req.query.sub;
var approval_url = _.find(billingAgreement.links, {rel:'approval_url'}).href;
res.redirect(approval_url);
});
@@ -82,10 +94,10 @@ exports.createPayment = function(req, res) {
var gift = req.query.gift ? JSON.parse(req.query.gift) : undefined;
var price = !gift ? 5.00
: gift.type=='gems' ? Number(gift.gems.amount/4).toFixed(2)
: Number(shared.content.subscriptionBlocks[gift.subscription.months].price).toFixed(2);
: Number(shared.content.subscriptionBlocks[gift.subscription.key].price).toFixed(2);
var description = !gift ? "HabitRPG Gems"
: gift.type=='gems' ? "HabitRPG Gems (Gift)"
: gift.subscription.months + "mo. HabitRPG Subscription (Gift)";
: shared.content.subscriptionBlocks[gift.subscription.key].months + "mo. HabitRPG Subscription (Gift)";
var create_payment = {
"intent": "sale",
"payer": {
@@ -11,7 +11,7 @@ var paypal = require('paypal-rest-sdk');
var blocks = require('habitrpg-shared').content.subscriptionBlocks;
var live = nconf.get('PAYPAL:mode')=='live';
var OP = 'get'; // list create update remove
var OP = 'create'; // list create update remove
paypal.configure({
'mode': nconf.get("PAYPAL:mode"), //sandbox or live
@@ -72,7 +72,7 @@ switch(OP) {
});
break;
case "create":
paypal.billingPlan.create(blocks["12"].definition, function(err,plan){
paypal.billingPlan.create(blocks["google_6mo"].definition, function(err,plan){
if (err) return console.log(err);
if (plan.state == "ACTIVE")
return console.log({err:err, plan:plan});
+20 -7
View File
@@ -4,6 +4,8 @@ var async = require('async');
var payments = require('./index');
var User = require('mongoose').model('User');
var shared = require('habitrpg-shared');
var mongoose = require('mongoose');
var cc = require('coupon-code');
/*
Setup Stripe response when posting payment
@@ -17,16 +19,27 @@ exports.checkout = function(req, res, next) {
async.waterfall([
function(cb){
if (sub) {
stripe.customers.create({
email: req.body.email,
metadata: {uuid: user._id},
card: token,
plan: sub.key
}, cb);
async.waterfall([
function(cb2){
if (!sub.discount) return cb2(null, null);
if (!req.query.coupon) return cb2('Please provide a coupon code for this plan.');
mongoose.model('Coupon').findOne({_id:cc.validate(req.query.coupon), event:sub.key}, cb2);
},
function(coupon, cb2){
if (sub.discount && !coupon) return cb2('Invalid coupon code.');
var customer = {
email: req.body.email,
metadata: {uuid: user._id},
card: token,
plan: sub.key
};
stripe.customers.create(customer, cb2);
}
], cb);
} else {
stripe.charges.create({
amount: !gift ? "500" //"500" = $5
: gift.type=='subscription' ? ""+shared.content.subscriptionBlocks[gift.subscription.months].price*100
: gift.type=='subscription' ? ""+shared.content.subscriptionBlocks[gift.subscription.key].price*100
: ""+gift.gems.amount/4*100,
currency: "usd",
card: token
+1 -1
View File
@@ -7,7 +7,7 @@ var autoinc = require('mongoose-id-autoinc');
var CouponSchema = new mongoose.Schema({
_id: {type: String, 'default': cc.generate},
event: {type:String, enum:['wondercon']},
event: {type:String, enum:['wondercon','google_6mo']},
user: {type: 'String', ref: 'User'}
});
+2
View File
@@ -20,4 +20,6 @@ router.get("/stripe/subscribe/cancel", auth.authWithUrl, i18n.getUserLanguage, p
router.post("/iap/android/verify", auth.authWithUrl, /*i18n.getUserLanguage, */payments.iapAndroidVerify);
router.post("/iap/ios/verify", /*auth.authWithUrl, i18n.getUserLanguage, */ payments.iapIosVerify);
router.get("/api/v2/coupons/valid-discount/:code", /*auth.authWithUrl, i18n.getUserLanguage, */ payments.validCoupon);
module.exports = router;
+1 -1
View File
@@ -8,7 +8,7 @@ var logging = require('./logging');
var isProd = nconf.get('NODE_ENV') === 'production';
var isDev = nconf.get('NODE_ENV') === 'development';
if (cluster.isMaster && (isDev || isProd)) {
if (false && cluster.isMaster && (isDev || isProd)) {
// Fork workers. If config.json has CORES=x, use that - otherwise, use all cpus-1 (production)
var cpus = require('os').cpus(),
cores = +nconf.get("CORES");