fleet/website/api/controllers/customers/save-billing-info-and-subscribe.js
eashaw e335e835c9
Add customer portal and license dispenser to fleetdm.com (#3546)
* Add images for customer portal, dashboard, and email templates

* updated email layout and reset password template, new email template

* update ajax-button component to have an optional spinner

* updated cloud-error & stripe-card-element component styles

* updates to user model, add quote and subscription

* Login, signup, forgot password, update profile

* link to customer portal from pricing

* new-license page, bootstrap updates

* create quote action, dashboard page, update routes

* Add new page styles to importer, update component styles

* updates to js-timestamp

* update modal styles and layout

* using @submitted on ajax form, controller updates

* Update create-quote.js

* updates to quote model, action updates, truncate license key on dashboard

* update email layout, subscribe action, user model

* Update importer.less

* style updates, order confirmation

* use correct font

* style updates

* create license key

* new-license page changes

* signup page changes

* add billing format to js-timestamp component, dashboard updates, change password

* swap get started link for customers

* order -> subscription

* Update login.ejs

* Lint fixes, page updates, mobile styles

* remove edit-profile route, update layout, bootstrap, forms

* change customer-layout name to match other layout names, update copyright year in layouts

* changes requested from code review and #3570

* submit button width, contact font-size

* Update dashboard.less

* Update bootstrap-overrides.less

* slack logo update, login text
2022-01-04 20:02:42 -06:00

133 lines
4.2 KiB
JavaScript
Vendored

module.exports = {
friendlyName: 'Save billing info and subscribe',
description: '',
inputs: {
quoteId: {
type: 'number',
required: true,
description: 'The quote to use (determines the price and number of hosts.)'
},
paymentSource: {
required: true,
description: 'New payment source info to use (instead of the saved default payment source).',
extendedDescription: 'If provided, this will also be saved as the new default payment source for the customer, replacing the existing default payment source (if there is one.)',
type: {
stripeToken: 'string',
billingCardLast4: 'string',
billingCardBrand: 'string',
billingCardExpMonth: 'string',
billingCardExpYear: 'string',
},
example: {
stripeToken: 'tok_199k3qEXw14QdSnRwmsK99MH',
billingCardLast4: '4242',
billingCardBrand: 'visa',
billingCardExpMonth: '08',
billingCardExpYear: '2023',
}
},
},
exits: {
couldNotSaveBillingInfo: {
description: 'The billing information provided could not be saved.',
responseType: 'badRequest'
},
},
fn: async function (inputs) {
const stripe = require('stripe')(sails.config.custom.stripeSecret);
let quoteRecord = await Quote.findOne({id: inputs.quoteId});
if(!quoteRecord) {
throw new Error(`Consistency violation: The specified quote (${inputs.quoteId}) no longer seems to exist.`);
}
// If this user has a subscription, we'll throw an error.
let doesUserHaveAnExistingSubscription = await Subscription.findOne({user: this.req.me.id});
if(doesUserHaveAnExistingSubscription) {
throw new Error(`Consistency violation: The requesting user (${this.req.me.emailAddress}) already has an existing subscription!`);
}
// What if the stripe customer id doesn't already exist on the user?
if (!this.req.me.stripeCustomerId) {
throw new Error(`Consistency violation: The logged-in user's (${this.req.me.emailAddress}) Stripe customer id has somehow gone missing!`);
}
// Write new payment card info ("token") to Stripe's API.
await sails.helpers.stripe.saveBillingInfo.with({
stripeCustomerId: this.req.me.stripeCustomerId,
token: inputs.paymentSource.stripeToken
})
.intercept({ type: 'StripeCardError' }, 'couldNotSaveBillingInfo');
// Save payment card info to our database.
await User.updateOne({ id: this.req.me.id })
.set({
hasBillingCard: true,
billingCardBrand: inputs.paymentSource.billingCardBrand,
billingCardLast4: inputs.paymentSource.billingCardLast4,
billingCardExpMonth: inputs.paymentSource.billingCardExpMonth,
billingCardExpYear: inputs.paymentSource.billingCardExpYear,
});
// Create the subscription for this order in Stripe
const subscription = await stripe.subscriptions.create({
customer: this.req.me.stripeCustomerId,
items: [
{
price: sails.config.custom.stripeSubscriptionProduct,
quantity: quoteRecord.numberOfHosts,
},
],
});
// Generate the license key for this subscription
let licenseKey = await sails.helpers.createLicenseKey.with({
numberOfHosts: quoteRecord.numberOfHosts,
organization: this.req.me.organization,
validTo: subscription.current_period_end
});
// Create the subscription record for this order.
await Subscription.create({
organization: this.req.me.organization,
numberOfHosts: quoteRecord.numberOfHosts,
subscriptionPrice: quoteRecord.quotedPrice,
user: this.req.me.id,
stripeSubscriptionId: subscription.id,
nextBillingAt: subscription.current_period_end * 1000,
fleetLicenseKey: licenseKey,
});
// Send the order confirmation template email
await sails.helpers.sendTemplateEmail.with({
to: this.req.me.emailAddress,
from: sails.config.custom.fromEmail,
fromName: sails.config.custom.fromName,
subject: 'Your Fleet Premium order',
template: 'email-order-confirmation',
templateData: {
firstName: this.req.me.firstName,
lastName: this.req.me.lastName,
}
});
}
};