UNPKG

ynkap-payment

Version:

Module de paiement Y-Nkap pour Angular - Intégration simple des paiements mobiles (Orange Money, MTN Mobile Money)

142 lines 17.6 kB
import { Injectable } from '@angular/core'; import { BehaviorSubject, throwError, timer } from 'rxjs'; import { mergeMap } from 'rxjs/operators'; import { ErrorCategory, YnkapError } from './models/error.model'; import * as i0 from "@angular/core"; export class ErrorHandlingService { constructor() { this.errorSubject = new BehaviorSubject(null); // Default retry options this.defaultRetryOptions = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 10000, nonRetryableErrors: [ ErrorCategory.AUTHENTICATION, ErrorCategory.AUTHORIZATION, ErrorCategory.VALIDATION ] }; } handleError(error) { let ynkapError; if (error instanceof YnkapError) { ynkapError = error; } else { ynkapError = new YnkapError(error.code || 'UNKNOWN_ERROR', error.message || 'Une erreur inattendue est survenue', error.details); } this.errorSubject.next(ynkapError); console.error('Y-Nkap Error:', ynkapError); } getError() { return this.errorSubject.asObservable(); } clearError() { this.errorSubject.next(null); } /** * Apply retry logic with exponential backoff for failed operations * @param error The error that occurred * @param retryFn Function to retry * @param options Retry options * @returns An observable that will retry the operation */ retryWithBackoff(error, retryFn, options) { const retryOpts = { ...this.defaultRetryOptions, ...options }; // Check if error is retryable if (!error.retryable) { return throwError(() => error); } // Check if the error type is in the non-retryable list if (retryOpts.nonRetryableErrors?.includes(error.code)) { return throwError(() => error); } // Check if we've exceeded max retries const attemptNumber = (error.details?.attemptNumber || 0) + 1; if (attemptNumber > retryOpts.maxRetries) { return throwError(() => error); } // Calculate backoff delay with exponential increase const delayMs = Math.min(retryOpts.baseDelayMs * Math.pow(2, attemptNumber - 1), retryOpts.maxDelayMs); // Call the onRetry callback if provided if (retryOpts.onRetry) { retryOpts.onRetry(error, attemptNumber); } // Update attempt number in error details error.details = { ...error.details, attemptNumber }; // Wait for the delay then retry return timer(delayMs).pipe(mergeMap(() => retryFn())); } /** * Convert any error to a standardized YnkapError * @param error The error to convert * @param context Optional context information * @returns A standardized YnkapError */ convertToYnkapError(error, context) { const timestamp = new Date(); // HTTP errors if (error && error.status) { const httpStatus = error.status; const errorBody = error.error || {}; let category; let retryable = false; switch (true) { case httpStatus === 401: category = ErrorCategory.AUTHENTICATION; retryable = false; break; case httpStatus === 403: category = ErrorCategory.AUTHORIZATION; retryable = false; break; case httpStatus >= 400 && httpStatus < 500: category = ErrorCategory.VALIDATION; retryable = false; break; case httpStatus >= 500: category = ErrorCategory.SERVER; retryable = true; break; default: category = ErrorCategory.UNKNOWN; retryable = true; } return new YnkapError(errorBody.code || category, errorBody.message || `Error ${httpStatus}: ${error.statusText || 'Unknown HTTP error'}`, { details: errorBody.details || {}, originalError: error, httpStatus, retryable, timestamp }); } // Network errors else if (error instanceof TypeError && error.message.includes('network')) { return new YnkapError(ErrorCategory.NETWORK, 'Network error: Could not connect to Y-Nkap API', { originalError: error, retryable: true, retryAfterMs: 3000, timestamp }); } // Other errors else { return new YnkapError(ErrorCategory.UNKNOWN, error?.message || 'An unknown error occurred', { originalError: error, retryable: true, details: { context }, timestamp }); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ErrorHandlingService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return []; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItaGFuZGxpbmcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3lua2FwL3NyYy9saWIvZXJyb3ItaGFuZGxpbmcvZXJyb3ItaGFuZGxpbmcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0RSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUMsT0FBTyxFQUFFLGFBQWEsRUFBZ0IsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7O0FBSy9FLE1BQU0sT0FBTyxvQkFBb0I7SUFlL0I7UUFkUSxpQkFBWSxHQUFHLElBQUksZUFBZSxDQUFvQixJQUFJLENBQUMsQ0FBQztRQUVwRSx3QkFBd0I7UUFDaEIsd0JBQW1CLEdBQWlCO1lBQzFDLFVBQVUsRUFBRSxDQUFDO1lBQ2IsV0FBVyxFQUFFLElBQUk7WUFDakIsVUFBVSxFQUFFLEtBQUs7WUFDakIsa0JBQWtCLEVBQUU7Z0JBQ2xCLGFBQWEsQ0FBQyxjQUFjO2dCQUM1QixhQUFhLENBQUMsYUFBYTtnQkFDM0IsYUFBYSxDQUFDLFVBQVU7YUFDekI7U0FDRixDQUFDO0lBRWEsQ0FBQztJQUVoQixXQUFXLENBQUMsS0FBVTtRQUNwQixJQUFJLFVBQXNCLENBQUM7UUFFM0IsSUFBSSxLQUFLLFlBQVksVUFBVSxFQUFFO1lBQy9CLFVBQVUsR0FBRyxLQUFLLENBQUM7U0FDcEI7YUFBTTtZQUNMLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FDekIsS0FBSyxDQUFDLElBQUksSUFBSSxlQUFlLEVBQzdCLEtBQUssQ0FBQyxPQUFPLElBQUksb0NBQW9DLEVBQ3JELEtBQUssQ0FBQyxPQUFPLENBQ2QsQ0FBQztTQUNIO1FBRUQs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QUFFLElBQUk7Z0JBQ2IsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFO2dCQUNwQixTQUFTO2FBQ1YsQ0FDRixDQUFDO1NBQ0g7SUFDSCxDQUFDOytHQWpLVSxvQkFBb0I7bUhBQXBCLG9CQUFvQixjQUZuQixNQUFNOzs0RkFFUCxvQkFBb0I7a0JBSGhDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCB0aHJvd0Vycm9yLCB0aW1lciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWVyZ2VNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBFcnJvckNhdGVnb3J5LCBSZXRyeU9wdGlvbnMsIFlua2FwRXJyb3IgfSBmcm9tICcuL21vZGVscy9lcnJvci5tb2RlbCc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIEVycm9ySGFuZGxpbmdTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBlcnJvclN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFlua2FwRXJyb3IgfCBudWxsPihudWxsKTtcbiAgXG4gIC8vIERlZmF1bHQgcmV0cnkgb3B0aW9uc1xuICBwcml2YXRlIGRlZmF1bHRSZXRyeU9wdGlvbnM6IFJldHJ5T3B0aW9ucyA9IHtcbiAgICBtYXhSZXRyaWVzOiAzLFxuICAgIGJhc2VEZWxheU1zOiAxMDAwLFxuICAgIG1heERlbGF5TXM6IDEwMDAwLFxuICAgIG5vblJldHJ5YWJsZUVycm9yczogW1xuICAgICAgRXJyb3JDYXRlZ29yeS5BVVRIRU5USUNBVElPTixcbiAgICAgIEVycm9yQ2F0ZWdvcnkuQVVUSE9SSVpBVElPTixcbiAgICAgIEVycm9yQ2F0ZWdvcnkuVkFMSURBVElPTlxuICAgIF1cbiAgfTtcblxuICBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgaGFuZGxlRXJyb3IoZXJyb3I6IGFueSk6IHZvaWQge1xuICAgIGxldCB5bmthcEVycm9yOiBZbmthcEVycm9yO1xuXG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgWW5rYXBFcnJvcikge1xuICAgICAgeW5rYXBFcnJvciA9IGVycm9yO1xuICAgIH0gZWxzZSB7XG4gICAgICB5bmthcEVycm9yID0gbmV3IFlua2FwRXJyb3IoXG4gICAgICAgIGVycm9yLmNvZGUgfHwgJ1VOS05PV05fRVJST1InLFxuICAgICAgICBlcnJvci5tZXNzYWdlIHx8ICdVbmUgZXJyZXVyIGluYXR0ZW5kdWUgZXN0IHN1cnZlbnVlJyxcbiAgICAgICAgZXJyb3IuZGV0YWlsc1xuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmVycm9yU3ViamVjdC5uZXh0KHlua2FwRXJyb3IpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ1ktTmthcCBFcnJvcjonLCB5bmthcEVycm9yKTtcbiAgfVxuXG4gIGdldEVycm9yKCk6IE9ic2VydmFibGU8WW5rYXBFcnJvciB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5lcnJvclN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBjbGVhckVycm9yKCk6IHZvaWQge1xuICAgIHRoaXMuZXJyb3JTdWJqZWN0Lm5leHQobnVsbCk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbHkgcmV0cnkgbG9naWMgd2l0aCBleHBvbmVudGlhbCBiYWNrb2ZmIGZvciBmYWlsZWQgb3BlcmF0aW9uc1xuICAgKiBAcGFyYW0gZXJyb3IgVGhlIGVycm9yIHRoYXQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHJldHJ5Rm4gRnVuY3Rpb24gdG8gcmV0cnlcbiAgICogQHBhcmFtIG9wdGlvbnMgUmV0cnkgb3B0aW9uc1xuICAgKiBAcmV0dXJucyBBbiBvYnNlcnZhYmxlIHRoYXQgd2lsbCByZXRyeSB0aGUgb3BlcmF0aW9uXG4gICAqL1xuICByZXRyeVdpdGhCYWNrb2ZmPFQ+KGVycm9yOiBZbmthcEVycm9yLCByZXRyeUZuOiAoKSA9PiBPYnNlcnZhYmxlPFQ+LCBvcHRpb25zPzogUGFydGlhbDxSZXRyeU9wdGlvbnM+KTogT2JzZXJ2YWJsZTxUPiB7XG4gICAgY29uc3QgcmV0cnlPcHRzOiBSZXRyeU9wdGlvbnMgPSB7IC4uLnRoaXMuZGVmYXVsdFJldHJ5T3B0aW9ucywgLi4ub3B0aW9ucyB9O1xuICAgIFxuICAgIC8vIENoZWNrIGlmIGVycm9yIGlzIHJldHJ5YWJsZVxuICAgIGlmICghZXJyb3IucmV0cnlhYmxlKSB7XG4gICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgfVxuICAgIFxuICAgIC8vIENoZWNrIGlmIHRoZSBlcnJvciB0eXBlIGlzIGluIHRoZSBub24tcmV0cnlhYmxlIGxpc3RcbiAgICBpZiAocmV0cnlPcHRzLm5vblJldHJ5YWJsZUVycm9ycz8uaW5jbHVkZXMoZXJyb3IuY29kZSkpIHtcbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgd2UndmUgZXhjZWVkZWQgbWF4IHJldHJpZXNcbiAgICBjb25zdCBhdHRlbXB0TnVtYmVyID0gKGVycm9yLmRldGFpbHM/LmF0dGVtcHROdW1iZXIgfHwgMCkgKyAxO1xuICAgIGlmIChhdHRlbXB0TnVtYmVyID4gcmV0cnlPcHRzLm1heFJldHJpZXMpIHtcbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2FsY3VsYXRlIGJhY2tvZmYgZGVsYXkgd2l0aCBleHBvbmVudGlhbCBpbmNyZWFzZVxuICAgIGNvbnN0IGRlbGF5TXMgPSBNYXRoLm1pbihcbiAgICAgIHJldHJ5T3B0cy5iYXNlRGVsYXlNcyAqIE1hdGgucG93KDIsIGF0dGVtcHROdW1iZXIgLSAxKSxcbiAgICAgIHJldHJ5T3B0cy5tYXhEZWxheU1zXG4gICAgKTtcbiAgICBcbiAgICAvLyBDYWxsIHRoZSBvblJldHJ5IGNhbGxiYWNrIGlmIHByb3ZpZGVkXG4gICAgaWYgKHJldHJ5T3B0cy5vblJldHJ5KSB7XG4gICAgICByZXRyeU9wdHMub25SZXRyeShlcnJvciwgYXR0ZW1wdE51bWJlcik7XG4gICAgfVxuICAgIFxuICAgIC8vIFVwZGF0ZSBhdHRlbXB0IG51bWJlciBpbiBlcnJvciBkZXRhaWxzXG4gICAgZXJyb3IuZGV0YWlscyA9IHsgLi4uZXJyb3IuZGV0YWlscywgYXR0ZW1wdE51bWJlciB9O1xuICAgIFxuICAgIC8vIFdhaXQgZm9yIHRoZSBkZWxheSB0aGVuIHJldHJ5XG4gICAgcmV0dXJuIHRpbWVyKGRlbGF5TXMpLnBpcGUoXG4gICAgICBtZXJnZU1hcCgoKSA9PiByZXRyeUZuKCkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFueSBlcnJvciB0byBhIHN0YW5kYXJkaXplZCBZbmthcEVycm9yXG4gICAqIEBwYXJhbSBlcnJvciBUaGUgZXJyb3IgdG8gY29udmVydFxuICAgKiBAcGFyYW0gY29udGV4dCBPcHRpb25hbCBjb250ZXh0IGluZm9ybWF0aW9uXG4gICAqIEByZXR1cm5zIEEgc3RhbmRhcmRpemVkIFlua2FwRXJyb3JcbiAgICovXG4gIHByaXZhdGUgY29udmVydFRvWW5rYXBFcnJvcihlcnJvcjogYW55LCBjb250ZXh0Pzogc3RyaW5nKTogWW5rYXBFcnJvciB7XG4gICAgY29uc3QgdGltZXN0YW1wID0gbmV3IERhdGUoKTtcbiAgICAvLyBIVFRQIGVycm9yc1xuICAgIGlmIChlcnJvciAmJiBlcnJvci5zdGF0dXMpIHtcbiAgICAgIGNvbnN0IGh0dHBTdGF0dXMgPSBlcnJvci5zdGF0dXM7XG4gICAgICBjb25zdCBlcnJvckJvZHkgPSBlcnJvci5lcnJvciB8fCB7fTtcbiAgICAgIGxldCBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeTtcbiAgICAgIGxldCByZXRyeWFibGUgPSBmYWxzZTtcbiAgICAgIHN3aXRjaCAodHJ1ZSkge1xuICAgICAgICBjYXNlIGh0dHBTdGF0dXMgPT09IDQwMTpcbiAgICAgICAgICBjYXRlZ29yeSA9IEVycm9yQ2F0ZWdvcnkuQVVUSEVOVElDQVRJT047XG4gICAgICAgICAgcmV0cnlhYmxlID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgaHR0cFN0YXR1cyA9PT0gNDAzOlxuICAgICAgICAgIGNhdGVnb3J5ID0gRXJyb3JDYXRlZ29yeS5BVVRIT1JJWkFUSU9OO1xuICAgICAgICAgIHJldHJ5YWJsZSA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIGh0dHBTdGF0dXMgPj0gNDAwICYmIGh0dHBTdGF0dXMgPCA1MDA6XG4gICAgICAgICAgY2F0ZWdvcnkgPSBFcnJvckNhdGVnb3J5LlZBTElEQVRJT047XG4gICAgICAgICAgcmV0cnlhYmxlID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgaHR0cFN0YXR1cyA+PSA1MDA6XG4gICAgICAgICAgY2F0ZWdvcnkgPSBFcnJvckNhdGVnb3J5LlNFUlZFUjtcbiAgICAgICAgICByZXRyeWFibGUgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGNhdGVnb3J5ID0gRXJyb3JDYXRlZ29yeS5VTktOT1dOO1xuICAgICAgICAgIHJldHJ5YWJsZSA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFlua2FwRXJyb3IoXG4gICAgICAgIGVycm9yQm9keS5jb2RlIHx8IGNhdGVnb3J5LFxuICAgICAgICBlcnJvckJvZHkubWVzc2FnZSB8fCBgRXJyb3IgJHtodHRwU3RhdHVzfTogJHtlcnJvci5zdGF0dXNUZXh0IHx8ICdVbmtub3duIEhUVFAgZXJyb3InfWAsXG4gICAgICAgIHtcbiAgICAgICAgZGV0YWlsczogZXJyb3JCb2R5LmRldGFpbHMgfHwge30sXG4gICAgICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yLFxuICAgICAgICBodHRwU3RhdHVzLFxuICAgICAgICAgIHJldHJ5YWJsZSxcbiAgICAgICAgICB0aW1lc3RhbXBcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IFxuICAgIC8vIE5ldHdvcmsgZXJyb3JzXG4gICAgZWxzZSBpZiAoZXJyb3IgaW5zdGFuY2VvZiBUeXBlRXJyb3IgJiYgZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnbmV0d29yaycpKSB7XG4gICAgICByZXR1cm4gbmV3IFlua2FwRXJyb3IoXG4gICAgICAgIEVycm9yQ2F0ZWdvcnkuTkVUV09SSyxcbiAgICAgICAgJ05ldHdvcmsgZXJyb3I6IENvdWxkIG5vdCBjb25uZWN0IHRvIFktTmthcCBBUEknLFxuICAgICAgICB7XG4gICAgICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yLFxuICAgICAgICByZXRyeWFibGU6IHRydWUsXG4gICAgICAgICAgcmV0cnlBZnRlck1zOiAzMDAwLFxuICAgICAgICAgIHRpbWVzdGFtcFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0gXG4gICAgLy8gT3RoZXIgZXJyb3JzXG4gICAgZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IFlua2FwRXJyb3IoXG4gICAgICAgIEVycm9yQ2F0ZWdvcnkuVU5LTk9XTixcbiAgICAgICAgZXJyb3I/Lm1lc3NhZ2UgfHwgJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnLFxuICAgICAgICB7XG4gICAgICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yLFxuICAgICAgICByZXRyeWFibGU6IHRydWUsXG4gICAgICAgICAgZGV0YWlsczogeyBjb250ZXh0IH0sXG4gICAgICAgICAgdGltZXN0YW1wXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iXX0=