PageSourceSearch

https://www.samen-gernand.de/plugins/xt_paypal_checkout/javascript…?209e94b8bcb1a0ca6d26050b7d1c1d3b

js samen-gernand.de collected 2026-09-26 14:46:07 UTC 73,177 bytes, 1,770 lines download raw bytes

1console.log('xt_paypal_checkout.js');
2
3let previousCountryCode = "";
4let operation = "add";
5let count = 0;
6
7const ppc_button_selector = '#paypal_button_container';
8
9function enableFoundingSources() {
10    if (window.paypal && window.paypal.Buttons) {
11        try {
12            paypal.getFundingSources().forEach(function (fundingSource) {
13                console.log(fundingSource, paypal.isFundingEligible(fundingSource));
14
15                if (paypal.isFundingEligible(fundingSource)) {
16                    let isApplepay = false;
17                    let isApplepayAvail = false;
18                    if (fundingSource === 'applepay') {
19                        isApplepay = true;
20                        if (!window.ApplePaySession) {
21                            console.log("This device does not support Apple Pay");
22                        } else if (!ApplePaySession.canMakePayments()) {
23                            console.log("This device, although an Apple device, is not capable of making Apple Pay payments");
24                        } else
25                            isApplepayAvail = true;
26                    }
27                    let me = document.getElementById("xt_paypal_checkout_" + fundingSource);
28                    if (me && (!isApplepay || isApplepayAvail)) {
29                        let parent = me.closest(".list-group-item");
30                        if (parent) {
31                            parent.style.display = "block";
32                        }
33                    }
34                }
35            });
36        } catch (e) {
37            console.warn('enableFoundingSources: error');
38            console.log(e);
39        }
40    } else {
41        console.warn("paypal checkout no available. could not resolve eligible fundingSource's");
42    }
43}
44
45
46function enablePaypalCardForm() {
47    try {
48        
49        const cardFields = paypal.CardFields({
50
51            style: {
52                'input': {
53                    'font-size': '12pt',
54                    'color': '#3A3A3A',
55
56                },
57                '.number': {
58                    'font-family': 'monospace'
59                },
60                '.valid': {
61                    'color': 'green'
62                },
63                '.invalid': {
64                    'color': 'purple'
65                }
66            },
67
68            createOrder: (data, actions) => ppcCreateOrder('card_processing', actions),
69            onApprove: (data, actions) => { console.log('enablePaypalCardForm onApprove', data, actions)},
70            onError: function (err) {
71                console.log('enablePaypalCardForm onError', err);
72                ppcp_log_js('enablePaypalCardForm onError', {}, err);
73                if (err.message) alert(err.message);
74                ppcWaitModal('hide');
75                //window.location.href = window.XT.baseUrl + '?page=checkout&page_action=payment&error=ERROR_PAYMENT'
76            }
77        });
78
79        if(cardFields.isEligible()) {
80
81
82            const cardStyle = {
83                'input': {
84                    'font-family': 'courier, monospace',
85                    'padding': '0.5rem 0.75rem'
86                },
87            };
88
89            let cf = cardFields.NumberField({
90                style: cardStyle,
91                placeholder: "4111 1111 1111 1111"
92            }).render("#card_number");
93
94            cardFields.ExpiryField({
95                style: cardStyle,
96                placeholder: "MM/JJ"
97            }).render("#card_expiration_date");
98
99            cardFields.CVVField({
100                style: cardStyle,
101                placeholder: "..."
102            }).render("#card_cvv");
103
104            cardFields.NameField({
105                style: cardStyle,
106                placeholder: "..."
107            }).render("#card_holder_name");
108
109
110
111            document.getElementById("card_form").addEventListener("submit", (event) => {
112                event.preventDefault();
113                console.log('submitting card form');
114
115                cardFields.getState().then( data => {
116                    return data.isFormValid;
117                }).then( cardFormValid => {
118
119                    let xt_form = ppcGetCheckoutForm();
120                    let xt_form_valid = xtSimpleCheckForm_ppc(xt_form)
121                    if(cardFormValid && xt_form_valid)
122                    {
123
124
125                        if (cardFormValid && xt_form_valid) {
126
127                            const errContainer = document.getElementById('card_container_error');
128                            errContainer.innerHTML = '';
129                            errContainer.style.display = 'none';
130
131                            ppcWaitModal();
132                            cardFields
133                                .submit({
134                                    cardholderName: document.getElementById("card_holder_name").value,
135                                    cardNumber: document.getElementById("card_number").value,
136                                })
137                                .then((data) => {
138                                    console.log(data);
139                                    ppcWaitModal();
140                                    xt_form.submit();
141                                })
142                                .catch((err) => {
143                                    ppcWaitModal('hide');
144                                    console.log("Payment could not be processed! " + JSON.stringify(err));
145
146                                    let errorMsg = '';
147                                    err.details.forEach(errDetail => {
148                                        errorMsg += errDetail.description + '. ';
149                                    });
150                                    errContainer.innerHTML += errorMsg;
151                                    errContainer.style.display = 'block';
152                                });
153                        }
154                    }
155                });
156            });
157
158        }
159
160    } catch (e) {
161        console.warn('enablePaypalCardForm: error');
162        console.log(e);
163    }
164}
165
166
167function enablePaypalButton(fundingSource, position) {
168    if (window.paypal && window.paypal.Buttons) {
169
170        console.log('creating button for fundingSource ' + fundingSource, paypal_checkout_constant);
171
172        let selector = ppc_button_selector + '_' + position;
173
174        try {
175            ppcFix_button_changed_html(selector);
176        } catch (e) {
177            console.log('ppcFix_button_changed_html failed', e);
178        }
179
180        try {
181            let button = paypal.Buttons({
182
183                fundingSource: fundingSource,
184                style: {
185                    label: 'buynow',
186                    height: paypal_checkout_constant.BUTTON_SIZE,    // medium | large | responsive
187                    shape: paypal_checkout_constant.BUTTON_SHAPE,      // pill | rect
188                    color: paypal_checkout_constant.BUTTON_COLOR,       // gold | blue | silver | white | bla
189                    tagline: false
190                },
191                createOrder: (data, actions) => ppcCreateOrder(data, actions),
192                onApprove: (data, actions) => ppcOnApprove(data, actions),
193                onError: function (err) {
194                    console.log(err);
195                    ppcWaitModal('hide');
196                    //window.location.href = window.XT.baseUrl + '?page=checkout&page_action=payment&error=ERROR_PAYMENT'
197                },
198                onCancel: function (data) {
199                    console.log(data);
200                    ppcWaitModal('hide');
201                },
202                onInit: function (data, actions) {
203                    console.log('ppcp onInit');
204
205                    let form = ppcGetCheckoutForm();
206
207                    if (form) {
208                        const valid = xtSimpleCheckForm_ppc(form, false);
209                        if (!valid) {
210                            actions.disable();
211                        }
212                        let cbox = form.querySelectorAll("input[type=checkbox]");
213                        cbox.forEach(box => {
214                            box.addEventListener('change', function (event) {
215                                const valid = xtSimpleCheckForm_ppc(form, false);
216                                if (valid) {
217                                    actions.enable();
218                                    box.classList.remove("xt-form-error");
219                                } else {
220                                    actions.disable();
221                                }
222
223                            });
224                        });
225                    }
226
227                },
228                onClick: function (data, actions) {
229                    console.log('ppcp onClick');
230
231                    let form = ppcGetCheckoutForm();
232
233                    if (form) {
234                        const valid = xtSimpleCheckForm_ppc(form, true, true);
235                        if (!valid) {
236                            actions.reject();
237                        }
238                        let cbox = form.querySelectorAll("input[type=checkbox]");
239                        cbox.forEach(box => {
240                            box.addEventListener('change', function (event) {
241                                const valid = xtSimpleCheckForm_ppc(form, false);
242                                if (valid) {
243                                    actions.resolve();
244                                    box.classList.remove("xt-form-error");
245                                } else {
246                                    actions.reject();
247                                }
248
249                            });
250                        });
251                    }
252
253                }
254            }).render(selector);
255        } catch (e) {
256            console.warn('enablePaypalButton: error creating paypal button for selector [' + ppc_button_selector + '_' + position + ']');
257            console.log(e);
258        }
259    } else {
260        console.warn('enablePaypalButton: paypal checkout no available. could not create button for fundingSource ' + fundingSource)
261    }
262}
263
264function enablePaypalButtons_additional_payment(position, ap_no) {
265    if (window.paypal && window.paypal.Buttons) {
266
267        console.log('creating button for additional payment ' , paypal_checkout_constant);
268        console.log('creating button for additional payment ' , ap_no);
269
270        let selector = ppc_button_selector + '_' + position;
271
272        try {
273            let button = paypal.Buttons({
274
275                //fundingSource: '',
276                style: {
277                    label: 'pay',
278                    height: paypal_checkout_constant.BUTTON_SIZE,    // medium | large | responsive
279                    shape: paypal_checkout_constant.BUTTON_SHAPE,      // pill | rect
280                    color: paypal_checkout_constant.BUTTON_COLOR,       // gold | blue | silver | white | bla
281                    tagline: false
282                },
283                createOrder: (data, actions) => ppcCreateOrder(data, actions, selector, ap_no),
284                onApprove: (data, actions) => {
285                    ppcWaitModal();
286                    ppcCaptureOrder(data.orderID, ap_no)
287                    .then(function (resJson) {
288                        console.log('ppcCaptureOrder succes', resJson);
289                        //window.location.href = window.XT.baseUrl + 'pppayment/success?ap=' + ap_no;
290                        // TODO  window.XT.baseUrl fehlt der lang part zb de/
291                        window.location.href = window.XT.baseUrl + '?page=pppayment&page_action=success&ap=' + ap_no;
292                    }).catch((error) => {
293                        console.log('ppcCaptureOrder error', error);
294                        ppcWaitModal('hide');
295                    });
296
297                },
298
299                onError: function (err) {
300                    console.log(err);
301                    ppcWaitModal('hide');
302                    //window.location.href = window.XT.baseUrl + '?page=checkout&page_action=payment&error=ERROR_PAYMENT'
303                },
304                onCancel: function (data) {
305                    console.log(data);
306                    ppcWaitModal('hide');
307                },
308                onInit: function (data, actions) {
309                    console.log('ppcp onInit');
310
311                    let form = ppcGetCheckoutForm();
312
313                    if (form) {
314                        const valid = xtSimpleCheckForm_ppc(form, false);
315                        if (!valid) {
316                            actions.disable();
317                        }
318                        let cbox = form.querySelectorAll("input[type=checkbox]");
319                        cbox.forEach(box => {
320                            box.addEventListener('change', function (event) {
321                                const valid = xtSimpleCheckForm_ppc(form, false);
322                                if (valid) {
323                                    actions.enable();
324                                    box.classList.remove("xt-form-error");
325                                } else {
326                                    actions.disable();
327                                }
328
329                            });
330                        });
331                    }
332
333                },
334                onClick: function (data, actions) {
335                    console.log('ppcp onClick');
336
337                    let form = ppcGetCheckoutForm();
338
339                    if (form) {
340                        const valid = xtSimpleCheckForm_ppc(form, true, true);
341                        if (!valid) {
342                            actions.reject();
343                        }
344                        let cbox = form.querySelectorAll("input[type=checkbox]");
345                        cbox.forEach(box => {
346                            box.addEventListener('change', function (event) {
347                                const valid = xtSimpleCheckForm_ppc(form, false);
348                                if (valid) {
349                                    actions.resolve();
350                                    box.classList.remove("xt-form-error");
351                                } else {
352                                    actions.reject();
353                                }
354
355                            });
356                        });
357                    }
358
359                }
360            }).render(selector);
361        } catch (e) {
362            console.warn('enablePaypalButton: error creating paypal button for selector [' + ppc_button_selector + '_' + position + ']');
363            console.log(e)
364        }
365    } else {
366        console.warn('enablePaypalButton: paypal checkout no available. could not create button for fundingSource ' + fundingSource)
367    }
368}
369
370
371
372function renderAllEligibleButtons() {
373    if (window.paypal && window.paypal.Buttons) {
374
375        paypal.getFundingSources().forEach(function (fundingSource) {
376
377            console.log(fundingSource, paypal.isFundingEligible(fundingSource));
378
379            var button = paypal.Buttons({
380
381                fundingSource: fundingSource,
382                createOrder: (data, actions) => ppcCreateOrder(data, actions),
383                onApprove: (data, actions) => ppcOnApprove(data, actions),
384                onError: function (err) {
385                    console.log(err);
386                    ppcWaitModal('hide');
387                    window.location.replace(window.XT.baseUrl + '?page=checkout&page_action=payment&error=ERROR_PAYMENT');
388                },
389                onCancel: function (data) {
390                    console.log(data);
391                    ppcWaitModal('hide');
392                }
393            });
394
395        });
396
397    } else {
398        console.warn('renderAllEligibleButtons: paypal checkout no available');
399    }
400}
401
402function renderAllEligibleButtonsCart(position) {
403    console.log("renderAllEligibleButtonsCart position:" + position);
404    if (window.paypal && window.paypal.Buttons) {
405        try {
406            var button = paypal.Buttons({
407
408                //fundingSource: fundingSource,
409                style: {
410                    layout: 'horizontal',  // horizontal | vertical
411                    label: 'checkout',
412                    height: paypal_checkout_constant.BUTTON_SIZE,    // medium | large | responsive
413                    shape: paypal_checkout_constant.BUTTON_SHAPE,      // pill | rect
414                    color: paypal_checkout_constant.BUTTON_COLOR,       // gold | blue | silver | white | black
415                    tagline: false
416
417                },
418                createOrder: (data, actions, container) => ppcCreateOrder(data, actions, ppc_button_selector + '_' + position),
419                onApprove: (data, actions) => ppcOnApproveCart(data, actions),
420                onCancel: function (data) {
421                    console.log(data);
422                    ppcWaitModal('hide');
423                },
424                onShippingChange: (data, actions) => ppcGetShippingOptions(data, actions),
425            }).render(ppc_button_selector + '_' + position);
426        } catch (e) {
427            console.warn('renderAllEligibleButtonsCart: error creating paypal button for selector [' + ppc_button_selector + '_' + position + ']');
428            console.log(e)
429        }
430    } else {
431        console.warn('window.paypal not available');
432    }
433}
434
435function ppcGetShippingOptions(data, actions) {
436    console.log('ppcGetShippingOptions', data, actions);
437    console.log("previous country " + previousCountryCode, "current country " + data.shipping_address.country_code);
438
439    // ja einfach immer, entweder land hat sich geändert oder die versand-id
440    if (true || data.shipping_address.country_code != previousCountryCode || previousCountryCode == "") {
441
442        let url = baseUrl + '?page=PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS';
443
444        if (count > 0) {
445            operation = "replace"; // zur zeit wird eh immer ge add'ed in shippingOptions.php
446        }
447        count++;
448
449        return fetch(
450            url,
451            {
452                method: 'POST',
453                redirect: "error",
454                body: JSON.stringify({
455                    oderID: data.orderID,
456                    shipping_address: data.shipping_address,
457                    selected_shipping_option:  data.selected_shipping_option,
458                    operation: operation
459                })
460            }
461        ).then((response) => {
462            console.log('fast zurück von PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS', response);
463            let json = response.json();
464            return json;
465        }).then((response) => {
466            console.log('zurück von PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS', response);
467            if (response && response.error) {
468                // response.error wird imo zZ nicht verwendet
469                // wäre eine ander mgl zb für class.cart.php:_getContent_bottom und änderungen im cart
470                // fangen wir zZ über redirect-error
471                actions.reject();
472                window.location.replace(window.XT.baseUrl + '?page=cart');
473            }
474            if (response && response.needReload) {
475                // response.error wird imo zZ nicht verwendet
476                // wäre eine ander mgl zb für class.cart.php:_getContent_bottom und änderungen im cart
477                // fangen wir zZ über redirect-error
478                window.location.replace(window.XT.baseUrl + '?page=cart');
479            }
480            previousCountryCode = data.shipping_address.country_code;
481            return actions.resolve();
482        }).catch(reason => {
483            console.error('error in PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS', reason);
484            actions.reject();
485            // shippingOptions nur bei express
486            // wenn der reason ein redirect ist gehen wir in den cart
487            // bestimmt hat sich irgend etwas im cart geändert
488            // siehe class.cart.php:_getContent_bottom
489            window.location.replace(window.XT.baseUrl + '?page=cart');
490        });
491    }
492    return actions.resolve();
493}
494
495
496function ppcCreateOrder(data, actions, button_container_selector, ap_no = null) {
497    console.log({'fnc': 'ppcCreateOrder', 'data': data, 'actions': actions, 'container': button_container_selector, 'ap_no' : ap_no});
498
499    previousCountryCode = "";
500    operation = "add";
501    count = 0;
502
503    ppcWaitModal();
504
505    const form = ppcGetCheckoutForm();
506    let valid = true;
507    if (form) valid = xtSimpleCheckForm_ppc(form, true, true);
508
509    let isExpress = false;
510    let url = baseUrl + '?page=PAYPAL_CHECKOUT_ORDER_CREATE';
511    let isAddpay = false;
512    if(typeof ap_no === 'string' && ap_no.length > 0) {
513        isAddpay = true;
514        url = baseUrl + '?page=PAYPAL_CHECKOUT_ORDER_CREATE_ADD_PAY';
515    }
516
517    const page = window.XT.page.page_name;
518
519    if (valid) {
520        const formData = new URLSearchParams();
521        if (form) {
522            for (const pair of new FormData(form)) {
523                formData.append(pair[0], pair[1]);
524            }
525        }
526        if (data === 'card_processing') {
527            formData.append('card_processing', "1");
528            let ppcp_agree_save_method = document.getElementById('ppcp_agree_save_payment_method');
529            if(ppcp_agree_save_method && ppcp_agree_save_method.checked)
530            {
531                formData.append('ppcp_agree_save_payment_method', "1");
532            }
533
534        } else if (page !== 'checkout') {
535            // ar we in cart / product  => express checkout ?
536            const page = window.XT.page.page_name;
537
538            isExpress = true;
539            formData.append('ppcp_express_checkout', 'true');// apple_pay_checkout  ppcp_express_checkout
540
541            // check if cart or product
542            const form = document.getElementById('main_product_form');
543            if (!form) {
544                // fallback versuch für artikel seite
545                document.querySelector('form[name=product]');
546            }
547
548            if (form) { // products page, append quantity and products_id to request
549
550                // now check we are not in eg coe_cart_popup. then there no need to add the product to cart
551                // check the pp-container has the product form as parent
552                let add_ADD_PRODUCT_param = true; // weil alles andere Ausnahme sein sollte.... ):
553                const button_container = document.querySelector(button_container_selector);
554                if (button_container) {
555                    // das sollte wohl klappen bis hier
556                    // jetzt schauen wir nach dont_add_product_when_paypal_button_is_child_of_one_of_this_containers
557                    // definiert in paypal-checkout-cart-and-product_ignored_containers.tpl.html (tpl-überschreibbar)
558                    if (typeof dont_add_product_when_paypal_button_is_child_of_one_of_this_containers != 'undefined') {
559                        dont_add_product_when_paypal_button_is_child_of_one_of_this_containers.forEach(function (container_selector, index) {
560                            const container = document.querySelector(container_selector);
561                            if (container)
562                                add_ADD_PRODUCT_param = (add_ADD_PRODUCT_param && !container.contains(button_container));
563                        });
564                    }
565
566                }
567
568                console.log("add_ADD_PRODUCT_param => " + add_ADD_PRODUCT_param);
569
570                if (add_ADD_PRODUCT_param) {
571                    for (const pair of new FormData(form)) {
572                        formData.append(pair[0], pair[1]);
573                    }
574                }
575            }
576            formData.delete('action');
577        }
578
579        if (data && data.shippingContact_ap) {
580            formData.append('shippingContact_ap', JSON.stringify(data.shippingContact_ap));
581        }
582
583        if (data && data.billingContact_ap) {
584            formData.append('billingContact_ap', JSON.stringify(data.billingContact_ap));
585        }
586
587        if(typeof ap_no === 'string' && ap_no.length > 0) {
588            formData.append('ap_no', ap_no);
589        }
590
591        return fetch(
592            url,
593            {
594                method: 'POST',
595                body: formData,
596                redirect: "error"
597            }
598        ).then(function (response) {
599            console.log(response);
600            ppcWaitModal('hide');
601            return response.json();
602        }).then(function (resJson) {
603            console.log(resJson);
604            if(isAddpay) ppcWaitModal('hide');
605            else ppcWaitModal();
606            if(typeof data != 'undefined' && data.paymentSource === "card" && resJson.data.payer_action)
607            {
608                window.location.replace(resJson.data.payer_action);
609            }
610            if (typeof isStandardCard != 'undefined' && isStandardCard)
611                ppcWaitModal('hide');
612            return resJson.data.id;
613        }).catch((error) => {
614            console.log(error, isExpress);
615            ppcWaitModal('hide');
616            if(isAddpay) throw error;
617            if (!isExpress) window.location.replace(window.XT.baseUrl + '?page=cart');
618            else if (page != 'product') window.location.replace(window.XT.baseUrl + '?page=cart');
619            else if (page == 'product') location.reload();
620        });
621    }
622}
623
624function ppcCaptureOrder(ppcp_order_id, ap_no = '') {
625    console.log({'fnc': 'ppcCaptureOrder', 'ppcp_order_id': ppcp_order_id});
626
627    ppcWaitModal();
628
629    let url = baseUrl + '?page=PAYPAL_CHECKOUT_ORDER_CAPTURE';
630
631    return fetch(
632        url,
633        {
634            method: 'POST',
635            headers: {
636                'Content-Type': 'application/json'
637            },
638            body: JSON.stringify({ppcp_order_id: ppcp_order_id, ap_no: ap_no}),
639            redirect: "error"
640        }
641    ).then(function (response) {
642        console.log(response);
643        ppcWaitModal('hide');
644        return response.json();
645    }).then(function (resJson) {
646        console.log(resJson);
647        return resJson.id;
648    }).catch((error) => {
649        console.log('ppcCaptureOrder error', error);
650    });
651
652}
653
654function ppcGetOrder(ppcp_order_id) {
655    console.log({'fnc': 'ppcGetOrder', 'ppcp_order_id': ppcp_order_id});
656
657    ppcWaitModal();
658
659    let url = baseUrl + '?page=PAYPAL_CHECKOUT_ORDER_GET&ppcp_order_id=' + ppcp_order_id;
660
661    return fetch(
662        url,
663        {
664            method: 'GET',
665            redirect: "error"
666        }
667    ).then(function (response) {
668        console.log(response);
669        ppcWaitModal('hide');
670        return response.json();
671    }).catch((error) => {
672        console.log('ppcGetOrder error', error);
673    });
674
675}
676
677function ppcOnApprove(data, actions) {
678    console.log({'fnc': 'ppcOnApprove', 'data': data, 'actions': actions});
679
680    ppcWaitModal();
681
682    const form = ppcGetCheckoutForm();
683
684    let url = baseUrl + '?page=checkout&page_action=process';
685    let formData = new URLSearchParams();
686    if (form) {
687        for (const pair of new FormData(form)) {
688            formData.append(pair[0], pair[1]);
689        }
690    }
691    formData.delete("page_action");
692
693    return fetch(
694        url,
695        {
696            method: 'POST',
697            body: formData,
698            redirect: "error"
699        }
700    ).then(function (response) {
701        console.log(response);
702        if (!response.ok) {
703            throw Error(response.statusText);
704        }
705        return response.json();
706    }).then(function (resJson) {
707        console.log(resJson);
708
709        ppcWaitModal();
710        setTimeout(function () {
711            document.getElementById("ppc_oops").style.display = "block"
712        }, 3000);
713
714        window.location.replace(baseUrl + '?page=checkout&page_action=success')
715    }).catch((error) => {
716        ppcWaitModal('hide');
717        console.log(error);
718        window.location.replace(window.XT.baseUrl + '?page=cart')
719    });
720}
721
722function ppcOnApproveCart(data, actions) {
723    console.log({'fnc': 'ppcOnApproveCart', 'data': data, 'actions': actions});
724    ppcWaitModal();
725    window.location.replace(baseUrl + '?page=checkout&ppcp_express_checkout=true');
726}
727
728function ppcSetupPuiForm() {
729    let pui_div = document.querySelector("div[id=xt_paypal_checkout_pui]");
730    if (pui_div) {
731        const regexPrefix = /^[0-9]{0,3}?$/;
732        const regexPhone = /^[0-9]{0,14}?$/;
733        const regexDate = /^[1-9]{2}\.[0-9]{2}\.[0-9]{4}$/;
734
735        let inputPrefix = document.getElementById("paypal_checkout_selection_pui_phoneNumberPrefix");
736        if (inputPrefix) {
737            setInputFilter(inputPrefix, function (value) {
738                return regexPrefix.test(value);
739            }, "0-9 / min2 / max 3");
740        }
741
742        let inputPhone = document.getElementById("paypal_checkout_selection_pui_phoneNumber");
743        if (inputPhone) {
744            setInputFilter(inputPhone, function (value) {
745                return regexPhone.test(value);
746            }, "0-9 / min3 / max 14");
747        }
748
749        let inputDate = document.getElementById("paypal_checkout_selection_pui_birthdate");
750        if (inputDate && false) {
751            setInputFilter(inputDate, function (value) {
752                return regexDate.test(value);
753            }, "Format 31.01.1980 / 1980-01-31");
754        }
755
756        let form = pui_div.closest("form");
757        if (form) {
758            form.addEventListener('submit', function (event) {
759                let paypalSelected = form.querySelector("input[value^=xt_paypal_checkout_]:checked");
760                if (paypalSelected) {
761                    event.preventDefault();
762                    let puiSelected = form.querySelector("input[value=xt_paypal_checkout_pui]:checked");
763                    if (puiSelected) {
764                        // regex anpassen
765                        const regexPrefixSubmit = /^[0-9]{2,3}?$/;
766                        const regexPhoneSubmit = /^[0-9]{3,14}?$/;
767                        const regexDateSubmit = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
768
769                        let validPrefix = regexPrefixSubmit.test(inputPrefix.value);
770                        let validPhone = regexPhoneSubmit.test(inputPhone.value);
771                        let validDate = regexDateSubmit.test(inputDate.value);
772
773                        if (validPrefix && validPhone && validDate)
774                            form.submit();
775                        else {
776                            if (!validPrefix) {
777                                inputPrefix.classList.add("input-error", "ppcp-has-error", "animated", "shake");
778                                inputPrefix.setCustomValidity('min 2');
779                                inputPrefix.reportValidity();
780
781                                setTimeout(function () {
782                                    inputPrefix.classList.remove("input-error", "ppcp-has-error", "animated", "shake");
783                                }, 1000);
784                            } else if (!validPhone) {
785                                inputPhone.classList.add("input-error", "ppcp-has-error", "animated", "shake");
786                                inputPhone.setCustomValidity('min 3');
787                                inputPhone.reportValidity();
788
789                                setTimeout(function () {
790                                    inputPhone.classList.remove("input-error", "ppcp-has-error", "animated", "shake");
791                                }, 1000);
792                            } else if (!validDate) {
793                                inputDate.classList.add("input-error", "ppcp-has-error", "animated", "shake");
794                                setTimeout(function () {
795                                    inputDate.classList.remove("input-error", "ppcp-has-error", "animated", "shake");
796                                }, 1000);
797                            }
798
799                            // ew_evelations
800                            setTimeout(function () {
801
802                                form.querySelectorAll("button[type=submit], input[type=submit]").forEach(function (btn, index) {
803                                    btn.removeAttribute("disabled");
804                                    btn.removeAttribute("data-loading");
805                                });
806                            }, 100);
807                        }
808                    } else {
809                        form.submit();
810                    }
811                }
812            });
813        }
814    }
815}
816
817function ppcRemoveBackButton() {
818    try {
819        let form = ppcGetCheckoutForm();
820        if (form) {
821            form.querySelectorAll('a[href*="checkout/payment"]').forEach(
822                element => element.remove()
823            );
824        }
825    } catch (e) {
826        console.log(e);
827    }
828}
829
830function ppcRemoveSubmitButton() {
831    try {
832        let form = ppcGetCheckoutForm();
833        if (form) {
834            form.querySelectorAll("button:not(.paypal-card-button)").forEach(
835                element => element.remove()
836            );
837        }
838    } catch (e) {
839        console.log(e);
840    }
841}
842
843function ppcWaitModal(close) {
844
845    console.log('ppcWaitModal', close);
846    try {
847        const modal = document.getElementById('ppc_wait_overlay');
848        if (modal) {
849            if (typeof close === 'undefined')
850                modal.classList.remove("hidden");
851            else
852                modal.classList.add("hidden");
853        } else console.warn('ES WURDE KEIN ppc_wait_overlay GEFUNDEN');
854    } catch (e) {
855        console.info(e);
856    }
857}
858
859function deleteSavedPaymentMethod(paymentToken)
860{
861
862    let url = baseUrl + '?page=PAYPAL_CHECKOUT_DELETE_PAYMENT_TOKEN';
863
864    ppcWaitModal();
865
866    return fetch(
867        url,
868        {
869            method: 'POST',
870            body: JSON.stringify({paymentToken: paymentToken}),
871            redirect: "error"
872        }
873    )
874}
875
876function ppcSavePaymentMethodInfoModal(close) {
877    try {
878        const modal = document.getElementById('ppc_save_payment_method_info_overlay');
879        if (modal) {
880            if (typeof close === 'undefined')
881            {
882                modal.classList.remove("hidden");
883                modal.addEventListener('click', (e) => {
884                    if(e.target === e.currentTarget){
885                        ppcSavePaymentMethodInfoModal(true);
886                    }
887                });
888            }
889            else
890            {
891                modal.classList.add("hidden");
892                modal.removeEventListener('click', e => { })
893            }
894        } else console.warn('ES WURDE KEIN ppc_save_payment_method_info_overlay GEFUNDEN');
895    } catch (e) {
896        console.info(e);
897    }
898}
899
900let vaultedPaymentsDeleteLinksAdded = false;
901function addVaultedPaymentDeleteLink()
902{
903    document.querySelectorAll('[id="xt_paypal_checkout_paypal_vaulted"]', '[id="xt_paypal_checkout_card_vaulted"]').forEach(node => {
904        let link = node.querySelector(".ppcp-delete-payment-token");
905        if(link && !vaultedPaymentsDeleteLinksAdded)
906        {
907            link.addEventListener("click", ev => {
908
909                if(confirm("{txt key=TEXT_XT_PAYPAL_CHECKOUT_SAVED_PAYMENT_DELETE}")) {
910                    try {
911                        ppcWaitModal();
912                        deleteSavedPaymentMethod(link.dataset.paymentToken).
913                        then(function (response) {
914                            console.log(response);
915                            window.location.reload();
916                        }).catch((error) => {
917                            console.log('deleteSavedPaymentMethod', error);
918                        });
919                    } catch (e) {
920                        console.log(e);
921                        ppcWaitModal('hide');
922                    }
923                }
924            });
925        }
926        vaultedPaymentsDeleteLinksAdded = true;
927    })
928}
929document.addEventListener('DOMContentLoaded', function ()
930{
931    console.log('adding delete-vaulted-payment link');
932    addVaultedPaymentDeleteLink();
933});
934
935
936// Restricts input for the given textbox to the given inputFilter function.
937function setInputFilter(textbox, inputFilter, errMsg) {
938    ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout"].forEach(function (event) {
939        textbox.addEventListener(event, function (e) {
940            if (inputFilter(this.value)) {
941                // Accepted value
942                if (["keydown", "mousedown", "focusout"].indexOf(e.type) >= 0) {
943                    this.classList.remove("input-error");
944                    this.setCustomValidity("");
945                }
946                this.oldValue = this.value;
947                this.oldSelectionStart = this.selectionStart;
948                this.oldSelectionEnd = this.selectionEnd;
949            } else if (this.hasOwnProperty("oldValue")) {
950                // Rejected value - restore the previous one
951                this.classList.add("input-error");
952                this.setCustomValidity(errMsg);
953                this.reportValidity();
954                this.value = this.oldValue;
955                this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
956            } else {
957                // Rejected value - nothing to restore
958                this.value = "";
959            }
960        });
961    });
962}
963
964function ppcFix_button_changed_html(selector) {
965    try {
966        // in templates vor xt 6.5 ist auf der confirmation das $button_changed_html an der falsche stelle eingebunden
967        let submitButton = document.querySelector("form[id=checkout-form] button[type=submit]");
968        if (!submitButton) {
969            const form = ppcGetCheckoutForm();
970            if (form)
971                submitButton = form.querySelector("button[type=submit]");
972        }
973        if (submitButton) {
974            const btnContainer = submitButton.querySelector(selector);
975            console.log(btnContainer);
976            if (btnContainer) {
977                submitButton.parentElement.insertBefore(btnContainer, submitButton);
978                submitButton.parentElement.removeChild(submitButton);
979            }
980        }
981    } catch (e) {
982        console.log(e);
983    }
984}
985
986if (typeof xtSimpleCheckForm_ppc != 'function') {
987    window.xtSimpleCheckForm_ppc = function (form, scrollTo, showTermsWarning) {
988        var errorElements = [];
989
990        if (scrollTo !== true && scrollTo !== false) scrollTo = true;
991        if (showTermsWarning !== true && showTermsWarning !== false) showTermsWarning = false;
992
993
994        form.querySelectorAll('input[type=checkbox].xt-form-required').forEach(function (el) {
995            if (el.checked !== true) {
996                errorElements.push(el);
997            }
998        });
999
1000        form.querySelectorAll('input[type=radio].xt-form-required').forEach(function (el) {
1001            //
1002        });
1003
1004
1005        form.querySelectorAll('input[type=text].xt-form-required').forEach(function (el) {
1006            //
1007        });
1008
1009        // ....
1010
1011        if (errorElements.length) {
1012            errorElements.forEach(function (el) {
1013                el.classList.add('xt-form-error');
1014                if (el.name == 'conditions_accepted' && showTermsWarning) {
1015                    let div = document.getElementById('TEXT_ERROR_CONDITIONS_ACCEPTED');
1016                    if (div)
1017                        div.style.display = 'block';
1018                }
1019            });
1020            if (scrollTo && !ppcIsInViewport(errorElements[0])) {
1021                errorElements[0].closest('form').scrollIntoView({
1022                    behavior: 'smooth'
1023                });
1024            }
1025            // evelations button reaktivieren
1026            setTimeout(function () {
1027                console.log('clearing submit button');
1028                form.querySelectorAll("[data-loading]").forEach((el) => {
1029                    el.removeAttribute('data-loading');
1030                    el.removeAttribute('disabled');
1031                });
1032                form = document.getElementById("card_form");
1033                if(form)
1034                {
1035                    form.querySelectorAll("[data-loading]").forEach((el) => {
1036                        el.removeAttribute('data-loading');
1037                        el.removeAttribute('disabled');
1038                    });
1039                }
1040            }, 1000);
1041            return false;
1042        }
1043
1044        return true;
1045    };
1046}
1047
1048function ppcGetCheckoutForm() {
1049    let xt_form = document.getElementById("checkout-form");
1050    if (!xt_form) xt_form = document.getElementById("checkout_form");
1051    if (!xt_form) xt_form = document.getElementById("formCard"); // danke dafür ador, hauptsache eigene id's
1052    if (!xt_form) {
1053        let inp = document.querySelector('input[type=hidden][name=action][value=process]');
1054        if (inp)
1055            xt_form = inp.parentElement;
1056    }
1057    if (!xt_form) console.warn('ES WURDE KEIN FORMULAR GEFUNDEN. form[id=checkout_form] bzw form[id=checkout-form] oder input[type=hidden][name=action][value=process]');
1058    return xt_form;
1059}
1060
1061function ppcIsInViewport(element) {
1062    const rect = element.getBoundingClientRect();
1063    return (
1064        rect.top >= 0 &&
1065        rect.left >= 0 &&
1066        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1067        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
1068    );
1069}
1070
1071let logWorker = null;
1072if (window.Worker) {
1073    logWorker = new Worker(baseUrl + 'plugins/xt_paypal_checkout/javascript/log-worker.js');
1074    console.log(logWorker);
1075}
1076
1077
1078
1079async function ppcp_log_js(fnc, data = {}, error = null) {
1080
1081    let url = baseUrl + '?page=PAYPAL_CHECKOUT_LOG';
1082
1083    if(window.Worker && logWorker !== null && typeof paypal_checkout_constant !== 'undefined') {
1084        logWorker.postMessage({
1085            url: url,
1086            ppcp_session_id: paypal_checkout_constant.PPCP_SESSION_ID,
1087            fnc: fnc,
1088            data: data,
1089            error: error
1090        });
1091    }
1092    else if(typeof paypal_checkout_constant !== 'undefined')
1093    {
1094        console.error('ppcp log worker not available.');
1095        return fetch(
1096            url,
1097            {
1098                method: 'POST',
1099                redirect: "error",
1100                body: JSON.stringify({ppcp_session_id: paypal_checkout_constant.PPCP_SESSION_ID, fnc: fnc, data: data})
1101            }
1102        ).then((response) => { }
1103        ).catch(error => {
1104                console.error('PAYPAL_CHECKOUT_LOG error.', error);
1105        });
1106    }
1107}
1108
1109/****
1110 *
1111 *      APPLE PAY
1112 * */
1113let getShippingOptions_ap = countryCode => {
1114    console.log('getShippingOptions_ap', "current country ap " + currentCountryCode_ap, "new country ap " + countryCode);
1115
1116    let url = baseUrl + '?page=PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS_AP';
1117
1118    return fetch(
1119        url,
1120        {
1121            method: 'POST',
1122            headers: {
1123                'Content-Type': 'application/json'
1124            },
1125            redirect: "error",
1126            body: JSON.stringify({country_code: countryCode})
1127        }
1128    ).then((response) => {
1129        console.log('fast zurück von PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS_AP', response);
1130        return response.json();
1131    }).then(function (resJson) {
1132        console.log(resJson);
1133        return resJson;
1134    }).catch(error => {
1135        console.error('PAYPAL_CHECKOUT_GET_SHIPPING_OPTIONS_AP error. returning empty array', error);
1136        ppcp_log_js('error getShippingOptions_ap', {}, error);
1137        return [];
1138    });
1139}
1140
1141let setShippingMethod_ap = (countryCode, shippingCode) => {
1142    console.log('setShippingMethod_ap', "shippingCode " + shippingCode + ". countryCode " + countryCode);
1143
1144    let url = baseUrl + '?page=PAYPAL_CHECKOUT_SET_SHIPPING_METHOD_AP';
1145
1146    return fetch(
1147        url,
1148        {
1149            method: 'POST',
1150            headers: {
1151                'Content-Type': 'application/json'
1152            },
1153            redirect: "error",
1154            body: JSON.stringify({
1155                country_code: countryCode,
1156                shipping_code: shippingCode
1157            })
1158        }
1159    ).then((response) => {
1160        console.log('fast zurück von PAYPAL_CHECKOUT_SET_SHIPPING_METHOD_AP', response);
1161        return response.json();
1162    }).then(function (resJson) {
1163        console.log(resJson);
1164        return resJson;
1165    }).catch(error => {
1166        console.error('PAYPAL_CHECKOUT_SET_SHIPPING_METHOD_AP error. returning empty array', error);
1167        return [];
1168    });
1169}
1170
1171let check_applepay = async () => {
1172    return new Promise((resolve, reject) => {
1173        let error_message = "";
1174        if (!window.ApplePaySession) {
1175            error_message = "This device does not support Apple Pay";
1176        } else if (!ApplePaySession.canMakePayments()) {
1177            error_message = "This device, although an Apple device, is not capable of making Apple Pay payments";
1178        }
1179        if (error_message !== "") {
1180            reject(error_message);
1181        } else {
1182            resolve();
1183        }
1184    });
1185};
1186
1187async function setupApplepay(appendToContainer) {
1188    let container = appendToContainer || "paypal_button_container_checkout";
1189    check_applepay()
1190        .then(() => {
1191            const applepay = paypal.Applepay();
1192
1193            applepay.config()
1194                .then(async applePayConfig => {
1195                    console.log(applePayConfig);
1196                    if (applePayConfig.isEligible) {
1197
1198                        let appleButton = document.createElement('apple-pay-button');
1199                        appleButton.setAttribute('id', 'btn-apple-pay');
1200                        appleButton.setAttribute('buttonstyle', paypal_checkout_constant.BUTTON_TYPE_AP); // TODO  payment config
1201                        appleButton.setAttribute('type', 'continue');
1202                        appleButton.setAttribute('locale', paypal_checkout_constant.language);
1203
1204                        document.getElementById(container).appendChild(appleButton);
1205
1206                        let shippingResult = await getShippingOptions_ap(currentCountryCode_ap);
1207                        currentTotal_ap = shippingResult.newTotal;
1208                        console.log('applepay shippings', shippingResult);
1209
1210                        appleButton.addEventListener('click', e => {
1211
1212                            let xt_form = ppcGetCheckoutForm();
1213
1214                            if (xtSimpleCheckForm_ppc(xt_form, true, true)) {
1215
1216                                const paymentRequest = {
1217                                    countryCode: applePayConfig.countryCode,
1218                                    merchantCapabilities: applePayConfig.merchantCapabilities,
1219                                    supportedNetworks: applePayConfig.supportedNetworks,
1220                                    currencyCode: applePayConfig.currencyCode,
1221
1222                                    billingContact: billingContact_ap,
1223                                    shippingContact: shippingContact_ap,
1224                                    shippingContactEditingMode: 'available', //storePickup
1225
1226                                    requiredShippingContactFields: ["name", "phone", "postalAddress"],
1227                                    requiredBillingContactFields: ["name", /*"phone",*/ "postalAddress", "email"],
1228
1229                                    lineItems: [
1230                                        {
1231                                            label: subTotalLabel_ap,
1232                                            type: "final",
1233                                            amount: shippingResult.newSubtotal
1234                                        },
1235                                        {
1236                                            label: paypal_checkout_constant.TEXT_SHIPPING_COSTS + " " + shippingResult.shipping_label,
1237                                            type: "final",
1238                                            amount: shippingResult.shipping_price
1239                                        }
1240                                    ],
1241
1242
1243                                    total: {
1244                                        label: totalLabel_ap,
1245                                        type: "final",
1246                                        amount: shippingResult.newTotal
1247                                    },
1248                                    shippingMethods: shippingResult.shippings
1249                                };
1250
1251
1252                                const session = new ApplePaySession(4, paymentRequest);
1253
1254
1255                                console.log('apple pay session created', session);
1256
1257
1258                                session.oncouponcodechanged = (event) => {
1259                                    console.log('on coupon code changed', event);
1260                                }
1261
1262
1263                                session.onpaymentmethodselected_DISABLED = (event) => {
1264                                    console.log('on payment method selected. zZ machen wir hier nichts', event);
1265
1266                                    // Define ApplePayPaymentMethodUpdate based on the selected payment method.
1267                                    // No updates or errors are needed, pass an empty object.
1268                                    // empty object funktioniert leider nicht
1269                                    const update = {};
1270                                    session.completePaymentMethodSelection(update);
1271                                }
1272
1273                                session.onshippingcontactselected = (event) => {
1274
1275                                    console.log('applepay on shipping contact selected', event);
1276
1277                                    // Define ApplePayShippingContactUpdate based on the selected shipping contact.
1278                                    if (event.shippingContact.countryCode !== currentCountryCode_ap) {
1279                                        // würde uns eigentlich reichen
1280                                        // aber die event handler müssen immer ein update object haben
1281                                        // und dieses mus ein newTotal lineItem haben
1282                                    }
1283
1284                                    getShippingOptions_ap(event.shippingContact.countryCode)
1285                                        .then(shippingResult => {
1286
1287                                            let type = 'final';
1288                                            let errors = [];
1289                                            if (shippingResult.shippings && shippingResult.shippings.length === 0) {
1290                                                type = 'pending';
1291                                                errors = [new ApplePayError("shippingContactInvalid", "country", paypal_checkout_constant.WARNING_NO_SHIPPING_FOR_ZONE)];
1292                                            }
1293
1294                                            if (shippingResult.success) {
1295                                                const update = {
1296                                                    newTotal: {
1297                                                        label: totalLabel_ap,
1298                                                        type: type,
1299                                                        amount: shippingResult.newTotal,
1300                                                    },
1301                                                    newShippingMethods: shippingResult.shippings || [],
1302
1303                                                    errors: errors
1304
1305                                                };
1306                                                session.completeShippingContactSelection(update);
1307                                                currentCountryCode_ap = event.shippingContact.countryCode;
1308                                                currentTotal_ap = shippingResult.newTotal;
1309                                            } else {
1310                                                throw new Error(shippingResult.msg || "Error fetching shipping options")
1311                                            }
1312                                        })
1313                                        .catch(error => {
1314                                            console.log(' error in onshippingcontactselected while retrieving shipping options', error);
1315                                            ppcp_log_js('error onshippingcontactselected > getShippingOptions_ap', {}, error);
1316                                            session.completeShippingContactSelection({
1317                                                newTotal: {label: totalLabel_ap, type: "pending", amount: currentTotal_ap},
1318                                                errors: [new ApplePayError("shippingContactInvalid", "country", "Error fetching shipping options")]
1319                                            });
1320                                        });
1321                                }
1322
1323                                session.onshippingmethodselected = (event) => {
1324                                    console.log('applepay on shipping method selected', event);
1325                                    // todo hier ansetzen für onepage
1326
1327                                    setShippingMethod_ap(currentCountryCode_ap, event.shippingMethod.identifier)
1328                                        .then(shippingResult => {
1329
1330                                            if (shippingResult.success) {
1331                                                const update = {
1332                                                    newTotal: {
1333                                                        label: totalLabel_ap,
1334                                                        type: "final",
1335                                                        amount: shippingResult.newTotal,
1336                                                    }
1337                                                    //newShippingMethods: shippingResult.shippings
1338
1339                                                };
1340
1341                                                session.completeShippingMethodSelection(update);
1342                                                currentTotal_ap = shippingResult.newTotal;
1343                                            } else {
1344                                                throw new Error(shippingResult.msg || "Error setting shipping method")
1345                                            }
1346                                        })
1347                                        .catch(error => {
1348                                            console.log(' error in onshippingmethodselected while retrieving shipping options', error);
1349                                            ppcp_log_js('error onshippingmethodselected > setShippingMethod_ap', {}, error);
1350                                            session.completeShippingMethodSelection({
1351                                                newTotal: {
1352                                                    label: totalLabel_ap,
1353                                                    type: "pending",
1354                                                    amount: currentTotal_ap,
1355                                                }
1356                                            });
1357                                        });
1358                                }
1359
1360                                session.onvalidatemerchant = (event) => {
1361                                    console.log('on validate merchant', event);
1362                                    applepay.validateMerchant({
1363                                        validationUrl: event.validationURL,
1364                                        displayName: window.location.hostname
1365                                    })
1366                                        .then(validateResult => {
1367
1368                                            console.log('on validate merchant validateResult', validateResult);
1369                                            session.completeMerchantValidation(vali
1369dateResult.merchantSession);
1370                                        })
1371                                        .catch(validateError => {
1372                                            console.error('validateError', validateError);
1373                                            ppcp_log_js('error onvalidatemerchant', {}, validateError);
1374                                            session.abort();
1375                                        });
1376                                };
1377
1378                                session.onpaymentauthorized = (event) => {
1379                                    console.log('on apple payment authorized', event);
1380                                    console.log('Your billing address is:', event.payment.billingContact);
1381                                    console.log('Your shipping address is:', event.payment.shippingContact);
1382                                    // The `billingContact` and `shippingContact` object use the `ApplePayPaymentContact` format.
1383                                    // Find more details about this object at this URL:
1384                                    // https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentcontact
1385                                    ppcCreateOrder({
1386                                        billingContact_ap: event.payment.billingContact,
1387                                        shippingContact_ap: event.payment.shippingContact
1388                                    })
1389                                        .then((ppOrderId) => {
1390                                            console.log('ppc order created. ppOrderId', ppOrderId);
1391                                            applepay.confirmOrder({
1392                                                orderId: ppOrderId,
1393                                                token: event.payment.token,
1394                                                billingContact: event.payment.billingContact,
1395                                                shippingContact: event.payment.shippingContact
1396                                            })
1397                                                .then(confirmResult => {
1398                                                    console.log('confirmResult', confirmResult)
1399
1400                                                    // Submit approval to the server and authorize or capture the order.
1401                                                    ppcCaptureOrder(ppOrderId)
1402                                                        .then(captureResult => {
1403                                                            console.log('ppc capture result applepay. setting ApplePaySession.STATUS_SUCCESS', captureResult);
1404
1405                                                            session.completePayment(ApplePaySession.STATUS_SUCCESS);
1406
1407                                                            ppcWaitModal();
1408                                                            window.location.replace(baseUrl + '?page=checkout&page_action=payment_process')
1409                                                        })
1410                                                        .catch(captureError => {
1411                                                            console.error('ppc error when capture applepay', captureError);
1412                                                            session.completePayment(ApplePaySession.STATUS_FAILURE);
1413                                                            ppcp_log_js('error when capture applepay. onpaymentauthorized > ppcCreateOrder > confirmOrder > ppcCaptureOrder', {}, captureError);
1414                                                        });
1415
1416                                                })
1417                                                .catch(confirmError => {
1418                                                    console.error('Error confirming order with applepay token', confirmError);
1419                                                    session.completePayment(ApplePaySession.STATUS_FAILURE);
1420
1421                                                    ppcp_log_js('Error confirming order with applepay token. onpaymentauthorized > ppcCreateOrder > confirmOrder',
1422                                                        {
1423                                                                orderId: ppOrderId,
1424                                                                token: event && event.payment ? event.payment.token : "n/a",
1425                                                                billingContact: event && event.payment ? event.payment.billingContact : "n/a",
1426                                                                shippingContact: event && event.payment ? event.payment.shippingContact : "n/a"
1427                                                            },
1428                                                            confirmError
1429                                                    );
1430
1431                                                });
1432
1433                                        })
1434                                        .catch((error) => {
1435                                            console.log('error onpaymentauthorized > ppcCreateOrder', error);
1436                                            session.completePayment(ApplePaySession.STATUS_FAILURE);
1437                                            ppcp_log_js('error onpaymentauthorized > ppcCreateOrder', {}, error);
1438                                        });
1439
1440                                };
1441
1442                                session.oncancel = event => {
1443                                    console.log('apple pay session canceled', event);
1444
1445                                    let url = baseUrl + '?page=PAYPAL_CHECKOUT_RESET_ADDRESSES_AP';
1446
1447                                    return fetch(
1448                                        url,
1449                                        {
1450                                            method: 'POST',
1451                                            //redirect: "error",
1452                                            body: JSON.stringify({})
1453                                        }
1454                                    ).then((response) => {
1455                                        console.log('fast zurück von PAYPAL_CHECKOUT_RESET_ADDRESSES_AP', response);
1456                                        return response.json();
1457                                    }).then(function (resJson) {
1458                                        console.log(resJson);
1459                                        return resJson;
1460                                    }).catch(error => {
1461                                        console.error('PAYPAL_CHECKOUT_RESET_ADDRESSES_AP error', error);
1462                                        return [];
1463                                    });
1464                                };
1465
1466                                session.begin();
1467                            } // form validated
1468                        });
1469                    }
1470                })
1471                .catch(applePayConfigError => {
1472                    console.error('Error while fetching Apple Pay configuration.', applePayConfigError);
1473                });
1474        })
1475        .catch(errorMessage => {
1476            console.log(errorMessage)
1477        })
1478}
1479
1480/****
1481 *
1482 *      GOOGLE PAY
1483 * */
1484/* Configure your site's support for payment methods supported by the Google Pay */
1485const googleBaseRequest = {
1486    apiVersion: 2,
1487    apiVersionMinor: 0
1488};
1489
1490const googleAllowedCardNetworks = ["AMEX", "DISCOVER", "JCB", "MASTERCARD", "VISA"];
1491const googleAllowedCardAuthMethods = [ "PAN_ONLY", "CRYPTOGRAM_3DS"];
1492
1493let googlePayConfig = null;
1494let googlePaymentsClient = null;
1495const googlePaymentsEnvironment = window?.paypal_checkout_constant?.googlePaymentsEnvironment || null;
1496console.log('googlePaymentsEnvironment', googlePaymentsEnvironment);
1497async function setupGooglepay() {
1498
1499    console.log('setupGooglepay');
1500
1501    try {
1502        googlePayConfig = await paypal.Googlepay().config();
1503
1504        googlePaymentsClient = getGooglePaymentsClient();
1505        const readyToPay = await googlePaymentsClient.isReadyToPay(googlePayConfig);
1506        if (readyToPay.result) {
1507            addGooglePayButton();
1508        }
1509    }
1510    catch(e){
1511       console.log('setupGooglePay', e);
1512    }
1513}
1514
1515
1516function addGooglePayButton(appendToContainer) {
1517
1518    console.log('addGooglePayButton')
1519
1520    try {
1521        let container = appendToContainer || "paypal_button_container_checkout";
1522
1523        const baseCardPaymentMethod = {
1524            type: 'CARD',
1525            parameters: {
1526                allowedAuthMethods: googleAllowedCardAuthMethods,
1527                allowedCardNetworks: googleAllowedCardNetworks
1528            }
1529        };
1530
1531        const button =
1532            googlePaymentsClient.createButton({
1533                onClick: onGooglePaymentButtonClicked,
1534                allowedPaymentMethods: [baseCardPaymentMethod],
1535                buttonLocale: paypal_checkout_constant.language_short
1536            });
1537
1538        document.getElementById(container).appendChild(button);
1539    }
1540    catch(e){
1541        console.log('addGooglePayButton', e);
1542    }
1543}
1544
1545async function onGooglePaymentButtonClicked()
1546{
1547    let xt_form = ppcGetCheckoutForm();
1548    let xt_form_valid = xtSimpleCheckForm_ppc(xt_form, true, true)
1549
1550    if(xt_form_valid) {
1551        const paymentDataRequest = await getGooglePaymentDataRequest();
1552        const paymentsClient = getGooglePaymentsClient(googlePaymentsEnvironment);
1553
1554        await paymentsClient.loadPaymentData(paymentDataRequest).then(result => {
1555            console.log('result' , result);
1556            //alert('reload');
1557            //window.location.reload();
1558            window.location.replace(baseUrl + '?page=checkout&page_action=payment_process')
1559        }).catch(err => {
1560            console.log('Google Pay loadPaymentData error/cancel', err);
1561        });
1562    }
1563}
1564
1565function onGooglePaymentDataChanged(intermediatePaymentData)
1566{
1567    console.log('intermediatePaymentData', intermediatePaymentData);
1568
1569    return new Promise(function(resolve, reject) {
1570
1571        let shippingAddress = intermediatePaymentData.shippingAddress;
1572        let shippingOptionData = intermediatePaymentData.shippingOptionData;
1573        let paymentDataRequestUpdate = {};
1574
1575        if (intermediatePaymentData.callbackTrigger === "INITIALIZE" || intermediatePaymentData.callbackTrigger === "SHIPPING_ADDRESS") {
1576            if(false && shippingAddress.administrativeArea === "NJ") { // beispiel
1577                paymentDataRequestUpdate.error = getGoogleUnserviceableAddressError();
1578            }
1579            else {
1580                paymentDataRequestUpdate.newShippingOptionParameters = getGoogleDefaultShippingOptions();
1581                let selectedShippingOptionId = paymentDataRequestUpdate.newShippingOptionParameters.defaultSelectedOptionId;
1582                paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(selectedShippingOptionId);
1583            }
1584        }
1585        else if (intermediatePaymentData.callbackTrigger === "SHIPPING_OPTION") {
1586            paymentDataRequestUpdate.newTransactionInfo = calculateNewTransactionInfo(shippingOptionData.id);
1587        }
1588
1589        resolve(paymentDataRequestUpdate);
1590    });
1591}
1592
1593function onGooglePaymentAuthorized(paymentData)
1594{
1595    console.log("onGooglePaymentAuthorized", 'paymentData', paymentData);
1596
1597    return new Promise(function (resolve, reject) {
1598
1599        processPayment(paymentData)
1600            .then(function (data) {
1601                resolve({ transactionState: "SUCCESS" });
1602                console.log('processPayment.then', data);
1603                if(data && data.error)
1604                {
1605                    alert(data.error.message);
1606                    window.location.reload();
1607                }
1608            })
1609            .catch(error => {
1610                console.log('processPayment.catch', error);
1611
1612                ppcp_log_js('error onGooglePaymentAuthorized > processPayment', paymentData, error );
1613
1614                resolve({
1615                    transactionState: "ERROR",
1616                    error: {
1617                        message: error.message,
1618                    },
1619                });
1620            });
1621    });
1622}
1623
1624async function processPayment(paymentData)
1625{
1626    console.log("processPayment", 'paymentData', paymentData);
1627
1628    try {
1629        let orderId = await ppcCreateOrder({}, null);
1630
1631        const { status } = await paypal.Googlepay().confirmOrder({
1632            orderId: orderId,
1633            paymentMethodData: paymentData.paymentMethodData,
1634        });
1635
1636        if (status === "APPROVED") {
1637            /* Capture the Order */
1638            console.log('capturing g-pay order');
1639            const captureResponse = await ppcCaptureOrder(orderId);
1640            console.log('getting g-pay order');
1641            const orderResponse = await ppcGetOrder(orderId);
1642            console.log('checking captureResponse === orderId');
1643            if(captureResponse === orderId)
1644                return { transactionState: "SUCCESS" };
1645            else
1646            {
1647                console.error('error google processPayment: createOrderId does not match captureOrderId', {payment_data: paymentData, captureResponse:captureResponse} );
1648                ppcp_log_js('error google processPayment: createOrderId does not match captureOrderId', {payment_data: paymentData, captureResponse:captureResponse} );
1649                return {
1650                    transactionState: "ERROR",
1651                    error: {
1652                        message: "createOrderId does not match captureOrderId",
1653                    }
1654                };
1655            }
1656        }
1657        else if (status === "PAYER_ACTION_REQUIRED") {
1658            console.log("==== Confirm Payment Completed Payer Action Required =====");
1659
1660            let isTimedOut = false;
1661
1662            const payerActionPromise = (async () => {
1663                await paypal
1664                    .Googlepay()
1665                    .initiatePayerAction({orderId: orderId});
1666
1667                console.log("===== Payer Action Completed =====");
1668
1669                const orderResponse = await ppcGetOrder(orderId);
1670
1671                ppcp_log_js('check order if already captured', {
1672                    orderResponse: orderResponse
1673                });
1674
1675                console.log("===== 3DS Contingency Result Fetched =====");
1676                console.log(
1677                    orderResponse?.payment_source?.google_pay?.card?.authentication_result
1678                );
1679
1680                if(isTimedOut)
1681                {
1682                    controller.abort();
1683                    console.error('error google processPayment: payerActionPromise timed out');
1684                    return {
1685                        transactionState: "ERROR",
1686                        error: {
1687                            message: "Timed out waiting for Payer Action",
1688                        },
1689                    };
1690                }
1691
1692                const captureResponse = await ppcCaptureOrder(orderId);
1693
1694                if (orderId === orderResponse?.id && orderId === captureResponse) {
1695                    return {transactionState: "SUCCESS"};
1696                } else {
1697                    return {
1698                        transactionState: "ERROR",
1699                        error: {
1700                            message: "createOrderId does not match captureOrderId",
1701                        },
1702                    };
1703                }
1704            })();
1705
1706            const timeoutPromise = new Promise((resolve) => {
1707                setTimeout(() => {
1708                    isTimedOut = true;
1709                    resolve({
1710                        transactionState: "ERROR",
1711                        error: {
1712                            message: "Payer action timed out",
1713                        },
1714                    });
1715                }, 29000);
1716            });
1717
1718            let r = await Promise.race([payerActionPromise, timeoutPromise]);
1719            console.log('race winner', r);
1720
1721            return r;
1722        }
1723        else {
1724            console.error('error google processPayment ', { paymentData: paymentData, status: status } );
1725            ppcp_log_js('error google processPayment ', {paymentData: paymentData, status: status} );
1726            return { transactionState: "ERROR" };
1727        }
1728
1729    } catch (err) {
1730        console.error("error google processPayment", err);
1731        return {
1732            transactionState: "ERROR",
1733            error: {
1734                message: err.message,
1735            },
1736        };
1737    }
1738}
1739
1740async function getGooglePaymentDataRequest()
1741{
1742    const paymentDataRequest = Object.assign({}, googleBaseRequest);
1743
1744    paymentDataRequest.allowedPaymentMethods    = googlePayConfig.allowedPaymentMethods;
1745    paymentDataRequest.merchantInfo             = googlePayConfig.merchantInfo;
1746    paymentDataRequest.transactionInfo          = getGoogleTransactionInfo();
1747    paymentDataRequest.shippingAddressRequired  = false;
1748    paymentDataRequest.callbackIntents          = ["PAYMENT_AUTHORIZATION"];
1749
1750    return paymentDataRequest;
1751}
1752
1753function getGoogleTransactionInfo(){
1754
1755    return google_transaction_info;
1756}
1757
1758function getGooglePaymentsClient(environment)
1759{
1760    let env = environment || googlePaymentsEnvironment;
1761
1762    return new google.payments.api.PaymentsClient({
1763        environment: env,
1764        paymentDataCallbacks: {
1765            //onPaymentDataChanged: onGooglePaymentDataChanged, // später im cart
1766            onPaymentAuthorized: onGooglePaymentAuthorized
1767        }
1768    });
1769}
1770

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.