Added a payment-received HipChat notification.

This commit is contained in:
Nick Winter 2014-11-25 13:20:09 -08:00
parent 8f55b9bc1b
commit ab6251281e

View file

@ -17,13 +17,13 @@ products = {
gems: 5000
id: 'gems_5'
}
'gems_10': {
amount: 999
gems: 11000
id: 'gems_10'
}
'gems_20': {
amount: 1999
gems: 25000
@ -43,7 +43,7 @@ PaymentHandler = class PaymentHandler extends Handler
payment.set 'recipient', req.user._id
payment.set 'created', new Date().toISOString()
payment
post: (req, res) ->
appleReceipt = req.body.apple?.rawReceipt
appleTransactionID = req.body.apple?.transactionID
@ -51,46 +51,46 @@ PaymentHandler = class PaymentHandler extends Handler
stripeToken = req.body.stripe?.token
stripeTimestamp = parseInt(req.body.stripe?.timestamp)
productID = req.body.productID
if not (appleReceipt or (stripeTimestamp and productID))
return @sendBadInputError(res, 'Need either apple.rawReceipt or stripe.timestamp and productID')
if stripeTimestamp and not productID
return @sendBadInputError(res, 'Need productID if paying with Stripe.')
if stripeTimestamp and (not stripeToken) and (not user.get('stripeCustomerID'))
return @sendBadInputError(res, 'Need stripe.token if new customer.')
if appleReceipt
if not appleTransactionID
return @sendBadInputError(res, 'Apple purchase? Need to specify which transaction.')
@handleApplePaymentPost(req, res, appleReceipt, appleTransactionID, appleLocalPrice)
else
@handleStripePaymentPost(req, res, stripeTimestamp, productID, stripeToken)
#- Apple payments
handleApplePaymentPost: (req, res, receipt, transactionID, localPrice) ->
formFields = { 'receipt-data': receipt }
#- verify receipt with Apple
#- verify receipt with Apple
verifyReq = request.post({url: config.apple.verifyURL, json: formFields}, (err, verifyRes, body) =>
if err or not body?.receipt?.in_app or (not body?.bundle_id is 'com.codecombat.CodeCombat')
console.warn 'apple receipt error?', err, body
@sendBadInputError(res, 'Unable to verify Apple receipt.')
return
transaction = _.find body.receipt.in_app, { transaction_id: transactionID }
return @sendBadInputError(res, 'Invalid transactionID.') unless transaction
return @sendBadInputError(res, 'Invalid transactionID.') unless transaction
#- Check existence
transactionID = transaction.transaction_id
criteria = { 'ios.transactionID': transactionID }
Payment.findOne(criteria).exec((err, payment) =>
if payment
unless payment.get('recipient').equals(req.user._id)
return @sendForbiddenError(res)
@ -119,17 +119,18 @@ PaymentHandler = class PaymentHandler extends Handler
return @sendDatabaseError(res, err) if err
@incrementGemsFor(req.user, product.gems, (err) =>
return @sendDatabaseError(res, err) if err
@sendPaymentHipChatMessage user: req.user, payment: payment
@sendCreated(res, @formatEntity(req, payment))
)
)
)
)
#- Stripe payments
handleStripePaymentPost: (req, res, timestamp, productID, token) ->
# First, make sure we save the payment info as a Customer object, if we haven't already.
if not req.user.get('stripeCustomerID')
stripe.customers.create({
@ -145,10 +146,10 @@ PaymentHandler = class PaymentHandler extends Handler
(err) =>
return @sendDatabaseError(res, err)
)
else
@beginStripePayment(req, res, timestamp, productID)
beginStripePayment: (req, res, timestamp, productID) ->
product = products[productID]
@ -168,29 +169,30 @@ PaymentHandler = class PaymentHandler extends Handler
)
)
],
((err, results) =>
return @sendDatabaseError(res, err) if err
return @sendDatabaseError(res, err) if err
[payment, charge] = results
if not (payment or charge)
# Proceed normally from the beginning
@chargeStripe(req, res, payment, product)
else if charge and not payment
# Initialized Payment. Start from charging.
@recordStripeCharge(req, res, payment, product, charge)
else
# Charged Stripe and recorded it. Recalculate gems to make sure credited the purchase.
@recalculateGemsFor(req.user, (err) =>
return @sendDatabaseError(res, err) if err
@sendPaymentHipChatMessage user: req.user, payment: payment
@sendSuccess(res, @formatEntity(req, payment))
)
)
)
chargeStripe: (req, res, payment, product) ->
stripe.charges.create({
amount: product.amount
@ -206,7 +208,7 @@ PaymentHandler = class PaymentHandler extends Handler
}).then(
# success case
((charge) => @recordStripeCharge(req, res, payment, product, charge)),
# error case
((err) =>
if err.type in ['StripeCardError', 'StripeInvalidRequestError']
@ -214,8 +216,8 @@ PaymentHandler = class PaymentHandler extends Handler
else
@sendDatabaseError(res, 'Error charging card, please retry.'))
)
recordStripeCharge: (req, res, payment, product, charge) ->
return @sendError(res, 500, 'Fake db error for testing.') if req.body.breakAfterCharging
payment = @makeNewInstance(req)
@ -241,9 +243,9 @@ PaymentHandler = class PaymentHandler extends Handler
)
)
#- Incrementing/recalculating gems
incrementGemsFor: (user, gems, done) ->
purchased = _.clone(user.get('purchased'))
if not purchased?.gems
@ -251,10 +253,10 @@ PaymentHandler = class PaymentHandler extends Handler
purchased.gems = gems
user.set('purchased', purchased)
user.save((err) -> done(err))
else
user.update({$inc: {'purchased.gems': gems}}, {}, (err) -> done(err))
recalculateGemsFor: (user, done) ->
Payment.find({recipient: user._id}).select('gems').exec((err, payments) ->
@ -264,7 +266,14 @@ PaymentHandler = class PaymentHandler extends Handler
purchased.gems = gems
user.set('purchased', purchased)
user.save((err) -> done(err))
)
sendPaymentHipChatMessage: (options) ->
try
message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service'}."
hipchat.sendHipChatMessage message
catch e
log.error "Couldn't send HipChat message on payment because of error: #{e}"
module.exports = new PaymentHandler()