Updated stripe to store and retrieve from metadata

no-issue

This means that we will not have to make api requests to find out the
customers subscriptions
This commit is contained in:
Fabien O'Carroll 2019-10-08 14:09:59 +07:00
parent d11a0db726
commit 6806505a4c
2 changed files with 66 additions and 50 deletions

View File

@ -199,7 +199,9 @@ module.exports = function MembersApi({
return res.end(); return res.end();
} }
const customer = await stripe.getCustomer(event.data.object.customer); const customer = await stripe.getCustomer(event.data.object.customer, {
expand: ['subscriptions.data.default_payment_method']
});
const member = await users.get({email: customer.email}) || await users.create({email: customer.email}); const member = await users.get({email: customer.email}) || await users.create({email: customer.email});
await stripe.handleCheckoutSessionCompletedWebhook(member, customer); await stripe.handleCheckoutSessionCompletedWebhook(member, customer);

View File

@ -116,7 +116,7 @@ module.exports = class StripePaymentProcessor {
}); });
await Promise.all(activeSubscriptions.map((subscription) => { await Promise.all(activeSubscriptions.map((subscription) => {
return del(this._stripe, 'subscriptions', subscription.subscription); return del(this._stripe, 'subscriptions', subscription.id);
})); }));
return true; return true;
@ -125,47 +125,33 @@ module.exports = class StripePaymentProcessor {
async getSubscriptions(member) { async getSubscriptions(member) {
const metadata = await this.storage.get(member); const metadata = await this.storage.get(member);
const customers = await Promise.all(metadata.map(async (data) => { const customers = metadata.customers.reduce((customers, customer) => {
try { return Object.assign(customers, {
const customer = await this.getCustomer(data.customer_id, { [customer.customer_id]: {
expand: ['subscriptions.data.default_payment_method'] id: customer.customer_id,
}); name: customer.name,
return customer; email: customer.email
} catch (err) {
debug(`Ignoring Error getting customer for active subscriptions ${err.message}`);
return null;
}
}));
return customers.reduce(function (subscriptions, customer) {
if (!customer) {
return subscriptions;
}
if (customer.deleted) {
return subscriptions;
}
return subscriptions.concat(customer.subscriptions.data.reduce(function (subscriptions, subscription) {
// Subscription has more than one plan
// was not created by us - ignore it.
if (!subscription.plan) {
return subscriptions;
} }
});
}, {});
const payment = subscription.default_payment_method; return metadata.subscriptions.map((subscription) => {
return subscriptions.concat([{ return {
customer: customer.id, id: subscription.subscription_id,
status: subscription.status, customer: customers[subscription.customer_id],
subscription: subscription.id, plan: {
plan: subscription.plan.id, id: subscription.plan_id,
name: subscription.plan.nickname, nickname: subscription.plan_nickname,
interval: subscription.plan.interval, interval: subscription.plan_interval,
amount: subscription.plan.amount, amount: subscription.plan_amount,
currency: subscription.plan.currency, currency: subscription.plan_currency
last4: payment && payment.card && payment.card.last4 || null, },
validUntil: subscription.current_period_end status: subscription.status,
}]); start_date: subscription.start_date,
}, [])); default_payment_card_last4: subscription.default_payment_card_last4,
}, []); current_period_end: subscription.current_period_end
};
});
} }
async getActiveSubscriptions(member) { async getActiveSubscriptions(member) {
@ -178,24 +164,52 @@ module.exports = class StripePaymentProcessor {
async handleCheckoutSessionCompletedWebhook(member, customer) { async handleCheckoutSessionCompletedWebhook(member, customer) {
await this._addCustomerToMember(member, customer); await this._addCustomerToMember(member, customer);
if (!customer.subscriptions || !customer.subscriptions.data) {
return;
}
for (const subscription of customer.subscriptions.data) {
await this._updateSubscription(subscription);
}
} }
async _addCustomerToMember(member, customer) { async _addCustomerToMember(member, customer) {
const metadata = await this.storage.get(member);
// Do not add the customer if they are already linked
if (metadata.some(data => data.customer_id === customer.id)) {
return;
}
debug(`Attaching customer to member ${member.email} ${customer.id}`); debug(`Attaching customer to member ${member.email} ${customer.id}`);
return this.storage.set(member, metadata.concat({ await this.storage.set({
customer_id: customer.id customer: {
})); customer_id: customer.id,
member_id: member.id,
name: customer.name,
email: customer.email
}
});
}
async _updateSubscription(subscription) {
debug(`Attaching subscription to customer ${subscription.customer} ${subscription.id}`);
const payment = subscription.default_payment_method;
await this.storage.set({
subscription: {
customer_id: subscription.customer,
subscription_id: subscription.id,
status: subscription.status,
current_period_end: new Date(subscription.current_period_end * 1000),
start_date: new Date(subscription.start_date * 1000),
default_payment_card_last4: payment && payment.card && payment.card.last4 || null,
plan_id: subscription.plan.id,
plan_nickname: subscription.plan.nickname,
plan_interval: subscription.plan.interval,
plan_amount: subscription.plan.amount,
plan_currency: subscription.plan.currency
}
});
} }
async _customerForMemberCheckoutSession(member) { async _customerForMemberCheckoutSession(member) {
const metadata = await this.storage.get(member); const metadata = await this.storage.get(member);
for (const data in metadata) { for (const data in metadata.customers) {
try { try {
const customer = await this.getCustomer(data.customer_id); const customer = await this.getCustomer(data.customer_id);
if (!customer.deleted) { if (!customer.deleted) {