@@ -6,26 +6,75 @@ module ProcessOut {
66 }
77
88 export class APMViewRedirect extends APMViewImpl < RedirectProps > {
9+ /** After a retryable headless error (e.g. pop-up blocked), show the normal Pay / Cancel UI. */
10+ private headlessManualFallback = false
11+
12+ styles = css `
13+ .redirect-headless-loading {
14+ justify-content : center;
15+ align-items : center;
16+ flex-direction : column;
17+ gap : 8px ;
18+ min-height : 120px ;
19+ }
20+ `
21+
22+ protected componentDidMount ( ) : void {
23+ const headless = ContextImpl . context . redirect && ContextImpl . context . redirect . enableHeadlessMode
24+ if ( headless && ! this . headlessManualFallback ) {
25+ this . handleRedirectClick ( )
26+ }
27+ }
28+
929 handleRedirectClick ( ) {
1030 ContextImpl . context . events . emit ( 'redirect-initiated' )
31+ const pm = this . props . config . payment_method
32+ const actionOptions = pm
33+ ? new ActionHandlerOptions (
34+ pm . gateway_name . toLowerCase ( ) ,
35+ pm . logo && pm . logo . light_url ? pm . logo . light_url . raster : undefined ,
36+ )
37+ : undefined
1138 ContextImpl . context . poClient . handleAction (
12- this . props . config . redirect . url ,
39+ this . props . config . redirect . url ,
1340 ( ) => {
1441 ContextImpl . context . events . emit ( 'redirect-completed' )
1542 ContextImpl . context . page . load ( APIImpl . getCurrentStep )
1643 } ,
1744 ( err ) => {
18- ContextImpl . context . events . emit ( 'failure' , {
19- failure : {
20- message : err . message ,
21- code : err . code
45+ const failure = {
46+ message : err . message ,
47+ code : err . code ,
48+ }
49+ const headless = ContextImpl . context . redirect && ContextImpl . context . redirect . enableHeadlessMode
50+ if ( headless ) {
51+ if (
52+ ! this . headlessManualFallback &&
53+ ( failure . code === 'customer.popup-blocked' || failure . code === 'customer.canceled' )
54+ ) {
55+ this . headlessManualFallback = true
56+ this . forceUpdate ( )
57+ return
2258 }
23- } )
24- }
59+ ContextImpl . context . page . criticalFailure ( {
60+ title : 'Could not open payment' ,
61+ code : failure . code ,
62+ message : failure . message ,
63+ } )
64+ return
65+ }
66+ ContextImpl . context . events . emit ( 'failure' , { failure } )
67+ } ,
68+ actionOptions ,
2569 )
2670 }
2771
2872 render ( ) {
73+ const headless = ContextImpl . context . redirect && ContextImpl . context . redirect . enableHeadlessMode
74+ if ( headless && ! this . headlessManualFallback ) {
75+ return page ( { className : 'redirect-headless-loading' } , Loader ( ) )
76+ }
77+
2978 const redirectLabel = `Pay ${ formatCurrency ( this . props . config . invoice . amount , this . props . config . invoice . currency ) } ` ;
3079 return (
3180 Main ( {
0 commit comments