From 7376a333c232562ff1a35055d3002a0b402cc693 Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Fri, 6 Sep 2019 13:07:35 +0800 Subject: [PATCH] Removed lib/subscriptions no-issue This is no longer used --- ghost/members-api/lib/subscriptions/index.js | 90 ------------- .../stripe/api/createDeterministicApi.js | 75 ----------- .../stripe/api/createStripeRequest.js | 56 --------- .../stripe/api/customers.js | 12 -- .../payment-processors/stripe/api/index.js | 6 - .../payment-processors/stripe/api/plans.js | 21 ---- .../payment-processors/stripe/api/products.js | 12 -- .../stripe/api/stripeRequests.js | 26 ---- .../stripe/api/subscriptions.js | 64 ---------- .../payment-processors/stripe/index.js | 119 ------------------ 10 files changed, 481 deletions(-) delete mode 100644 ghost/members-api/lib/subscriptions/index.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createDeterministicApi.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createStripeRequest.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/customers.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/index.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/plans.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/products.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/stripeRequests.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/api/subscriptions.js delete mode 100644 ghost/members-api/lib/subscriptions/payment-processors/stripe/index.js diff --git a/ghost/members-api/lib/subscriptions/index.js b/ghost/members-api/lib/subscriptions/index.js deleted file mode 100644 index 7b91bd843c..0000000000 --- a/ghost/members-api/lib/subscriptions/index.js +++ /dev/null @@ -1,90 +0,0 @@ -const stripe = require('./payment-processors/stripe'); - -const adapters = { - stripe -}; - -module.exports = class PaymentProcessorService { - constructor(config) { - this._ready = new Promise((resolve, reject) => { - this._resolveReady = resolve; - this._rejectReady = reject; - }); - process.nextTick(() => this.configure(config)); - } - - configure({processors}) { - this._processors = {}; - Promise.all(processors.map(({ - adapter, - config - }) => { - this._processors[adapter] = new adapters[adapter]; - return this._processors[adapter].configure(config); - })).then(() => { - return Object.keys(this._processors); - }).then(this._resolveReady, this._rejectReady); - - return this._ready; - } - - getAdapters() { - return this._ready; - } - - getConfig(adapter) { - if (!adapter) { - return Promise.reject(new Error('getConfig(adapter) requires an adapter')); - } - - return this._ready.then(() => { - return this._processors[adapter].getConfig(); - }); - } - - getPublicConfig(adapter) { - if (!adapter) { - return Promise.reject(new Error('getPublicConfig(adapter) requires an adapter')); - } - - return this._ready.then(() => { - return this._processors[adapter].getPublicConfig(); - }); - } - - createSubscription(member, metadata) { - if (!metadata.adapter) { - return Promise.reject(new Error('createSubscription(member, { adapter }) requires an adapter')); - } - return this._ready.then(() => { - return this._processors[metadata.adapter].createSubscription(member, metadata); - }); - } - - getSubscription(member, metadata) { - if (!metadata.adapter) { - return Promise.reject(new Error('getSubscription(member, { adapter }) requires an adapter')); - } - return this._ready.then(() => { - return this._processors[metadata.adapter].getSubscription(member, metadata); - }); - } - - removeSubscription(member, metadata) { - if (!metadata.adapter) { - return Promise.reject(new Error('removeSubscription(member, { adapter }) requires an adapter')); - } - return this._ready.then(() => { - return this._processors[metadata.adapter].removeSubscription(member, metadata); - }); - } - - removeCustomer(member, metadata) { - if (!metadata.adapter) { - return Promise.reject(new Error('removeCustomer(member, { adapter }) requires an adapter')); - } - return this._ready.then(() => { - return this._processors[metadata.adapter].removeCustomer(member, metadata); - }); - } -}; diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createDeterministicApi.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createDeterministicApi.js deleted file mode 100644 index 1e53e59611..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createDeterministicApi.js +++ /dev/null @@ -1,75 +0,0 @@ -const hash = data => require('crypto').createHash('sha256').update(data).digest('hex'); -const { - del: stripeDel, - create: stripeCreate, - retrieve: stripeRetrieve -} = require('./stripeRequests'); - -function createDeterministicApi(resource, validResult, getAttrs, generateHashSeed) { - const get = createGetter(resource, validResult); - const create = createCreator(resource, getAttrs); - const remove = createRemover(resource, get, generateHashSeed); - const ensure = createEnsurer(get, create, generateHashSeed); - - return { - get, create, remove, ensure - }; -} - -function prefixHashSeed(stripe, seed) { - const prefix = stripe.__TEST_MODE__ ? 'test_' : 'prod_'; - return prefix + seed; -} - -function createGetter(resource, validResult) { - return function get(stripe, object, idSeed) { - const id = hash(prefixHashSeed(stripe, idSeed)); - return stripeRetrieve(stripe, resource, id) - .then((result) => { - if (validResult(result)) { - return result; - } - return get(stripe, object, id); - }, (err) => { - err.id_requested = id; - throw err; - }); - }; -} - -function createCreator(resource, getAttrs) { - return function create(stripe, id, object, ...rest) { - return stripeCreate( - stripe, - resource, - Object.assign(getAttrs(object, ...rest), {id}) - ); - }; -} - -function createRemover(resource, get, generateHashSeed) { - return function remove(stripe, object, ...rest) { - return get(stripe, object, generateHashSeed(object, ...rest)).then((res) => { - return stripeDel(stripe, resource, res.id); - }).catch((err) => { - if (err.code !== 'resource_missing') { - throw err; - } - }); - }; -} - -function createEnsurer(get, create, generateHashSeed) { - return function ensure(stripe, object, ...rest) { - return get(stripe, object, generateHashSeed(object, ...rest)) - .catch((err) => { - if (err.code !== 'resource_missing') { - throw err; - } - const id = err.id_requested; - return create(stripe, id, object, ...rest); - }); - }; -} - -module.exports = createDeterministicApi; diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createStripeRequest.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createStripeRequest.js deleted file mode 100644 index fbaf51c2b9..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/createStripeRequest.js +++ /dev/null @@ -1,56 +0,0 @@ -module.exports = function createStripeRequest(makeRequest) { - return function stripeRequest(...args) { - const errorHandler = (err) => { - switch (err.type) { - case 'StripeCardError': - // Card declined - throw err; - case 'RateLimitError': - // Ronseal - return exponentiallyBackoff(makeRequest, ...args).catch((err) => { - // We do not want to recurse further if we get RateLimitError - // after running the exponential backoff - if (err.type === 'RateLimitError') { - throw err; - } - return errorHandler(err); - }); - case 'StripeInvalidRequestError': - // Invalid params to the request - throw err; - case 'StripeAPIError': - // Rare internal server error from stripe - throw err; - case 'StripeConnectionError': - // Weird network/https issue - throw err; - case 'StripeAuthenticationError': - // Invalid API Key (probably) - throw err; - default: - throw err; - } - }; - return makeRequest(...args).catch(errorHandler); - }; -}; - -function exponentiallyBackoff(makeRequest, ...args) { - function backoffRequest(timeout, ...args) { - return new Promise(resolve => setTimeout(resolve, timeout)).then(() => { - return makeRequest(...args).catch((err) => { - if (err.type !== 'RateLimitError') { - throw err; - } - - if (timeout > 30000) { - throw err; - } - - return backoffRequest(timeout * 2, ...args); - }); - }); - } - - return backoffRequest(1000, ...args); -} diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/customers.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/customers.js deleted file mode 100644 index 84b2d5daa4..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/customers.js +++ /dev/null @@ -1,12 +0,0 @@ -const createDeterministicApi = require('./createDeterministicApi'); - -const isNotDeleted = x => !x.deleted; -const getCustomerAttr = ({email}) => ({email}); -const getCustomerHashSeed = member => member.email; - -module.exports = createDeterministicApi( - 'customers', - isNotDeleted, - getCustomerAttr, - getCustomerHashSeed -); diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/index.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/index.js deleted file mode 100644 index 10d023c619..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - customers: require('./customers'), - products: require('./products'), - plans: require('./plans'), - subscriptions: require('./subscriptions') -}; diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/plans.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/plans.js deleted file mode 100644 index 69a5e66a68..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/plans.js +++ /dev/null @@ -1,21 +0,0 @@ -const createDeterministicApi = require('./createDeterministicApi'); - -const isActive = x => x.active; -const getPlanAttr = ({name, amount, interval, currency}, product) => ({ - nickname: name, - amount, - interval, - currency, - product: product.id, - billing_scheme: 'per_unit' -}); -const getPlanHashSeed = (plan, product) => { - return product.id + plan.interval + plan.currency + plan.amount; -}; - -module.exports = createDeterministicApi( - 'plans', - isActive, - getPlanAttr, - getPlanHashSeed -); diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/products.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/products.js deleted file mode 100644 index eb9bc13ecd..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/products.js +++ /dev/null @@ -1,12 +0,0 @@ -const createDeterministicApi = require('./createDeterministicApi'); - -const isActive = x => x.active; -const getProductAttr = ({name}) => ({name, type: 'service'}); -const getProductHashSeed = () => 'Ghost Subscription'; - -module.exports = createDeterministicApi( - 'products', - isActive, - getProductAttr, - getProductHashSeed -); diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/stripeRequests.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/stripeRequests.js deleted file mode 100644 index 7b8d52ef29..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/stripeRequests.js +++ /dev/null @@ -1,26 +0,0 @@ -const createStripeRequest = require('./createStripeRequest'); - -const createSource = createStripeRequest(function (stripe, customerId, stripeToken) { - return stripe.customers.createSource(customerId, { - source: stripeToken - }); -}); - -const retrieve = createStripeRequest(function (stripe, resource, id) { - return stripe[resource].retrieve(id); -}); - -const create = createStripeRequest(function (stripe, resource, object) { - return stripe[resource].create(object); -}); - -const del = createStripeRequest(function (stripe, resource, id) { - return stripe[resource].del(id); -}); - -module.exports = { - createSource, - retrieve, - create, - del -}; diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/subscriptions.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/subscriptions.js deleted file mode 100644 index 90f32a56a4..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/api/subscriptions.js +++ /dev/null @@ -1,64 +0,0 @@ -const customers = require('./customers'); -const {del, create, createSource} = require('./stripeRequests'); - -function removeSubscription(stripe, member) { - return customers.get(stripe, member, member.email).then((customer) => { - // CASE customer has no subscriptions - if (!customer.subscriptions || customer.subscriptions.total_count === 0) { - throw new Error('Cannot remove subscription'); - } - - const subscription = customer.subscriptions.data[0]; - - return del(stripe, 'subscriptions', subscription.id); - }); -} - -function getSubscription(stripe, member) { - return customers.get(stripe, member, member.email).then((customer) => { - // CASE customer has either none or multiple subscriptions - if (!customer.subscriptions || customer.subscriptions.total_count !== 1) { - return {}; - } - - const subscription = customer.subscriptions.data[0]; - - // CASE subscription has multiple plans - if (subscription.items.total_count !== 1) { - return {}; - } - - const plan = subscription.plan; - - return { - validUntil: subscription.current_period_end, - plan: plan.nickname, - amount: plan.amount, - status: subscription.status - }; - }).catch(() => { - return {}; - }); -} - -function createSubscription(stripe, member, metadata) { - return customers.ensure(stripe, member, member.email).then((customer) => { - if (customer.subscriptions && customer.subscriptions.total_count !== 0) { - throw new Error('Customer already has a subscription'); - } - - return createSource(stripe, customer.id, metadata.stripeToken).then(() => { - return create(stripe, 'subscriptions', { - customer: customer.id, - items: [{plan: metadata.plan.id}], - coupon: metadata.coupon - }); - }); - }); -} - -module.exports = { - create: createSubscription, - get: getSubscription, - remove: removeSubscription -}; diff --git a/ghost/members-api/lib/subscriptions/payment-processors/stripe/index.js b/ghost/members-api/lib/subscriptions/payment-processors/stripe/index.js deleted file mode 100644 index 3e7283a39e..0000000000 --- a/ghost/members-api/lib/subscriptions/payment-processors/stripe/index.js +++ /dev/null @@ -1,119 +0,0 @@ -const api = require('./api'); - -module.exports = class StripePaymentProcessor { - constructor() { - this._ready = new Promise((resolve, reject) => { - this._resolveReady = resolve; - this._rejectReady = reject; - }); - } - - configure(config) { - const stripe = require('stripe')(config.secret_token); - stripe.__TEST_MODE__ = config.secret_token.startsWith('sk_test_'); - - api.products.ensure(stripe, config.product).then((product) => { - return Promise.all( - config.plans.map(plan => api.plans.ensure(stripe, plan, product)) - ).then((plans) => { - this._stripe = stripe; - this._product = product; - this._plans = plans; - this._public_token = config.public_token; - return { - product, - plans - }; - }); - }).then(this._resolveReady, this._rejectReady); - - return this._ready; - } - - getConfig() { - if (!this._plans) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - return this._ready.then(() => { - return this._plans; - }); - } - - getPublicConfig() { - if (!this._plans) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - return this._ready.then(() => { - return { - adapter: 'stripe', - config: { - publicKey: this._public_token, - plans: this._plans.map(({id, currency, amount, interval, nickname}) => ({ - id, currency, amount, interval, - name: nickname - })) - } - }; - }); - } - - createSubscription(member, metadata) { - if (!this._stripe) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - if (!metadata.stripeToken) { - throw new Error('createSubscription(member, {stripeToken}) missing stripeToken'); - } - - if (!metadata.plan) { - throw new Error('createSubscription(member, {plan}) missing plan'); - } - - return this._ready.then(() => { - const plan = this._plans.find(plan => plan.nickname === metadata.plan); - - if (!plan) { - throw new Error('Unknown plan'); - } - - return api.subscriptions.create(this._stripe, member, { - plan, - stripeToken: metadata.stripeToken, - coupon: metadata.coupon - }); - }); - } - - getSubscription(member) { - if (!this._stripe) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - return this._ready.then(() => { - return api.subscriptions.get(this._stripe, member); - }); - } - - removeSubscription(member) { - if (!this._stripe) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - return this._ready.then(() => { - return api.subscriptions.remove(this._stripe, member); - }); - } - - removeCustomer(member) { - if (!this._stripe) { - throw new Error('StripePaymentProcessor must be configured()'); - } - - return this._ready.then(() => { - return api.customers.remove(this._stripe, member); - }); - } -};