Ghost/ghost/stripe/lib/StripeService.js
Ronald Langeveld a64eaeccf2
Refactored Stripe webhook controller (#20918)
no issue

- Moved business logic from `WebhookController` to dedicated service
classes (`SubscriptionEventService`, `InvoiceEventService`,
`CheckoutSessionEventService`).
- Reduced controller complexity.
- Added unit tests for individual services, increasing overall test
coverage.
- Improved maintainability and scalability by isolating responsibilities
in specific services, making future updates easier and safer.
2024-09-09 12:54:22 +09:00

137 lines
4.6 KiB
JavaScript

const WebhookManager = require('./WebhookManager');
const StripeAPI = require('./StripeAPI');
const StripeMigrations = require('./StripeMigrations');
const WebhookController = require('./WebhookController');
const DomainEvents = require('@tryghost/domain-events');
const {StripeLiveEnabledEvent, StripeLiveDisabledEvent} = require('./events');
const SubscriptionEventService = require('./services/webhook/SubscriptionEventService');
const InvoiceEventService = require('./services/webhook/InvoiceEventService');
const CheckoutSessionEventService = require('./services/webhook/CheckoutSessionEventService');
module.exports = class StripeService {
constructor({
labs,
membersService,
donationService,
staffService,
StripeWebhook,
models
}) {
const api = new StripeAPI({labs});
const migrations = new StripeMigrations({
models,
api
});
const webhookManager = new WebhookManager({
StripeWebhook,
api
});
const subscriptionEventService = new SubscriptionEventService({
get memberRepository(){
return membersService.api.members;
}
});
const invoiceEventService = new InvoiceEventService({
api,
get memberRepository(){
return membersService.api.members;
},
get eventRepository(){
return membersService.api.events;
},
get productRepository(){
return membersService.api.productRepository;
}
});
const checkoutSessionEventService = new CheckoutSessionEventService({
api,
get memberRepository(){
return membersService.api.members;
},
get productRepository(){
return membersService.api.productRepository;
},
get eventRepository(){
return membersService.api.events;
},
get donationRepository(){
return donationService.repository;
},
get staffServiceEmails(){
return staffService.api.emails;
},
sendSignupEmail(email){
return membersService.api.sendEmailWithMagicLink({
email,
requestedType: 'signup-paid',
options: {
forceEmailType: true
},
tokenData: {}
});
}
});
const webhookController = new WebhookController({
webhookManager,
subscriptionEventService,
invoiceEventService,
checkoutSessionEventService
});
this.models = models;
this.api = api;
this.webhookManager = webhookManager;
this.migrations = migrations;
this.webhookController = webhookController;
}
async connect() {
DomainEvents.dispatch(StripeLiveEnabledEvent.create({message: 'Stripe Live Mode Enabled'}));
}
async disconnect() {
await this.models.Product.forge().query().update({
monthly_price_id: null,
yearly_price_id: null
});
await this.models.StripePrice.forge().query().del();
await this.models.StripeProduct.forge().query().del();
await this.models.MemberStripeCustomer.forge().query().del();
await this.models.Offer.forge().query().update({
stripe_coupon_id: null
});
await this.webhookManager.stop();
this.api.configure(null);
DomainEvents.dispatch(StripeLiveDisabledEvent.create({message: 'Stripe Live Mode Disabled'}));
}
async configure(config) {
this.api.configure({
secretKey: config.secretKey,
publicKey: config.publicKey,
enablePromoCodes: config.enablePromoCodes,
get enableAutomaticTax() {
return config.enableAutomaticTax;
},
checkoutSessionSuccessUrl: config.checkoutSessionSuccessUrl,
checkoutSessionCancelUrl: config.checkoutSessionCancelUrl,
checkoutSetupSessionSuccessUrl: config.checkoutSetupSessionSuccessUrl,
checkoutSetupSessionCancelUrl: config.checkoutSetupSessionCancelUrl,
testEnv: config.testEnv
});
await this.webhookManager.configure({
webhookSecret: config.webhookSecret,
webhookHandlerUrl: config.webhookHandlerUrl
});
await this.webhookManager.start();
}
};