Plugin Directory

Changeset 3464247


Ignore:
Timestamp:
02/18/2026 11:05:05 AM (3 weeks ago)
Author:
payplus
Message:

Payplus gateway version 8.0.6

Location:
payplus-payment-gateway/trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • payplus-payment-gateway/trunk/CHANGELOG.md

    r3461765 r3464247  
    22
    33All notable changes to this project will be documented in this file.
     4
     5## [8.0.6]  - 18-02-2026 - (Bliss)
     6
     7- Tweak     - Added automatic polling fallback for iframe payment redirects in both blocks and classic checkouts. This ensures reliable redirects for Firefox users and other scenarios where the iframe cannot communicate via postMessage. The system polls the server for order completion status and redirects to the thank-you page automatically.
     8- Fix       - Fixed EMV POS device functionality issue when only one admin user was configured.
    49
    510## [8.0.5]  - 15-02-2026 - (Vaturi)
  • payplus-payment-gateway/trunk/assets/js/checkout.js

    r3458643 r3464247  
    5252    });
    5353
    54     // Firefox blocks cross-origin iframe from navigating top window. When PayPlus iframe sends
    55     // postMessage with redirect URL (or thank-you page loads in iframe), parent performs the redirect.
     54    // ── Firefox-safe iframe redirect: 3-layer approach ──────────────────────
     55    //
     56    // Layer 1 (sandbox): The iframe has sandbox="allow-top-navigation-by-user-activation"
     57    //   so if the user clicked inside the iframe, Firefox allows top navigation natively.
     58    //
     59    // Layer 2 (postMessage fast-path): When ipn_response finishes inside the iframe,
     60    //   it sends a postMessage with the redirect URL. The parent picks it up here
     61    //   and redirects immediately — no polling delay.
     62    //
     63    // Layer 3 (polling fallback): If both above fail (e.g. cross-origin, no user gesture),
     64    //   the parent polls the server every 1.5s for order status and redirects when
     65    //   the order moves to processing/completed.
     66    //
     67    // Together these three layers guarantee a redirect in every browser.
     68    // ──────────────────────────────────────────────────────────────────────────
     69
     70    var _payplusPollDone = false; // shared flag so postMessage can cancel polling
     71
     72    // Layer 2: postMessage listener (fast-path)
    5673    window.addEventListener('message', function(e) {
    5774        if (!e.data || e.data.type !== 'payplus_redirect' || !e.data.url) {
     
    6178            var u = new URL(e.data.url, window.location.origin);
    6279            if (u.origin === window.location.origin) {
     80                _payplusPollDone = true; // cancel any active polling
    6381                window.location.href = e.data.url;
    6482            }
     
    6785        }
    6886    });
     87
     88    // Layer 3: polling fallback
     89    function startOrderStatusPoll(result) {
     90        if (!result || !result.order_id || !result.order_received_url) return;
     91
     92        var redirectUrl = result.order_received_url;
     93        var orderKey = '';
     94        try {
     95            var u = new URL(redirectUrl, window.location.origin);
     96            orderKey = u.searchParams.get('key') || '';
     97        } catch (err) {
     98            return;
     99        }
     100        if (!orderKey) return;
     101
     102        var pollCount = 0;
     103        var maxPolls = 200; // ~5 min at 1.5s interval
     104
     105        function poll() {
     106            if (_payplusPollDone) return;
     107            pollCount++;
     108            if (pollCount > maxPolls) return;
     109
     110            jQuery.ajax({
     111                url: payplus_script_checkout.ajax_url,
     112                type: 'POST',
     113                data: {
     114                    action: 'payplus_check_order_redirect',
     115                    _ajax_nonce: payplus_script_checkout.frontNonce,
     116                    order_id: result.order_id,
     117                    order_key: orderKey,
     118                },
     119                dataType: 'json',
     120                success: function(res) {
     121                    if (_payplusPollDone) return;
     122                    if (res && res.success && res.data && res.data.status) {
     123                        var s = res.data.status;
     124                        if (s === 'processing' || s === 'completed' || s === 'wc-processing' || s === 'wc-completed') {
     125                            _payplusPollDone = true;
     126                            window.location.href = res.data.redirect_url || redirectUrl;
     127                        }
     128                    }
     129                },
     130            });
     131        }
     132
     133        // First poll immediately, then every 1.5s
     134        poll();
     135        var pollTimer = setInterval(function() {
     136            if (_payplusPollDone) {
     137                clearInterval(pollTimer);
     138                return;
     139            }
     140            poll();
     141        }, 1500);
     142    }
    69143
    70144    //function to hide other payment methods when subscription order
     
    10371111                                    );
    10381112                                }
     1113                                // Start polling for order completion (Layer 3 fallback)
     1114                                // Only in new mode — legacy mode relies on direct redirect from iframe.
     1115                                if (!payplus_script_checkout.iframeRedirectLegacy) {
     1116                                    startOrderStatusPoll(result);
     1117                                }
    10391118                                return true;
    10401119                            }
     
    14891568        iframe.setAttribute("style", `border:0px`);
    14901569        iframe.setAttribute("allowpaymentrequest", "allowpaymentrequest");
     1570        // In new (default) mode: sandbox the iframe so Firefox allows top navigation
     1571        // only after a user gesture, avoiding the "prevented redirect" prompt.
     1572        // In legacy mode: skip sandbox so the old direct wp_safe_redirect works as before.
     1573        if (!payplus_script_checkout.iframeRedirectLegacy) {
     1574            iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation-by-user-activation");
     1575        }
    14911576        return iframe;
    14921577    }
  • payplus-payment-gateway/trunk/assets/js/checkout.min.js

    r3458643 r3464247  
    1 jQuery(function(e){if("undefined"==typeof wc_checkout_params)return!1;let t=payplus_script_checkout.hostedFieldsIsMain,o=payplus_script_checkout.iframeAutoHeight,a="payment_method_payplus-payment-gateway-hostedfields";var n=jQuery("body > div.container.hostedFields");let i=!0;e.blockUI.defaults.overlayCSS.cursor="default";let c=Object.keys(payplus_script_checkout.hasSavedTokens);function s(){if(!(jQuery(".pp_iframe").length>0||jQuery(".pp_iframe_h").length>0||jQuery("#pp_iframe").length>0)){const e=jQuery(".payment_method_payplus-payment-gateway-hostedfields");if(e.length>0){e.hide(),jQuery(".payment_box.payment_method_payplus-payment-gateway-hostedfields").hide();const t=jQuery("input#payment_method_payplus-payment-gateway-hostedfields");t.is(":checked")&&jQuery("input#payment_method_payplus-payment-gateway").prop("checked",!0).trigger("change"),t.prop("disabled",!0)}}}s(),setTimeout(s,100),setTimeout(s,500),jQuery(document.body).on("updated_checkout",function(){s()}),window.addEventListener("message",function(e){if(e.data&&"payplus_redirect"===e.data.type&&e.data.url)try{new URL(e.data.url,window.location.origin).origin===window.location.origin&&(window.location.href=e.data.url)}catch(e){}});var r={updateTimer:!1,dirtyInput:!1,selectedPaymentMethod:!1,xhr:!1,$order_review:e("#order_review"),$checkout_form:e("form.checkout"),init:function(){e(document.body).on("update_checkout",this.update_checkout),e(document.body).on("init_checkout",this.init_checkout),this.$checkout_form.on("click",'input[name="payment_method"]',this.payment_method_selected),e(document.body).hasClass("woocommerce-order-pay")&&(this.$order_review.on("click",'input[name="payment_method"]',this.payment_method_selected),this.$order_review.on("submit",this.submitOrder),this.$order_review.attr("novalidate","novalidate")),this.$checkout_form.attr("novalidate","novalidate"),this.$checkout_form.on("submit",this.submit),this.$checkout_form.on("input validate change",".input-text, select, input:checkbox",this.validate_field),this.$checkout_form.on("update",this.trigger_update_checkout),this.$checkout_form.on("change",'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]',this.trigger_update_checkout),this.$checkout_form.on("change",".address-field select",this.input_changed),this.$checkout_form.on("change",".address-field input.input-text, .update_totals_on_change input.input-text",this.maybe_input_changed),this.$checkout_form.on("keydown",".address-field input.input-text, .update_totals_on_change input.input-text",this.queue_update_checkout),this.$checkout_form.on("change","#ship-to-different-address input",this.ship_to_different_address),this.$checkout_form.find("#ship-to-different-address input").trigger("change"),this.init_payment_methods(),"1"===wc_checkout_params.is_checkout&&e(document.body).trigger("init_checkout"),"yes"===wc_checkout_params.option_guest_checkout&&e("input#createaccount").on("change",this.toggle_create_account).trigger("change")},init_payment_methods:function(){var t=e(".woocommerce-checkout").find('input[name="payment_method"]');1===t.length&&t.eq(0).hide(),r.selectedPaymentMethod&&e("#"+r.selectedPaymentMethod).prop("checked",!0),0===t.filter(":checked").length&&t.eq(0).prop("checked",!0);var o=t.filter(":checked").eq(0).prop("id");t.length>1&&e('div.payment_box:not(".'+o+'")').filter(":visible").slideUp(0),t.filter(":checked").eq(0).trigger("click")},get_payment_method:function(){return r.$checkout_form.find('input[name="payment_method"]:checked').val()},payment_method_selected:function(t){if(h(!0),t.stopPropagation(),e(".payment_methods input.input-radio").length>1){var o=e("div.payment_box."+e(this).attr("ID")),a=e(this).is(":checked");a&&!o.is(":visible")&&(e("div.payment_box").filter(":visible").slideUp(230),a&&o.slideDown(230))}e(this).data("order_button_text")?e("#place_order").text(e(this).data("order_button_text")):e("#place_order").text(e("#place_order").data("value"));var n=e('.woocommerce-checkout input[name="payment_method"]:checked').attr("id");n!==r.selectedPaymentMethod&&e(document.body).trigger("payment_method_selected"),r.selectedPaymentMethod=n},toggle_create_account:function(){e("div.create-account").hide(),e(this).is(":checked")&&(e("#account_password").val("").trigger("change"),e("div.create-account").slideDown())},init_checkout:function(){e(document.body).trigger("update_checkout")},maybe_input_changed:function(e){r.dirtyInput&&r.input_changed(e)},input_changed:function(e){r.dirtyInput=e.target,r.maybe_update_checkout()},queue_update_checkout:function(e){if(9===(e.keyCode||e.which||0))return!0;r.dirtyInput=this,r.reset_update_checkout_timer(),r.updateTimer=setTimeout(r.maybe_update_checkout,"1000")},trigger_update_checkout:function(){r.reset_update_checkout_timer(),r.dirtyInput=!1,e(document.body).trigger("update_checkout")},maybe_update_checkout:function(){var t=!0;if(e(r.dirtyInput).length){var o=e(r.dirtyInput).closest("div").find(".address-field.validate-required");o.length&&o.each(function(){""===e(this).find("input.input-text").val()&&(t=!1)})}t&&r.trigger_update_checkout()},ship_to_different_address:function(){e("div.shipping_address").hide(),e(this).is(":checked")&&e("div.shipping_address").slideDown()},reset_update_checkout_timer:function(){clearTimeout(r.updateTimer)},is_valid_json:function(e){try{var t=JSON.parse(e);return t&&"object"==typeof t}catch(e){return!1}},validate_field:function(t){var o=e(this),a=o.closest(".form-row"),n=!0,i=a.is(".validate-required"),c=a.is(".validate-email"),s=a.is(".validate-phone"),r="",p=t.type;"input"===p&&a.removeClass("woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-invalid-phone woocommerce-validated"),"validate"!==p&&"change"!==p||(i&&("checkbox"!==o.attr("type")||o.is(":checked")?""===o.val()&&(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-required-field"),n=!1):(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-required-field"),n=!1)),c&&o.val()&&((r=new RegExp(/^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i)).test(o.val())||(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-email woocommerce-invalid-phone"),n=!1)),s&&(r=new RegExp(/[\s\#0-9_\-\+\/\(\)\.]/g),0<o.val().replace(r,"").length&&(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-phone"),n=!1)),n&&a.removeClass("woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-invalid-phone").addClass("woocommerce-validated"))},update_checkout:function(e,t){r.reset_update_checkout_timer(),r.updateTimer=setTimeout(r.update_checkout_action,"5",t)},update_checkout_action:function(o){if(r.xhr&&r.xhr.abort(),0!==e("form.checkout").length){o=void 0!==o?o:{update_shipping_method:!0};var s=e("#billing_country").val(),p=e("#billing_state").val(),d=e(":input#billing_postcode").val(),u=e("#billing_city").val(),m=e(":input#billing_address_1").val(),l=e(":input#billing_address_2").val(),h=s,_=p,y=d,f=u,g=m,k=l,v=e(r.$checkout_form).find(".address-field.validate-required:visible"),w=!0;v.length&&v.each(function(){""===e(this).find(":input").val()&&(w=!1)}),e("#ship-to-different-address").find("input").is(":checked")&&(h=e("#shipping_country").val(),_=e("#shipping_state").val(),y=e(":input#shipping_postcode").val(),f=e("#shipping_city").val(),g=e(":input#shipping_address_1").val(),k=e(":input#shipping_address_2").val());var b={security:wc_checkout_params.update_order_review_nonce,payment_method:r.get_payment_method(),country:s,state:p,postcode:d,city:u,address:m,address_2:l,s_country:h,s_state:_,s_postcode:y,s_city:f,s_address:g,s_address_2:k,has_full_address:w,post_data:e("form.checkout").serialize()};if(!1!==o.update_shipping_method){var F={};e('select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]').each(function(){F[e(this).data("index")]=e(this).val()}),b.shipping_method=F}e(".woocommerce-checkout-payment, .woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),r.xhr=e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","update_order_review"),data:b,success:function(o){if(o&&!0===o.reload)return void window.location.reload();e(".woocommerce-NoticeGroup-updateOrderReview").remove();var s=e("#terms").prop("checked"),p={};if(e(".payment_box :input").each(function(){var t=e(this).attr("id");t&&(-1!==e.inArray(e(this).attr("type"),["checkbox","radio"])?p[t]=e(this).prop("checked"):p[t]=e(this).val())}),payplus_script_checkout.isHostedFields&&0===c.length&&payplus_script_checkout.hidePPGateway){const e=function(e,t){const o=document.createElement("div");o.innerHTML=e;o.querySelectorAll(`.${t}`).forEach(e=>{e.remove()});return o.innerHTML}(o.fragments[".woocommerce-checkout-payment"],"wc_payment_method.payment_method_payplus-payment-gateway");o.fragments[".woocommerce-checkout-payment"]=e}e(".hostedFields").prop("outerHTML");o&&o.fragments&&(e.each(o.fragments,function(t,o){if(!r.fragments||r.fragments[t]!==o){e(t).replaceWith(o),payplus_script_checkout.isSubscriptionOrder&&e(".wc_payment_methods.payment_methods.methods .wc_payment_method").each(function(){e(this).attr("class").split(/\s+/).forEach(function(t){payplus_script_checkout.isLoggedIn?t.startsWith("payment_method_payplus-payment-gateway-")&&"payment_method_payplus-payment-gateway-hostedfields"!==t&&e(this).remove():t.startsWith("payment_method_payplus-payment-gateway-")&&e(this).remove()}.bind(this))}),document.querySelector("#payplus-checkout-image-div")||function(){if(void 0!==payplus_script_checkout?.customIcons[0]&&payplus_script_checkout?.customIcons[0]?.length>0){var t=e("<div></div>",{class:"payplus-checkout-image-container",id:"payplus-checkout-image-div",style:"display: flex;flex-wrap: wrap;justify-content: center;"});e.each(payplus_script_checkout.customIcons,function(o,a){var n=e("<img>",{src:a,class:"payplus-checkout-image",alt:"Image "+(o+1),style:"max-width: 100%; max-height:35px;object-fit: contain;"});t.append(n)}),e("div.payment_method_payplus-payment-gateway").prepend(t)}}();!function(){const e=document.querySelector("#payment_method_payplus-payment-gateway-multipass");if(e&&Object.keys(payplus_script_checkout.multiPassIcons).length>0){const n=payplus_script_checkout.multiPassIcons;function t(e){let t=document.querySelectorAll("img");for(let o of t)if(o.src.includes(e))return o;return null}function o(e,t){e&&t&&(e.style.height="32px",e.style.width="32px",e.style.transition="opacity 0.5s",e.style.opacity=0,setTimeout(()=>{e.src=t,e.style.opacity=1},500))}if(e){let i=t("multipassLogo.png");if(i){i.src;let c=0;const s=Object.keys(n).map(e=>n[e]);function a(){const e=s[c];o(i,e),c=(c+1)%s.length,Object.keys(payplus_script_checkout.multiPassIcons).length>1&&setTimeout(a,2e3)}a()}}}}()}e(t).unblock(),"undefined"!=typeof newPpShippingMethods&&createNewShippingMethods()}),payplus_script_checkout.isHostedFields&&h(a,t),r.fragments=o.fragments,"pp_iframe_h"===n.parent().attr("class")&&function(){if(payplus_script_checkout.isHostedFields){if(!(jQuery(".pp_iframe").length>0||jQuery(".pp_iframe_h").length>0))return jQuery(".payment_method_payplus-payment-gateway-hostedfields").hide(),void(jQuery("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")&&jQuery("input#payment_method_payplus-payment-gateway").prop("checked",!0).trigger("change"));if(i){i=!1;var o=e('<p class="hf-save form-row"><label for="save_token_checkbox"><input type="checkbox" name="wc-save-token" id="save_token_checkbox" value="1" style="margin:0 10px 0 10px;"/> '+payplus_script_checkout.saveCreditCard+"</label></p>");payplus_script_checkout.isLoggedIn&&payplus_script_checkout.isSavingCerditCards&&n.append(o),t?setTimeout(function(){e("input#"+a).prop("checked",!0),e("div.container.hostedFields").show()},1e3):setTimeout(function(){e(".payment_method_payplus-payment-gateway").css("display","block"),e("input#"+a).removeAttr("checked"),e(".container.hostedFields").hide(),e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").hide(),e("input#payment_method_payplus-payment-gateway").prop("checked",!0)},1e3)}e(document).on("change",'input[name="payment_method"]',function(){e("input#"+a).is(":checked")?e("div.container.hostedFields").show():e(".container.hostedFields").hide()})}}());let d=!1;if(d)return;d=!0;var u=e('input[name="shipping_method[0]"]:checked').closest("li").find("label").text();""===u&&(u=e('input[name="shipping_method[0]"]').closest("li").find("label").text());var m=u.match(/(\$|₪)\s*([0-9.,]+)|([0-9.,]+)\s*(\$|₪)/);let l=0;if(m){m[1]||m[4];l=m[2]||m[3]}function h(t,o){o&&(e(".woocommerce-SavedPaymentMethods-new").hide(),e(".woocommerce-SavedPaymentMethods-saveNew").hide()),setTimeout(function(){if(e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")){e(".container.hostedFields").show();const t=document.querySelector(".pp_iframe_h");t&&(t.style.display="block")}},2e3);var a=jQuery("#"+t),i=jQuery(".pp_iframe_h"),c=jQuery(".wc_payment_method."+t);let s=n.find(".hf-main").first();a.length&&i.length&&n.length&&(payplus_script_checkout.hostedFieldsWidth&&s.attr("style",function(e,t){return"width: "+payplus_script_checkout.hostedFieldsWidth+"% !important;"+(t?" "+t:"")}),i.append(n),c.append(i))}if(payplus_script_checkout.isHostedFields&&e(document.body).on("updated_checkout",function(){h(a,t)}),s&&e("#terms").prop("checked",!0),e.isEmptyObject(p)||e(".payment_box :input").each(function(){var t=e(this).attr("id");t&&(-1!==e.inArray(e(this).attr("type"),["checkbox","radio"])?e(this).prop("checked",p[t]).trigger("change"):(-1!==e.inArray(e(this).attr("type"),["select"])||null!==e(this).val()&&0===e(this).val().length)&&e(this).val(p[t]).trigger("change"))}),o&&"failure"===o.result){var _=e("form.checkout");e(".woocommerce-error, .woocommerce-message").remove(),o.messages?_.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-updateOrderReview">'+o.messages+"</div>"):_.prepend(o),_.find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),r.scroll_to_notices()}r.init_payment_methods(),e(document.body).trigger("updated_checkout",[o])}})}},handleUnloadEvent:function(e){if(-1===navigator.userAgent.indexOf("MSIE")&&!document.documentMode)return!0;e.preventDefault()},attachUnloadEventsOnSubmit:function(){e(window).on("beforeunload",this.handleUnloadEvent)},detachUnloadEventsOnSubmit:function(){e(window).off("beforeunload",this.handleUnloadEvent)},blockOnSubmit:function(t){1!==t.data("blockUI.isBlocked")&&(t.block({message:null,overlayCSS:{top:0,height:"100%",background:"#fff",opacity:.6}}),e(".blockUI.blockOverlay").css("position","fixed"))},submitOrder:function(){r.blockOnSubmit(e(this))},submit:function(){r.reset_update_checkout_timer();var t=e(this);return t.is(".processing")||!1!==t.triggerHandler("checkout_place_order")&&!1!==t.triggerHandler("checkout_place_order_"+r.get_payment_method())&&(t.addClass("processing"),r.blockOnSubmit(t),r.attachUnloadEventsOnSubmit(),e.ajaxSetup({dataFilter:function(e,t){if("json"!==t)return e;if(r.is_valid_json(e))return e;var o=e.match(/{"result.*}/);return null===o||r.is_valid_json(o[0])&&(e=o[0]),e}}),e.ajax({type:"POST",url:wc_checkout_params.checkout_url,data:t.serialize(),dataType:"json",success:function(o){if("hostedFields"===o.method)jQuery.ajax({type:"post",dataType:"json",url:payplus_script_checkout.ajax_url,data:{action:"get-hosted-payload",_ajax_nonce:payplus_script_checkout.frontNonce},success:function(e){const t=JSON.parse(e.data.hostedPayload);JSON.parse(e.data.hostedResponse);t.more_info&&!isNaN(t.more_info)&&"number"==typeof t.more_info?(overlay(),jQuery(".blocks-payplus_loader_hosted").fadeIn(),r.$checkout_form.removeClass("processing").unblock(),hf.SubmitPayment()):(window.onbeforeunload=null,window.removeEventListener("beforeunload",r.detachUnloadEventsOnSubmit()),alert("The payment page has expired, refresh the page to continue"),location.reload())}});else{if(r.detachUnloadEventsOnSubmit(),o.payplus_iframe&&"success"===o.result)return r.$checkout_form.removeClass("processing").unblock(),"samePageIframe"==o.viewMode?function(t){e(".alertify").remove();const o=new URL(window.location.href);o.searchParams.set("payplus-iframe","1"),window.history.pushState({},"",o);const a=document.querySelector(".pp_iframe"),n=a.getAttribute("data-height");a.innerHTML="",a.append(f(t,"100%",n)),e("#closeFrame").on("click",function(e){e.preventDefault(),a.style.display="none"}),e("#place_order").prop("disabled",!0),payplus_script_checkout.payplus_mobile&&e("html, body").animate({scrollTop:e(".place-order").offset().top});y()}(o.payplus_iframe.data.payment_page_link):"popupIframe"==o.viewMode&&function(e,t){let o=window.innerWidth;o<568&&(t="100%");alertify.popupIframePaymentPage||alertify.dialog("popupIframePaymentPage",function(){return{main:function(e){this.message=f(e,"100%",t),y()},setup:function(){return{options:{autoReset:!1,overflow:!1,maximizable:!1,movable:!1,frameless:!0,transition:"fade"},focus:{element:0}}},prepare:function(){this.setContent(this.message)},hooks:{onshow:function(){this.elements.dialog.style.maxWidth="100%",this.elements.dialog.style.width=o>768?payplus_script_checkout.iframeWidth||"40%":"98%",this.elements.dialog.style.height=o>568?"82%":"100%",this.elements.content.style.top="25px"}}}});alertify.popupIframePaymentPage(e)}(o.payplus_iframe.data.payment_page_link,700),!0;try{if("success"!==o.result||!1===t.triggerHandler("checkout_place_order_success",o))throw"failure"===o.result?"Result failure":"Invalid response";-1===o.redirect.indexOf("https://")||-1===o.redirect.indexOf("http://")?window.location=o.redirect:window.location=decodeURI(o.redirect)}catch(t){if(!0===o.reload)return void window.location.reload();!0===o.refresh&&e(document.body).trigger("update_checkout"),o.messages?r.submit_error(o.messages):r.submit_error('<div class="woocommerce-error">'+wc_checkout_params.i18n_checkout_error+"</div>")}}},error:function(e,t,o){r.detachUnloadEventsOnSubmit(),r.submit_error('<div class="woocommerce-error">'+o+"</div>")}})),!1},submit_error:function(t){e(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),r.$checkout_form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+t+"</div>"),r.$checkout_form.removeClass("processing").unblock(),r.$checkout_form.find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),r.scroll_to_notices(),e(document.body).trigger("checkout_error",[t])},scroll_to_notices:function(){var t=e(".woocommerce-NoticeGroup-updateOrderReview, .woocommerce-NoticeGroup-checkout");t.length||(t=e(".form.checkout")),e.scroll_to_notices(t)}},p={init:function(){e(document.body).on("click","a.showcoupon",this.show_coupon_form),e(document.body).on("click",".woocommerce-remove-coupon",this.remove_coupon),e("form.checkout_coupon").hide().on("submit",this.submit)},show_coupon_form:function(){return e(".checkout_coupon").slideToggle(400,function(){e(".checkout_coupon").find(":input:eq(0)").trigger("focus")}),!1},submit:function(){var t=e(this);if(t.is(".processing"))return!1;t.addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var o={security:wc_checkout_params.apply_coupon_nonce,coupon_code:t.find('input[name="coupon_code"]').val()};return e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","apply_coupon"),data:o,success:function(a){e(".woocommerce-error, .woocommerce-message").remove(),t.removeClass("processing").unblock(),a&&(t.before(a),t.slideUp(),e(document.body).trigger("applied_coupon_in_checkout",[o.coupon_code]),e(document.body).trigger("update_checkout",{update_shipping_method:!1}))},dataType:"html"}),!1},remove_coupon:function(t){t.preventDefault();var o=e(this).parents(".woocommerce-checkout-review-order"),a=e(this).data("coupon");o.addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var n={security:wc_checkout_params.remove_coupon_nonce,coupon:a};e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","remove_coupon"),data:n,success:function(t){e(".woocommerce-error, .woocommerce-message").remove(),o.removeClass("processing").unblock(),t&&(e("form.woocommerce-checkout").before(t),e(document.body).trigger("removed_coupon_in_checkout",[n.coupon_code]),e(document.body).trigger("update_checkout",{update_shipping_method:!1}),e("form.checkout_coupon").find('input[name="coupon_code"]').val(""))},error:function(){},dataType:"html"})}},d={init:function(){e(document.body).on("click","a.showlogin",this.show_login_form)},show_login_form:function(){return e("form.login, form.woocommerce-form--login").slideToggle(),!1}},u={init:function(){e(document.body).on("click","a.woocommerce-terms-and-conditions-link",this.toggle_terms)},toggle_terms:function(){if(e(".woocommerce-terms-and-conditions").length)return e(".woocommerce-terms-and-conditions").slideToggle(function(){var t=e(".woocommerce-terms-and-conditions-link");e(".woocommerce-terms-and-conditions").is(":visible")?(t.addClass("woocommerce-terms-and-conditions-link--open"),t.removeClass("woocommerce-terms-and-conditions-link--closed")):(t.removeClass("woocommerce-terms-and-conditions-link--open"),t.addClass("woocommerce-terms-and-conditions-link--closed"))}),!1}};if(r.init(),p.init(),d.init(),u.init(),payplus_script_checkout.hostedFieldsIsMain){var m=function(){e("li.payment_method_payplus-payment-gateway").attr("style","display: none !important;")};function l(){var t=e("input#payment_method_payplus-payment-gateway-hostedfields");t.length&&(t.is(":checked")||t.prop("checked",!0).trigger("change"),e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").show().css("display","block"))}m(),e(document.body).on("updated_checkout",function(){m(),l()}),setTimeout(function(){m(),l()},100)}if(e(document.body).on("change",'input[name="payment_method"]',function(){"payplus-payment-gateway-hostedfields"===e('input[name="payment_method"]:checked').val()&&e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").show()}),e(document.body).on("click","#place_order",function(t){var o=e('input[name="wc-payplus-payment-gateway-payment-token"]:checked').val(),a=e("input#payment_method_payplus-payment-gateway-hostedfields"),n=e("input#payment_method_payplus-payment-gateway");if(a.is(":checked")&&o&&"new"!==o){if(0===n.length)return alert("Error: Payment method not available for saved cards. Please contact support."),t.preventDefault(),!1;n.prop("checked",!0),a.prop("checked",!1)}}),e(document.body).on("change",'input[name="wc-payplus-payment-gateway-payment-token"]',function(){var t=e(this).val(),o=e("input#payment_method_payplus-payment-gateway-hostedfields"),a=e(".payment_method_payplus-payment-gateway"),n=e("input#payment_method_payplus-payment-gateway");if(o.is(":checked"))if("new"!==t){if(0===a.length){e(".payment_method_payplus-payment-gateway-hostedfields").before('<li class="wc_payment_method payment_method_payplus-payment-gateway" style="display:none !important;"><input id="payment_method_payplus-payment-gateway" type="radio" class="input-radio" name="payment_method" value="payplus-payment-gateway" /><label for="payment_method_payplus-payment-gateway">PayPlus</label><div class="payment_box payment_method_payplus-payment-gateway"></div></li>'),n=e("input#payment_method_payplus-payment-gateway")}else a.css("display","none");n.prop("checked",!0),e("body").attr("data-payplus-using-token","yes")}else o.prop("checked",!0),e("body").attr("data-payplus-using-token","no")}),e(document.body).on("click touchstart",".pp_iframe_h, .pp_iframe_h *",function(t){e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")&&(e('input[name="wc-payplus-payment-gateway-payment-token"]:checked').prop("checked",!1),e("input#wc-payplus-payment-gateway-payment-token-new").prop("checked",!0).trigger("change"))}),payplus_script_checkout.hostedFieldsIsMain)setInterval(function(){var t=e(document.activeElement);if(t.is("iframe")&&t.closest(".pp_iframe_h").length&&e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")){var o=e('input[name="wc-payplus-payment-gateway-payment-token"]:checked');o.length&&"new"!==o.val()&&(o.prop("checked",!1),e("input#wc-payplus-payment-gateway-payment-token-new").prop("checked",!0).trigger("change"))}},300);function h(t){e("#pp_iframe").length&&(e("#pp_iframe").is(":visible")||!0===t)&&e("#pp_iframe").fadeOut(()=>{e(".payplus-option-description-area").show(),e("#place_order").prop("disabled",!1)})}e(document.body).on("click touchstart",".pp_iframe_h",function(t){var o=e(this).closest("li.wc_payment_method");if(o.length){var a=o.find('input[name="payment_method"]');a.length&&!a.is(":checked")&&a.prop("checked",!0).trigger("click")}}),e(e(window).on("popstate",()=>{h(!1)}));let _=!1;function y(){if(_)console.log("Apple script already loaded");else{const e=document.createElement("script");e.src=payplus_script_checkout.payplus_import_applepay_script,document.body.append(e),_=!0}}function f(e,t,a){let n=document.createElement("iframe");return n.id="pp_iframe",n.name="payplus-iframe",n.src=e,o?(n.height="100%",n.maxHeight="100vh"):n.height=a,n.width=t,n.setAttribute("style","border:0px"),n.setAttribute("allowpaymentrequest","allowpaymentrequest"),n}});
     1jQuery(function(e){if("undefined"==typeof wc_checkout_params)return!1;let t=payplus_script_checkout.hostedFieldsIsMain,o=payplus_script_checkout.iframeAutoHeight,a="payment_method_payplus-payment-gateway-hostedfields";var n=jQuery("body > div.container.hostedFields");let i=!0;e.blockUI.defaults.overlayCSS.cursor="default";let c=Object.keys(payplus_script_checkout.hasSavedTokens);function s(){if(!(jQuery(".pp_iframe").length>0||jQuery(".pp_iframe_h").length>0||jQuery("#pp_iframe").length>0)){const e=jQuery(".payment_method_payplus-payment-gateway-hostedfields");if(e.length>0){e.hide(),jQuery(".payment_box.payment_method_payplus-payment-gateway-hostedfields").hide();const t=jQuery("input#payment_method_payplus-payment-gateway-hostedfields");t.is(":checked")&&jQuery("input#payment_method_payplus-payment-gateway").prop("checked",!0).trigger("change"),t.prop("disabled",!0)}}}s(),setTimeout(s,100),setTimeout(s,500),jQuery(document.body).on("updated_checkout",function(){s()});var _ppPD=!1;window.addEventListener("message",function(e){if(e.data&&"payplus_redirect"===e.data.type&&e.data.url)try{new URL(e.data.url,window.location.origin).origin===window.location.origin&&(_ppPD=!0,window.location.href=e.data.url)}catch(e){}});function startOrderStatusPoll(e){if(!e||!e.order_id||!e.order_received_url)return;var t=e.order_received_url,o="";try{o=new URL(t,window.location.origin).searchParams.get("key")||""}catch(e){return}if(!o)return;var a=0;function n(){if(!_ppPD&&!(++a>200))jQuery.ajax({url:payplus_script_checkout.ajax_url,type:"POST",data:{action:"payplus_check_order_redirect",_ajax_nonce:payplus_script_checkout.frontNonce,order_id:e.order_id,order_key:o},dataType:"json",success:function(e){if(!_ppPD&&e&&e.success&&e.data&&e.data.status){var o=e.data.status;"processing"!==o&&"completed"!==o&&"wc-processing"!==o&&"wc-completed"!==o||(_ppPD=!0,window.location.href=e.data.redirect_url||t)}}})}n();var i=setInterval(function(){_ppPD?(clearInterval(i),void 0):n()},1500)}var r={updateTimer:!1,dirtyInput:!1,selectedPaymentMethod:!1,xhr:!1,$order_review:e("#order_review"),$checkout_form:e("form.checkout"),init:function(){e(document.body).on("update_checkout",this.update_checkout),e(document.body).on("init_checkout",this.init_checkout),this.$checkout_form.on("click",'input[name="payment_method"]',this.payment_method_selected),e(document.body).hasClass("woocommerce-order-pay")&&(this.$order_review.on("click",'input[name="payment_method"]',this.payment_method_selected),this.$order_review.on("submit",this.submitOrder),this.$order_review.attr("novalidate","novalidate")),this.$checkout_form.attr("novalidate","novalidate"),this.$checkout_form.on("submit",this.submit),this.$checkout_form.on("input validate change",".input-text, select, input:checkbox",this.validate_field),this.$checkout_form.on("update",this.trigger_update_checkout),this.$checkout_form.on("change",'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]',this.trigger_update_checkout),this.$checkout_form.on("change",".address-field select",this.input_changed),this.$checkout_form.on("change",".address-field input.input-text, .update_totals_on_change input.input-text",this.maybe_input_changed),this.$checkout_form.on("keydown",".address-field input.input-text, .update_totals_on_change input.input-text",this.queue_update_checkout),this.$checkout_form.on("change","#ship-to-different-address input",this.ship_to_different_address),this.$checkout_form.find("#ship-to-different-address input").trigger("change"),this.init_payment_methods(),"1"===wc_checkout_params.is_checkout&&e(document.body).trigger("init_checkout"),"yes"===wc_checkout_params.option_guest_checkout&&e("input#createaccount").on("change",this.toggle_create_account).trigger("change")},init_payment_methods:function(){var t=e(".woocommerce-checkout").find('input[name="payment_method"]');1===t.length&&t.eq(0).hide(),r.selectedPaymentMethod&&e("#"+r.selectedPaymentMethod).prop("checked",!0),0===t.filter(":checked").length&&t.eq(0).prop("checked",!0);var o=t.filter(":checked").eq(0).prop("id");t.length>1&&e('div.payment_box:not(".'+o+'")').filter(":visible").slideUp(0),t.filter(":checked").eq(0).trigger("click")},get_payment_method:function(){return r.$checkout_form.find('input[name="payment_method"]:checked').val()},payment_method_selected:function(t){if(h(!0),t.stopPropagation(),e(".payment_methods input.input-radio").length>1){var o=e("div.payment_box."+e(this).attr("ID")),a=e(this).is(":checked");a&&!o.is(":visible")&&(e("div.payment_box").filter(":visible").slideUp(230),a&&o.slideDown(230))}e(this).data("order_button_text")?e("#place_order").text(e(this).data("order_button_text")):e("#place_order").text(e("#place_order").data("value"));var n=e('.woocommerce-checkout input[name="payment_method"]:checked').attr("id");n!==r.selectedPaymentMethod&&e(document.body).trigger("payment_method_selected"),r.selectedPaymentMethod=n},toggle_create_account:function(){e("div.create-account").hide(),e(this).is(":checked")&&(e("#account_password").val("").trigger("change"),e("div.create-account").slideDown())},init_checkout:function(){e(document.body).trigger("update_checkout")},maybe_input_changed:function(e){r.dirtyInput&&r.input_changed(e)},input_changed:function(e){r.dirtyInput=e.target,r.maybe_update_checkout()},queue_update_checkout:function(e){if(9===(e.keyCode||e.which||0))return!0;r.dirtyInput=this,r.reset_update_checkout_timer(),r.updateTimer=setTimeout(r.maybe_update_checkout,"1000")},trigger_update_checkout:function(){r.reset_update_checkout_timer(),r.dirtyInput=!1,e(document.body).trigger("update_checkout")},maybe_update_checkout:function(){var t=!0;if(e(r.dirtyInput).length){var o=e(r.dirtyInput).closest("div").find(".address-field.validate-required");o.length&&o.each(function(){""===e(this).find("input.input-text").val()&&(t=!1)})}t&&r.trigger_update_checkout()},ship_to_different_address:function(){e("div.shipping_address").hide(),e(this).is(":checked")&&e("div.shipping_address").slideDown()},reset_update_checkout_timer:function(){clearTimeout(r.updateTimer)},is_valid_json:function(e){try{var t=JSON.parse(e);return t&&"object"==typeof t}catch(e){return!1}},validate_field:function(t){var o=e(this),a=o.closest(".form-row"),n=!0,i=a.is(".validate-required"),c=a.is(".validate-email"),s=a.is(".validate-phone"),r="",p=t.type;"input"===p&&a.removeClass("woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-invalid-phone woocommerce-validated"),"validate"!==p&&"change"!==p||(i&&("checkbox"!==o.attr("type")||o.is(":checked")?""===o.val()&&(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-required-field"),n=!1):(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-required-field"),n=!1)),c&&o.val()&&((r=new RegExp(/^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i)).test(o.val())||(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-email woocommerce-invalid-phone"),n=!1)),s&&(r=new RegExp(/[\s\#0-9_\-\+\/\(\)\.]/g),0<o.val().replace(r,"").length&&(a.removeClass("woocommerce-validated").addClass("woocommerce-invalid woocommerce-invalid-phone"),n=!1)),n&&a.removeClass("woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-invalid-phone").addClass("woocommerce-validated"))},update_checkout:function(e,t){r.reset_update_checkout_timer(),r.updateTimer=setTimeout(r.update_checkout_action,"5",t)},update_checkout_action:function(o){if(r.xhr&&r.xhr.abort(),0!==e("form.checkout").length){o=void 0!==o?o:{update_shipping_method:!0};var s=e("#billing_country").val(),p=e("#billing_state").val(),d=e(":input#billing_postcode").val(),u=e("#billing_city").val(),m=e(":input#billing_address_1").val(),l=e(":input#billing_address_2").val(),h=s,_=p,y=d,f=u,g=m,k=l,v=e(r.$checkout_form).find(".address-field.validate-required:visible"),w=!0;v.length&&v.each(function(){""===e(this).find(":input").val()&&(w=!1)}),e("#ship-to-different-address").find("input").is(":checked")&&(h=e("#shipping_country").val(),_=e("#shipping_state").val(),y=e(":input#shipping_postcode").val(),f=e("#shipping_city").val(),g=e(":input#shipping_address_1").val(),k=e(":input#shipping_address_2").val());var b={security:wc_checkout_params.update_order_review_nonce,payment_method:r.get_payment_method(),country:s,state:p,postcode:d,city:u,address:m,address_2:l,s_country:h,s_state:_,s_postcode:y,s_city:f,s_address:g,s_address_2:k,has_full_address:w,post_data:e("form.checkout").serialize()};if(!1!==o.update_shipping_method){var F={};e('select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]').each(function(){F[e(this).data("index")]=e(this).val()}),b.shipping_method=F}e(".woocommerce-checkout-payment, .woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),r.xhr=e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","update_order_review"),data:b,success:function(o){if(o&&!0===o.reload)return void window.location.reload();e(".woocommerce-NoticeGroup-updateOrderReview").remove();var s=e("#terms").prop("checked"),p={};if(e(".payment_box :input").each(function(){var t=e(this).attr("id");t&&(-1!==e.inArray(e(this).attr("type"),["checkbox","radio"])?p[t]=e(this).prop("checked"):p[t]=e(this).val())}),payplus_script_checkout.isHostedFields&&0===c.length&&payplus_script_checkout.hidePPGateway){const e=function(e,t){const o=document.createElement("div");o.innerHTML=e;o.querySelectorAll(`.${t}`).forEach(e=>{e.remove()});return o.innerHTML}(o.fragments[".woocommerce-checkout-payment"],"wc_payment_method.payment_method_payplus-payment-gateway");o.fragments[".woocommerce-checkout-payment"]=e}e(".hostedFields").prop("outerHTML");o&&o.fragments&&(e.each(o.fragments,function(t,o){if(!r.fragments||r.fragments[t]!==o){e(t).replaceWith(o),payplus_script_checkout.isSubscriptionOrder&&e(".wc_payment_methods.payment_methods.methods .wc_payment_method").each(function(){e(this).attr("class").split(/\s+/).forEach(function(t){payplus_script_checkout.isLoggedIn?t.startsWith("payment_method_payplus-payment-gateway-")&&"payment_method_payplus-payment-gateway-hostedfields"!==t&&e(this).remove():t.startsWith("payment_method_payplus-payment-gateway-")&&e(this).remove()}.bind(this))}),document.querySelector("#payplus-checkout-image-div")||function(){if(void 0!==payplus_script_checkout?.customIcons[0]&&payplus_script_checkout?.customIcons[0]?.length>0){var t=e("<div></div>",{class:"payplus-checkout-image-container",id:"payplus-checkout-image-div",style:"display: flex;flex-wrap: wrap;justify-content: center;"});e.each(payplus_script_checkout.customIcons,function(o,a){var n=e("<img>",{src:a,class:"payplus-checkout-image",alt:"Image "+(o+1),style:"max-width: 100%; max-height:35px;object-fit: contain;"});t.append(n)}),e("div.payment_method_payplus-payment-gateway").prepend(t)}}();!function(){const e=document.querySelector("#payment_method_payplus-payment-gateway-multipass");if(e&&Object.keys(payplus_script_checkout.multiPassIcons).length>0){const n=payplus_script_checkout.multiPassIcons;function t(e){let t=document.querySelectorAll("img");for(let o of t)if(o.src.includes(e))return o;return null}function o(e,t){e&&t&&(e.style.height="32px",e.style.width="32px",e.style.transition="opacity 0.5s",e.style.opacity=0,setTimeout(()=>{e.src=t,e.style.opacity=1},500))}if(e){let i=t("multipassLogo.png");if(i){i.src;let c=0;const s=Object.keys(n).map(e=>n[e]);function a(){const e=s[c];o(i,e),c=(c+1)%s.length,Object.keys(payplus_script_checkout.multiPassIcons).length>1&&setTimeout(a,2e3)}a()}}}}()}e(t).unblock(),"undefined"!=typeof newPpShippingMethods&&createNewShippingMethods()}),payplus_script_checkout.isHostedFields&&h(a,t),r.fragments=o.fragments,"pp_iframe_h"===n.parent().attr("class")&&function(){if(payplus_script_checkout.isHostedFields){if(!(jQuery(".pp_iframe").length>0||jQuery(".pp_iframe_h").length>0))return jQuery(".payment_method_payplus-payment-gateway-hostedfields").hide(),void(jQuery("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")&&jQuery("input#payment_method_payplus-payment-gateway").prop("checked",!0).trigger("change"));if(i){i=!1;var o=e('<p class="hf-save form-row"><label for="save_token_checkbox"><input type="checkbox" name="wc-save-token" id="save_token_checkbox" value="1" style="margin:0 10px 0 10px;"/> '+payplus_script_checkout.saveCreditCard+"</label></p>");payplus_script_checkout.isLoggedIn&&payplus_script_checkout.isSavingCerditCards&&n.append(o),t?setTimeout(function(){e("input#"+a).prop("checked",!0),e("div.container.hostedFields").show()},1e3):setTimeout(function(){e(".payment_method_payplus-payment-gateway").css("display","block"),e("input#"+a).removeAttr("checked"),e(".container.hostedFields").hide(),e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").hide(),e("input#payment_method_payplus-payment-gateway").prop("checked",!0)},1e3)}e(document).on("change",'input[name="payment_method"]',function(){e("input#"+a).is(":checked")?e("div.container.hostedFields").show():e(".container.hostedFields").hide()})}}());let d=!1;if(d)return;d=!0;var u=e('input[name="shipping_method[0]"]:checked').closest("li").find("label").text();""===u&&(u=e('input[name="shipping_method[0]"]').closest("li").find("label").text());var m=u.match(/(\$|₪)\s*([0-9.,]+)|([0-9.,]+)\s*(\$|₪)/);let l=0;if(m){m[1]||m[4];l=m[2]||m[3]}function h(t,o){o&&(e(".woocommerce-SavedPaymentMethods-new").hide(),e(".woocommerce-SavedPaymentMethods-saveNew").hide()),setTimeout(function(){if(e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")){e(".container.hostedFields").show();const t=document.querySelector(".pp_iframe_h");t&&(t.style.display="block")}},2e3);var a=jQuery("#"+t),i=jQuery(".pp_iframe_h"),c=jQuery(".wc_payment_method."+t);let s=n.find(".hf-main").first();a.length&&i.length&&n.length&&(payplus_script_checkout.hostedFieldsWidth&&s.attr("style",function(e,t){return"width: "+payplus_script_checkout.hostedFieldsWidth+"% !important;"+(t?" "+t:"")}),i.append(n),c.append(i))}if(payplus_script_checkout.isHostedFields&&e(document.body).on("updated_checkout",function(){h(a,t)}),s&&e("#terms").prop("checked",!0),e.isEmptyObject(p)||e(".payment_box :input").each(function(){var t=e(this).attr("id");t&&(-1!==e.inArray(e(this).attr("type"),["checkbox","radio"])?e(this).prop("checked",p[t]).trigger("change"):(-1!==e.inArray(e(this).attr("type"),["select"])||null!==e(this).val()&&0===e(this).val().length)&&e(this).val(p[t]).trigger("change"))}),o&&"failure"===o.result){var _=e("form.checkout");e(".woocommerce-error, .woocommerce-message").remove(),o.messages?_.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-updateOrderReview">'+o.messages+"</div>"):_.prepend(o),_.find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),r.scroll_to_notices()}r.init_payment_methods(),e(document.body).trigger("updated_checkout",[o])}})}},handleUnloadEvent:function(e){if(-1===navigator.userAgent.indexOf("MSIE")&&!document.documentMode)return!0;e.preventDefault()},attachUnloadEventsOnSubmit:function(){e(window).on("beforeunload",this.handleUnloadEvent)},detachUnloadEventsOnSubmit:function(){e(window).off("beforeunload",this.handleUnloadEvent)},blockOnSubmit:function(t){1!==t.data("blockUI.isBlocked")&&(t.block({message:null,overlayCSS:{top:0,height:"100%",background:"#fff",opacity:.6}}),e(".blockUI.blockOverlay").css("position","fixed"))},submitOrder:function(){r.blockOnSubmit(e(this))},submit:function(){r.reset_update_checkout_timer();var t=e(this);return t.is(".processing")||!1!==t.triggerHandler("checkout_place_order")&&!1!==t.triggerHandler("checkout_place_order_"+r.get_payment_method())&&(t.addClass("processing"),r.blockOnSubmit(t),r.attachUnloadEventsOnSubmit(),e.ajaxSetup({dataFilter:function(e,t){if("json"!==t)return e;if(r.is_valid_json(e))return e;var o=e.match(/{"result.*}/);return null===o||r.is_valid_json(o[0])&&(e=o[0]),e}}),e.ajax({type:"POST",url:wc_checkout_params.checkout_url,data:t.serialize(),dataType:"json",success:function(o){if("hostedFields"===o.method)jQuery.ajax({type:"post",dataType:"json",url:payplus_script_checkout.ajax_url,data:{action:"get-hosted-payload",_ajax_nonce:payplus_script_checkout.frontNonce},success:function(e){const t=JSON.parse(e.data.hostedPayload);JSON.parse(e.data.hostedResponse);t.more_info&&!isNaN(t.more_info)&&"number"==typeof t.more_info?(overlay(),jQuery(".blocks-payplus_loader_hosted").fadeIn(),r.$checkout_form.removeClass("processing").unblock(),hf.SubmitPayment()):(window.onbeforeunload=null,window.removeEventListener("beforeunload",r.detachUnloadEventsOnSubmit()),alert("The payment page has expired, refresh the page to continue"),location.reload())}});else{if(r.detachUnloadEventsOnSubmit(),o.payplus_iframe&&"success"===o.result)return r.$checkout_form.removeClass("processing").unblock(),"samePageIframe"==o.viewMode?function(t){e(".alertify").remove();const o=new URL(window.location.href);o.searchParams.set("payplus-iframe","1"),window.history.pushState({},"",o);const a=document.querySelector(".pp_iframe"),n=a.getAttribute("data-height");a.innerHTML="",a.append(f(t,"100%",n)),e("#closeFrame").on("click",function(e){e.preventDefault(),a.style.display="none"}),e("#place_order").prop("disabled",!0),payplus_script_checkout.payplus_mobile&&e("html, body").animate({scrollTop:e(".place-order").offset().top});y()}(o.payplus_iframe.data.payment_page_link):"popupIframe"==o.viewMode&&function(e,t){let o=window.innerWidth;o<568&&(t="100%");alertify.popupIframePaymentPage||alertify.dialog("popupIframePaymentPage",function(){return{main:function(e){this.message=f(e,"100%",t),y()},setup:function(){return{options:{autoReset:!1,overflow:!1,maximizable:!1,movable:!1,frameless:!0,transition:"fade"},focus:{element:0}}},prepare:function(){this.setContent(this.message)},hooks:{onshow:function(){this.elements.dialog.style.maxWidth="100%",this.elements.dialog.style.width=o>768?payplus_script_checkout.iframeWidth||"40%":"98%",this.elements.dialog.style.height=o>568?"82%":"100%",this.elements.content.style.top="25px"}}}});alertify.popupIframePaymentPage(e)}(o.payplus_iframe.data.payment_page_link,700),payplus_script_checkout.iframeRedirectLegacy||startOrderStatusPoll(o),!0;try{if("success"!==o.result||!1===t.triggerHandler("checkout_place_order_success",o))throw"failure"===o.result?"Result failure":"Invalid response";-1===o.redirect.indexOf("https://")||-1===o.redirect.indexOf("http://")?window.location=o.redirect:window.location=decodeURI(o.redirect)}catch(t){if(!0===o.reload)return void window.location.reload();!0===o.refresh&&e(document.body).trigger("update_checkout"),o.messages?r.submit_error(o.messages):r.submit_error('<div class="woocommerce-error">'+wc_checkout_params.i18n_checkout_error+"</div>")}}},error:function(e,t,o){r.detachUnloadEventsOnSubmit(),r.submit_error('<div class="woocommerce-error">'+o+"</div>")}})),!1},submit_error:function(t){e(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),r.$checkout_form.prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+t+"</div>"),r.$checkout_form.removeClass("processing").unblock(),r.$checkout_form.find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),r.scroll_to_notices(),e(document.body).trigger("checkout_error",[t])},scroll_to_notices:function(){var t=e(".woocommerce-NoticeGroup-updateOrderReview, .woocommerce-NoticeGroup-checkout");t.length||(t=e(".form.checkout")),e.scroll_to_notices(t)}},p={init:function(){e(document.body).on("click","a.showcoupon",this.show_coupon_form),e(document.body).on("click",".woocommerce-remove-coupon",this.remove_coupon),e("form.checkout_coupon").hide().on("submit",this.submit)},show_coupon_form:function(){return e(".checkout_coupon").slideToggle(400,function(){e(".checkout_coupon").find(":input:eq(0)").trigger("focus")}),!1},submit:function(){var t=e(this);if(t.is(".processing"))return!1;t.addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var o={security:wc_checkout_params.apply_coupon_nonce,coupon_code:t.find('input[name="coupon_code"]').val()};return e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","apply_coupon"),data:o,success:function(a){e(".woocommerce-error, .woocommerce-message").remove(),t.removeClass("processing").unblock(),a&&(t.before(a),t.slideUp(),e(document.body).trigger("applied_coupon_in_checkout",[o.coupon_code]),e(document.body).trigger("update_checkout",{update_shipping_method:!1}))},dataType:"html"}),!1},remove_coupon:function(t){t.preventDefault();var o=e(this).parents(".woocommerce-checkout-review-order"),a=e(this).data("coupon");o.addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var n={security:wc_checkout_params.remove_coupon_nonce,coupon:a};e.ajax({type:"POST",url:wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%","remove_coupon"),data:n,success:function(t){e(".woocommerce-error, .woocommerce-message").remove(),o.removeClass("processing").unblock(),t&&(e("form.woocommerce-checkout").before(t),e(document.body).trigger("removed_coupon_in_checkout",[n.coupon_code]),e(document.body).trigger("update_checkout",{update_shipping_method:!1}),e("form.checkout_coupon").find('input[name="coupon_code"]').val(""))},error:function(){},dataType:"html"})}},d={init:function(){e(document.body).on("click","a.showlogin",this.show_login_form)},show_login_form:function(){return e("form.login, form.woocommerce-form--login").slideToggle(),!1}},u={init:function(){e(document.body).on("click","a.woocommerce-terms-and-conditions-link",this.toggle_terms)},toggle_terms:function(){if(e(".woocommerce-terms-and-conditions").length)return e(".woocommerce-terms-and-conditions").slideToggle(function(){var t=e(".woocommerce-terms-and-conditions-link");e(".woocommerce-terms-and-conditions").is(":visible")?(t.addClass("woocommerce-terms-and-conditions-link--open"),t.removeClass("woocommerce-terms-and-conditions-link--closed")):(t.removeClass("woocommerce-terms-and-conditions-link--open"),t.addClass("woocommerce-terms-and-conditions-link--closed"))}),!1}};if(r.init(),p.init(),d.init(),u.init(),payplus_script_checkout.hostedFieldsIsMain){var m=function(){e("li.payment_method_payplus-payment-gateway").attr("style","display: none !important;")};function l(){var t=e("input#payment_method_payplus-payment-gateway-hostedfields");t.length&&(t.is(":checked")||t.prop("checked",!0).trigger("change"),e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").show().css("display","block"))}m(),e(document.body).on("updated_checkout",function(){m(),l()}),setTimeout(function(){m(),l()},100)}if(e(document.body).on("change",'input[name="payment_method"]',function(){"payplus-payment-gateway-hostedfields"===e('input[name="payment_method"]:checked').val()&&e(".payment_box.payment_method_payplus-payment-gateway-hostedfields").show()}),e(document.body).on("click","#place_order",function(t){var o=e('input[name="wc-payplus-payment-gateway-payment-token"]:checked').val(),a=e("input#payment_method_payplus-payment-gateway-hostedfields"),n=e("input#payment_method_payplus-payment-gateway");if(a.is(":checked")&&o&&"new"!==o){if(0===n.length)return alert("Error: Payment method not available for saved cards. Please contact support."),t.preventDefault(),!1;n.prop("checked",!0),a.prop("checked",!1)}}),e(document.body).on("change",'input[name="wc-payplus-payment-gateway-payment-token"]',function(){var t=e(this).val(),o=e("input#payment_method_payplus-payment-gateway-hostedfields"),a=e(".payment_method_payplus-payment-gateway"),n=e("input#payment_method_payplus-payment-gateway");if(o.is(":checked"))if("new"!==t){if(0===a.length){e(".payment_method_payplus-payment-gateway-hostedfields").before('<li class="wc_payment_method payment_method_payplus-payment-gateway" style="display:none !important;"><input id="payment_method_payplus-payment-gateway" type="radio" class="input-radio" name="payment_method" value="payplus-payment-gateway" /><label for="payment_method_payplus-payment-gateway">PayPlus</label><div class="payment_box payment_method_payplus-payment-gateway"></div></li>'),n=e("input#payment_method_payplus-payment-gateway")}else a.css("display","none");n.prop("checked",!0),e("body").attr("data-payplus-using-token","yes")}else o.prop("checked",!0),e("body").attr("data-payplus-using-token","no")}),e(document.body).on("click touchstart",".pp_iframe_h, .pp_iframe_h *",function(t){e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")&&(e('input[name="wc-payplus-payment-gateway-payment-token"]:checked').prop("checked",!1),e("input#wc-payplus-payment-gateway-payment-token-new").prop("checked",!0).trigger("change"))}),payplus_script_checkout.hostedFieldsIsMain)setInterval(function(){var t=e(document.activeElement);if(t.is("iframe")&&t.closest(".pp_iframe_h").length&&e("input#payment_method_payplus-payment-gateway-hostedfields").is(":checked")){var o=e('input[name="wc-payplus-payment-gateway-payment-token"]:checked');o.length&&"new"!==o.val()&&(o.prop("checked",!1),e("input#wc-payplus-payment-gateway-payment-token-new").prop("checked",!0).trigger("change"))}},300);function h(t){e("#pp_iframe").length&&(e("#pp_iframe").is(":visible")||!0===t)&&e("#pp_iframe").fadeOut(()=>{e(".payplus-option-description-area").show(),e("#place_order").prop("disabled",!1)})}e(document.body).on("click touchstart",".pp_iframe_h",function(t){var o=e(this).closest("li.wc_payment_method");if(o.length){var a=o.find('input[name="payment_method"]');a.length&&!a.is(":checked")&&a.prop("checked",!0).trigger("click")}}),e(e(window).on("popstate",()=>{h(!1)}));let _=!1;function y(){if(_)console.log("Apple script already loaded");else{const e=document.createElement("script");e.src=payplus_script_checkout.payplus_import_applepay_script,document.body.append(e),_=!0}}function f(e,t,a){let n=document.createElement("iframe");return n.id="pp_iframe",n.name="payplus-iframe",n.src=e,o?(n.height="100%",n.maxHeight="100vh"):n.height=a,n.width=t,n.setAttribute("style","border:0px"),n.setAttribute("allowpaymentrequest","allowpaymentrequest"),payplus_script_checkout.iframeRedirectLegacy||n.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation-by-user-activation"),n}});
  • payplus-payment-gateway/trunk/block/dist/js/woocommerce-blocks/blocks.js

    r3459669 r3464247  
    101101    }
    102102
     103    // Prevent double redirects when both postMessage and polling fire
     104    var _payplusPollDone = false;
     105
    103106    // Firefox blocks cross-origin iframe from navigating top window. When PayPlus iframe sends
    104107    // postMessage with redirect URL (or thank-you page loads in iframe), parent performs the redirect.
     
    110113            var u = new URL(e.data.url, window.location.origin);
    111114            if (u.origin === window.location.origin) {
     115                _payplusPollDone = true;
    112116                window.location.href = e.data.url;
    113117            }
     
    116120        }
    117121    });
     122
     123    // Polling fallback: when iframe can't postMessage (sandbox/cross-origin), poll server for order status
     124    function startOrderStatusPoll(result) {
     125        if (!result || !result.order_id || !result.order_received_url) return;
     126
     127        var redirectUrl = result.order_received_url;
     128        var orderKey = '';
     129        try {
     130            var u = new URL(redirectUrl, window.location.origin);
     131            orderKey = u.searchParams.get('key') || '';
     132        } catch (err) {
     133            return;
     134        }
     135        if (!orderKey) return;
     136
     137        var attempts = 0;
     138        var maxAttempts = 600; // 90 seconds (600 * 150ms)
     139
     140        function poll() {
     141            if (_payplusPollDone || attempts++ > maxAttempts) {
     142                return;
     143            }
     144
     145            jQuery.ajax({
     146                url: payPlusGateWay.ajax_url || window.payplus_script?.ajax_url,
     147                type: 'POST',
     148                data: {
     149                    action: 'payplus_check_order_redirect',
     150                    _ajax_nonce: payPlusGateWay.frontNonce || window.payplus_script?.frontNonce,
     151                    order_id: result.order_id,
     152                    order_key: orderKey
     153                },
     154                dataType: 'json',
     155                success: function (response) {
     156                    if (_payplusPollDone) return;
     157
     158                    if (response && response.success && response.data && response.data.status) {
     159                        var status = response.data.status;
     160                        if (status === 'processing' || status === 'completed' ||
     161                            status === 'wc-processing' || status === 'wc-completed') {
     162                            _payplusPollDone = true;
     163                            window.location.href = response.data.redirect_url || redirectUrl;
     164                        }
     165                    }
     166                }
     167            });
     168        }
     169
     170        poll();
     171        var pollTimer = setInterval(function () {
     172            if (_payplusPollDone) {
     173                clearInterval(pollTimer);
     174                return;
     175            }
     176            poll();
     177        }, 150);
     178    }
    118179
    119180    (() => {
     
    596657                                        loader
    597658                                    );
     659                                    // Start polling for order status (fallback for redirect)
     660                                    var paymentDetails = payment.getPaymentResult().paymentDetails;
     661                                    if (paymentDetails.order_id && paymentDetails.order_received_url) {
     662                                        startOrderStatusPoll({
     663                                            order_id: paymentDetails.order_id,
     664                                            order_received_url: paymentDetails.order_received_url
     665                                        });
     666                                    }
    598667                                    // Disconnect the observer to stop observing further changes
    599668                                } else {
  • payplus-payment-gateway/trunk/block/dist/js/woocommerce-blocks/blocks.min.js

    r3459669 r3464247  
    1 const{CHECKOUT_STORE_KEY:CHECKOUT_STORE_KEY}=window.wc.wcBlocksData,{PAYMENT_STORE_KEY:PAYMENT_STORE_KEY}=window.wc.wcBlocksData,store=wp.data.select(CHECKOUT_STORE_KEY),payment=wp.data.select(PAYMENT_STORE_KEY),hasOrder=store.hasOrder(),isCheckout=!!document.querySelector('div[data-block-name="woocommerce/checkout"]');if(isCheckout||hasOrder){console.log("checkout page?",isCheckout),console.log("has order?",hasOrder);store.getCustomerId(),store.getAdditionalFields(),store.getOrderId();const e=window.wc.wcSettings.getPaymentMethodData("payplus-payment-gateway");function addScriptApple(){if(isMyScriptLoaded(e.importApplePayScript)){const t=document.createElement("script");t.src=e.importApplePayScript,document.body.append(t)}}function isMyScriptLoaded(e){for(var t=document.getElementsByTagName("script"),n=t.length;n--;)if(t[n].src==e)return!1;return!0}let t=window.wc.wcSettings.getPaymentMethodData("payplus-payment-gateway").gateways;t=e.isSubscriptionOrder?["payplus-payment-gateway"]:t,t=e.isSubscriptionOrder&&e.isLoggedIn?["payplus-payment-gateway","payplus-payment-gateway-hostedfields"]:t;let n=[];const o=window.React;for(let i=0;i<e.customIcons?.length;i++)n[i]=(0,o.createElement)("img",{src:e.customIcons[i],style:{maxHeight:"35px",height:"45px"}});const a=(0,o.createElement)("div",{className:"payplus-icons",style:{display:"flex",flexWrap:"wrap",width:"100%",maxWidth:"100%",gap:"5px"}},n);let s=!!e.customIcons[0]?.length;Object.keys(e.hasSavedTokens).length;const l=e.hideMainPayPlusGateway;if(e.hostedFieldsIsMain){const{dispatch:r}=window.wp.data,c=window.wc.wcBlocksData.PAYMENT_STORE_KEY,p="payplus-payment-gateway-hostedfields";try{r(c).__internalSetActivePaymentMethod(p)}catch(d){}}function startIframe(t,n,o){document.body.appendChild(n),n.appendChild(o);const a=payment.getActivePaymentMethod(),s=window.wc.wcSettings.getPaymentMethodData(a)[a+"-settings"];var l=document.createElement("iframe");l.id="pp_iframe",l.name="payplus-iframe",l.width="95%",l.height="100%",l.style.border="0",l.style.display="block",l.style.margin="auto",l.src=t;let i=document.querySelectorAll(".pp_iframe"),r=document.querySelector(`#radio-control-wc-payment-method-options-${a}`).nextElementSibling.querySelector(".pp_iframe");if(-1!==["samePageIframe","popupIframe"].indexOf(s.displayMode)){if("payplus-payment-gateway"!==a)for(let e=0;e<i.length;e++){const t=i[e].parentNode.parentNode;if(t){t.id.includes(a)&&(r=i[e])}}switch(s.displayMode=window.innerWidth<=768&&"samePageIframe"===s.displayMode?"popupIframe":s.displayMode,s.displayMode){case"samePageIframe":r.style.position="relative",r.style.height=s.iFrameHeight,n.style.display="none";break;case"popupIframe":r.style.width=window.innerWidth<=768?"98%":s.iFrameWidth||"40%",r.style.height=s.iFrameHeight,r.style.position="fixed",r.style.top="50%",r.style.left="50%",r.style.paddingBottom=window.innerWidth<=768?"20px":"10px",r.style.paddingTop=window.innerWidth<=768?"20px":"10px",r.style.backgroundColor="white",r.style.transform="translate(-50%, -50%)",r.style.zIndex=1e5,r.style.boxShadow="10px 10px 10px 10px grey",r.style.borderRadius="5px",document.body.style.overflow="hidden",document.getElementsByClassName("blocks-payplus_loader")[0].style.display="none"}r.style.display="block",r.style.border="none",r.style.overflow="scroll",r.style.msOverflowStyle="none",r.style.scrollbarWidth="none",r.firstElementChild.style.display="block",r.firstElementChild.style.cursor="pointer",r.firstElementChild.addEventListener("click",e=>{e.preventDefault(),r.style.display="none";var t=window.location.href;new URLSearchParams(t);location.reload()}),r.appendChild(l),e.importApplePayScript&&addScriptApple()}}function multiPassIcons(e,t=null){null===t&&(t=document.querySelector("#radio-control-wc-payment-method-options-payplus-payment-gateway-multipass"));const n=wcSettings.paymentMethodSortOrder.includes("payplus-payment-gateway-multipass");if(e&&n&&Object.keys(wcSettings.paymentMethodData["payplus-payment-gateway"].multiPassIcons).length>0){const n=wcSettings.paymentMethodData["payplus-payment-gateway"].multiPassIcons;if(t){let t=function(e){let t=document.querySelectorAll("img");for(let n of t)if(n.src.includes(e))return n;return null}("multipassLogo.png");if(t){t.src;let o=0;const a=Object.keys(n).map(e=>n[e]);!function e(){const n=a[o];!function(e,t){e&&t?(e.style.transition="opacity 0.5s",e.style.opacity=0,setTimeout(()=>{e.src=t,e.style.opacity=1},500)):console.log("Image or new source not found.")}(t,n),o=(o+1)%a.length,Object.keys(wcSettings.paymentMethodData["payplus-payment-gateway"].multiPassIcons).length>1&&setTimeout(e,2e3)}(),e=!1}}}}window.addEventListener("message",function(e){if(e.data&&"payplus_redirect"===e.data.type&&e.data.url)try{new URL(e.data.url,window.location.origin).origin===window.location.origin&&(window.location.href=e.data.url)}catch(e){}}),(()=>{const e=window.React,n=window.wc.wcBlocksRegistry,o=window.wp.i18n,l=window.wc.wcSettings,i=window.wp.htmlEntities,r=t,c=e=>(0,i.decodeEntities)(e.description||""),p=t=>{const{PaymentMethodLabel:n}=t.components;return(0,e.createElement)("div",{className:"payplus-method",style:{width:"100%"}},(0,e.createElement)(n,{text:t.text,icon:""!==t.icon?(0,e.createElement)("img",{style:{width:"64px",height:"32px",maxHeight:"100%",margin:"0px 10px",objectPosition:"center"},src:t.icon}):null}),(0,e.createElement)("div",{className:"pp_iframe"},(0,e.createElement)("button",{className:"closeFrame",id:"closeFrame",style:{position:"absolute",top:"0px",fontSize:"20px",right:"0px",border:"none",color:"black",backgroundColor:"transparent",display:"none"}},"x")),t.icon.search("PayPlusLogo.svg")>0&&s?a:null)};(()=>{for(let t=0;t<r.length;t++){const a=r[t],s=(0,l.getPaymentMethodData)(a,{}),d=(0,o.__)("Pay with Debit or Credit Card","payplus-payment-gateway"),y=(0,i.decodeEntities)(s?.title||"")||d,m={name:a,label:(0,e.createElement)(p,{text:y,icon:s.icon}),content:(0,e.createElement)(c,{description:s.description}),edit:(0,e.createElement)(c,{description:s.description}),canMakePayment:()=>!0,ariaLabel:y,supports:{showSaveOption:"payplus-payment-gateway"===a&&s.showSaveOption,features:s.supports}};(0,n.registerPaymentMethod)(m)}})()})(),document.addEventListener("DOMContentLoaded",function(){let e=!0;window.wc.wcSettings;var n=document.createElement("div");n.class="blocks-payplus_loader";const o=document.createElement("div");o.className="blocks-payplus_loader";const a=document.createElement("div");a.className="blocks-loader";const s=document.createElement("div");s.className="blocks-loader-background";const i=document.createElement("div");function r(){const e=document.querySelector(".wc-block-checkout__actions_row button");e&&!e.hasAttribute("data-payplus-listener")&&(e.setAttribute("data-payplus-listener","true"),e.addEventListener("click",function(){const e=payment.getActivePaymentMethod();if(e&&e.includes("payplus-payment-gateway")){const t=document.createElement("div");t.id="early-payplus-overlay",t.style.cssText="\n                            position: fixed;\n                            top: 0;\n                            left: 0;\n                            width: 100%;\n                            height: 100%;\n                            background-color: rgba(0, 0, 0, 0.5);\n                            z-index: 999999;\n                            display: flex;\n                            align-items: center;\n                            justify-content: center;\n                        ";const n=document.createElement("div");n.style.cssText="\n                            background: white;\n                            padding: 30px 50px;\n                            border-radius: 12px;\n                            text-align: center;\n                            color: #333;\n                            box-shadow: 0 8px 32px rgba(0,0,0,0.3);\n                            min-width: 300px;\n                        ";const o=document.createElement("div");o.style.cssText="\n                            font-size: 18px;\n                            font-weight: 500;\n                            margin-bottom: 15px;\n                        ";const a=document.createElement("div");a.style.cssText="\n                            font-size: 24px;\n                            color: #007cba;\n                        ",n.appendChild(o),n.appendChild(a),t.appendChild(n),document.body.appendChild(t);let s=0;const l=setInterval(()=>{s=s%3+1,a.textContent=".".repeat(s)},400);if("payplus-payment-gateway-hostedfields"===e)o.textContent=window.payplus_i18n&&window.payplus_i18n.processing_payment?window.payplus_i18n.processing_payment:"Processing your payment now";else{o.textContent=window.payplus_i18n&&window.payplus_i18n.generating_page?window.payplus_i18n.generating_page:"Generating payment page";const e=1e3*Math.random()+4e3;setTimeout(()=>{o.textContent=window.payplus_i18n&&window.payplus_i18n.loading_page?window.payplus_i18n.loading_page:"Loading payment page"},e)}const i=setInterval(()=>{if(store.isComplete()||store.hasError()){clearInterval(l),clearInterval(i);const e=document.getElementById("early-payplus-overlay");e&&e.remove()}},100);setTimeout(()=>{clearInterval(l),clearInterval(i);const e=document.getElementById("early-payplus-overlay");e&&e.remove()},15e3)}}))}i.className="blocks-loader-text",s.appendChild(i),a.appendChild(s),o.appendChild(a),n.appendChild(o),r();const c=setInterval(()=>{r()},1e3);setTimeout(()=>{clearInterval(c)},1e4),setTimeout(function(){console.log("observer started");const o=document.createElement("div");o.style.backgroundColor="rgba(0, 0, 0, 0.5)",o.id="overlay",o.style.position="fixed",o.style.height="100%",o.style.width="100%",o.style.top="0",o.style.zIndex="5",setTimeout(()=>{let t=document.querySelector("#radio-control-wc-payment-method-options-payplus-payment-gateway-multipass");e&&t&&(multiPassIcons(e,t),e=!1)},3e3),payPlusCC=document.querySelector("#radio-control-wc-payment-method-options-payplus-payment-gateway");const a=new MutationObserver((e,a)=>{const s=payment.getActivePaymentMethod();if(0===s.search("payplus-payment-gateway-hostedfields")){const e=document.getElementsByClassName("pp_iframe_h")[0];if(e&&(e.style.display="flex",!e.querySelector(".payplus-hosted-place-order"))){const t=document.querySelector(".wc-block-checkout__actions_row button"),n=e.querySelector("#ppLogo"),o=window.wc.wcSettings.getPaymentMethodData("payplus-payment-gateway-hostedfields"),a=o&&"yes"===o.show_hide_submit_button;if(t&&n&&a){const e=document.createElement("button");e.className="btn btn-primary payplus-hosted-place-order wp-element-button wc-block-components-button wp-element-button contained",e.type="button",e.textContent=t.textContent,e.style.cssText="\n                                    margin-top: 15px;\n                                    margin-bottom: 15px;\n                                    margin-right: auto;\n                                    margin-left: auto;\n                                    width: 90%;\n                                    background-color: rgb(0, 0, 0);\n                                    color: white;\n                                    border: none;\n                                    border-radius: 10px;\n                                    padding: 12px 24px;\n                                    font-size: 16px;\n                                    font-weight: 600;\n                                    cursor: pointer;\n                                ",e.addEventListener("click",function(e){e.preventDefault(),t.click()}),n.parentNode.insertBefore(e,n)}}}else{const e=document.getElementsByClassName("pp_iframe_h")[0];e&&(e.style.display="none")}if(l){const e=document.querySelector("#radio-control-wc-payment-method-options-payplus-payment-gateway")?.closest(".wc-block-components-radio-control-accordion-option");e&&(e.style.display="none")}if(store.hasError())try{let e=payment.getPaymentResult();if(null==e||""===e)throw new Error("Payment result is empty, null, or undefined.");console.log("Payment result:",e);let t=document.querySelectorAll(".pp_iframe")[0];t.style.width=window.innerWidth<=768?"95%":"55%",t.style.height="200px",t.style.position="fixed",t.style.backgroundColor="white",t.style.display="flex",t.style.alignItems="center",t.style.textAlign="center",t.style.justifyContent="center",t.style.top="50%",t.style.left="50%",t.style.transform="translate(-50%, -50%)",t.style.zIndex=1e5,t.style.boxShadow="10px 10px 10px 10px grey",t.style.borderRadius="25px",t.innerHTML=void 0!==e.paymentDetails.errorMessage?e.paymentDetails.errorMessage+"<br>"+(window.payplus_i18n&&window.payplus_i18n.click_to_close?window.payplus_i18n.click_to_close:"Click this to close."):e.message+"<br>"+(window.payplus_i18n&&window.payplus_i18n.click_to_close?window.payplus_i18n.click_to_close:"Click this to close."),t.addEventListener("click",e=>{e.preventDefault(),t.style.display="none",location.reload()}),console.log(e.paymentDetails.errorMessage),void 0!==e.paymentDetails.errorMessage?alert(e.paymentDetails.errorMessage):alert(e.message),a.disconnect()}catch(e){console.error("An error occurred:",e.message)}if(store.isComplete()){if(a.disconnect(),0===s.search("payplus-payment-gateway-hostedfields")){hf.SubmitPayment(),document.body.style.overflow="hidden",document.body.style.backgroundColor="white",document.body.style.opacity="0.7",document.querySelector(".blocks-payplus_loader_hosted").style.display="block";return document.querySelectorAll('input[type="radio"], input').forEach(e=>{e.disabled=!0}),void hf.Upon("pp_responseFromServer",e=>{e.detail.errors&&location.reload()})}if(0===s.search("payplus-payment-gateway")&&0!==s.search("payplus-payment-gateway-pos-emv")){const e=window.wc.wcSettings.getPaymentMethodData(s)[s+"-settings"],l=-1!==["samePageIframe","popupIframe"].indexOf(e.displayMode);console.log("isIframe?",l),-1!==t.indexOf(payment.getActivePaymentMethod())&&0===payment.getActiveSavedToken().length&&(console.log("isComplete: "+store.isComplete()),l&&(payment.getPaymentResult().paymentDetails.paymentPageLink?.length>0?(console.log("paymentPageLink",payment.getPaymentResult().paymentDetails.paymentPageLink),startIframe(payment.getPaymentResult().paymentDetails.paymentPageLink,o,n)):(alert(window.payplus_i18n&&window.payplus_i18n.payment_page_failed?window.payplus_i18n.payment_page_failed:"Error: the payment page failed to load."),location.reload())),a.disconnect())}}}),s=document.body;a.observe(s,{childList:!0,subtree:!0})}(),1e3)})}
     1const { CHECKOUT_STORE_KEY } = window.wc.wcBlocksData;
     2const { PAYMENT_STORE_KEY } = window.wc.wcBlocksData;
     3
     4const store = wp.data.select(CHECKOUT_STORE_KEY);
     5const payment = wp.data.select(PAYMENT_STORE_KEY);
     6const hasOrder = store.hasOrder();
     7
     8const isCheckout = !document.querySelector(
     9    'div[data-block-name="woocommerce/checkout"]'
     10)
     11    ? false
     12    : true;
     13
     14if (isCheckout || hasOrder) {
     15    console.log("checkout page?", isCheckout);
     16    console.log("has order?", hasOrder);
     17
     18    const customerId = store.getCustomerId();
     19    const additionalFields = store.getAdditionalFields();
     20    const orderId = store.getOrderId();
     21    const payPlusGateWay = window.wc.wcSettings.getPaymentMethodData(
     22        "payplus-payment-gateway"
     23    );
     24
     25    function addScriptApple() {
     26        if (isMyScriptLoaded(payPlusGateWay.importApplePayScript)) {
     27            const script = document.createElement("script");
     28            script.src = payPlusGateWay.importApplePayScript;
     29            document.body.append(script);
     30        }
     31    }
     32
     33    function isMyScriptLoaded(url) {
     34        var scripts = document.getElementsByTagName("script");
     35        for (var i = scripts.length; i--; ) {
     36            if (scripts[i].src == url) {
     37                return false;
     38            }
     39        }
     40        return true;
     41    }
     42
     43    let gateways = window.wc.wcSettings.getPaymentMethodData(
     44        "payplus-payment-gateway"
     45    ).gateways;
     46
     47    gateways = payPlusGateWay.isSubscriptionOrder
     48        ? ["payplus-payment-gateway"]
     49        : gateways;
     50
     51    gateways =
     52        payPlusGateWay.isSubscriptionOrder && payPlusGateWay.isLoggedIn
     53            ? [
     54                  "payplus-payment-gateway",
     55                  "payplus-payment-gateway-hostedfields",
     56              ]
     57            : gateways;
     58
     59    let customIcons = [];
     60
     61    const w = window.React;
     62    for (let c = 0; c < payPlusGateWay.customIcons?.length; c++) {
     63        customIcons[c] = (0, w.createElement)("img", {
     64            src: payPlusGateWay.customIcons[c],
     65            style: { maxHeight: "35px", height: "45px" },
     66        });
     67    }
     68
     69    const divCustomIcons = (0, w.createElement)(
     70        "div",
     71        {
     72            className: "payplus-icons",
     73            style: {
     74                display: "flex",
     75                flexWrap: "wrap",
     76                width: "100%",
     77                maxWidth: "100%",
     78                gap: "5px",
     79            },
     80        },
     81        customIcons
     82    );
     83
     84    let isCustomeIcons = !!payPlusGateWay.customIcons[0]?.length;
     85    const hasSavedTokens =
     86        Object.keys(payPlusGateWay.hasSavedTokens).length > 0;
     87    const hideMainPayPlusGateway = payPlusGateWay.hideMainPayPlusGateway;
     88    const hostedFieldsIsMain = payPlusGateWay.hostedFieldsIsMain;
     89
     90    // Auto-select hosted fields if hostedFieldsIsMain is true
     91    if (hostedFieldsIsMain) {
     92        const { dispatch } = window.wp.data;
     93        const PAYMENT_STORE_KEY = window.wc.wcBlocksData.PAYMENT_STORE_KEY;
     94        const OUR_GATEWAY = 'payplus-payment-gateway-hostedfields';
     95
     96        try {
     97            dispatch(PAYMENT_STORE_KEY).__internalSetActivePaymentMethod(OUR_GATEWAY);
     98        } catch (error) {
     99            // Silently ignore errors
     100        }
     101    }
     102
     103    // Prevent double redirects when both postMessage and polling fire
     104    var _payplusPollDone = false;
     105
     106    // Firefox blocks cross-origin iframe from navigating top window. When PayPlus iframe sends
     107    // postMessage with redirect URL (or thank-you page loads in iframe), parent performs the redirect.
     108    window.addEventListener("message", function (e) {
     109        if (!e.data || e.data.type !== "payplus_redirect" || !e.data.url) {
     110            return;
     111        }
     112        try {
     113            var u = new URL(e.data.url, window.location.origin);
     114            if (u.origin === window.location.origin) {
     115                _payplusPollDone = true;
     116                window.location.href = e.data.url;
     117            }
     118        } catch (err) {
     119            // ignore invalid URL
     120        }
     121    });
     122
     123    // Polling fallback: when iframe can't postMessage (sandbox/cross-origin), poll server for order status
     124    function startOrderStatusPoll(result) {
     125        if (!result || !result.order_id || !result.order_received_url) return;
     126
     127        var redirectUrl = result.order_received_url;
     128        var orderKey = '';
     129        try {
     130            var u = new URL(redirectUrl, window.location.origin);
     131            orderKey = u.searchParams.get('key') || '';
     132        } catch (err) {
     133            return;
     134        }
     135        if (!orderKey) return;
     136
     137        var attempts = 0;
     138        var maxAttempts = 600; // 90 seconds (600 * 150ms)
     139
     140        function poll() {
     141            if (_payplusPollDone || attempts++ > maxAttempts) {
     142                return;
     143            }
     144
     145            jQuery.ajax({
     146                url: payPlusGateWay.ajax_url || window.payplus_script?.ajax_url,
     147                type: 'POST',
     148                data: {
     149                    action: 'payplus_check_order_redirect',
     150                    _ajax_nonce: payPlusGateWay.frontNonce || window.payplus_script?.frontNonce,
     151                    order_id: result.order_id,
     152                    order_key: orderKey
     153                },
     154                dataType: 'json',
     155                success: function (response) {
     156                    if (_payplusPollDone) return;
     157
     158                    if (response && response.success && response.data && response.data.status) {
     159                        var status = response.data.status;
     160                        if (status === 'processing' || status === 'completed' ||
     161                            status === 'wc-processing' || status === 'wc-completed') {
     162                            _payplusPollDone = true;
     163                            window.location.href = response.data.redirect_url || redirectUrl;
     164                        }
     165                    }
     166                }
     167            });
     168        }
     169
     170        poll();
     171        var pollTimer = setInterval(function () {
     172            if (_payplusPollDone) {
     173                clearInterval(pollTimer);
     174                return;
     175            }
     176            poll();
     177        }, 150);
     178    }
     179
     180    (() => {
     181        ("use strict");
     182        const e = window.React,
     183            t = window.wc.wcBlocksRegistry,
     184            a = window.wp.i18n,
     185            p = window.wc.wcSettings,
     186            n = window.wp.htmlEntities,
     187            i = gateways,
     188            s = (e) => (0, n.decodeEntities)(e.description || ""),
     189            y = (t) => {
     190                const { PaymentMethodLabel: a } = t.components;
     191                return (0, e.createElement)(
     192                    "div",
     193                    { className: "payplus-method", style: { width: "100%" } },
     194                    (0, e.createElement)(a, {
     195                        text: t.text,
     196                        icon:
     197                            t.icon !== ""
     198                                ? (0, e.createElement)("img", {
     199                                      style: {
     200                                          width: "64px",
     201                                          height: "32px",
     202                                          maxHeight: "100%",
     203                                          margin: "0px 10px",
     204                                          objectPosition: "center",
     205                                      },
     206                                      src: t.icon,
     207                                  })
     208                                : null,
     209                    }),
     210                    (0, e.createElement)(
     211                        "div",
     212                        { className: "pp_iframe" },
     213                        (0, e.createElement)(
     214                            "button",
     215                            {
     216                                className: "closeFrame",
     217                                id: "closeFrame",
     218                                style: {
     219                                    position: "absolute",
     220                                    top: "0px",
     221                                    fontSize: "20px",
     222                                    right: "0px",
     223                                    border: "none",
     224                                    color: "black",
     225                                    backgroundColor: "transparent",
     226                                    display: "none",
     227                                },
     228                            },
     229                            "x"
     230                        )
     231                    ),
     232                    t.icon.search("PayPlusLogo.svg") > 0 && isCustomeIcons
     233                        ? divCustomIcons
     234                        : null
     235                );
     236            };
     237        (() => {
     238            for (let c = 0; c < i.length; c++) {
     239                const l = i[c],
     240                    o = (0, p.getPaymentMethodData)(l, {}),
     241                    m = (0, a.__)(
     242                        "Pay with Debit or Credit Card",
     243                        "payplus-payment-gateway"
     244                    ),
     245                    r = (0, n.decodeEntities)(o?.title || "") || m,
     246                    w = {
     247                        name: l,
     248                        label: (0, e.createElement)(y, {
     249                            text: r,
     250                            icon: o.icon,
     251                        }),
     252                        content: (0, e.createElement)(s, {
     253                            description: o.description,
     254                        }),
     255                        edit: (0, e.createElement)(s, {
     256                            description: o.description,
     257                        }),
     258                        canMakePayment: () => !0,
     259                        ariaLabel: r,
     260                        supports: {
     261                            showSaveOption:
     262                                l === "payplus-payment-gateway"
     263                                    ? o.showSaveOption
     264                                    : false,
     265                            features: o.supports,
     266                        },
     267                    };
     268                (0, t.registerPaymentMethod)(w);
     269            }
     270        })();
     271    })();
     272
     273    document.addEventListener("DOMContentLoaded", function () {
     274        // Function to start observing for the target element
     275        let loopImages = true;
     276        let WcSettings = window.wc.wcSettings;
     277
     278        var loader = document.createElement("div");
     279        loader.class = "blocks-payplus_loader";
     280
     281        // Add loader content
     282        const loaderContent = document.createElement("div");
     283        loaderContent.className = "blocks-payplus_loader";
     284        const loaderInner = document.createElement("div");
     285        loaderInner.className = "blocks-loader";
     286        const loaderBackground = document.createElement("div");
     287        loaderBackground.className = "blocks-loader-background";
     288        const loaderText = document.createElement("div");
     289        loaderText.className = "blocks-loader-text";
     290        loaderBackground.appendChild(loaderText);
     291        loaderInner.appendChild(loaderBackground);
     292        loaderContent.appendChild(loaderInner);
     293        loader.appendChild(loaderContent);
     294
     295        // Add early loading indicator for Place Order button
     296        function addEarlyLoadingIndicator() {
     297            const placeOrderButton = document.querySelector(
     298                ".wc-block-checkout__actions_row button"
     299            );
     300
     301            if (placeOrderButton && !placeOrderButton.hasAttribute('data-payplus-listener')) {
     302                placeOrderButton.setAttribute('data-payplus-listener', 'true');
     303                placeOrderButton.addEventListener("click", function () {
     304                    const activePaymentMethod = payment.getActivePaymentMethod();
     305
     306                    // Check if it's a PayPlus payment method
     307                    if (activePaymentMethod && activePaymentMethod.includes("payplus-payment-gateway")) {
     308                        // Show loading immediately
     309                        const overlay = document.createElement("div");
     310                        overlay.id = "early-payplus-overlay";
     311                        overlay.style.cssText = `
     312                            position: fixed;
     313                            top: 0;
     314                            left: 0;
     315                            width: 100%;
     316                            height: 100%;
     317                            background-color: rgba(0, 0, 0, 0.5);
     318                            z-index: 999999;
     319                            display: flex;
     320                            align-items: center;
     321                            justify-content: center;
     322                        `;
     323
     324                        const loadingContainer = document.createElement("div");
     325                        loadingContainer.style.cssText = `
     326                            background: white;
     327                            padding: 30px 50px;
     328                            border-radius: 12px;
     329                            text-align: center;
     330                            color: #333;
     331                            box-shadow: 0 8px 32px rgba(0,0,0,0.3);
     332                            min-width: 300px;
     333                        `;
     334
     335                        const loadingText = document.createElement("div");
     336                        loadingText.style.cssText = `
     337                            font-size: 18px;
     338                            font-weight: 500;
     339                            margin-bottom: 15px;
     340                        `;
     341
     342                        const loadingDots = document.createElement("div");
     343                        loadingDots.style.cssText = `
     344                            font-size: 24px;
     345                            color: #007cba;
     346                        `;
     347
     348                        loadingContainer.appendChild(loadingText);
     349                        loadingContainer.appendChild(loadingDots);
     350                        overlay.appendChild(loadingContainer);
     351                        document.body.appendChild(overlay);
     352
     353                        // Animate dots
     354                        let dotCount = 0;
     355                        const animateDots = () => {
     356                            dotCount = (dotCount % 3) + 1;
     357                            loadingDots.textContent = '.'.repeat(dotCount);
     358                        };
     359                        const dotInterval = setInterval(animateDots, 400);
     360
     361                        // Check if it's hosted fields payment method
     362                        if (activePaymentMethod === "payplus-payment-gateway-hostedfields") {
     363                            // For hosted fields: show "Processing your payment now..."
     364                            loadingText.textContent = (window.payplus_i18n && window.payplus_i18n.processing_payment)
     365                                ? window.payplus_i18n.processing_payment
     366                                : "Processing your payment now";
     367                        } else {
     368                            // For other PayPlus methods: Phase 1: Generating payment page (1-1.5 seconds)
     369                            loadingText.textContent = (window.payplus_i18n && window.payplus_i18n.generating_page)
     370                                ? window.payplus_i18n.generating_page
     371                                : "Generating payment page";
     372                            const phase1Duration = Math.random() * 1000 + 4000; // 4-5 seconds
     373
     374                            setTimeout(() => {
     375                                // Phase 2: Loading payment page (until store.isComplete() is true)
     376                                loadingText.textContent = (window.payplus_i18n && window.payplus_i18n.loading_page)
     377                                    ? window.payplus_i18n.loading_page
     378                                    : "Loading payment page";
     379                            }, phase1Duration);
     380                        }
     381
     382                        // Only remove when store actually completes or error occurs
     383                        const checkForCompletion = setInterval(() => {
     384                            // Check if checkout is complete or has error
     385                            if (store.isComplete() || store.hasError()) {
     386                                clearInterval(dotInterval);
     387                                clearInterval(checkForCompletion);
     388                                const earlyOverlay = document.getElementById("early-payplus-overlay");
     389                                if (earlyOverlay) {
     390                                    earlyOverlay.remove();
     391                                }
     392                            }
     393                        }, 100);
     394
     395                        // Safety cleanup after 15 seconds (extended time)
     396                        setTimeout(() => {
     397                            clearInterval(dotInterval);
     398                            clearInterval(checkForCompletion);
     399                            const earlyOverlay = document.getElementById("early-payplus-overlay");
     400                            if (earlyOverlay) {
     401                                earlyOverlay.remove();
     402                            }
     403                        }, 15000);
     404                    }
     405                });
     406            }
     407        }
     408
     409        // Try to add the early loading indicator immediately and periodically
     410        addEarlyLoadingIndicator();
     411        const intervalId = setInterval(() => {
     412            addEarlyLoadingIndicator();
     413        }, 1000);
     414
     415        // Clear interval after 10 seconds to avoid memory leaks
     416        setTimeout(() => {
     417            clearInterval(intervalId);
     418        }, 10000);
     419
     420        function startObserving(event) {
     421            console.log("observer started");
     422
     423            const overlay = document.createElement("div");
     424            overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
     425            overlay.id = "overlay";
     426            overlay.style.position = "fixed";
     427            overlay.style.height = "100%";
     428            overlay.style.width = "100%";
     429            overlay.style.top = "0";
     430            overlay.style.zIndex = "5";
     431
     432            setTimeout(() => {
     433                let element = document.querySelector(
     434                    "#radio-control-wc-payment-method-options-payplus-payment-gateway-multipass"
     435                );
     436                if (loopImages && element) {
     437                    multiPassIcons(loopImages, element);
     438                    loopImages = false;
     439                }
     440            }, 3000);
     441
     442            payPlusCC = document.querySelector(
     443                "#radio-control-wc-payment-method-options-payplus-payment-gateway"
     444            );
     445
     446            const observer = new MutationObserver((mutationsList, observer) => {
     447                const activePaymentMethod = payment.getActivePaymentMethod();
     448               
     449                if (
     450                    activePaymentMethod.search(
     451                        "payplus-payment-gateway-hostedfields"
     452                    ) === 0
     453                ) {
     454                    const ppIframeElement =
     455                        document.getElementsByClassName("pp_iframe_h")[0];
     456                    if (ppIframeElement) {
     457                        ppIframeElement.style.display = "flex";
     458                       
     459                        // Add Place Order button to hosted fields if not already added
     460                        if (!ppIframeElement.querySelector('.payplus-hosted-place-order')) {
     461                            const originalPlaceOrderButton = document.querySelector('.wc-block-checkout__actions_row button');
     462                            const ppLogo = ppIframeElement.querySelector('#ppLogo');
     463                           
     464                            // Check if the show_hide_submit_button setting is enabled
     465                            const hostedFieldsSettings = window.wc.wcSettings.getPaymentMethodData('payplus-payment-gateway-hostedfields');
     466                            const showSubmitButton = hostedFieldsSettings && hostedFieldsSettings.show_hide_submit_button === 'yes';
     467                           
     468                            if (originalPlaceOrderButton && ppLogo && showSubmitButton) {
     469                                const hostedPlaceOrderButton = document.createElement('button');
     470                                hostedPlaceOrderButton.className = 'btn btn-primary payplus-hosted-place-order wp-element-button wc-block-components-button wp-element-button contained';
     471                                hostedPlaceOrderButton.type = 'button';
     472                                hostedPlaceOrderButton.textContent = originalPlaceOrderButton.textContent;
     473                                hostedPlaceOrderButton.style.cssText = `
     474                                    margin-top: 15px;
     475                                    margin-bottom: 15px;
     476                                    margin-right: auto;
     477                                    margin-left: auto;
     478                                    width: 90%;
     479                                    background-color: rgb(0, 0, 0);
     480                                    color: white;
     481                                    border: none;
     482                                    border-radius: 10px;
     483                                    padding: 12px 24px;
     484                                    font-size: 16px;
     485                                    font-weight: 600;
     486                                    cursor: pointer;
     487                                `;
     488                               
     489                                // Clone the click behavior from the original button
     490                                hostedPlaceOrderButton.addEventListener('click', function(e) {
     491                                    e.preventDefault();
     492                                    originalPlaceOrderButton.click();
     493                                });
     494                               
     495                                // Insert the button right before the ppLogo
     496                                ppLogo.parentNode.insertBefore(hostedPlaceOrderButton, ppLogo);
     497                            }
     498                        }
     499                    }
     500                } else {
     501                    // Hide hosted fields iframe when a different payment method is selected
     502                    const ppIframeElement =
     503                        document.getElementsByClassName("pp_iframe_h")[0];
     504                    if (ppIframeElement) {
     505                        ppIframeElement.style.display = "none";
     506                    }
     507                }
     508                if (hideMainPayPlusGateway) {
     509                    const parentDiv = document
     510                        .querySelector(
     511                            "#radio-control-wc-payment-method-options-payplus-payment-gateway"
     512                        )
     513                        ?.closest(
     514                            ".wc-block-components-radio-control-accordion-option"
     515                        );
     516                    if (parentDiv) {
     517                        parentDiv.style.display = "none";
     518                    }
     519                }
     520                if (store.hasError()) {
     521                    try {
     522                        let getPaymentResult = payment.getPaymentResult();
     523
     524                        if (
     525                            getPaymentResult === null ||
     526                            getPaymentResult === undefined ||
     527                            getPaymentResult === ""
     528                        ) {
     529                            throw new Error(
     530                                "Payment result is empty, null, or undefined."
     531                            );
     532                        }
     533
     534                        // Process the result here
     535                        console.log("Payment result:", getPaymentResult);
     536                        let pp_iframe =
     537                            document.querySelectorAll(".pp_iframe")[0];
     538                        pp_iframe.style.width =
     539                            window.innerWidth <= 768 ? "95%" : "55%";
     540                        pp_iframe.style.height = "200px";
     541                        pp_iframe.style.position = "fixed";
     542                        pp_iframe.style.backgroundColor = "white";
     543                        pp_iframe.style.display = "flex";
     544                        pp_iframe.style.alignItems = "center";
     545                        pp_iframe.style.textAlign = "center";
     546                        pp_iframe.style.justifyContent = "center";
     547                        pp_iframe.style.top = "50%";
     548                        pp_iframe.style.left = "50%";
     549                        pp_iframe.style.transform = "translate(-50%, -50%)";
     550                        pp_iframe.style.zIndex = 100000;
     551                        pp_iframe.style.boxShadow = "10px 10px 10px 10px grey";
     552                        pp_iframe.style.borderRadius = "25px";
     553                        pp_iframe.innerHTML =
     554                            getPaymentResult.paymentDetails.errorMessage !==
     555                            undefined
     556                                ? getPaymentResult.paymentDetails.errorMessage +
     557                                  "<br>" +
     558                                  ((window.payplus_i18n && window.payplus_i18n.click_to_close)
     559                                      ? window.payplus_i18n.click_to_close
     560                                      : "Click this to close.")
     561                                : getPaymentResult.message +
     562                                  "<br>" +
     563                                  ((window.payplus_i18n && window.payplus_i18n.click_to_close)
     564                                      ? window.payplus_i18n.click_to_close
     565                                      : "Click this to close.");
     566
     567                        pp_iframe.addEventListener("click", (e) => {
     568                            e.preventDefault();
     569                            pp_iframe.style.display = "none";
     570                            location.reload();
     571                        });
     572                        console.log(
     573                            getPaymentResult.paymentDetails.errorMessage
     574                        );
     575                        if (
     576                            getPaymentResult.paymentDetails.errorMessage !==
     577                            undefined
     578                        ) {
     579                            alert(getPaymentResult.paymentDetails.errorMessage);
     580                        } else {
     581                            alert(getPaymentResult.message);
     582                        }
     583
     584                        observer.disconnect();
     585                    } catch (error) {
     586                        // Handle the error here
     587                        console.error("An error occurred:", error.message);
     588                    }
     589                }
     590                if (store.isComplete()) {
     591                    observer.disconnect();
     592                    if (
     593                        activePaymentMethod.search(
     594                            "payplus-payment-gateway-hostedfields"
     595                        ) === 0
     596                    ) {
     597                        hf.SubmitPayment();
     598                        document.body.style.overflow = "hidden";
     599                        document.body.style.backgroundColor = "white";
     600                        document.body.style.opacity = "0.7";
     601                        document.querySelector(
     602                            ".blocks-payplus_loader_hosted"
     603                        ).style.display = "block";
     604                        const inputs = document.querySelectorAll(
     605                            'input[type="radio"], input'
     606                        );
     607                        inputs.forEach((input) => {
     608                            input.disabled = true;
     609                        });
     610                        hf.Upon("pp_responseFromServer", (e) => {
     611                            if (e.detail.errors) {
     612                                location.reload();
     613                            }
     614                        });
     615                        return;
     616                    }
     617
     618                    if (
     619                        activePaymentMethod.search(
     620                            "payplus-payment-gateway"
     621                        ) === 0 &&
     622                        activePaymentMethod.search(
     623                            "payplus-payment-gateway-pos-emv"
     624                        ) !== 0
     625                    ) {
     626                        const gateWaySettings =
     627                            window.wc.wcSettings.getPaymentMethodData(
     628                                activePaymentMethod
     629                            )[activePaymentMethod + "-settings"];
     630                        const isIframe =
     631                            ["samePageIframe", "popupIframe"].indexOf(
     632                                gateWaySettings.displayMode
     633                            ) !== -1;
     634                        console.log("isIframe?", isIframe);
     635                        if (
     636                            gateways.indexOf(
     637                                payment.getActivePaymentMethod()
     638                            ) !== -1 &&
     639                            payment.getActiveSavedToken().length === 0
     640                        ) {
     641                            console.log("isComplete: " + store.isComplete());
     642                            // Call the function to handle the target element
     643                            if (isIframe) {
     644                                if (
     645                                    payment.getPaymentResult().paymentDetails
     646                                        .paymentPageLink?.length > 0
     647                                ) {
     648                                    console.log(
     649                                        "paymentPageLink",
     650                                        payment.getPaymentResult()
     651                                            .paymentDetails.paymentPageLink
     652                                    );
     653                                    startIframe(
     654                                        payment.getPaymentResult()
     655                                            .paymentDetails.paymentPageLink,
     656                                        overlay,
     657                                        loader
     658                                    );
     659                                    // Start polling for order status (fallback for redirect)
     660                                    var paymentDetails = payment.getPaymentResult().paymentDetails;
     661                                    if (paymentDetails.order_id && paymentDetails.order_received_url) {
     662                                        startOrderStatusPoll({
     663                                            order_id: paymentDetails.order_id,
     664                                            order_received_url: paymentDetails.order_received_url
     665                                        });
     666                                    }
     667                                    // Disconnect the observer to stop observing further changes
     668                                } else {
     669                                    alert(
     670                                        (window.payplus_i18n && window.payplus_i18n.payment_page_failed)
     671                                            ? window.payplus_i18n.payment_page_failed
     672                                            : "Error: the payment page failed to load."
     673                                    );
     674                                    location.reload();
     675                                }
     676                            }
     677                            observer.disconnect();
     678                        }
     679                    }
     680                }
     681            });
     682            // Start observing the target node for configured mutations
     683            const targetNode = document.body; // Or any other parent node where the element might be added
     684            const config = { childList: true, subtree: true };
     685            observer.observe(targetNode, config);
     686        }
     687        // Wait for a few seconds before starting to observe
     688        setTimeout(startObserving(), 1000); // Adjust the time (in milliseconds) as needed
     689    });
     690
     691    function startIframe(paymentPageLink, overlay, loader) {
     692        document.body.appendChild(overlay);
     693        overlay.appendChild(loader);
     694        const activePaymentMethod = payment.getActivePaymentMethod();
     695        const gateWaySettings =
     696            window.wc.wcSettings.getPaymentMethodData(activePaymentMethod)[
     697                activePaymentMethod + "-settings"
     698            ];
     699        var iframe = document.createElement("iframe");
     700        iframe.id = "pp_iframe";
     701        iframe.name = "payplus-iframe";
     702        iframe.width = "95%";
     703        iframe.height = "100%";
     704        iframe.style.border = "0";
     705        iframe.style.display = "block";
     706        iframe.style.margin = "auto";
     707
     708        iframe.src = paymentPageLink;
     709        let pp_iframes = document.querySelectorAll(".pp_iframe");
     710        let pp_iframe = document
     711            .querySelector(
     712                `#radio-control-wc-payment-method-options-${activePaymentMethod}`
     713            )
     714            .nextElementSibling.querySelector(".pp_iframe");
     715        if (
     716            ["samePageIframe", "popupIframe"].indexOf(
     717                gateWaySettings.displayMode
     718            ) !== -1
     719        ) {
     720            if (activePaymentMethod !== "payplus-payment-gateway") {
     721                for (let c = 0; c < pp_iframes.length; c++) {
     722                    const grandparent = pp_iframes[c].parentNode.parentNode;
     723                    if (grandparent) {
     724                        const grandparentId = grandparent.id;
     725                        if (grandparentId.includes(activePaymentMethod)) {
     726                            pp_iframe = pp_iframes[c];
     727                        } else {
     728                        }
     729                    } else {
     730                    }
     731                }
     732            }
     733            gateWaySettings.displayMode =
     734                window.innerWidth <= 768 &&
     735                gateWaySettings.displayMode === "samePageIframe"
     736                    ? "popupIframe"
     737                    : gateWaySettings.displayMode;
     738            switch (gateWaySettings.displayMode) {
     739                case "samePageIframe":
     740                    pp_iframe.style.position = "relative";
     741                    pp_iframe.style.height = gateWaySettings.iFrameHeight;
     742                    overlay.style.display = "none";
     743                    break;
     744                case "popupIframe":
     745                    pp_iframe.style.width =
     746                        window.innerWidth <= 768 ? "98%" : (gateWaySettings.iFrameWidth || "40%");
     747                    pp_iframe.style.height = gateWaySettings.iFrameHeight;
     748                    pp_iframe.style.position = "fixed";
     749                    pp_iframe.style.top = "50%";
     750                    pp_iframe.style.left = "50%";
     751                    pp_iframe.style.paddingBottom =
     752                        window.innerWidth <= 768 ? "20px" : "10px";
     753                    pp_iframe.style.paddingTop =
     754                        window.innerWidth <= 768 ? "20px" : "10px";
     755                    pp_iframe.style.backgroundColor = "white";
     756                    pp_iframe.style.transform = "translate(-50%, -50%)";
     757                    pp_iframe.style.zIndex = 100000;
     758                    pp_iframe.style.boxShadow = "10px 10px 10px 10px grey";
     759                    pp_iframe.style.borderRadius = "5px";
     760                    document.body.style.overflow = "hidden";
     761                    document.getElementsByClassName(
     762                        "blocks-payplus_loader"
     763                    )[0].style.display = "none";
     764                    break;
     765                default:
     766                    break;
     767            }
     768
     769            pp_iframe.style.display = "block";
     770            pp_iframe.style.border = "none";
     771            pp_iframe.style.overflow = "scroll";
     772            pp_iframe.style.msOverflowStyle = "none"; // For Internet Explorer 10+
     773            pp_iframe.style.scrollbarWidth = "none"; // For Firefox
     774            pp_iframe.firstElementChild.style.display = "block";
     775            pp_iframe.firstElementChild.style.cursor = "pointer";
     776            pp_iframe.firstElementChild.addEventListener("click", (e) => {
     777                e.preventDefault();
     778                pp_iframe.style.display = "none";
     779                var currentUrl = window.location.href;
     780                var params = new URLSearchParams(currentUrl);
     781                location.reload();
     782            });
     783            pp_iframe.appendChild(iframe);
     784            if (payPlusGateWay.importApplePayScript) {
     785                addScriptApple();
     786            }
     787        }
     788    }
     789
     790    function multiPassIcons(loopImages, element = null) {
     791        /* Check if multipass method is available and if so check for clubs and replace icons! */
     792        if (element === null) {
     793            element = document.querySelector(
     794                "#radio-control-wc-payment-method-options-payplus-payment-gateway-multipass"
     795            );
     796        }
     797        const isMultiPass = wcSettings.paymentMethodSortOrder.includes(
     798            "payplus-payment-gateway-multipass"
     799        );
     800        if (
     801            loopImages &&
     802            isMultiPass &&
     803            Object.keys(
     804                wcSettings.paymentMethodData["payplus-payment-gateway"]
     805                    .multiPassIcons
     806            ).length > 0
     807        ) {
     808            // console.log("isMultiPass");
     809            const multiPassIcons =
     810                wcSettings.paymentMethodData["payplus-payment-gateway"]
     811                    .multiPassIcons;
     812
     813            // Function to find an image by its src attribute
     814            function findImageBySrc(src) {
     815                // Find all images within the document
     816                let images = document.querySelectorAll("img");
     817                // Loop through images to find the one with the matching src
     818                for (let img of images) {
     819                    if (img.src.includes(src)) {
     820                        return img;
     821                    }
     822                }
     823                return null;
     824            }
     825
     826            // Function to replace the image source with fade effect
     827            function replaceImageSourceWithFade(image, newSrc) {
     828                if (image && newSrc) {
     829                    image.style.transition = "opacity 0.5s";
     830                    image.style.opacity = 0;
     831
     832                    setTimeout(() => {
     833                        image.src = newSrc;
     834                        image.style.opacity = 1;
     835                    }, 500);
     836                } else {
     837                    console.log("Image or new source not found.");
     838                }
     839            }
     840
     841            // Example usage
     842            if (element) {
     843                // Find the image with the specific src
     844                let imageToChange = findImageBySrc("multipassLogo.png");
     845                if (imageToChange) {
     846                    let originalSrc = imageToChange.src;
     847                    let imageIndex = 0;
     848                    const imageKeys = Object.keys(multiPassIcons);
     849                    const sources = imageKeys.map((key) => multiPassIcons[key]);
     850
     851                    function loopReplaceImageSource() {
     852                        const newSrc = sources[imageIndex];
     853                        replaceImageSourceWithFade(imageToChange, newSrc);
     854                        imageIndex = (imageIndex + 1) % sources.length;
     855                        if (
     856                            Object.keys(
     857                                wcSettings.paymentMethodData[
     858                                    "payplus-payment-gateway"
     859                                ].multiPassIcons
     860                            ).length > 1
     861                        ) {
     862                            setTimeout(loopReplaceImageSource, 2000); // Change image every 3 seconds
     863                        }
     864                    }
     865
     866                    loopReplaceImageSource();
     867                    loopImages = false;
     868                }
     869            }
     870        }
     871        /* finished multipass image replace */
     872    }
     873
     874
     875    const putOverlay = (remove = false) => {
     876        if (remove) {
     877            // If remove is true, remove the overlay and restore scrolling
     878            if ($overlay) {
     879                $overlay.remove();
     880                jQuery("body").css({
     881                    overflow: "", // Restore scrolling
     882                });
     883                $overlay = null; // Clear the reference
     884            }
     885        } else {
     886            // If remove is false, create and show the overlay
     887            if (!$overlay) {
     888                $overlay = jQuery("<div></div>")
     889                    .css({
     890                        position: "fixed",
     891                        top: 0,
     892                        left: 0,
     893                        width: "100%",
     894                        height: "100%",
     895                        backgroundColor: "rgba(255, 255, 255, 0.7)", // milky opacity
     896                        zIndex: 9999,
     897                        cursor: "not-allowed",
     898                    })
     899                    .appendTo("body");
     900
     901                // Prevent scrolling
     902                jQuery("body").css({
     903                    overflow: "hidden",
     904                });
     905
     906                // Disallow clicks on overlay
     907                $overlay.on("click", function (event) {
     908                    event.stopPropagation();
     909                    event.preventDefault();
     910                });
     911            }
     912        }
     913    };
     914}
  • payplus-payment-gateway/trunk/hashes.json

    r3461765 r3464247  
    11{
    2     "\/payplus-payment-gateway.php": "fe72878a245d155c4255d241360c4254e9a76d1f023907f7df7ff6b13308bc0b",
     2    "\/payplus-payment-gateway.php": "35622fd247563811c1052e5af13f15662c5156a2a5a57a94d23fb9dab076ee3e",
    33    "\/index.php": "c491dec192c55a18cd5d9ec23375720d58d40455dc685e7e4093c1198cc76b89",
    4     "\/CHANGELOG.md": "e134511809d59c7dcaf0a96ed1b62beae0fdbd6c2b4d1d715867c54082d757ef",
    5     "\/includes\/blocks\/class-wc-payplus-blocks-support.php": "684cf7dbe9408624bc44192992c35c77a4c79116783f44eea8cc58f0daccc458",
     4    "\/CHANGELOG.md": "c09e4b0e34fff28b2b3d02e890a59640de596b36f7d140bb6ffbb3fecccacb42",
     5    "\/includes\/blocks\/class-wc-payplus-blocks-support.php": "885e40ffcbc71bded19e7fec8946b29ce314440b183c5665df62f75a9a6719ec",
    66    "\/includes\/wc_payplus_express_checkout.php": "0e227cc783f67068b2f23fd4e1045ac6b2b2969c483a11e8661a3ea3fa8c3b7d",
    77    "\/includes\/wc_payplus_invoice.php": "6e3442e8336ec9b2a0532170982937ee555dd590f14c3aedfcb27e0ba8e0215f",
    88    "\/includes\/wc-payplus-activation-functions.php": "04c26cc834bf48d48aa7b66b6663cb7ae9539540ce54e7b32282983a9122daf2",
    9     "\/includes\/wc_payplus_gateway.php": "7419c98bb87439e9af0a77a6614d8434f0bb5474cd1ec2e1b6335fb70ea41098",
     9    "\/includes\/wc_payplus_gateway.php": "07d14db8faa00cccf8e3019f9c9e7d4843ea8a7c1e2a5916e3f7265ae8f4c3d7",
    1010    "\/includes\/admin\/class-wc-payplus-admin-settings.php": "1cced01c730dbf8b8fc7bcef323de918d95b615519f937830ee54bbdf245fcac",
    1111    "\/includes\/admin\/class-wc-payplus-admin.php": "e24d0009ab06349acbde8028ef7319c8496cf2f4de82fe7c66e076b9bf7a9afc",
     
    1616    "\/includes\/class-wc-payplus-embedded.php": "ec7c9cb5c850e1840e0efa50e7c9c18f1f7aca9604819170d8d40e5fc1c70c6b",
    1717    "\/includes\/class-wc-payplus-hosted-fields.php": "3ac49de130d06fad83f641ae6f7e93b7bb774a05764e6d38341e776c8106ca1c",
    18     "\/includes\/class-wc-payplus-form-fields.php": "5f44bc36fd2a0e493802942931e02934a0ea517802c981a357a025e515553a86",
     18    "\/includes\/class-wc-payplus-form-fields.php": "f8f3638ff7bfed927f0cb99ac89c9b668947e76b0c2bd294ce42d70baea82a03",
    1919    "\/includes\/class-wc-payplus-error-handler.php": "9ea1f9a88633bf3a822823e53e0edeabfc031e6b895a4a28a1b327dfaa8d3dd4",
    2020    "\/includes\/class-wc-payplus-order-data.php": "adcfd3d155228fea50e57798822e0f2042a233f772e114327d98b616ea73ad6f",
     
    2727    "\/languages\/payplus-payment-gateway.pot": "8869bece7da90f4afeafadf4ca2dfcf350f753bbe0663db16a083f1e0de8035d",
    2828    "\/templates\/hostedFields.php": "640574751191114c65fc137aa7b4ad7011452ce43043be1bd3ec0c4f6db26676",
    29     "\/readme.txt": "af231a8ae663020f87054f53baf76d1696f0c6ba724eb72496d8e9abe0c6af02",
     29    "\/readme.txt": "53b9f7dc90a034d04ac5dd4e1616dbfbe1455f29b2f359a221b4aa0f05af121c",
    3030    "\/assets\/css\/alertify.min.css": "12e60b6d60e45a69e3dc0f442bb4005eb47fba5ceb42fc6435cd8b4867a3f69d",
    3131    "\/assets\/css\/admin.scss": "02157f910d6c8f917da018bac5fed1022046b427e2a5a9174fc5cc68182070c5",
     
    121121    "\/assets\/js\/front.js": "2fa318e8e55c74203429c466d46d407b99e01ec596eb307e1efb535e18001090",
    122122    "\/assets\/js\/payplus-hosted-fields\/dist\/payplus-hosted-fields.min.js": "d8dbf1919a7307776634a6690fbb182e3652d3d16c56cae3b71c9061e85b0a0f",
    123     "\/assets\/js\/checkout.min.js": "22515ca338f5d4710be593cac426f1d83b3241446e4e52749b6c5c79f2eba47c",
     123    "\/assets\/js\/checkout.min.js": "b1b45e6ee406dd844110728bd123b2b685d6f05d8ec573f9e58b30742f1bdae0",
    124124    "\/assets\/js\/admin.min.js": "78eb38cc7b3e871a8cfc882ab0254c075480dc8a29403d8d0f6d907eb3933ebc",
    125125    "\/assets\/js\/admin.js": "2de8d3a1cba863a77f8efc6c12112c8d4f08d58423488c3d54c39d5adf081c10",
    126126    "\/assets\/js\/alertify.min.js": "cb1d39a1e5cacaff5d2ee78770996d3c0f75a6f2a46fa6a960ae729b20a9244f",
    127127    "\/assets\/js\/admin-payments.min.js": "d1ae64a19bebaaf50e6e273f78c5f1154d577c4395a63bd22910d30a58151836",
    128     "\/assets\/js\/checkout.js": "1a79dfeec37a934dbd4e5bdf5d28b7386b44d4bfcf4cfd90ce6ba87f7ce5c00d",
     128    "\/assets\/js\/checkout.js": "57d7193954278fd03deb1cdef94f7a14cfccac2d37077ce6018f82b027a40765",
    129129    "\/block\/dist\/css\/woocommerce-blocks\/style.css": "5b51b0d574ac6e17118924b59c0d2bdabd115a9db88b28d514146804e4204326",
    130     "\/block\/dist\/js\/woocommerce-blocks\/blocks.min.js": "2bb1606f24e198b944e2299521f81d6e76f88ce22773960bc1c3953aa23b85c2",
    131     "\/block\/dist\/js\/woocommerce-blocks\/blocks.js": "8a0f08e7dca049d098151a66589c8ce7d7e734cfba13e3a4ba95d25b9c13d28b",
     130    "\/block\/dist\/js\/woocommerce-blocks\/blocks.min.js": "9b79f3c5f68ba7cbf7fc30a26013d6a16b2106c95fa24218d090ba6640ecbbd5",
     131    "\/block\/dist\/js\/woocommerce-blocks\/blocks.js": "9b79f3c5f68ba7cbf7fc30a26013d6a16b2106c95fa24218d090ba6640ecbbd5",
    132132    "\/block\/dist\/js\/woocommerce-blocks\/blocks.asset.php": "888e6a1635c15d8041b5bc620a9caf8ba13c6ca43ce638dccef694add8f5e13a"
    133133}
  • payplus-payment-gateway/trunk/includes/blocks/class-wc-payplus-blocks-support.php

    r3459669 r3464247  
    504504
    505505                $payment_details['paymentPageLink'] = $responseArray['data']['payment_page_link'];
     506                $payment_details['order_received_url'] = $order->get_checkout_order_received_url();
    506507            }
    507508            $result->set_payment_details($payment_details);
  • payplus-payment-gateway/trunk/includes/class-wc-payplus-form-fields.php

    r3461765 r3464247  
    10991099                'custom_attributes' => array('disabled' => 'disabled'),
    11001100            ],
     1101            'iframe_redirect_legacy' => [
     1102                'title' => __('Iframe redirect — legacy mode', 'payplus-payment-gateway'),
     1103                'type' => 'checkbox',
     1104                'label' => __('Use direct redirect from iframe (may require Firefox permission)', 'payplus-payment-gateway'),
     1105                'default' => 'no',
     1106                'desc_tip' => true,
     1107                'description' => __('When checked, the payment iframe redirects the browser directly (the old method). Firefox users may see a "prevented redirect" prompt they need to allow. When unchecked (default), the checkout page detects payment completion via server polling and redirects automatically — no browser prompt needed.', 'payplus-payment-gateway'),
     1108            ],
    11011109            'pos_override' => [
    11021110                'title' => __('POS Override', 'payplus-payment-gateway'),
  • payplus-payment-gateway/trunk/includes/wc_payplus_gateway.php

    r3461765 r3464247  
    21142114        if (in_array($this->display_mode, ['samePageIframe', 'popupIframe']) && !$is_token || $this->id === "payplus-payment-gateway-hostedfields") {
    21152115            $result['payplus_iframe'] = $this->receipt_page($order_id, null, false, '', 0, true);
     2116            // Provide order details so the checkout page can poll for completion status.
     2117            // This powers the Firefox-safe polling fallback for iframe redirects.
     2118            $order = wc_get_order($order_id);
     2119            if ($order) {
     2120                $result['order_id']           = $order_id;
     2121                $result['order_received_url'] = $order->get_checkout_order_received_url();
     2122            }
    21162123        }
    21172124        return $result;
  • payplus-payment-gateway/trunk/payplus-payment-gateway.php

    r3461765 r3464247  
    55 * Description: Accept credit/debit card payments or other methods such as bit, Apple Pay, Google Pay in one page. Create digitally signed invoices & much more.
    66 * Plugin URI: https://www.payplus.co.il/wordpress
    7  * Version: 8.0.5
     7 * Version: 8.0.6
    88 * Tested up to: 6.9
    99 * Requires Plugins: woocommerce
     
    2020define('PAYPLUS_PLUGIN_URL_ASSETS_IMAGES', PAYPLUS_PLUGIN_URL . "assets/images/");
    2121define('PAYPLUS_PLUGIN_DIR', dirname(__FILE__));
    22 define('PAYPLUS_VERSION', '8.0.5');
    23 define('PAYPLUS_VERSION_DB', 'payplus_8_0_5');
     22define('PAYPLUS_VERSION', '8.0.6');
     23define('PAYPLUS_VERSION_DB', 'payplus_8_0_6');
    2424define('PAYPLUS_TABLE_PROCESS', 'payplus_payment_process');
    2525class WC_PayPlus
     
    8989        add_action('wp_ajax_nopriv_make-hosted-payment', [$this, 'hostedPayment']);
    9090        add_action('wp_ajax_run_payplus_invoice_runner', [$this, 'ajax_run_payplus_invoice_runner']);
     91
     92        // AJAX endpoint for client-side polling of order status (Firefox iframe redirect fallback)
     93        add_action('wp_ajax_payplus_check_order_redirect', [$this, 'ajax_payplus_check_order_redirect']);
     94        add_action('wp_ajax_nopriv_payplus_check_order_redirect', [$this, 'ajax_payplus_check_order_redirect']);
    9195
    9296        //end custom hook
     
    966970                }
    967971                $redirect_to = add_query_arg('order-received', $order_id, get_permalink(wc_get_page_id('checkout')));
    968                 wp_safe_redirect($redirect_to);
    969                 exit;
     972                $this->payplus_redirect_graceful($redirect_to);
    970973            } else {
    971974                // no order id
     
    10571060                }
    10581061                WC()->session->__unset('save_payment_method');
    1059                 wp_safe_redirect($linkRedirect);
    1060                 exit;
     1062                $this->payplus_redirect_graceful($linkRedirect);
    10611063            } else {
    10621064                $countProcess = intval($result->count_process);
     
    10901092
    10911093                WC()->session->__unset('save_payment_method');
    1092                 wp_safe_redirect($linkRedirect);
    1093                 exit;
     1094                $this->payplus_redirect_graceful($linkRedirect);
    10941095            }
    10951096        } elseif (
     
    11021103                $linkRedirect = html_entity_decode(esc_url($this->payplus_gateway->get_return_url($order)));
    11031104                WC()->session->__unset('save_payment_method');
    1104                 wp_safe_redirect($linkRedirect);
    1105                 exit;
    1106             }
    1107         }
     1105                $this->payplus_redirect_graceful($linkRedirect);
     1106            }
     1107        }
     1108    }
     1109
     1110    /**
     1111     * AJAX handler: returns order status + redirect URL for client-side polling.
     1112     *
     1113     * The checkout page polls this endpoint after opening the payment iframe.
     1114     * When the order moves to processing/completed (via IPN callback), the
     1115     * client-side JS detects it and redirects the top window — completely
     1116     * bypassing any iframe-to-parent navigation that Firefox might block.
     1117     */
     1118    public function ajax_payplus_check_order_redirect()
     1119    {
     1120        check_ajax_referer('frontNonce', '_ajax_nonce');
     1121
     1122        $order_id  = isset($_REQUEST['order_id']) ? absint($_REQUEST['order_id']) : 0;
     1123        $order_key = isset($_REQUEST['order_key']) ? sanitize_text_field(wp_unslash($_REQUEST['order_key'])) : '';
     1124
     1125        if (!$order_id || !$order_key) {
     1126            wp_send_json_error(['status' => 'invalid']);
     1127        }
     1128
     1129        $order = wc_get_order($order_id);
     1130        if (!$order || $order->get_order_key() !== $order_key) {
     1131            wp_send_json_error(['status' => 'invalid']);
     1132        }
     1133
     1134        $status       = $order->get_status();
     1135        $redirect_url = $order->get_checkout_order_received_url();
     1136
     1137        wp_send_json_success([
     1138            'status'       => $status,
     1139            'redirect_url' => $redirect_url,
     1140        ]);
     1141    }
     1142
     1143    /**
     1144     * Graceful redirect that works inside iframes (Firefox-safe).
     1145     *
     1146     * DEFAULT (new method — iframe_redirect_legacy = no):
     1147     *   When running inside an iframe, outputs a tiny HTML page that sends
     1148     *   postMessage to the parent with the redirect URL. The parent checkout
     1149     *   page picks it up and redirects, or the polling fallback catches it.
     1150     *   No Firefox "prevented redirect" prompt.
     1151     *
     1152     * LEGACY (iframe_redirect_legacy = yes):
     1153     *   Uses wp_safe_redirect directly — the old behaviour. Firefox may show
     1154     *   a "prevented redirect" prompt that the user must allow.
     1155     *
     1156     * When running in the top window (direct visit), both modes do a normal redirect.
     1157     *
     1158     * @param string $url The URL to redirect to.
     1159     */
     1160    private function payplus_redirect_graceful($url)
     1161    {
     1162        // Check if legacy (old) redirect mode is enabled in plugin settings
     1163        $use_legacy = property_exists($this->payplus_payment_gateway_settings, 'iframe_redirect_legacy')
     1164            && $this->payplus_payment_gateway_settings->iframe_redirect_legacy === 'yes';
     1165
     1166        if ($use_legacy) {
     1167            // Old method: direct wp_safe_redirect (Firefox may prompt to allow)
     1168            wp_safe_redirect($url);
     1169            exit;
     1170        }
     1171
     1172        // New method: postMessage to parent + polling fallback
     1173        $url = esc_url($url);
     1174        nocache_headers();
     1175        header('Content-Type: text/html; charset=utf-8');
     1176        echo '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>';
     1177        echo '<script>(function(){';
     1178        echo 'var u=' . wp_json_encode($url) . ';';
     1179        // If we are inside an iframe, send postMessage to parent and show message.
     1180        // The parent will handle the actual redirect.
     1181        echo 'if(window.self!==window.top){';
     1182        echo 'try{window.parent.postMessage({type:"payplus_redirect",url:u},window.location.origin);}catch(e){}';
     1183        echo 'document.body.innerText="' . esc_js(__('Payment received — redirecting…', 'payplus-payment-gateway')) . '";';
     1184        echo '}else{';
     1185        // Top window — just redirect normally.
     1186        echo 'window.location.href=u;';
     1187        echo '}';
     1188        echo '})();</script>';
     1189        echo '</body></html>';
     1190        exit;
    11081191    }
    11091192
     
    15101593                            "enableDoubleCheckIfPruidExists" => isset($this->payplus_gateway) && $this->payplus_gateway->enableDoubleCheckIfPruidExists ? true : false,
    15111594                            "hostedPayload" => WC()->session ? WC()->session->get('hostedPayload') : null,
     1595                            "iframeRedirectLegacy" => boolval(property_exists($this->payplus_payment_gateway_settings, 'iframe_redirect_legacy') && $this->payplus_payment_gateway_settings->iframe_redirect_legacy === 'yes'),
    15121596                        ]
    15131597                    );
  • payplus-payment-gateway/trunk/readme.txt

    r3461765 r3464247  
    55Tested up to: 6.9
    66Requires PHP: 7.4
    7 Stable tag: 8.0.5
     7Stable tag: 8.0.6
    88PlugIn URL: https://www.payplus.co.il/wordpress
    99License: GPLv2 or later
     
    8686
    8787== Changelog ==
     88
     89== 8.0.6  - 18-02-2026 =
     90
     91- Tweak     - Added automatic polling fallback for iframe payment redirects in both blocks and classic checkouts. This ensures reliable redirects for Firefox users and other scenarios where the iframe cannot communicate via postMessage. The system polls the server for order completion status and redirects to the thank-you page automatically.
     92- Fix       - Fixed EMV POS device functionality issue when only one admin user was configured.
    8893
    8994== 8.0.5  - 15-02-2026 =
Note: See TracChangeset for help on using the changeset viewer.