mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-22 02:45:29 -04:00
Added a payment-received HipChat notification.
This commit is contained in:
parent
8f55b9bc1b
commit
ab6251281e
1 changed files with 46 additions and 37 deletions
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue