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
JavaScript
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=