billings - handleCheckBillingSettingConnection
MODIFY
src/integration/billing/BillingFactory.ts
src/integration/billing/BillingFactory.ts
@@ -13,15 +13,25 @@ import Utils from '../../utils/Utils';
const MODULE_NAME = 'BillingFactory';
export default class BillingFactory {
- static async getBillingImpl(tenantID: string): Promise<BillingIntegration> {
+ static async getBillingImpl(tenantID: string, settings?: BillingSettings): Promise<BillingIntegration> {
// Get the tenant
const tenant: Tenant = await TenantStorage.getTenant(tenantID);
// Check if billing is active
if (Utils.isTenantComponentActive(tenant, TenantComponents.PRICING) &&
Utils.isTenantComponentActive(tenant, TenantComponents.BILLING)) {
+ if (!settings) {
// Get the billing's settings
const allSettings: BillingSettings[] = await BillingStorage.getBillingSettings(tenantID);
- const settings: BillingSettings = allSettings[0];
+ settings = allSettings[0];
+ } else {
+ // Specific situation to pre-check billing settings
+ await Logging.logDebug({
+ tenantID: tenant.id,
+ action: ServerAction.BILLING,
+ module: MODULE_NAME, method: 'getBillingImpl',
+ message: 'Now checking billing connectivity with settings not yet persisted'
+ });
+ }
if (settings) {
let billingIntegrationImpl = null;
switch (settings.type) {

MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -78,7 +78,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
source: Constants.CENTRAL_SERVER,
module: MODULE_NAME, method: 'checkConnection',
action: ServerAction.CHECK_CONNECTION,
- message: 'Failed to connect to Stripe',
+ message: 'Failed to connect to Stripe - Key is inconsistent',
detailedMessages: { error: error.message, stack: error.stack }
});
}
@@ -92,11 +92,11 @@ export default class StripeBillingIntegration extends BillingIntegration {
source: Constants.CENTRAL_SERVER,
module: MODULE_NAME, method: 'checkConnection',
action: ServerAction.CHECK_CONNECTION,
- message: 'Failed to connect to Stripe'
+ message: 'Failed to get a Stripe instance'
});
}
- // TODO - rethink that part - this is slow and useless!
- // this.productionMode = await StripeBillingIntegration.isConnectedToALiveAccount(this.stripe);
+ // Let's make sure the connection works as expected
+ this.productionMode = await StripeBillingIntegration.isConnectedToALiveAccount(this.stripe);
}
}

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -815,6 +815,7 @@ export default class BillingService {
isTransactionBillingActivated, usersLastSynchronizedOn,
immediateBillingAllowed, periodicBillingAllowed, taxID,
};
+ // TODO - clarify how to avoid the hardcoded "stripe" property here
billingSettings.stripe = newBillingProperties.stripe;
// Update timestamp
billingSettings.lastChangedBy = { 'id': req.user.id };
@@ -846,8 +847,44 @@ export default class BillingService {
// eslint-disable-next-line @typescript-eslint/require-await
public static async handleCheckBillingSettingConnection(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- // TODO - check connection settings before saving!
- res.sendStatus(StatusCodes.NOT_IMPLEMENTED);
+ // Check if component is active
+ UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
+ Action.CHECK_CONNECTION, Entity.BILLING, MODULE_NAME, 'handleCheckBillingSettingConnection');
+ // -----------------------------------------------------------------------
+ // GOAL: Check the connection settings before (and without) saving them!
+ // -----------------------------------------------------------------------
+ const newBillingProperties = req.body as Partial<BillingSettings>;
+ newBillingProperties.id = req.params.id;
+ UtilsService.assertIdIsProvided(action, newBillingProperties.id, MODULE_NAME, 'handleCheckBillingSettingConnection', req.user);
+ if (!await Authorizations.canCheckConnectionBilling(req.user)) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.FORBIDDEN,
+ user: req.user,
+ action: Action.UPDATE, entity: Entity.SETTING,
+ module: MODULE_NAME, method: 'handleCheckBillingSettingConnection',
+ });
+ }
+ // Load current settings
+ const billingSettings = await BillingStorage.getBillingSetting(req.user.tenantID, newBillingProperties.id);
+ await BillingService.alterSensitiveData(req.user.tenantID, billingSettings, newBillingProperties);
+ // Apply new settings (not yet saved)
+ // TODO - clarify how to avoid the hardcoded "stripe" property here
+ billingSettings.stripe = newBillingProperties.stripe;
+ // Create the Billing Implementation Instance
+ const billingImpl = await BillingFactory.getBillingImpl(req.user.tenantID, billingSettings);
+ if (!billingImpl) {
+ throw new AppError({
+ source: Constants.CENTRAL_SERVER,
+ errorCode: HTTPError.GENERAL_ERROR,
+ message: 'Billing service is not configured',
+ module: MODULE_NAME, method: 'handleCheckBillingConnection',
+ action: action,
+ user: req.user
+ });
+ }
+ await billingImpl.checkConnection();
+ // Ok
+ res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}

billings - handleCheckBillingSettingConnection