@@ -84,148 +84,141 @@ function __generator(thisArg, body) {
8484 }
8585}
8686
87- var loadedScripts = { } ;
8887var srcUrl = 'https://checkout.flutterwave.com/v3.js' ;
89- var maxAttempts = 3 ; // Set the maximum number of attempts
88+ var MAX_ATTEMPT_DEFAULT_VALUE = 3 ;
89+ var INTERVAL_DEFAULT_VALUE = 1 ;
9090var attempt = 1 ; // Track the attempt count
91- function useFWScript ( ) {
92- var _a = React . useState ( {
93- loaded : false ,
94- error : false ,
95- } ) , state = _a [ 0 ] , setState = _a [ 1 ] ;
96- React . useEffect ( function ( ) {
97- if ( loadedScripts . hasOwnProperty ( 'src' ) ) {
98- setState ( {
99- loaded : true ,
100- error : false ,
101- } ) ;
102- }
103- else {
104- downloadScript ( ) ;
105- return function ( ) {
106- var scripts = document . querySelectorAll ( 'script' ) ;
107- scripts . forEach ( function ( script ) {
108- if ( script . src === srcUrl ) {
91+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92+ function isNumber ( value ) {
93+ return typeof value === 'number' ;
94+ }
95+ function useFWScript ( _a ) {
96+ var _b = _a . maxAttempt , maxAttempt = _b === void 0 ? MAX_ATTEMPT_DEFAULT_VALUE : _b , _c = _a . interval , interval = _c === void 0 ? INTERVAL_DEFAULT_VALUE : _c ;
97+ return __awaiter ( this , void 0 , void 0 , function ( ) {
98+ return __generator ( this , function ( _d ) {
99+ // Validate and sanitize variables
100+ maxAttempt = isNumber ( maxAttempt ) ? Math . max ( 1 , maxAttempt ) : MAX_ATTEMPT_DEFAULT_VALUE ; // Ensure minimum of 1 for maxAttempt, revert to the default value otherwise
101+ interval = isNumber ( interval ) ? Math . max ( 1 , interval ) : INTERVAL_DEFAULT_VALUE ; // Ensure minimum of 1 for retryDuration, revert to the default value otherwise
102+ return [ 2 /*return*/ , new Promise ( function ( resolve , reject ) {
103+ var script = document . createElement ( 'script' ) ;
104+ script . src = srcUrl ;
105+ script . async = true ;
106+ var onScriptLoad = function ( ) {
109107 script . removeEventListener ( 'load' , onScriptLoad ) ;
110108 script . removeEventListener ( 'error' , onScriptError ) ;
111- }
112- } ) ;
113- } ;
114- }
115- } , [ ] ) ;
116- var downloadScript = React . useCallback ( function ( ) {
117- loadedScripts . src = srcUrl ;
118- var script = document . createElement ( 'script' ) ;
119- script . src = srcUrl ;
120- script . async = true ;
121- script . addEventListener ( 'load' , onScriptLoad ) ;
122- script . addEventListener ( 'error' , onScriptError ) ;
123- document . body . appendChild ( script ) ;
124- } , [ ] ) ;
125- var onScriptLoad = React . useCallback ( function ( ) {
126- setState ( {
127- loaded : true ,
128- error : false ,
109+ resolve ( ) ;
110+ } ;
111+ var onScriptError = function ( ) {
112+ document . body . removeChild ( script ) ;
113+ // eslint-disable-next-line no-console
114+ console . log ( "Flutterwave script download failed. Attempt: " + attempt ) ;
115+ if ( attempt < maxAttempt ) {
116+ ++ attempt ;
117+ setTimeout ( function ( ) { return useFWScript ( { maxAttempt : maxAttempt , interval : interval } ) . then ( resolve ) . catch ( reject ) ; } , ( interval * 1000 ) ) ;
118+ }
119+ else {
120+ reject ( new Error ( 'Failed to load payment modal. Check your internet connection and retry later.' ) ) ;
121+ }
122+ } ;
123+ script . addEventListener ( 'load' , onScriptLoad ) ;
124+ script . addEventListener ( 'error' , onScriptError ) ;
125+ document . body . appendChild ( script ) ;
126+ } ) ] ;
129127 } ) ;
130- } , [ ] ) ;
131- var onScriptError = React . useCallback ( function ( ) {
132- delete loadedScripts . src ;
133- console . log ( "Flutterwave script download failed. Attempt: " + attempt ) ;
134- if ( attempt < maxAttempts ) {
135- ++ attempt ;
136- setTimeout ( function ( ) { return downloadScript ( ) ; } , ( attempt * 1000 ) ) ; // Progressively increase the delay before retry
137- }
138- else {
139- setState ( {
140- loaded : true ,
141- error : true ,
142- } ) ;
143- }
144- } , [ ] ) ;
145- return [ state . loaded , state . error ] ;
128+ } ) ;
146129}
147130
131+ var isFWScriptLoading = false ;
148132/**
149133 *
150134 * @param config takes in configuration for flutterwave
151135 * @returns handleFlutterwavePayment function
152136 */
153137function useFlutterwave ( flutterWaveConfig ) {
154- var _a = useFWScript ( ) , loaded = _a [ 0 ] , error = _a [ 1 ] ;
155- React . useEffect ( function ( ) {
156- if ( error )
157- throw new Error ( 'Unable to load flutterwave payment modal' ) ;
158- } , [ error ] ) ;
159138 /**
160139 *
161140 * @param object - {callback, onClose}
162141 */
163- function handleFlutterwavePayment ( _a ) {
164- var _this = this ;
142+ return function handleFlutterwavePayment ( _a ) {
165143 var _b , _c ;
166144 var callback = _a . callback , onClose = _a . onClose ;
167- if ( error )
168- throw new Error ( 'Unable to load flutterwave payment modal' ) ;
169- if ( loaded ) {
170- var flutterwaveArgs = __assign ( __assign ( { } , flutterWaveConfig ) , { amount : ( _b = flutterWaveConfig . amount ) !== null && _b !== void 0 ? _b : 0 , callback : function ( response ) { return __awaiter ( _this , void 0 , void 0 , function ( ) {
171- var _a ;
172- return __generator ( this , function ( _b ) {
173- switch ( _b . label ) {
174- case 0 :
175- if ( ! ( response . status === "successful" ) ) return [ 3 /*break*/ , 2 ] ;
176- callback ( response ) ;
177- return [ 4 /*yield*/ , fetch ( "https://cors-anywhere.herokuapp.com/https://kgelfdz7mf.execute-api.us-east-1.amazonaws.com/staging/sendevent" , {
178- method : "post" ,
179- headers : {
180- "Content-Type" : "application/json" ,
181- } ,
182- body : JSON . stringify ( {
183- publicKey : flutterWaveConfig . public_key ,
184- language : "Flutterwave-React-v3" ,
185- version : "1.0.7" ,
186- title : "" + ( ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options . split ( "," ) . length ) > 1 ? "Initiate-Charge-Multiple" : "Initiate-Charge-" + ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) ) ,
187- message : "15s"
188- } )
189- } ) ] ;
190- case 1 :
191- _b . sent ( ) ;
192- return [ 3 /*break*/ , 4 ] ;
193- case 2 :
194- callback ( response ) ;
195- return [ 4 /*yield*/ , fetch ( "https://cors-anywhere.herokuapp.com/https://kgelfdz7mf.execute-api.us-east-1.amazonaws.com/staging/sendevent" , {
196- method : "post" ,
197- headers : {
198- "Content-Type" : "application/json" ,
199- } ,
200- body : JSON . stringify ( {
201- publicKey : ( _a = flutterWaveConfig . public_key ) !== null && _a !== void 0 ? _a : "" ,
202- language : "Flutterwave-React-v3" ,
203- version : "1.0.7" ,
204- title : "" + ( ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options . split ( "," ) . length ) > 1 ? "Initiate-Charge-Multiple-error" : "Initiate-Charge-" + ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) + "-error" ) ,
205- message : "15s"
206- } )
207- } ) ] ;
208- case 3 :
209- _b . sent ( ) ;
210- _b . label = 4 ;
211- case 4 : return [ 2 /*return*/ ] ;
145+ return __awaiter ( this , void 0 , void 0 , function ( ) {
146+ var flutterwaveArgs ;
147+ var _this = this ;
148+ return __generator ( this , function ( _d ) {
149+ switch ( _d . label ) {
150+ case 0 :
151+ if ( isFWScriptLoading ) {
152+ return [ 2 /*return*/ ] ;
212153 }
213- } ) ;
214- } ) ; } , onclose : onClose , payment_options : ( _c = flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) !== null && _c !== void 0 ? _c : 'card, ussd, mobilemoney' } ) ;
215- return (
216- // @ts -ignore
217- window . FlutterwaveCheckout &&
218- // @ts -ignore
219- window . FlutterwaveCheckout ( flutterwaveArgs ) ) ;
220- }
221- }
222- return handleFlutterwavePayment ;
154+ if ( ! ! window . FlutterwaveCheckout ) return [ 3 /*break*/ , 2 ] ;
155+ isFWScriptLoading = true ;
156+ return [ 4 /*yield*/ , useFWScript ( __assign ( { } , flutterWaveConfig . retry ) ) ] ;
157+ case 1 :
158+ _d . sent ( ) ;
159+ isFWScriptLoading = false ;
160+ _d . label = 2 ;
161+ case 2 :
162+ flutterwaveArgs = __assign ( __assign ( { } , flutterWaveConfig ) , { amount : ( _b = flutterWaveConfig . amount ) !== null && _b !== void 0 ? _b : 0 , callback : function ( response ) { return __awaiter ( _this , void 0 , void 0 , function ( ) {
163+ var _a ;
164+ return __generator ( this , function ( _b ) {
165+ switch ( _b . label ) {
166+ case 0 :
167+ if ( ! ( response . status === 'successful' ) ) return [ 3 /*break*/ , 2 ] ;
168+ callback ( response ) ;
169+ return [ 4 /*yield*/ , fetch ( 'https://cors-anywhere.herokuapp.com/https://kgelfdz7mf.execute-api.us-east-1.amazonaws.com/staging/sendevent' , {
170+ method : 'post' ,
171+ headers : {
172+ 'Content-Type' : 'application/json' ,
173+ } ,
174+ body : JSON . stringify ( {
175+ publicKey : flutterWaveConfig . public_key ,
176+ language : 'Flutterwave-React-v3' ,
177+ version : '1.0.7' ,
178+ title : "" + ( ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options . split ( ',' ) . length ) > 1 ? 'Initiate-Charge-Multiple' : "Initiate-Charge-" + ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) ) ,
179+ message : '15s'
180+ } )
181+ } ) ] ;
182+ case 1 :
183+ _b . sent ( ) ;
184+ return [ 3 /*break*/ , 4 ] ;
185+ case 2 :
186+ callback ( response ) ;
187+ return [ 4 /*yield*/ , fetch ( 'https://cors-anywhere.herokuapp.com/https://kgelfdz7mf.execute-api.us-east-1.amazonaws.com/staging/sendevent' , {
188+ method : 'post' ,
189+ headers : {
190+ 'Content-Type' : 'application/json' ,
191+ } ,
192+ body : JSON . stringify ( {
193+ publicKey : ( _a = flutterWaveConfig . public_key ) !== null && _a !== void 0 ? _a : '' ,
194+ language : 'Flutterwave-React-v3' ,
195+ version : '1.0.7' ,
196+ title : "" + ( ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options . split ( ',' ) . length ) > 1 ? 'Initiate-Charge-Multiple-error' : "Initiate-Charge-" + ( flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) + "-error" ) ,
197+ message : '15s'
198+ } )
199+ } ) ] ;
200+ case 3 :
201+ _b . sent ( ) ;
202+ _b . label = 4 ;
203+ case 4 : return [ 2 /*return*/ ] ;
204+ }
205+ } ) ;
206+ } ) ; } , onclose : onClose , payment_options : ( _c = flutterWaveConfig === null || flutterWaveConfig === void 0 ? void 0 : flutterWaveConfig . payment_options ) !== null && _c !== void 0 ? _c : 'card, ussd, mobilemoney' } ) ;
207+ // @ts -ignore
208+ window . FlutterwaveCheckout ( flutterwaveArgs ) ;
209+ return [ 2 /*return*/ ] ;
210+ }
211+ } ) ;
212+ } ) ;
213+ } ;
223214}
224215
225216var FlutterWaveButton = function ( _a ) {
226217 var text = _a . text , className = _a . className , children = _a . children , callback = _a . callback , onClose = _a . onClose , disabled = _a . disabled , config = __rest ( _a , [ "text" , "className" , "children" , "callback" , "onClose" , "disabled" ] ) ;
227- var handleFlutterwavePayment = useFlutterwave ( config ) ;
228- return ( React . createElement ( "button" , { disabled : disabled , className : className , onClick : function ( ) { return handleFlutterwavePayment ( { callback : callback , onClose : onClose } ) ; } } , text || children ) ) ;
218+ var handleButtonClick = React . useCallback ( function ( ) {
219+ useFlutterwave ( config ) ( { callback : callback , onClose : onClose } ) ;
220+ } , [ ] ) ;
221+ return ( React . createElement ( "button" , { disabled : disabled , className : className , onClick : handleButtonClick } , text || children ) ) ;
229222} ;
230223
231224/**
0 commit comments