mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-07-23 12:32:06 +00:00
ed51d8b13f
major merge of features from the hosted branch that was created temporarily during the initial launch of jambonz.org
72 lines
2.8 KiB
JavaScript
72 lines
2.8 KiB
JavaScript
const router = require('express').Router();
|
|
//const debug = require('debug')('jambonz:api-server');
|
|
const Account = require('../../models/account');
|
|
const {retrieveSubscription} = require('../../utils/stripe-utils');
|
|
const stripeFactory = require('stripe');
|
|
const express = require('express');
|
|
const sysError = require('../error');
|
|
|
|
/** Invoice events */
|
|
const handleInvoicePaymentSucceeded = async(logger, obj) => {
|
|
const {subscription} = obj;
|
|
logger.debug({obj}, `payment for ${obj.billing_reason} succeeded`);
|
|
const sub = await retrieveSubscription(logger, subscription);
|
|
if ('active' === sub.status) {
|
|
const {account_sid} = sub.metadata;
|
|
if (await Account.activateSubscription(logger, account_sid, sub.id,
|
|
'subscription_create' === obj.billing_reason ? 'upgrade to paid plan' : 'change plan details')) {
|
|
logger.info(`handleInvoicePaymentSucceeded: activated subscription for account ${account_sid}`);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Two cases:
|
|
* (1) A subscription renewal fails. In this case we deactivate subscription
|
|
* and the customer is down until they provide payment.
|
|
* (2) A customer adds capacity during the month, and the pro-rated amount fails.
|
|
* In this case, we leave the new subscription in a pending state
|
|
* The customer continues (for the rest of the month at least) at
|
|
* previous capacity levels.
|
|
*/
|
|
|
|
const handleInvoicePaymentFailed = async(logger, obj) => {
|
|
const {subscription} = obj;
|
|
const sub = await retrieveSubscription(logger, subscription);
|
|
logger.debug({obj}, `payment for ${obj.billing_reason} failed, subscription status is ${sub.status}`);
|
|
const {account_sid} = sub.metadata;
|
|
if (await Account.deactivateSubscription(logger, account_sid, 'payment failed')) {
|
|
logger.info(`handleInvoicePaymentFailed: deactivated subscription for account ${account_sid}`);
|
|
}
|
|
};
|
|
|
|
const handleInvoiceEvents = async(logger, evt) => {
|
|
if (evt.type === 'invoice.payment_succeeded') handleInvoicePaymentSucceeded(logger, evt.data.object);
|
|
else if (evt.type === 'invoice.payment_failed') handleInvoicePaymentFailed(logger, evt.data.object);
|
|
};
|
|
|
|
|
|
router.post('/', express.raw({type: 'application/json'}), async(req, res) => {
|
|
const {logger} = req.app.locals;
|
|
const sig = req.get('stripe-signature');
|
|
|
|
let evt;
|
|
try {
|
|
if (!process.env.STRIPE_WEBHOOK_SECRET) throw new Error('missing webhook secret');
|
|
const stripe = stripeFactory(process.env.STRIPE_API_KEY);
|
|
evt = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
|
|
res.sendStatus(204);
|
|
} catch (err) {
|
|
sysError(logger, res, err);
|
|
}
|
|
|
|
/* process event */
|
|
logger.info(`received webhook: ${evt.type}`);
|
|
if (evt.type.startsWith('invoice.')) handleInvoiceEvents(logger, evt);
|
|
else {
|
|
logger.debug(evt, 'unhandled stripe webook');
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|