@@ -185,6 +185,7 @@ module ProcessOut {
185185 if ( ! container ) {
186186 throw new Exception ( "processout-js.undefined-field" , `The card field for the ${ options . type } does not exist in the given container.` ) ;
187187 }
188+
188189 if ( container instanceof HTMLInputElement ) {
189190 throw new Exception ( "processout-js.invalid-field" , `The card field for the ${ options . type } must be an input field.` ) ;
190191 }
@@ -209,6 +210,23 @@ module ProcessOut {
209210 this . spawn ( success , error ) ;
210211 }
211212
213+
214+ private postMessage ( message : any , retries : number = 3 , delay : number = 50 ) : void {
215+ if ( retries <= 0 ) {
216+ throw new Exception ( "processout-js.field.unavailable" , "Tried to locate the iframe content window but failed." ) ;
217+ }
218+
219+ if ( ! this . iframe || ! this . iframe . contentWindow ) {
220+ setTimeout ( ( ) => this . postMessage ( message , retries - 1 , delay ) , delay ) ;
221+ return ;
222+ }
223+
224+ try {
225+ this . iframe . contentWindow . postMessage ( message , "*" ) ;
226+ } catch ( e ) {
227+ throw new Exception ( "processout-js.field.unavailable" , "Iframe content window found but failed to post message: " + e . message ) ;
228+ }
229+ }
212230 /**
213231 * Spawn spawns the iframe used to embed the field
214232 * @param {callback } success
@@ -248,7 +266,9 @@ module ProcessOut {
248266 // Firefox from (wrongfully) caching the iframe
249267 // content: https://bugzilla.mozilla.org/show_bug.cgi?id=354176
250268 if ( navigator . userAgent . match ( / f i r e f o x | f x i o s / i) ) {
251- this . iframe . contentWindow . location . replace ( endpoint ) ;
269+ if ( this . iframe && this . iframe . contentWindow ) {
270+ this . iframe . contentWindow . location . replace ( endpoint ) ;
271+ }
252272 }
253273 } catch ( e ) { /* ... */ }
254274 } . bind ( this ) ;
@@ -274,14 +294,15 @@ module ProcessOut {
274294 // and the iframe should reply with a ready state
275295
276296 if ( data . action == "alive" ) {
297+
277298 // The field's iframe is available, let's set it up
278- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
299+ this . postMessage ( JSON . stringify ( {
279300 "namespace" : Message . fieldNamespace ,
280301 "projectID" : this . instance . getProjectID ( ) ,
281302 "action" : "setup" ,
282303 "formID" : this . form . getUID ( ) ,
283304 "data" : this . options
284- } ) , "*" ) ;
305+ } ) ) ;
285306 }
286307
287308 if ( data . action == "ready" ) {
@@ -293,17 +314,17 @@ module ProcessOut {
293314 // Finally we also want to request for a resize, as some
294315 // browser fail to compute the height of the iframe
295316 // if it isn't displayed yet
296- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
317+ this . postMessage ( JSON . stringify ( {
297318 "namespace" : Message . fieldNamespace ,
298319 "projectID" : this . instance . getProjectID ( ) ,
299320 "action" : "resize"
300- } ) , "*" ) ;
321+ } ) ) ;
301322
302323 // Hook an event listener for the focus event to focus
303324 // on the input when the user presses tab on older
304325 // browser: otherwise the iframe would get focused, but
305326 // not the field within it (hello IE)
306- this . iframe . addEventListener ( "focus" , function ( event ) {
327+ this . iframe . addEventListener ( "focus" , function ( ) {
307328 this . focus ( ) ;
308329 } . bind ( this ) ) ;
309330 }
@@ -364,8 +385,13 @@ module ProcessOut {
364385 case "event" :
365386 if ( data . data . name in this . handlers ) {
366387 var handlers = this . handlers [ data . data . name ] ;
367- for ( var i = 0 ; i < handlers . length ; i ++ )
368- handlers [ 0 ] ( data . data . data ) ;
388+ for ( var i = 0 ; i < handlers . length ; i ++ ) {
389+ try {
390+ handlers [ 0 ] ( data . data . data ) ;
391+ } catch ( e ) {
392+ // ignoring errors that come from the merchant's codebase
393+ }
394+ }
369395 }
370396 break ;
371397 case "resize" :
@@ -399,12 +425,12 @@ module ProcessOut {
399425 this . options . style = ( < any > Object ) . assign (
400426 this . options . style , options . style ) ;
401427
402- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
428+ this . postMessage ( JSON . stringify ( {
403429 "namespace" : Message . fieldNamespace ,
404430 "projectID" : this . instance . getProjectID ( ) ,
405431 "action" : "update" ,
406432 "data" : this . options
407- } ) , "*" ) ;
433+ } ) ) ;
408434 }
409435
410436 /**
@@ -419,12 +445,12 @@ module ProcessOut {
419445 this . handlers [ e ] = [ ] ;
420446
421447 this . handlers [ e ] . push ( h ) ;
422- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
448+ this . postMessage ( JSON . stringify ( {
423449 "namespace" : Message . fieldNamespace ,
424450 "projectID" : this . instance . getProjectID ( ) ,
425451 "action" : "registerEvent" ,
426452 "data" : e
427- } ) , "*" ) ;
453+ } ) ) ;
428454 }
429455
430456 /**
@@ -442,25 +468,25 @@ module ProcessOut {
442468 * @return {void }
443469 */
444470 public blur ( ) : void {
445- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
471+ this . postMessage ( JSON . stringify ( {
446472 "messageID" : Math . random ( ) . toString ( ) ,
447473 "namespace" : Message . fieldNamespace ,
448474 "projectID" : this . instance . getProjectID ( ) ,
449475 "action" : "blur"
450- } ) , "*" ) ;
476+ } ) ) ;
451477 }
452478
453479 /**
454480 * focus focuses on the card field
455481 * @return {void }
456482 */
457483 public focus ( ) : void {
458- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
484+ this . postMessage ( JSON . stringify ( {
459485 "messageID" : Math . random ( ) . toString ( ) ,
460486 "namespace" : Message . fieldNamespace ,
461487 "projectID" : this . instance . getProjectID ( ) ,
462488 "action" : "focus"
463- } ) , "*" ) ;
489+ } ) ) ;
464490 }
465491
466492 /**
@@ -474,12 +500,12 @@ module ProcessOut {
474500 var id = Math . random ( ) . toString ( ) ;
475501
476502 // Ask the iframe for its value
477- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
503+ this . postMessage ( JSON . stringify ( {
478504 "messageID" : id ,
479505 "namespace" : Message . fieldNamespace ,
480506 "projectID" : this . instance . getProjectID ( ) ,
481507 "action" : "validate"
482- } ) , "*" ) ;
508+ } ) ) ;
483509
484510 // Our timeout, just in case
485511 var fetchingTimeout =
@@ -523,7 +549,7 @@ module ProcessOut {
523549 // Tell our field it should start the tokenization process and
524550 // expect a response
525551 var id = Math . random ( ) . toString ( ) ;
526- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
552+ this . postMessage ( JSON . stringify ( {
527553 "messageID" : id ,
528554 "namespace" : Message . fieldNamespace ,
529555 "projectID" : this . instance . getProjectID ( ) ,
@@ -532,7 +558,7 @@ module ProcessOut {
532558 "fields" : fields ,
533559 "data" : data
534560 }
535- } ) , "*" ) ;
561+ } ) ) ;
536562
537563 // Our timeout, just in case
538564 var fetchingTimeout =
@@ -571,13 +597,13 @@ module ProcessOut {
571597 // Tell our field it should start the tokenization process and
572598 // expect a response
573599 var id = Math . random ( ) . toString ( ) ;
574- this . iframe . contentWindow . postMessage ( JSON . stringify ( {
600+ this . postMessage ( JSON . stringify ( {
575601 "messageID" : id ,
576602 "namespace" : Message . fieldNamespace ,
577603 "projectID" : this . instance . getProjectID ( ) ,
578604 "action" : "refresh-cvc" ,
579605 "data" : cardUID
580- } ) , "*" ) ;
606+ } ) ) ;
581607
582608 // Our timeout, just in case
583609 var fetchingTimeout =
0 commit comments