Merge pull request #2343 from overleaf/ta-invoice-attempt-callback

Collect Past Due Invoices on Paypal Billing Info Updates

GitOrigin-RevId: 6a0d298db8589ae6ba7cb62e4dfd562a1f292db0
This commit is contained in:
Timothée Alby
2019-11-12 09:14:58 +00:00
committed by sharelatex
parent 012bef257d
commit e000fd4615
7 changed files with 284 additions and 29 deletions
@@ -529,12 +529,12 @@ module.exports = RecurlyWrapper = {
)
},
getAccounts(queryParams, callback) {
getPaginatedEndpoint(resource, queryParams, callback) {
queryParams.per_page = queryParams.per_page || 200
let allAccounts = []
var getPageOfAccounts = (cursor = null) => {
let allItems = []
var getPage = (cursor = null) => {
const opts = {
url: 'accounts',
url: resource,
qs: queryParams
}
if (cursor != null) {
@@ -549,11 +549,10 @@ module.exports = RecurlyWrapper = {
logger.warn({ err }, 'could not get accoutns')
callback(err)
}
allAccounts = allAccounts.concat(data.accounts)
const items = data[resource]
allItems = allItems.concat(items)
logger.log(
`got another ${data.accounts.length}, total now ${
allAccounts.length
}`
`got another ${items.length}, total now ${allItems.length}`
)
cursor = __guard__(
response.headers.link != null
@@ -563,15 +562,15 @@ module.exports = RecurlyWrapper = {
)
if (cursor != null) {
cursor = decodeURIComponent(cursor)
return getPageOfAccounts(cursor)
return getPage(cursor)
} else {
return callback(err, allAccounts)
return callback(err, allItems)
}
})
})
}
return getPageOfAccounts()
return getPage()
},
getAccount(accountId, callback) {
@@ -645,6 +644,30 @@ module.exports = RecurlyWrapper = {
)
},
getAccountPastDueInvoices(accountId, callback) {
RecurlyWrapper.apiRequest(
{
url: `accounts/${accountId}/invoices?state=past_due`
},
(error, response, body) => {
if (error) {
return callback(error)
}
RecurlyWrapper._parseInvoicesXml(body, callback)
}
)
},
attemptInvoiceCollection(invoiceId, callback) {
RecurlyWrapper.apiRequest(
{
url: `invoices/${invoiceId}/collect`,
method: 'put'
},
callback
)
},
updateSubscription(subscriptionId, options, callback) {
logger.log(
{ subscriptionId, options },
@@ -926,6 +949,10 @@ module.exports = RecurlyWrapper = {
return RecurlyWrapper._parseXmlAndGetAttribute(xml, 'errors', callback)
},
_parseInvoicesXml(xml, callback) {
return RecurlyWrapper._parseXmlAndGetAttribute(xml, 'invoices', callback)
},
_parseXmlAndGetAttribute(xml, attribute, callback) {
return RecurlyWrapper._parseXml(xml, function(error, data) {
if (error != null) {
@@ -356,7 +356,6 @@ module.exports = SubscriptionController = {
recurlyCallback(req, res, next) {
logger.log({ data: req.body }, 'received recurly callback')
// we only care if a subscription has exipired
const event = Object.keys(req.body)[0]
const eventData = req.body[event]
if (
@@ -367,7 +366,7 @@ module.exports = SubscriptionController = {
].includes(event)
) {
const recurlySubscription = eventData.subscription
return SubscriptionHandler.recurlyCallback(
return SubscriptionHandler.syncSubscription(
recurlySubscription,
{ ip: req.ip },
function(err) {
@@ -377,6 +376,17 @@ module.exports = SubscriptionController = {
return res.sendStatus(200)
}
)
} else if (event === 'billing_info_updated_notification') {
const recurlyAccountCode = eventData.account.account_code
return SubscriptionHandler.attemptPaypalInvoiceCollection(
recurlyAccountCode,
function(err) {
if (err) {
return next(err)
}
return res.sendStatus(200)
}
)
} else {
return res.sendStatus(200)
}
@@ -230,7 +230,7 @@ const SubscriptionHandler = {
})
},
recurlyCallback(recurlySubscription, requesterData, callback) {
syncSubscription(recurlySubscription, requesterData, callback) {
return RecurlyWrapper.getSubscription(
recurlySubscription.uuid,
{ includeAccount: true },
@@ -259,6 +259,38 @@ const SubscriptionHandler = {
)
},
// attempt to collect past due invoice for customer. Only do that when a) the
// customer is using Paypal and b) there is only one past due invoice.
// This is used because Recurly doesn't always attempt collection of paast due
// invoices after Paypal billing info were updated.
attemptPaypalInvoiceCollection(recurlyAccountCode, callback) {
RecurlyWrapper.getBillingInfo(recurlyAccountCode, (error, billingInfo) => {
if (error) {
return callback(error)
}
if (!billingInfo.paypal_billing_agreement_id) {
// this is not a Paypal user
return callback()
}
RecurlyWrapper.getAccountPastDueInvoices(
recurlyAccountCode,
(error, pastDueInvoices) => {
if (error) {
return callback(error)
}
if (pastDueInvoices.length !== 1) {
// no past due invoices, or more than one. Ignore.
return callback()
}
RecurlyWrapper.attemptInvoiceCollection(
pastDueInvoices[0].invoice_number,
callback
)
}
)
})
},
extendTrial(subscription, daysToExend, callback) {
return RecurlyWrapper.extendTrial(
subscription.recurlySubscription_id,