Plugin Directory

Changeset 3783345


Ignore:
Timestamp:
11/04/2026 07:59:55 AM (less than one hour ago)
Author:
michaelbengtsson
Message:

Update to version 2.24.1 from GitHub

Location:
klarna-checkout-for-woocommerce
Files:
58 edited
1 copied

Legend:

Unmodified
Added
Removed
  • klarna-checkout-for-woocommerce/tags/2.24.1/assets/js/klarna-checkout-for-woocommerce.js

    r3743403 r3783345  
    3030                suspended: false,
    3131                // True once a shipping address is known (via shipping_address_change or change event).
    32                 // Prevents api.suspend from being called before Kustom has an address to fetch shipping for.
     32                // With Kustom Shipping Assistant, prevents api.suspend from being called before Kustom has an address to fetch shipping for.
    3333                shippingAddressKnown: false,
     34                lastOrderTotal: null,
    3435
    3536                redirectAttemptCount: 0,
    … …  
    116117                /**
    117118                 * Suspends the Kustom Iframe.
    118                  * Will not suspend again if already suspended, and will not suspend before a shipping
    119                  * address is known (to avoid triggering premature KSA external TMS shipping fetches).
     119                 * Will not suspend again if already suspended. With Kustom Shipping Assistant, will not suspend before
     120                 * a shipping address is known (to avoid triggering premature KSA external TMS shipping fetches).
     121                 * Without it, the iframe must always be suspended, since it only fetches the updated order on resume.
    120122                 * @param {boolean} autoResumeBool
    121                  */
    122                 kcoSuspend: function ( autoResumeBool ) {
    123                         if ( window._klarnaCheckout && ! kco_wc.validation && ! kco_wc.suspended && kco_wc.shippingAddressKnown ) {
     123                 * @param {boolean} ignoreAddress Suspend even if no shipping address is known yet.
     124                 */
     125                kcoSuspend: function ( autoResumeBool, ignoreAddress ) {
     126                        const waitForAddress = "yes" === kco_params.ksa_enabled && ! kco_wc.shippingAddressKnown && ! ignoreAddress
     127                        if ( window._klarnaCheckout && ! kco_wc.validation && ! kco_wc.suspended && ! waitForAddress ) {
    124128                                kco_wc.log( "kcoSuspend", autoResumeBool )
    125129                                window._klarnaCheckout( function ( api ) {
    … …  
    131135                                        } )
    132136                                } )
     137                        }
     138                },
     139
     140                /**
     141                 * Suspends the iframe after a cart total change so the next resume fetches the updated order.
     142                 * @param {Event} event
     143                 * @param {Object} data The update_order_review response.
     144                 */
     145                maybeSuspendOnTotalChange: function ( event, data ) {
     146                        const orderTotal = data && data.fragments ? data.fragments.kco_order_total : undefined
     147                        if ( undefined === orderTotal ) {
     148                                return
     149                        }
     150
     151                        const previousTotal = kco_wc.lastOrderTotal
     152                        kco_wc.lastOrderTotal = orderTotal
     153                        if ( null !== previousTotal && orderTotal !== previousTotal ) {
     154                                kco_wc.kcoSuspend( true, true )
    133155                        }
    134156                },
    … …  
    224246                        var form = $( 'form[name="checkout"] input, form[name="checkout"] select, textarea' )
    225247                        var checkout_add_ons_moved = false
    226                         for ( i = 0; i < form.length; i++ ) {
     248                        for ( let i = 0; i < form.length; i++ ) {
    227249                                var name = form[ i ].name.replace( "[]", "\\[\\]" ) // Escape any empty "array" keys to prevent errors.
    228250                                // Check if field is inside the order review.
    … …  
    603625                                kco_wc.kcoSuspend( true )
    604626                        } )
     627                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.maybeSuspendOnTotalChange )
    605628                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.kcoResume )
    606629                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.maybeDisplayShippingPrice )
    … …  
    632655                                                                "given_name" in data && $( "#billing_first_name" ).val( data.given_name )
    633656                                                                "family_name" in data && $( "#billing_last_name" ).val( data.family_name )
     657                                                                "street_address" in data && $( "#billing_address_1" ).val( data.street_address )
     658                                                                "street_address2" in data && $( "#billing_address_2" ).val( data.street_address2 )
     659                                                                "city" in data && $( "#billing_city" ).val( data.city )
    634660                                                                "postal_code" in data && $( "#billing_postcode" ).val( data.postal_code )
    635661                                                                "country" in data && $( "#billing_country" ).val( country )
     662                                                                "phone" in data && $( "#billing_phone" ).val( data.phone )
    636663                                                                "email" in data && $( "#billing_email" ).val( data.email )
    637664                                                                $( "#billing_country" ).trigger( "change" )
    … …  
    646673                                                                "given_name" in data && $( "#shipping_first_name" ).val( data.given_name )
    647674                                                                "family_name" in data && $( "#shipping_last_name" ).val( data.family_name )
     675                                                                "street_address" in data && $( "#shipping_address_1" ).val( data.street_address )
     676                                                                "street_address2" in data && $( "#shipping_address_2" ).val( data.street_address2 )
     677                                                                "city" in data && $( "#shipping_city" ).val( data.city )
    648678                                                                "postal_code" in data && $( "#shipping_postcode" ).val( data.postal_code )
    649679                                                                "country" in data && $( "#shipping_country" ).val( country )
     680                                                                "phone" in data && $( "#shipping_phone" ).val( data.phone )
    650681                                                                $( "#shipping_country" ).trigger( "change" )
    651682
    … …  
    660691                                                        "given_name" in data && $( "#billing_first_name" ).val( data.given_name )
    661692                                                        "family_name" in data && $( "#billing_last_name" ).val( data.family_name )
     693                                                        "street_address" in data && $( "#billing_address_1" ).val( data.street_address )
     694                                                        "street_address2" in data && $( "#billing_address_2" ).val( data.street_address2 )
     695                                                        "city" in data && $( "#billing_city" ).val( data.city )
    662696                                                        "postal_code" in data && $( "#billing_postcode" ).val( data.postal_code )
    663697                                                        "country" in data && $( "#billing_country" ).val( country )
     698                                                        "phone" in data && $( "#billing_phone" ).val( data.phone )
    664699                                                        "email" in data && $( "#billing_email" ).val( data.email )
    665700                                                        $( "#billing_country" ).trigger( "change" )
  • klarna-checkout-for-woocommerce/tags/2.24.1/assets/js/klarna-checkout-for-woocommerce.min.js

    r3743403 r3783345  
    1 jQuery(function(a){if("undefined"==typeof kco_params)return!1;var t={bodyEl:a("body"),checkoutFormSelector:a("form.checkout"),paymentMethodEl:a('input[name="payment_method"]'),paymentMethod:"",selectAnotherSelector:"#klarna-checkout-select-other",shippingUpdated:!1,validation:!1,preventPaymentMethodChange:!1,timeout:null,interval:null,klarnaUpdateNeeded:!1,shippingEmailExists:!1,suspended:!1,shippingAddressKnown:!1,redirectAttemptCount:0,documentReady:function(){if(0<t.paymentMethodEl.length)t.paymentMethod=t.paymentMethodEl.filter(":checked").val();else{if(!(0<a("ul.wc_payment_methods").length))return;t.paymentMethod="kco"}if("kco"===t.paymentMethod){t.log(kco_params),"kco"===t.paymentMethod&&a("#ship-to-different-address-checkbox").prop("checked",!0),kco_params.pay_for_order||(t.moveExtraCheckoutFields(),t.updateShipping(!1));let o=!1;new MutationObserver(function(e){e.forEach(function(e){"attributes"===e.type&&"class"===e.attributeName&&(a("html").hasClass("klarna-checkout-fso-open")?o=!0:o&&(e=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout",(e=a(e)).length&&e.find(".woocommerce-error").length&&a("html, body").not(":animated").animate({scrollTop:e.offset().top-100},1e3),t.unblock(),o=!1))})}).observe(document.querySelector("html"),{attributes:!0,attributeFilter:["class"]})}},unblock:function(){t.kcoSuspend(),t.checkoutFormSelector.removeClass("processing"),a(".woocommerce-checkout-review-order-table").unblock(),a(t.checkoutFormSelector).unblock(),t.kcoResume()},kcoSuspend:function(o){window._klarnaCheckout&&!t.validation&&!t.suspended&&t.shippingAddressKnown&&(t.log("kcoSuspend",o),window._klarnaCheckout(function(e){t.suspended=!0,e.suspend({autoResume:{enabled:o}})}))},kcoResume:function(){window._klarnaCheckout&&!t.validation&&t.suspended&&(t.suspended=!1,t.log("kcoResume"),window._klarnaCheckout(function(e){e.resume()}))},changeFromKco:function(e){e.preventDefault(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",dataType:"json",data:{kco:!1,nonce:kco_params.change_payment_method_nonce},url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})},maybeChangeToKco:function(){t.preventPaymentMethodChange||(t.log(a(this).val()),"kco"===a(this).val()&&(a(".woocommerce-info").remove(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",data:{kco:!0,nonce:kco_params.change_payment_method_nonce},dataType:"json",url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})))},moveExtraCheckoutFields:function(){a(".woocommerce-additional-fields").appendTo("#kco-extra-checkout-fields");var e=a('form[name="checkout"] input, form[name="checkout"] select, textarea'),o=!1;for(i=0;i<e.length;i++){var n=e[i].name.replace("[]","\\[\\]");a("table.woocommerce-checkout-review-order-table").find(e[i]).length||-1===a.inArray(n,kco_params.standard_woo_checkout_fields)&&("wc_checkout_add_ons"===a("p#"+n+"_field").parent().attr("id")?o||(o=!0,a("div#wc_checkout_add_ons").appendTo("#kco-extra-checkout-fields")):(0<a("p#"+n+"_field").length?("shipping_email"===n&&(t.shippingEmailExists=!0),a("p#"+n+"_field")):a('input[name="'+n+'"]').closest("p")).appendTo("#kco-extra-checkout-fields"))}a(".woocommerce-account-fields").insertAfter(a("#createaccount").closest("p"))},maybeDisplayShippingPrice:function(){var e;a(".kco-shipping").length||"kco"===t.paymentMethod&&"yes"===kco_params.shipping_methods_in_iframe&&"no"===kco_params.is_confirmation_page&&(1<a('#shipping_method input[type="radio"]').length?a('#shipping_method input[type="radio"]:checked').each(function(){var e=a(this).attr("id"),e=a('label[for="'+e+'"]').text();a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")}):1===a('#shipping_method input[type="hidden"]').length?(e=a('#shipping_method input[name="shipping_method[0]"]').attr("id"),e=a('label[for="'+e+'"]').text(),a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")):a(".woocommerce-shipping-totals td").html(kco_params.no_shipping_message))},updateCart:function(){t.kcoSuspend(!0),a.ajax({type:"POST",url:kco_params.update_cart_url,data:{checkout:a("form.checkout").serialize(),nonce:kco_params.update_cart_nonce},dataType:"json",success:function(e){},error:function(e){},complete:function(e){a("body").trigger("update_checkout"),t.kcoResume()}})},getKlarnaOrder:function(){return console.log("getKustomOrder"),t.preventPaymentMethodChange=!0,a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.get_klarna_order_url,data:{nonce:kco_params.get_klarna_order_nonce},dataType:"json",success:function(e){t.setCustomerData(e.data),0<a("form.checkout #terms").length&&a("form.checkout #terms").prop("checked",!0),console.log("success")},error:function(e){console.log("error"),window.location.reload()},complete:function(e){}})},setCustomerData:function(e){t.log("setCustomerData",e),"object"==typeof e&&null!==e&&("billing_address"in e&&null!==e.billing_address&&(a("#billing_first_name").val("given_name"in e.billing_address?e.billing_address.given_name:""),a("#billing_last_name").val("family_name"in e.billing_address?e.billing_address.family_name:""),a("#billing_company").val("organization_name"in e.billing_address?e.billing_address.organization_name:""),a("#billing_address_1").val("street_address"in e.billing_address?e.billing_address.street_address:""),a("#billing_address_2").val("street_address2"in e.billing_address?e.billing_address.street_address2:""),a("#billing_city").val("city"in e.billing_address?e.billing_address.city:""),a("#billing_postcode").val("postal_code"in e.billing_address?e.billing_address.postal_code:""),a("#billing_phone").val("phone"in e.billing_address?e.billing_address.phone:""),a("#billing_email").val("email"in e.billing_address?e.billing_address.email:""),a("#billing_country").val("country"in e.billing_address?e.billing_address.country.toUpperCase():""),a("#billing_state").val("region"in e.billing_address?e.billing_address.region:""),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur")),"shipping_address"in e)&&null!==e.shipping_address&&(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#shipping_first_name").val("given_name"in e.shipping_address?e.shipping_address.given_name:""),a("#shipping_last_name").val("family_name"in e.shipping_address?e.shipping_address.family_name:""),a("#shipping_company").val("organization_name"in e.shipping_address?e.shipping_address.organization_name:""),a("#shipping_address_1").val("street_address"in e.shipping_address?e.shipping_address.street_address:""),a("#shipping_address_2").val("street_address2"in e.shipping_address?e.shipping_address.street_address2:""),a("#shipping_city").val("city"in e.shipping_address?e.shipping_address.city:""),a("#shipping_postcode").val("postal_code"in e.shipping_address?e.shipping_address.postal_code:""),a("#shipping_country").val("country"in e.shipping_address?e.shipping_address.country.toUpperCase():""),a("#shipping_state").val("region"in e.shipping_address?e.shipping_address.region:""),a("#shipping_phone").val("phone"in e.shipping_address?e.shipping_address.phone:""),!0===t.shippingEmailExists)&&a("#shipping_email")&&a("#shipping_email").val("email"in e.shipping_address?e.shipping_address.email:"")},checkUrl:function(e){window.location.hash&&-1<window.location.hash.indexOf("#klarna-success")&&(t.logToFile("klarna-success hashtag detected in URL."),e({should_proceed:!0}),clearInterval(t.interval),clearTimeout(t.timeout),t.unblock())},failOrder:function(e,o,n){n({should_proceed:!1,message:a(o).text().trim()}),t.validation=!1;n=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout";a("body").trigger("update_checkout"),a(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),a(n).prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+o+"</div>"),a(n).removeClass("processing").unblock(),a(n).find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),a(document.body).trigger("checkout_error",[o])},logToFile:function(e){a.ajax({url:kco_params.log_to_file_url,type:"POST",dataType:"json",data:{message:"object"==typeof e?JSON.stringify(e):e,nonce:kco_params.log_to_file_nonce}})},log:function(...e){kco_params.logging&&console.log(...e)},updateShipping:function(e){var o=JSON.stringify(e);a("#kco_shipping_data").val()!==o&&(a("#kco_shipping_data").val(o),a("body").trigger("kco_shipping_option_changed",[e]),a("body").trigger("update_checkout"))},convertCountry:function(o){return Object.keys(kco_params.countries).find(e=>kco_params.countries[e]===o)},placeKlarnaOrder:function(n){t.getKlarnaOrder().done(function(e){e.success?(a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.submit_order,data:a("form.checkout").serialize(),dataType:"json",success:function(o){try{if("success"!==o.result)throw"Result failed";t.logToFile('Successfully placed order. Sending "should_proceed: true" to Kustom'),n({should_proceed:!0})}catch(e){o.messages?(t.logToFile({type:"checkout_error",message:o.messages}),t.failOrder("submission",o.messages,n)):(t.logToFile({type:"checkout_error",message:"No message"}),t.failOrder("submission",'<div class="woocommerce-error">Checkout error</div>',n))}},error:function(e){var o=(e.responseText||"").trimStart().startsWith("<");t.logToFile({type:"ajax_error",status:e.status,response:o?"[HTML body stripped]":e.responseText||""}),t.failOrder("ajax-error",'<div class="woocommerce-error">Internal Server Error</div>',n)}})):t.failOrder("get_order",'<div class="woocommerce-error">Failed to get the order from Kustom</div>',n),t.validation=!1})},update_checkout:a.Callbacks("unique stopOnFalse"),init:function(){"yes"!==kco_params.is_order_received_page&&(a(document).ready(t.documentReady),t.bodyEl.on("update_checkout",function(){t.kcoSuspend(!0)}),t.bodyEl.on("updated_checkout",t.kcoResume),t.bodyEl.on("updated_checkout",t.maybeDisplayShippingPrice),t.bodyEl.on("change","input.qty",t.updateCart),t.bodyEl.on("change",'input[name="payment_method"]',t.maybeChangeToKco),t.bodyEl.on("click",t.selectAnotherSelector,t.changeFromKco),t.update_checkout.add(function(){return t.log("fire update_checkout"),a("form.checkout").trigger("update_checkout"),!1}),"function"==typeof window._klarnaCheckout)&&window._klarnaCheckout(function(e){e.on({shipping_address_change:function(e){t.log("shipping_address_change",e),t.shippingAddressKnown=!0;var o=t.convertCountry(e.country.toUpperCase());"billing_only"===kco_params.woocommerce_ship_to_destination?("given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()):(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#ship-to-different-address-checkbox").trigger("change"),a("#ship-to-different-address-checkbox").trigger("blur"),"given_name"in e&&a("#shipping_first_name").val(e.given_name),"family_name"in e&&a("#shipping_last_name").val(e.family_name),"postal_code"in e&&a("#shipping_postcode").val(e.postal_code),"country"in e&&a("#shipping_country").val(o),a("#shipping_country").trigger("change"),a("form.checkout").trigger("update_checkout"))},billing_address_change:function(e){t.log("billing_address_change",e);var o=t.convertCountry(e.country.toUpperCase());"given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()},change:function(e){t.log("change",e),e.country&&e.postal_code&&(t.shippingAddressKnown=!0)},order_total_change:function(e){t.log("order_total_change",e)},shipping_option_change:function(e){t.log("shipping_option_change",e),t.log(e),t.updateShipping(e)},can_not_complete_order:function(e){t.log("can_not_complete_order",e)},validation_callback:function(e,o){t.validation=!0,t.logToFile("validation_callback from Kustom triggered"),kco_params.pay_for_order?o({should_proceed:!0}):t.placeKlarnaOrder(o)},customer:function(e){e="person"===e.type?"b2c":"b2b";a.ajax({url:kco_params.customer_type_changed_url,type:"POST",data:{nonce:kco_params.customer_type_changed_nonce,customer_type:e}})},checkbox_change:e=>{var{key:e,checked:o}=e;a.ajax({url:kco_params.checkbox_changed_url,type:"POST",data:{nonce:kco_params.checkbox_changed_nonce,key:e,checked:o},success:e=>{e.data.refresh_checkout&&(a(document.body).trigger("wc_fragment_refresh"),a(document.body).trigger("update_checkout"))}})},redirect_initiated:e=>{t.log("redirect_initiated",e),1<=t.redirectAttemptCount?t.logToFile(`Redirect was initiated by Kustom, but the user was not redirected. This is attempt ${redirectAttemptCount}.`):t.logToFile("Redirect initiated by Kustom, the user is about to be redirected to the confirmation page."),t.redirectAttemptCount+=1}})})}};t.init()});
     1jQuery(function(a){if("undefined"==typeof kco_params)return!1;var t={bodyEl:a("body"),checkoutFormSelector:a("form.checkout"),paymentMethodEl:a('input[name="payment_method"]'),paymentMethod:"",selectAnotherSelector:"#klarna-checkout-select-other",shippingUpdated:!1,validation:!1,preventPaymentMethodChange:!1,timeout:null,interval:null,klarnaUpdateNeeded:!1,shippingEmailExists:!1,suspended:!1,shippingAddressKnown:!1,lastOrderTotal:null,redirectAttemptCount:0,documentReady:function(){if(0<t.paymentMethodEl.length)t.paymentMethod=t.paymentMethodEl.filter(":checked").val();else{if(!(0<a("ul.wc_payment_methods").length))return;t.paymentMethod="kco"}if("kco"===t.paymentMethod){t.log(kco_params),"kco"===t.paymentMethod&&a("#ship-to-different-address-checkbox").prop("checked",!0),kco_params.pay_for_order||(t.moveExtraCheckoutFields(),t.updateShipping(!1));let o=!1;new MutationObserver(function(e){e.forEach(function(e){"attributes"===e.type&&"class"===e.attributeName&&(a("html").hasClass("klarna-checkout-fso-open")?o=!0:o&&(e=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout",(e=a(e)).length&&e.find(".woocommerce-error").length&&a("html, body").not(":animated").animate({scrollTop:e.offset().top-100},1e3),t.unblock(),o=!1))})}).observe(document.querySelector("html"),{attributes:!0,attributeFilter:["class"]})}},unblock:function(){t.kcoSuspend(),t.checkoutFormSelector.removeClass("processing"),a(".woocommerce-checkout-review-order-table").unblock(),a(t.checkoutFormSelector).unblock(),t.kcoResume()},kcoSuspend:function(o,e){e="yes"===kco_params.ksa_enabled&&!t.shippingAddressKnown&&!e;!window._klarnaCheckout||t.validation||t.suspended||e||(t.log("kcoSuspend",o),window._klarnaCheckout(function(e){t.suspended=!0,e.suspend({autoResume:{enabled:o}})}))},maybeSuspendOnTotalChange:function(e,o){var n,o=o&&o.fragments?o.fragments.kco_order_total:void 0;void 0!==o&&(n=t.lastOrderTotal,t.lastOrderTotal=o,null!==n)&&o!==n&&t.kcoSuspend(!0,!0)},kcoResume:function(){window._klarnaCheckout&&!t.validation&&t.suspended&&(t.suspended=!1,t.log("kcoResume"),window._klarnaCheckout(function(e){e.resume()}))},changeFromKco:function(e){e.preventDefault(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",dataType:"json",data:{kco:!1,nonce:kco_params.change_payment_method_nonce},url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})},maybeChangeToKco:function(){t.preventPaymentMethodChange||(t.log(a(this).val()),"kco"===a(this).val()&&(a(".woocommerce-info").remove(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",data:{kco:!0,nonce:kco_params.change_payment_method_nonce},dataType:"json",url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})))},moveExtraCheckoutFields:function(){a(".woocommerce-additional-fields").appendTo("#kco-extra-checkout-fields");var o=a('form[name="checkout"] input, form[name="checkout"] select, textarea'),n=!1;for(let e=0;e<o.length;e++){var i=o[e].name.replace("[]","\\[\\]");a("table.woocommerce-checkout-review-order-table").find(o[e]).length||-1===a.inArray(i,kco_params.standard_woo_checkout_fields)&&("wc_checkout_add_ons"===a("p#"+i+"_field").parent().attr("id")?n||(n=!0,a("div#wc_checkout_add_ons").appendTo("#kco-extra-checkout-fields")):(0<a("p#"+i+"_field").length?("shipping_email"===i&&(t.shippingEmailExists=!0),a("p#"+i+"_field")):a('input[name="'+i+'"]').closest("p")).appendTo("#kco-extra-checkout-fields"))}a(".woocommerce-account-fields").insertAfter(a("#createaccount").closest("p"))},maybeDisplayShippingPrice:function(){var e;a(".kco-shipping").length||"kco"===t.paymentMethod&&"yes"===kco_params.shipping_methods_in_iframe&&"no"===kco_params.is_confirmation_page&&(1<a('#shipping_method input[type="radio"]').length?a('#shipping_method input[type="radio"]:checked').each(function(){var e=a(this).attr("id"),e=a('label[for="'+e+'"]').text();a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")}):1===a('#shipping_method input[type="hidden"]').length?(e=a('#shipping_method input[name="shipping_method[0]"]').attr("id"),e=a('label[for="'+e+'"]').text(),a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")):a(".woocommerce-shipping-totals td").html(kco_params.no_shipping_message))},updateCart:function(){t.kcoSuspend(!0),a.ajax({type:"POST",url:kco_params.update_cart_url,data:{checkout:a("form.checkout").serialize(),nonce:kco_params.update_cart_nonce},dataType:"json",success:function(e){},error:function(e){},complete:function(e){a("body").trigger("update_checkout"),t.kcoResume()}})},getKlarnaOrder:function(){return console.log("getKustomOrder"),t.preventPaymentMethodChange=!0,a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.get_klarna_order_url,data:{nonce:kco_params.get_klarna_order_nonce},dataType:"json",success:function(e){t.setCustomerData(e.data),0<a("form.checkout #terms").length&&a("form.checkout #terms").prop("checked",!0),console.log("success")},error:function(e){console.log("error"),window.location.reload()},complete:function(e){}})},setCustomerData:function(e){t.log("setCustomerData",e),"object"==typeof e&&null!==e&&("billing_address"in e&&null!==e.billing_address&&(a("#billing_first_name").val("given_name"in e.billing_address?e.billing_address.given_name:""),a("#billing_last_name").val("family_name"in e.billing_address?e.billing_address.family_name:""),a("#billing_company").val("organization_name"in e.billing_address?e.billing_address.organization_name:""),a("#billing_address_1").val("street_address"in e.billing_address?e.billing_address.street_address:""),a("#billing_address_2").val("street_address2"in e.billing_address?e.billing_address.street_address2:""),a("#billing_city").val("city"in e.billing_address?e.billing_address.city:""),a("#billing_postcode").val("postal_code"in e.billing_address?e.billing_address.postal_code:""),a("#billing_phone").val("phone"in e.billing_address?e.billing_address.phone:""),a("#billing_email").val("email"in e.billing_address?e.billing_address.email:""),a("#billing_country").val("country"in e.billing_address?e.billing_address.country.toUpperCase():""),a("#billing_state").val("region"in e.billing_address?e.billing_address.region:""),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur")),"shipping_address"in e)&&null!==e.shipping_address&&(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#shipping_first_name").val("given_name"in e.shipping_address?e.shipping_address.given_name:""),a("#shipping_last_name").val("family_name"in e.shipping_address?e.shipping_address.family_name:""),a("#shipping_company").val("organization_name"in e.shipping_address?e.shipping_address.organization_name:""),a("#shipping_address_1").val("street_address"in e.shipping_address?e.shipping_address.street_address:""),a("#shipping_address_2").val("street_address2"in e.shipping_address?e.shipping_address.street_address2:""),a("#shipping_city").val("city"in e.shipping_address?e.shipping_address.city:""),a("#shipping_postcode").val("postal_code"in e.shipping_address?e.shipping_address.postal_code:""),a("#shipping_country").val("country"in e.shipping_address?e.shipping_address.country.toUpperCase():""),a("#shipping_state").val("region"in e.shipping_address?e.shipping_address.region:""),a("#shipping_phone").val("phone"in e.shipping_address?e.shipping_address.phone:""),!0===t.shippingEmailExists)&&a("#shipping_email")&&a("#shipping_email").val("email"in e.shipping_address?e.shipping_address.email:"")},checkUrl:function(e){window.location.hash&&-1<window.location.hash.indexOf("#klarna-success")&&(t.logToFile("klarna-success hashtag detected in URL."),e({should_proceed:!0}),clearInterval(t.interval),clearTimeout(t.timeout),t.unblock())},failOrder:function(e,o,n){n({should_proceed:!1,message:a(o).text().trim()}),t.validation=!1;n=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout";a("body").trigger("update_checkout"),a(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),a(n).prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+o+"</div>"),a(n).removeClass("processing").unblock(),a(n).find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),a(document.body).trigger("checkout_error",[o])},logToFile:function(e){a.ajax({url:kco_params.log_to_file_url,type:"POST",dataType:"json",data:{message:"object"==typeof e?JSON.stringify(e):e,nonce:kco_params.log_to_file_nonce}})},log:function(...e){kco_params.logging&&console.log(...e)},updateShipping:function(e){var o=JSON.stringify(e);a("#kco_shipping_data").val()!==o&&(a("#kco_shipping_data").val(o),a("body").trigger("kco_shipping_option_changed",[e]),a("body").trigger("update_checkout"))},convertCountry:function(o){return Object.keys(kco_params.countries).find(e=>kco_params.countries[e]===o)},placeKlarnaOrder:function(n){t.getKlarnaOrder().done(function(e){e.success?(a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.submit_order,data:a("form.checkout").serialize(),dataType:"json",success:function(o){try{if("success"!==o.result)throw"Result failed";t.logToFile('Successfully placed order. Sending "should_proceed: true" to Kustom'),n({should_proceed:!0})}catch(e){o.messages?(t.logToFile({type:"checkout_error",message:o.messages}),t.failOrder("submission",o.messages,n)):(t.logToFile({type:"checkout_error",message:"No message"}),t.failOrder("submission",'<div class="woocommerce-error">Checkout error</div>',n))}},error:function(e){var o=(e.responseText||"").trimStart().startsWith("<");t.logToFile({type:"ajax_error",status:e.status,response:o?"[HTML body stripped]":e.responseText||""}),t.failOrder("ajax-error",'<div class="woocommerce-error">Internal Server Error</div>',n)}})):t.failOrder("get_order",'<div class="woocommerce-error">Failed to get the order from Kustom</div>',n),t.validation=!1})},update_checkout:a.Callbacks("unique stopOnFalse"),init:function(){"yes"!==kco_params.is_order_received_page&&(a(document).ready(t.documentReady),t.bodyEl.on("update_checkout",function(){t.kcoSuspend(!0)}),t.bodyEl.on("updated_checkout",t.maybeSuspendOnTotalChange),t.bodyEl.on("updated_checkout",t.kcoResume),t.bodyEl.on("updated_checkout",t.maybeDisplayShippingPrice),t.bodyEl.on("change","input.qty",t.updateCart),t.bodyEl.on("change",'input[name="payment_method"]',t.maybeChangeToKco),t.bodyEl.on("click",t.selectAnotherSelector,t.changeFromKco),t.update_checkout.add(function(){return t.log("fire update_checkout"),a("form.checkout").trigger("update_checkout"),!1}),"function"==typeof window._klarnaCheckout)&&window._klarnaCheckout(function(e){e.on({shipping_address_change:function(e){t.log("shipping_address_change",e),t.shippingAddressKnown=!0;var o=t.convertCountry(e.country.toUpperCase());"billing_only"===kco_params.woocommerce_ship_to_destination?("given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"street_address"in e&&a("#billing_address_1").val(e.street_address),"street_address2"in e&&a("#billing_address_2").val(e.street_address2),"city"in e&&a("#billing_city").val(e.city),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"phone"in e&&a("#billing_phone").val(e.phone),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()):(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#ship-to-different-address-checkbox").trigger("change"),a("#ship-to-different-address-checkbox").trigger("blur"),"given_name"in e&&a("#shipping_first_name").val(e.given_name),"family_name"in e&&a("#shipping_last_name").val(e.family_name),"street_address"in e&&a("#shipping_address_1").val(e.street_address),"street_address2"in e&&a("#shipping_address_2").val(e.street_address2),"city"in e&&a("#shipping_city").val(e.city),"postal_code"in e&&a("#shipping_postcode").val(e.postal_code),"country"in e&&a("#shipping_country").val(o),"phone"in e&&a("#shipping_phone").val(e.phone),a("#shipping_country").trigger("change"),a("form.checkout").trigger("update_checkout"))},billing_address_change:function(e){t.log("billing_address_change",e);var o=t.convertCountry(e.country.toUpperCase());"given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"street_address"in e&&a("#billing_address_1").val(e.street_address),"street_address2"in e&&a("#billing_address_2").val(e.street_address2),"city"in e&&a("#billing_city").val(e.city),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"phone"in e&&a("#billing_phone").val(e.phone),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()},change:function(e){t.log("change",e),e.country&&e.postal_code&&(t.shippingAddressKnown=!0)},order_total_change:function(e){t.log("order_total_change",e)},shipping_option_change:function(e){t.log("shipping_option_change",e),t.log(e),t.updateShipping(e)},can_not_complete_order:function(e){t.log("can_not_complete_order",e)},validation_callback:function(e,o){t.validation=!0,t.logToFile("validation_callback from Kustom triggered"),kco_params.pay_for_order?o({should_proceed:!0}):t.placeKlarnaOrder(o)},customer:function(e){e="person"===e.type?"b2c":"b2b";a.ajax({url:kco_params.customer_type_changed_url,type:"POST",data:{nonce:kco_params.customer_type_changed_nonce,customer_type:e}})},checkbox_change:e=>{var{key:e,checked:o}=e;a.ajax({url:kco_params.checkbox_changed_url,type:"POST",data:{nonce:kco_params.checkbox_changed_nonce,key:e,checked:o},success:e=>{e.data.refresh_checkout&&(a(document.body).trigger("wc_fragment_refresh"),a(document.body).trigger("update_checkout"))}})},redirect_initiated:e=>{t.log("redirect_initiated",e),1<=t.redirectAttemptCount?t.logToFile(`Redirect was initiated by Kustom, but the user was not redirected. This is attempt ${redirectAttemptCount}.`):t.logToFile("Redirect initiated by Kustom, the user is about to be redirected to the confirmation page."),t.redirectAttemptCount+=1}})})}};t.init()});
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/build/checkout.asset.php

    r3641654 r3783345  
    1 <?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-registry', 'wc-settings', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-polyfill'), 'version' => 'b6572d146d9a5337699f');
     1<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-registry', 'wc-settings', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-polyfill'), 'version' => '421df203be0c2da7bc3e');
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/build/checkout.js

    r3641654 r3783345  
    1 (()=>{"use strict";const e=window.React,t=window.wp.htmlEntities,n=window.wp.element,c=window.wc.wcBlocksRegistry,o=window.wc.wcSettings,r=window.wp.data,a=()=>{const e=(0,r.select)("wc/store/payment");if(!e)return!1;const t=Object.keys(e.getAvailablePaymentMethods()||{});return 1===t.length&&"kco"===t[0]},i=()=>{var e;return"kco"===(null===(e=document.querySelector('input[name="radio-control-wc-payment-method-options"]:checked'))||void 0===e?void 0:e.value)},l=window.wc.blocksCheckout;var u=function(e,t,n,c){return new(n||(n=Promise))(function(o,r){function a(e){try{l(c.next(e))}catch(e){r(e)}}function i(e){try{l(c.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(a,i)}l((c=c.apply(e,t||[])).next())})};const s=(0,o.getSetting)("kco_data",{}),d=(0,t.decodeEntities)(s.title||"Kustom Checkout"),p=(0,t.decodeEntities)(s.description||""),k=(0,t.decodeEntities)(s.iconUrl||""),h=s.features||[],m=t=>{const{activePaymentMethod:c,billing:o,cartData:r}=t,{isActive:d,suspendKCO:k,resumeKCO:h}=((e,t)=>{const[c,o]=(0,n.useState)(i()||"kco"===t),[r,s]=(0,n.useState)(null),[d,p]=(0,n.useState)(null),{snippet:k,shippingInIframe:h,countryCodes:m}=e,f=(e=>["#shipping-fields","#billing-fields","#contact-fields",".wc-block-components-checkout-place-order-button",".wp-block-woocommerce-checkout-terms-block",e?"#shipping-option":"",a()?".wc-block-checkout__payment-method":""])(h),w=(0,n.useRef)(),b=(0,n.useRef)(null),g=(0,n.useRef)(null),y=(0,n.useRef)({billing:null,shipping:null}),C=(0,n.useRef)(null),_=(0,n.useRef)(""),v=(0,n.useCallback)(()=>{const e=k.match(/<script.*?>([\s\S]*?)<\/script>/),t=e?e[1]:"";return{htmlContentText:k.replace(/<script.*<\/script>/,""),scriptContentText:t}},[k]),E=(0,n.useCallback)((e=!0)=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(t){t.suspend({autoResume:e})})},[]),x=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.resume()})},[]),O=(0,n.useCallback)(e=>Object.keys(m).find(t=>m[t]===e.toUpperCase())||"",[m]),S=(0,n.useCallback)(e=>Object.assign(Object.assign({},e),{country:(null==e?void 0:e.country)?O(e.country):""}),[O]),R=(0,n.useCallback)(()=>u(void 0,void 0,void 0,function*(){const{billing:e,shipping:t}=y.current;y.current={billing:null,shipping:null};const n=t||e;if(!n)return;const c={action:"address_changed",billing:e||{},shipping:n},o=JSON.stringify(c);if(o!==_.current)return _.current=o,(0,l.extensionCartUpdate)({namespace:"kco-block",data:c}).then(()=>{}).catch(e=>{_.current=""}).finally(()=>{});x()}),[x]),T=(0,n.useCallback)((e,t)=>{E(),y.current[e]=S(t),C.current&&clearTimeout(C.current),C.current=setTimeout(()=>{C.current=null,R()},100)},[E,S,R]),j=(0,n.useCallback)(e=>T("shipping",e),[T]),K=(0,n.useCallback)(e=>T("billing",e),[T]),P=(0,n.useCallback)(e=>u(void 0,void 0,void 0,function*(){return E(),(0,l.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"shipping_option_changed"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{x()})}),[E,x]),A=(0,n.useCallback)(e=>u(void 0,void 0,void 0,function*(){return E(),(0,l.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"load"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{x()})}),[E,x]);(0,n.useEffect)(()=>{const{htmlContentText:e,scriptContentText:t}=v();s(e),p(t)},[k,v]);const M=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.on({load:A,shipping_address_change:j,billing_address_change:K,shipping_option_change:P,change:e=>{},user_interacted:e=>{},customer:e=>{},shipping_address_update_error:e=>{},order_total_change:e=>{},checkbox_change:e=>{},can_not_complete_order:e=>{},network_error:e=>{},load_confirmation:e=>{},redirect_initiated:e=>{}})})},[j,K,P,A]);return(0,n.useEffect)(()=>()=>{C.current&&(clearTimeout(C.current),C.current=null)},[]),(0,n.useEffect)(()=>(c&&r&&!w.current&&(f.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: none;")}),b.current=(e=>{const t=document.createElement("div");t.id="kco-wrapper",t.className="wc-block-checkout__klarna-checkout wc-block-components-klarna-checkout-block",t.innerHTML=e;const n=document.querySelector(".wc-block-checkout__payment-method");return n&&n.after(t),t})(r),g.current=document.createElement("script"),g.current.textContent=d,document.body.appendChild(g.current),w.current=c),M(),()=>{i()||(b.current&&b.current.remove(),f.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: block;")}),document.body.removeChild(g.current),b.current=null,g.current=null,w.current=c)}),[c,r,d,f,M]),{isActive:c,elementsToHide:f,suspendKCO:E,resumeKCO:x}})(s,c);return(0,n.useEffect)(()=>{d&&(k(),h())},[o.cartTotalItems,d,h,k]),""===p?null:e.createElement("div",{className:"wc-block-components-klarna-checkout"},e.createElement("p",null,p))},f={name:"kco",label:e.createElement(()=>e.createElement("div",{style:{display:"flex",gap:16,width:"100%",justifyContent:"space-between",paddingRight:16}},e.createElement("span",null,d),e.createElement("img",{src:k,alt:d})),null),content:e.createElement(m,null),edit:e.createElement(m,null),placeOrderButtonLabel:"Pay with Kustom Checkout",canMakePayment:()=>(!s.error&&s.snippet||console.error("Failed to initialize Kustom Checkout: "+s.error),!0),ariaLabel:d,supports:{features:h}};(0,c.registerPaymentMethod)(f)})();
     1(()=>{"use strict";const e=window.React,t=window.wp.htmlEntities,n=window.wp.element,c=window.wc.wcBlocksRegistry,r=window.wc.wcSettings,o=window.wp.data,l=()=>{const e=(0,o.select)("wc/store/payment");if(!e)return!1;const t=Object.keys(e.getAvailablePaymentMethods()||{});return 1===t.length&&"kco"===t[0]},u=()=>{var e;return"kco"===(null===(e=document.querySelector('input[name="radio-control-wc-payment-method-options"]:checked'))||void 0===e?void 0:e.value)},i=window.wc.blocksCheckout;var a=function(e,t,n,c){return new(n||(n=Promise))(function(r,o){function l(e){try{i(c.next(e))}catch(e){o(e)}}function u(e){try{i(c.throw(e))}catch(e){o(e)}}function i(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(l,u)}i((c=c.apply(e,t||[])).next())})};const s=(e,t,c)=>{const[r,o]=(0,n.useState)(u()||"kco"===t),[s,d]=(0,n.useState)(null),[p,k]=(0,n.useState)(null),{snippet:m,shippingInIframe:h,countryCodes:f}=e,b=(e=>["#shipping-fields","#billing-fields","#contact",".wc-block-components-checkout-place-order-button",".wp-block-woocommerce-checkout-terms-block",e?"#shipping-option":"",l()?".wc-block-checkout__payment-method":""])(h),w=(0,n.useRef)(),v=(0,n.useRef)(null),y=(0,n.useRef)(null),g=(0,n.useRef)({billing:null,shipping:null}),C=(0,n.useRef)(null),_=(0,n.useRef)(""),E=(0,n.useRef)(""),x=(0,n.useRef)(null),O=(0,n.useRef)(null),S=(0,n.useRef)(!1),R=(0,n.useRef)(null),T=(0,n.useCallback)(()=>{const e=m.match(/<script.*?>([\s\S]*?)<\/script>/),t=e?e[1]:"";return{htmlContentText:m.replace(/<script.*<\/script>/,""),scriptContentText:t}},[m]),A=(0,n.useCallback)((e=!0)=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(t){t.suspend({autoResume:e})})},[]),K=(0,n.useCallback)(()=>{S.current||"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.resume()})},[]),j=(0,n.useCallback)(e=>Object.keys(f).find(t=>f[t]===e.toUpperCase())||"",[f]),q=(0,n.useCallback)(e=>Object.assign(Object.assign({},e),{country:(null==e?void 0:e.country)?j(e.country):""}),[j]),U=(0,n.useCallback)(()=>a(void 0,void 0,void 0,function*(){const{billing:e,shipping:t}=g.current;g.current={billing:null,shipping:null};const n=t||e;if(!n)return;const c={action:"address_changed",billing:e||{},shipping:n},r=JSON.stringify(c);if(r!==_.current)return _.current=r,(0,i.extensionCartUpdate)({namespace:"kco-block",data:c}).then(()=>{}).catch(e=>{_.current=""}).finally(()=>{});K()}),[K]),M=(0,n.useCallback)(()=>{var e,t,n,c,r,o,l;const u=window,i=null===(t=null===(e=null==u?void 0:u.wc)||void 0===e?void 0:e.wcBlocksData)||void 0===t?void 0:t.CHECKOUT_STORE_KEY;return i&&null!==(l=null===(o=null===(r=null===(c=null===(n=null==u?void 0:u.wp)||void 0===n?void 0:n.data)||void 0===c?void 0:c.select(i))||void 0===r?void 0:r.getExtensionData)||void 0===o?void 0:o.call(r))&&void 0!==l?l:{}},[]),P=(0,n.useCallback)(()=>a(void 0,void 0,void 0,function*(){O.current=null;const e=M(),t=JSON.stringify(e);if(t!==E.current){E.current=t;try{yield(0,i.extensionCartUpdate)({namespace:"kco-block",data:{action:"extension_data_changed",extensions:e}})}catch(e){E.current="",x.current=null}}S.current&&!O.current&&(S.current=!1,K())}),[M,K]),N=(0,n.useCallback)((e,t)=>{A(),g.current[e]=q(t),C.current&&clearTimeout(C.current),C.current=setTimeout(()=>{C.current=null,U()},100)},[A,q,U]),L=(0,n.useCallback)(e=>N("shipping",e),[N]),B=(0,n.useCallback)(e=>N("billing",e),[N]),D=(0,n.useCallback)(e=>a(void 0,void 0,void 0,function*(){return A(),(0,i.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"shipping_option_changed"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{K()})}),[A,K]),H=(0,n.useCallback)(e=>a(void 0,void 0,void 0,function*(){return A(),(0,i.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"load"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{K()})}),[A,K]);(0,n.useEffect)(()=>{const{htmlContentText:e,scriptContentText:t}=T();d(e),k(t)},[m,T]);const I=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.on({load:H,shipping_address_change:L,billing_address_change:B,shipping_option_change:D,change:e=>{},user_interacted:e=>{},customer:e=>{},shipping_address_update_error:e=>{},order_total_change:e=>{},checkbox_change:e=>{},can_not_complete_order:e=>{},network_error:e=>{},load_confirmation:e=>{},redirect_initiated:e=>{}})})},[L,B,D,H]);return(0,n.useEffect)(()=>()=>{C.current&&(clearTimeout(C.current),C.current=null)},[]),(0,n.useEffect)(()=>{var e,t;const n=window;if(!r||"function"!=typeof(null===(t=null===(e=null==n?void 0:n.wp)||void 0===e?void 0:e.data)||void 0===t?void 0:t.subscribe))return;const c=e=>{const t=M();t!==x.current&&(x.current=t,JSON.stringify(t)!==E.current&&(e&&!S.current&&(S.current=!0,A()),O.current&&clearTimeout(O.current),O.current=setTimeout(P,500)))},o=n.wp.data.subscribe(()=>c(!0));return c(!1),()=>{O.current&&(clearTimeout(O.current),O.current=null),x.current=null,S.current=!1,o()}},[r,M,P,A]),(0,n.useEffect)(()=>(r&&s&&!w.current&&(b.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: none;")}),R.current=(()=>{const e=document.querySelector("#contact-fields");if(!e)return()=>{};const t=()=>{const t=(e=>{var t;const n=e.querySelector(".wc-block-components-checkout-step__content");return Array.from(null!==(t=null==n?void 0:n.children)&&void 0!==t?t:[]).some(e=>"contact"!==e.id&&null!==e.querySelector("input, select, textarea"))})(e)?"display: block;":"display: none;";e.getAttribute("style")!==t&&e.setAttribute("style",t)};t();const n=new MutationObserver(t);return n.observe(e,{childList:!0,subtree:!0}),()=>{n.disconnect(),e.setAttribute("style","display: block;")}})(),v.current=(e=>{const t=document.createElement("div");t.id="kco-wrapper",t.className="wc-block-checkout__klarna-checkout wc-block-components-klarna-checkout-block",t.innerHTML=e;const n=document.querySelector(".wc-block-checkout__payment-method");return n&&n.after(t),t})(s),y.current=document.createElement("script"),y.current.textContent=p,document.body.appendChild(y.current),w.current=r),I(),()=>{var e;u()||(v.current&&v.current.remove(),b.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: block;")}),null===(e=R.current)||void 0===e||e.call(R),R.current=null,document.body.removeChild(y.current),v.current=null,y.current=null,w.current=r)}),[r,s,p,b,I]),{isActive:r,elementsToHide:b,suspendKCO:A,resumeKCO:K}},d=(0,r.getSetting)("kco_data",{}),p=(0,t.decodeEntities)(d.title||"Kustom Checkout"),k=(0,t.decodeEntities)(d.description||""),m=(0,t.decodeEntities)(d.iconUrl||""),h=d.features||[],f=t=>{const{activePaymentMethod:c,billing:r,cartData:o}=t,{isActive:l,suspendKCO:u,resumeKCO:i}=s(d,c);return(0,n.useEffect)(()=>{l&&(u(),i())},[r.cartTotalItems,l,i,u]),""===k?null:e.createElement("div",{className:"wc-block-components-klarna-checkout"},e.createElement("p",null,k))},b={name:"kco",label:e.createElement(()=>e.createElement("div",{style:{display:"flex",gap:16,width:"100%",justifyContent:"space-between",paddingRight:16}},e.createElement("span",null,p),e.createElement("img",{src:m,alt:p})),null),content:e.createElement(f,null),edit:e.createElement(f,null),placeOrderButtonLabel:"Pay with Kustom Checkout",canMakePayment:()=>(!d.error&&d.snippet||console.error("Failed to initialize Kustom Checkout: "+d.error),!0),ariaLabel:p,supports:{features:h}};(0,c.registerPaymentMethod)(b)})();
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/src/BlockExtension.php

    r3767993 r3783345  
    127127                                kco_update_wc_shipping( $data );
    128128                                break;
     129                        case 'extension_data_changed':
     130                                $this->store_extension_data( $data );
     131                                break;
    129132                        case 'load':
    130133                                // No action needed here for now. We just want to trigger an update of the WooCommerce cart.
    … …  
    133136                                break;
    134137                }
     138        }
     139
     140        /**
     141         * Store the checkout block's extension data in the session.
     142         * Third party blocks keep it in the browser and expect it in the checkout POST, which we build
     143         * server side from the validation callback, so OrderValidation reads it back from here.
     144         *
     145         * @param array $data The data from the API.
     146         *
     147         * @return void
     148         */
     149        private function store_extension_data( $data ) {
     150                $extensions = $data['extensions'] ?? array();
     151
     152                if ( ! is_array( $extensions ) ) {
     153                        return;
     154                }
     155
     156                // An empty object means the shopper cleared everything, so drop what an earlier push stored.
     157                if ( empty( $extensions ) ) {
     158                        WC()->session->__unset( 'kco_wc_extension_data' );
     159                        return;
     160                }
     161
     162                WC()->session->set( 'kco_wc_extension_data', $extensions );
    135163        }
    136164
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/src/Checkout/hooks/useKcoIframe.tsx

    r3641654 r3783345  
    33        addIframe,
    44        getElementsToHide,
     5        hideContactStepWhenEmpty,
    56        hideElements,
    67        removeIframe,
    … …  
    2627 */
    2728const ADDRESS_UPDATE_DEBOUNCE_MS = 100;
     29
     30/**
     31 * How long to wait for the checkout data store to settle before sending extension data.
     32 * Typing in a third party field emits a store change per keystroke, and we only want one
     33 * cart update once the shopper stops.
     34 */
     35const EXTENSION_DATA_DEBOUNCE_MS = 500;
    2836
    2937/**
    … …  
    6674        // Signature of the last address update we sent, so an unchanged address is not sent twice.
    6775        const lastSentAddressRef = useRef<string>('');
     76        // Signature of the last extension data we sent, for the same reason. Starts unsent so the first
     77        // snapshot always goes out, even an empty one that clears what an earlier page stored.
     78        const lastSentExtensionDataRef = useRef<string>('');
     79        // The extension data object last seen in the store, and the push waiting to go out.
     80        const lastSeenExtensionDataRef = useRef<unknown>(null);
     81        const extensionUpdateTimerRef = useRef<ReturnType<
     82                typeof setTimeout
     83        > | null>(null);
     84        // Whether we suspended the iframe for an extension data push, so only we resume it.
     85        const extensionSuspendedRef = useRef<boolean>(false);
     86        // Stops watching the contact step for fields from other plugins.
     87        const stopContactStepRef = useRef<(() => void) | null>(null);
    6888
    6989        /**
    … …  
    103123         */
    104124        const resumeKCO = useCallback((): void => {
     125                // An extension data push is pending, sendExtensionData resumes once it is stored.
     126                if (extensionSuspendedRef.current) {
     127                        return;
     128                }
     129
    105130                // If the Kustom Checkout script hasn't loaded yet, do nothing.
    106131                if ('function' !== typeof window._klarnaCheckout) {
    … …  
    193218                return response;
    194219        }, [resumeKCO]);
     220
     221        /**
     222         * Read the extension data third party blocks keep in the checkout data store.
     223         *
     224         * @return {Record<string, unknown>} - The extension data, keyed by namespace.
     225         */
     226        const getExtensionData = useCallback((): Record<string, unknown> => {
     227                const globals = window as any;
     228                const checkoutStore = globals?.wc?.wcBlocksData?.CHECKOUT_STORE_KEY;
     229
     230                return checkoutStore
     231                        ? (globals?.wp?.data?.select(checkoutStore)?.getExtensionData?.() ??
     232                                        {})
     233                        : {};
     234        }, []);
     235
     236        /**
     237         * Send the checkout block's extension data to the WooCommerce session.
     238         * The Kustom order is submitted server side from the validation callback, which cannot read the
     239         * browser's checkout store, so the data has to be stored before the shopper pays.
     240         *
     241         * @return {Promise<void>}
     242         */
     243        const sendExtensionData = useCallback(async (): Promise<void> => {
     244                extensionUpdateTimerRef.current = null;
     245                const extensions = getExtensionData();
     246                const signature = JSON.stringify(extensions);
     247
     248                // Nothing changed since the last push, so skip the round trip.
     249                if (signature !== lastSentExtensionDataRef.current) {
     250                        lastSentExtensionDataRef.current = signature;
     251
     252                        try {
     253                                await extensionCartUpdate({
     254                                        namespace: 'kco-block',
     255                                        data: { action: 'extension_data_changed', extensions },
     256                                });
     257                        } catch (_error) {
     258                                // Send again on the next store change, since the session does not have this data.
     259                                lastSentExtensionDataRef.current = '';
     260                                lastSeenExtensionDataRef.current = null;
     261                        }
     262                }
     263
     264                // Let the shopper pay again, unless a newer change is already waiting to be sent.
     265                if (extensionSuspendedRef.current && !extensionUpdateTimerRef.current) {
     266                        extensionSuspendedRef.current = false;
     267                        resumeKCO();
     268                }
     269        }, [getExtensionData, resumeKCO]);
    195270
    196271        /**
    … …  
    388463
    389464        useEffect(() => {
     465                const globals = window as any;
     466
     467                if (!isActive || 'function' !== typeof globals?.wp?.data?.subscribe) {
     468                        return;
     469                }
     470
     471                /**
     472                 * Schedule a push when the extension data changed since it was last sent.
     473                 *
     474                 * @param {boolean} holdPayment - Whether to suspend the iframe until the push is stored.
     475                 * @return {void}
     476                 */
     477                const onStoreChange = (holdPayment: boolean): void => {
     478                        const extensions = getExtensionData();
     479
     480                        // The store returns the same object until something changes, so most calls stop here.
     481                        if (extensions === lastSeenExtensionDataRef.current) {
     482                                return;
     483                        }
     484                        lastSeenExtensionDataRef.current = extensions;
     485
     486                        if (
     487                                JSON.stringify(extensions) === lastSentExtensionDataRef.current
     488                        ) {
     489                                return;
     490                        }
     491
     492                        // The validation callback reads the session, so the shopper must not pay before this is stored.
     493                        if (holdPayment && !extensionSuspendedRef.current) {
     494                                extensionSuspendedRef.current = true;
     495                                suspendKCO();
     496                        }
     497
     498                        if (extensionUpdateTimerRef.current) {
     499                                clearTimeout(extensionUpdateTimerRef.current);
     500                        }
     501                        extensionUpdateTimerRef.current = setTimeout(
     502                                sendExtensionData,
     503                                EXTENSION_DATA_DEBOUNCE_MS
     504                        );
     505                };
     506
     507                // Third party fields write straight to the checkout data store, and there is no event to
     508                // listen for, so watch the store itself and push once the changes settle.
     509                const unsubscribe = globals.wp.data.subscribe(() =>
     510                        onStoreChange(true)
     511                );
     512
     513                // Send whatever was already filled in before the iframe was shown.
     514                onStoreChange(false);
     515
     516                return () => {
     517                        if (extensionUpdateTimerRef.current) {
     518                                clearTimeout(extensionUpdateTimerRef.current);
     519                                extensionUpdateTimerRef.current = null;
     520                        }
     521                        lastSeenExtensionDataRef.current = null;
     522                        extensionSuspendedRef.current = false;
     523                        unsubscribe();
     524                };
     525        }, [isActive, getExtensionData, sendExtensionData, suspendKCO]);
     526
     527        useEffect(() => {
    390528                // Only show the iframe if the Kustom Checkout is active, we have the content and it was not active before.
    391529                if (isActive && htmlContent && !prevIsActive.current) {
    392530                        hideElements(elementsToHide);
     531                        stopContactStepRef.current = hideContactStepWhenEmpty();
    393532                        // Add the iframe and script to the WooCommerce checkout page.
    394533                        kcoWrapperRef.current = addIframe(htmlContent);
    … …  
    409548
    410549                        showElements(elementsToHide);
     550                        stopContactStepRef.current?.();
     551                        stopContactStepRef.current = null;
    411552                        document.body.removeChild(scriptRef.current);
    412553                        kcoWrapperRef.current = null;
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/src/Checkout/lib.ts

    r3583083 r3783345  
    1414                '#shipping-fields', // Hide shipping fields since they are handled in the iframe.
    1515                '#billing-fields', // Hide billing fields since they are handled in the iframe.
    16                 '#contact-fields', // Hide contact fields since they are handled in the iframe.
     16                '#contact', // Hide the email field since it is handled in the iframe. The step itself is handled by hideContactStepWhenEmpty.
    1717                '.wc-block-components-checkout-place-order-button', // Hide the place order button since it is handled in the iframe.
    1818                '.wp-block-woocommerce-checkout-terms-block', // Hide the terms and conditions block since it is handled in the iframe.
    … …  
    5858                }
    5959        });
     60};
     61
     62/**
     63 * Test if the contact step holds fields from other plugins, such as the Smart Coupons gift form.
     64 * Checks for form controls rather than height, since nothing has a height while the step is hidden.
     65 *
     66 * @param {Element} step - The contact step element.
     67 * @return {boolean} - True if another block in the step has a form field, false otherwise.
     68 */
     69const contactStepHasOtherFields = (step: Element): boolean => {
     70        const content = step.querySelector(
     71                '.wc-block-components-checkout-step__content'
     72        );
     73
     74        return Array.from(content?.children ?? []).some(
     75                (child) =>
     76                        child.id !== 'contact' &&
     77                        child.querySelector('input, select, textarea') !== null
     78        );
     79};
     80
     81/**
     82 * Hide the contact step when the email field is all it holds, and show it again if another plugin's block mounts into it.
     83 * Other plugins can only place their blocks inside the step, so hiding it whole would hide their fields too.
     84 *
     85 * @return {() => void} - Stops watching the step and shows it again.
     86 */
     87export const hideContactStepWhenEmpty = (): (() => void) => {
     88        const step = document.querySelector('#contact-fields');
     89        if (!step) {
     90                return () => {};
     91        }
     92
     93        /**
     94         * Show or hide the step depending on what it currently holds.
     95         *
     96         * @return {void}
     97         */
     98        const sync = (): void => {
     99                const style = contactStepHasOtherFields(step)
     100                        ? 'display: block;'
     101                        : 'display: none;';
     102                if (step.getAttribute('style') !== style) {
     103                        step.setAttribute('style', style);
     104                }
     105        };
     106
     107        sync();
     108        const observer = new MutationObserver(sync);
     109        observer.observe(step, { childList: true, subtree: true });
     110
     111        return () => {
     112                observer.disconnect();
     113                step.setAttribute('style', 'display: block;');
     114        };
    60115};
    61116
  • klarna-checkout-for-woocommerce/tags/2.24.1/blocks/src/OrderValidation.php

    r3767993 r3783345  
    249249                        throw new Exception( 'Order is already paid.', 400 );
    250250                }
     251        }
     252
     253        /**
     254         * Get the extension data the checkout block script stashed in the session.
     255         *
     256         * @param string $wc_cart_token The cart token from the Kustom order merchant data.
     257         *
     258         * @return array
     259         */
     260        private static function get_stashed_extension_data( $wc_cart_token ) {
     261                try {
     262                        $session = ExpressSession::open( $wc_cart_token );
     263                } catch ( Exception $e ) {
     264                        return array();
     265                }
     266
     267                $extensions = $session->get( 'kco_wc_extension_data', array() );
     268
     269                return is_array( $extensions ) ? $extensions : array();
    251270        }
    252271
    … …  
    326345                );
    327346
     347                // Pass on the extension data the checkout block collected in the browser. Not for express
     348                // orders, which never pass through the checkout page, so that data is not theirs.
     349                $extensions = $express_context ? array() : self::get_stashed_extension_data( $wc_cart_token );
     350                if ( ! empty( $extensions ) ) {
     351                        $body['extensions'] = $extensions;
     352                }
     353
    328354                // The order key is required by the Store API to pay for an existing order, and omitted for the create flow.
    329355                if ( $order ) {
  • klarna-checkout-for-woocommerce/tags/2.24.1/classes/class-kco-checkout.php

    r3743403 r3783345  
    2222                add_filter( 'woocommerce_checkout_fields', array( $this, 'add_shipping_data_input' ) );
    2323                add_action( 'woocommerce_before_calculate_totals', array( $this, 'update_shipping_method' ), 9999 );
     24                add_filter( 'advanced_woo_discount_rules_exclude_hooks_from_removing', array( $this, 'keep_update_shipping_method_hook' ) );
    2425                add_action( 'woocommerce_after_calculate_totals', array( $this, 'update_klarna_order' ), 99999 );
     26                add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'add_order_total_fragment' ) );
    2527
    2628                // Handle potential shipping selection errors.
    … …  
    9799
    98100        /**
     101         * Keep the shipping method update when Woo Discount Rules suppresses third party discount plugins.
     102         *
     103         * That setting removes all other callbacks from woocommerce_before_calculate_totals, so the shipping option selected
     104         * in Kustom never reached WooCommerce and Kustom Shipping Assistant was replaced by another shipping method.
     105         *
     106         * @param array $allowed_hooks Callbacks to keep as 'Class|method', keyed by hook name.
     107         *
     108         * @return array
     109         */
     110        public function keep_update_shipping_method_hook( $allowed_hooks ) {
     111                $allowed_hooks['woocommerce_before_calculate_totals']   = (array) ( $allowed_hooks['woocommerce_before_calculate_totals'] ?? array() );
     112                $allowed_hooks['woocommerce_before_calculate_totals'][] = get_class( $this ) . '|update_shipping_method';
     113
     114                return $allowed_hooks;
     115        }
     116
     117        /**
    99118         * Update the Kustom order after calculations from WooCommerce has run.
    100119         *
    … …  
    135154                        }
    136155                }
     156        }
     157
     158        /**
     159         * Add the cart total to the checkout fragments.
     160         *
     161         * @param array $fragments The checkout fragments.
     162         *
     163         * @return array
     164         */
     165        public function add_order_total_fragment( $fragments ) {
     166                if ( 'kco' !== WC()->session->get( 'chosen_payment_method' ) ) {
     167                        return $fragments;
     168                }
     169
     170                $fragments['kco_order_total'] = (string) WC()->cart->get_total( 'edit' );
     171
     172                return $fragments;
    137173        }
    138174
  • klarna-checkout-for-woocommerce/tags/2.24.1/classes/class-kco-gateway.php

    r3767993 r3783345  
    77
    88use Krokedil\KustomCheckout\CheckoutFlow\CheckoutFlow;
     9use Krokedil\KustomCheckout\ShippingAssistant\Settings as ShippingAssistantSettings;
    910use Krokedil\KustomCheckout\Utility\BlocksUtility;
    1011use Krokedil\KustomCheckout\Utility\SettingsUtility;
    … …  
    449450                                'is_order_received_page'          => is_order_received_page() ? 'yes' : 'no',
    450451                                'shipping_methods_in_iframe'      => $this->shipping_methods_in_iframe,
     452                                'ksa_enabled'                     => ShippingAssistantSettings::is_enabled() ? 'yes' : 'no',
    451453                                'required_fields_text'            => __( 'Please fill in all required checkout fields.', 'klarna-checkout-for-woocommerce' ),
    452454                                'email_exists'                    => $email_exists,
  • klarna-checkout-for-woocommerce/tags/2.24.1/classes/requests/checkout/post/class-kco-request-update.php

    r3743403 r3783345  
    9191
    9292                if ( kco_wc_prefill_allowed() ) {
    93                         $request_body['billing_address'] = array(
    94                                 'email'             => WC()->checkout()->get_value( 'billing_email' ),
    95                                 'postal_code'       => WC()->checkout()->get_value( 'billing_postcode' ),
    96                                 'country'           => WC()->checkout()->get_value( 'billing_country' ),
    97                                 'phone'             => WC()->checkout()->get_value( 'billing_phone' ),
    98                                 'given_name'        => WC()->checkout()->get_value( 'billing_first_name' ),
    99                                 'family_name'       => WC()->checkout()->get_value( 'billing_last_name' ),
    100                                 'organization_name' => WC()->checkout()->get_value( 'billing_company' ),
    101                                 'street_address'    => WC()->checkout()->get_value( 'billing_address_1' ),
    102                                 'street_address2'   => WC()->checkout()->get_value( 'billing_address_2' ),
    103                                 'city'              => WC()->checkout()->get_value( 'billing_city' ),
    104                                 'region'            => WC()->checkout()->get_value( 'billing_state' ),
    105                         );
     93                        // Built the same way as when the order is created: only fields that have a value are sent, since Kustom keeps whatever it already stored for the fields we omit.
     94                        $billing_address = KCO_Request_Create::get_billing_address_from_customer();
    10695
    107                         $request_body['shipping_address'] = array(
    108                                 'postal_code'       => WC()->checkout()->get_value( 'shipping_postcode' ),
    109                                 'country'           => WC()->checkout()->get_value( 'shipping_country' ),
    110                                 'given_name'        => WC()->checkout()->get_value( 'shipping_first_name' ),
    111                                 'family_name'       => WC()->checkout()->get_value( 'shipping_last_name' ),
    112                                 'organization_name' => WC()->checkout()->get_value( 'shipping_company' ),
    113                                 'street_address'    => WC()->checkout()->get_value( 'shipping_address_1' ),
    114                                 'street_address2'   => WC()->checkout()->get_value( 'shipping_address_2' ),
    115                                 'city'              => WC()->checkout()->get_value( 'shipping_city' ),
    116                                 'region'            => WC()->checkout()->get_value( 'shipping_state' ),
    117                         );
     96                        if ( ! empty( $billing_address ) ) {
     97                                $request_body['billing_address'] = $billing_address;
     98                        }
    11899
    119                         $request_body['shipping_address'] = wp_parse_args( $request_body['billing_address'], $request_body['shipping_address'] ?? array() );
     100                        if ( 'yes' === ( $this->settings['allow_separate_shipping'] ?? 'no' ) ) {
     101                                $shipping_address = KCO_Request_Create::get_shipping_address_from_customer();
     102
     103                                if ( ! empty( $shipping_address ) ) {
     104                                        $request_body['shipping_address'] = $shipping_address;
     105                                }
     106                        } elseif ( ! empty( $billing_address ) ) {
     107                                $request_body['shipping_address'] = $billing_address;
     108                        }
    120109                }
    121110
  • klarna-checkout-for-woocommerce/tags/2.24.1/composer-dependencies.json

    r3743403 r3783345  
    22    "require": {
    33        "php": ">=7.4",
    4         "krokedil/wp-api": "^1.2.0",
     4        "krokedil/wp-api": "1.2.0",
    55        "krokedil/woocommerce": "^1.0",
    66        "krokedil/shipping": "2.4.0",
    77        "krokedil/support": "1.0.4",
    8         "krokedil/settings-page": "^1.1.0"
     8        "krokedil/settings-page": "1.3.8"
    99    },
    1010    "config": {
  • klarna-checkout-for-woocommerce/tags/2.24.1/composer-dependencies.lock

    r3743403 r3783345  
    55        "This file is @generated automatically"
    66    ],
    7     "content-hash": "e54adb7c33248f480bac51b2f22597b1",
     7    "content-hash": "b8aee8296192d0086586b33de8b773f8",
    88    "packages": [
    99        {
    1010            "name": "krokedil/settings-page",
    11             "version": "1.3.6",
     11            "version": "1.3.8",
    1212            "source": {
    1313                "type": "git",
    1414                "url": "https://github.com/krokedil/settings-page.git",
    15                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f"
    16             },
    17             "dist": {
    18                 "type": "zip",
    19                 "url": "https://api.github.com/repos/krokedil/settings-page/zipball/9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
    20                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
     15                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63"
     16            },
     17            "dist": {
     18                "type": "zip",
     19                "url": "https://api.github.com/repos/krokedil/settings-page/zipball/8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
     20                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
    2121                "shasum": ""
    2222            },
    … …  
    6262                    "./vendor/bin/phpstan analyse --memory-limit=2G"
    6363                ],
     64                "phpstan:baseline": [
     65                    "./vendor/bin/phpstan analyse --memory-limit=2G --generate-baseline"
     66                ],
    6467                "lint": [
    6568                    "vendor/bin/phpcs . --standard=phpcs.xml --extensions=php -q -s"
    … …  
    8689            "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    8790            "support": {
    88                 "source": "https://github.com/krokedil/settings-page/tree/1.3.6",
     91                "source": "https://github.com/krokedil/settings-page/tree/1.3.8",
    8992                "issues": "https://github.com/krokedil/settings-page/issues"
    9093            },
    91             "time": "2026-08-14T11:07:15+00:00"
     94            "time": "2026-10-29T09:53:20+00:00"
    9295        },
    9396        {
  • klarna-checkout-for-woocommerce/tags/2.24.1/composer.lock

    r3767993 r3783345  
    73427342        "php": "8.0"
    73437343    },
    7344     "plugin-api-version": "2.6.0"
     7344    "plugin-api-version": "2.9.0"
    73457345}
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/autoload.php

    r3743403 r3783345  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1::getLoader();
     22return ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8::getLoader();
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/composer/autoload_real.php

    r3743403 r3783345  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1
     5class ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8
    66{
    77    private static $loader;
    … …  
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInite54adb7c33248f480bac51b2f22597b1::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInitb8aee8296192d0086586b33de8b773f8::getInitializer($loader));
    3333
    3434        $loader->register(true);
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/composer/autoload_static.php

    r3743403 r3783345  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInite54adb7c33248f480bac51b2f22597b1
     7class ComposerStaticInitb8aee8296192d0086586b33de8b773f8
    88{
    99    public static $prefixLengthsPsr4 = array (
    … …  
    133133    {
    134134        return \Closure::bind(function () use ($loader) {
    135             $loader->prefixLengthsPsr4 = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$prefixLengthsPsr4;
    136             $loader->prefixDirsPsr4 = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$prefixDirsPsr4;
    137             $loader->classMap = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$classMap;
     135            $loader->prefixLengthsPsr4 = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$prefixLengthsPsr4;
     136            $loader->prefixDirsPsr4 = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$prefixDirsPsr4;
     137            $loader->classMap = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$classMap;
    138138
    139139        }, null, ClassLoader::class);
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/composer/installed.json

    r3743403 r3783345  
    33        {
    44            "name": "krokedil\/settings-page",
    5             "version": "1.3.6",
    6             "version_normalized": "1.3.6.0",
     5            "version": "1.3.8",
     6            "version_normalized": "1.3.8.0",
    77            "source": {
    88                "type": "git",
    99                "url": "https:\/\/github.com\/krokedil\/settings-page.git",
    10                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f"
    11             },
    12             "dist": {
    13                 "type": "zip",
    14                 "url": "https:\/\/api.github.com\/repos\/krokedil\/settings-page\/zipball\/9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
    15                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
     10                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63"
     11            },
     12            "dist": {
     13                "type": "zip",
     14                "url": "https:\/\/api.github.com\/repos\/krokedil\/settings-page\/zipball\/8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
     15                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
    1616                "shasum": ""
    1717            },
    … …  
    2525                "wpackagist-theme\/storefront": "4.6.2"
    2626            },
    27             "time": "2026-08-14T11:07:15+00:00",
     27            "time": "2026-10-29T09:53:20+00:00",
    2828            "type": "library",
    2929            "extra": {
    … …  
    5959                    ".\/vendor\/bin\/phpstan analyse --memory-limit=2G"
    6060                ],
     61                "phpstan:baseline": [
     62                    ".\/vendor\/bin\/phpstan analyse --memory-limit=2G --generate-baseline"
     63                ],
    6164                "lint": [
    6265                    "vendor\/bin\/phpcs . --standard=phpcs.xml --extensions=php -q -s"
    … …  
    8386            "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    8487            "support": {
    85                 "source": "https:\/\/github.com\/krokedil\/settings-page\/tree\/1.3.6",
     88                "source": "https:\/\/github.com\/krokedil\/settings-page\/tree\/1.3.8",
    8689                "issues": "https:\/\/github.com\/krokedil\/settings-page\/issues"
    8790            },
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/composer/installed.php

    r3767993 r3783345  
    33namespace KrokedilKlarnaCheckoutDeps;
    44
    5 return array('root' => array('name' => '__root__', 'pretty_version' => '2.24.0', 'version' => '2.24.0.0', 'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '2.24.0', 'version' => '2.24.0.0', 'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.6', 'version' => '1.3.6.0', 'reference' => '9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/shipping' => array('pretty_version' => '2.4.0', 'version' => '2.4.0.0', 'reference' => '12c7e30742725174ae8cdb2839b873aa40a29817', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/shipping', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.4', 'version' => '1.0.4.0', 'reference' => '96da75792434a2553c6af9e891e646705fd33e7c', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/woocommerce' => array('pretty_version' => '1.9.2', 'version' => '1.9.2.0', 'reference' => '6c38cf569df5eeb3598f206d449eca86ae9ac402', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/woocommerce', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/wp-api' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '3473dd2fb6b31ed5060ecd69877c98b5287ebe48', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/wp-api', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '707984727bd5b2b670e59559d3ed2500240cf875', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(0 => '2.0.x-dev'), 'dev_requirement' => \false)));
     5return array('root' => array('name' => '__root__', 'pretty_version' => '2.24.1', 'version' => '2.24.1.0', 'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '2.24.1', 'version' => '2.24.1.0', 'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.8', 'version' => '1.3.8.0', 'reference' => '8ba11d2e62dfc0b63d75ec295374ea183fcdac63', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/shipping' => array('pretty_version' => '2.4.0', 'version' => '2.4.0.0', 'reference' => '12c7e30742725174ae8cdb2839b873aa40a29817', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/shipping', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.4', 'version' => '1.0.4.0', 'reference' => '96da75792434a2553c6af9e891e646705fd33e7c', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/woocommerce' => array('pretty_version' => '1.9.2', 'version' => '1.9.2.0', 'reference' => '6c38cf569df5eeb3598f206d449eca86ae9ac402', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/woocommerce', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/wp-api' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '3473dd2fb6b31ed5060ecd69877c98b5287ebe48', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/wp-api', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '707984727bd5b2b670e59559d3ed2500240cf875', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(0 => '2.0.x-dev'), 'dev_requirement' => \false)));
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/krokedil/settings-page/assets/js/support.js

    r3454335 r3783345  
    66      params: {
    77        beaconId: "",
    8         systemReport: {},
    98      },
    109      init: function () {
    … …  
    3938        }
    4039
    41         if (!this.params.systemReport) {
     40
     41        const systemReport = this.generateReport();
     42        if (!systemReport) {
    4243          return;
    4344        }
    4445
    45         const systemReportFile = this.objToFile(
    46           this.params.systemReport,
    47           "system-report.json"
    48         );
     46        const systemReportFile = new File([systemReport], "system-report.txt", {
     47          type: "text/plain",
     48          lastModified: Date.now(),
     49        });
    4950
    5051        window.Beacon("prefill", {
    … …  
    6970      },
    7071
    71       objToFile: function (obj, fileName) {
    72         const stringVal = JSON.stringify(obj);
     72      // Port of WooCommerce's generateReport (assets/js/admin/system-status.js), run on the hidden status report.
     73      generateReport: function () {
     74        let report = "";
    7375
    74         return new File([stringVal], fileName, {
    75           type: "application/json",
    76           lastModified: Date.now(),
     76        $("#krokedil-status-report .wc_status_table thead, #krokedil-status-report .wc_status_table tbody").each(function () {
     77          if ($(this).is("thead")) {
     78            const label = $(this).find("th:eq(0)").data("exportLabel") || $(this).text();
     79            report = report + "\n### " + label.trim() + " ###\n\n";
     80            return;
     81          }
     82
     83          $("tr", $(this)).each(function () {
     84            const label = $(this).find("td:eq(0)").data("exportLabel") || $(this).find("td:eq(0)").text();
     85            const the_name = label.trim().replace(/(<([^>]+)>)/gi, ""); // Remove HTML.
     86
     87            const $value_html = $(this).find("td:eq(2)").clone();
     88            $value_html.find(".private").remove();
     89            $value_html.find(".dashicons-yes").replaceWith("&#10004;");
     90            $value_html.find(".dashicons-no-alt, .dashicons-warning").replaceWith("&#10060;");
     91
     92            let the_value = $value_html.text().trim();
     93            const value_array = the_value.split(", ");
     94
     95            // Put each item of a comma separated list (e.g. plugins) on its own line.
     96            if (value_array.length > 1) {
     97              the_value = value_array.join("\n") + "\n";
     98            }
     99
     100            if (the_name || the_value) {
     101              report = report + the_name + ": " + the_value + "\n";
     102            } else {
     103              report = report + "\n";
     104            }
     105          });
    77106        });
     107
     108        return report;
    78109      },
    79110
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/krokedil/settings-page/changelog.md

    r3696507 r3783345  
    99
    1010------------------
     11## [1.3.8] - 2026-10-29
     12### Changed
     13
     14* The support ticket now attaches the WooCommerce system status report as text (`system-report.txt`), the same report as WooCommerce's "Get system report" button, including sections added by other plugins. It replaces the JSON export from the `/wc/v3/system_status` REST endpoint.
     15
     16## [1.3.7] - 2026-09-28
     17### Fixed
     18
     19* Fixed an "Undefined array key" PHP warning that could occur with certain settings configurations.
     20
    1121## [1.3.6] - 2026-08-14
    1222### Fixed
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/krokedil/settings-page/composer.json

    r3696507 r3783345  
    22    "name": "krokedil\/settings-page",
    33    "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    4     "version": "1.3.6",
     4    "version": "1.3.8",
    55    "type": "library",
    66    "require-dev": {
    … …  
    6363        "makepot": "wp --allow-root i18n make-pot .\/src .\/languages\/krokedil-settings.pot --domain=krokedil-settings",
    6464        "phpstan": ".\/vendor\/bin\/phpstan analyse --memory-limit=2G",
     65        "phpstan:baseline": ".\/vendor\/bin\/phpstan analyse --memory-limit=2G --generate-baseline",
    6566        "lint": "vendor\/bin\/phpcs . --standard=phpcs.xml --extensions=php -q -s",
    6667        "lint:fix": "vendor\/bin\/phpcbf . --standard=phpcs.xml --extensions=php -q -s",
    6768        "lint:changes": "git diff --name-only HEAD~1 | grep '\\.php$' | xargs vendor\/bin\/phpcs --standard=phpcs.xml --extensions=php -q -s",
    6869        "lint:fix:changes": "git diff --name-only HEAD~1 | grep '\\.php$' | xargs vendor\/bin\/phpcbf --standard=phpcs.xml --extensions=php -q -s"
     70    },
     71    "scripts-descriptions": {
     72        "phpstan": "Run PHPStan static analysis at the level set in phpstan.neon. Findings that predate the analysis are suppressed by phpstan-baseline.neon, so a failure means new code introduced it.",
     73        "phpstan:baseline": "Regenerate phpstan-baseline.neon from the current findings. Only run this when intentionally accepting new suppressions, otherwise fix the reported errors instead."
    6974    }
    7075}
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/krokedil/settings-page/src/Addons.php

    r3696507 r3783345  
    119119        add_thickbox();
    120120        // Required for the plugin installer to work.
    121         $addons = $this->addons['items'];
    122         $content = $this->addons['content'];
     121        $addons = $this->addons['items'] ?? array();
     122        $content = $this->addons['content'] ?? array();
    123123        ?>
    124124                <div class="krokedil_addons">
    125                 <div class="krokedil_addons__info">
    126                                 <?php
    127         foreach ($content as $item) {
    128             ?>
     125                        <?php
     126        if (!empty($content)) {
     127            ?>
     128                        <div class="krokedil_addons__info">
     129                                <?php
     130            foreach ($content as $item) {
     131                ?>
    129132                                        <?php
    130             echo wp_kses_post(self::print_content($item));
    131             ?>
    132                                 <?php
    133         }
    134         ?>
    135                         </div>
     133                echo wp_kses_post(self::print_content($item));
     134                ?>
     135                                <?php
     136            }
     137            ?>
     138                        </div>
     139                        <?php
     140        }
     141        ?>
    136142
    137143                        <?php
    138144        // translators: %s is the plugin name.
    139145        ?>
     146                        <?php
     147        if (!empty($addons)) {
     148            ?>
    140149                        <div class='krokedil_addons__cards'>
    141150                                <?php
    142         foreach ($addons as $addon) {
    143             ?>
     151            foreach ($addons as $addon) {
     152                ?>
    144153                                        <?php
    145             $this->print_addon_card($addon);
    146             ?>
    147                                 <?php
    148         }
    149         ?>
    150                         </div>
     154                $this->print_addon_card($addon);
     155                ?>
     156                                <?php
     157            }
     158            ?>
     159                        </div>
     160                        <?php
     161        }
     162        ?>
    151163                </div>
    152164                <?php
  • klarna-checkout-for-woocommerce/tags/2.24.1/dependencies/krokedil/settings-page/src/Support.php

    r3696507 r3783345  
    6161        // Load CSS.
    6262        wp_enqueue_style('krokedil-support-page');
    63         // If the WC Version is 9.0 or above, get the container for the RestAPiUtil, else us the WC()->api class property.
    64         // The deprecation notice says 9.1.0, but the WC()->api property is not set in 9.0.0.
    65         // @see https://github.com/woocommerce/woocommerce/blob/5690850e47284b3a9afd4e61dec01121159ca9e8/plugins/woocommerce/src/Internal/Utilities/LegacyRestApiStub.php#L183-L187.
    66         $legacy_wc = \version_compare(WC_VERSION, '9.0', '<=');
    67         $system_report = '';
    68         if ($legacy_wc) {
    69             $system_report = WC()->api->get_endpoint_data('/wc/v3/system_status');
    70         } elseif (\class_exists(\Automattic\WooCommerce\Utilities\RestApiUtil::class)) {
    71             $system_report = wc_get_container()->get(\Automattic\WooCommerce\Utilities\RestApiUtil::class)->get_endpoint_data('/wc/v3/system_status');
    72         }
    7363        $beacon_id = '9c22f83e-3611-42aa-a148-1ca06de53566';
    7464        // Localize the support scrip.
    75         wp_localize_script('krokedil-support-page', 'krokedil_support_params', array('systemReport' => $system_report, 'beaconId' => $beacon_id));
     65        wp_localize_script('krokedil-support-page', 'krokedil_support_params', array('beaconId' => $beacon_id));
    7666        // Load JS. Only add the inline script if there is one, since wp_add_inline_script does not accept empty data.
    7767        $beacon_script = self::hs_beacon_script($this->support['use_helpscout'] ?? 'yes');
    … …  
    113103            ?></button>
    114104                                        <?php
     105            // Hidden WooCommerce status report, turned into the text report by support.js and attached to the Beacon.
     106            ?>
     107                                        <div id="krokedil-status-report" hidden>
     108                                                <?php
     109            if (\class_exists(\WC_Admin_Status::class)) {
     110                \WC_Admin_Status::status_report();
     111            }
     112            ?>
     113                                        </div>
     114                                        <?php
    115115        }
    116116        ?>
  • klarna-checkout-for-woocommerce/tags/2.24.1/includes/kco-functions.php

    r3767993 r3783345  
    609609        WC()->session->__unset( 'kco_wc_prefill_consent' );
    610610        WC()->session->__unset( 'kco_wc_order_id' );
     611        WC()->session->__unset( 'kco_wc_extension_data' );
    611612}
    612613
  • klarna-checkout-for-woocommerce/tags/2.24.1/klarna-checkout-for-woocommerce.php

    r3767993 r3783345  
    66 * Author: Kustom
    77 * Author URI: https://klarna.com/
    8  * Version: 2.24.0
     8 * Version: 2.24.1
    99 * Text Domain: klarna-checkout-for-woocommerce
    1010 * Domain Path: /languages
    … …  
    4545 * Required minimums and constants
    4646 */
    47 define( 'KCO_WC_VERSION', '2.24.0' );
     47define( 'KCO_WC_VERSION', '2.24.1' );
    4848define( 'KCO_WC_MIN_PHP_VER', '5.6.0' );
    4949define( 'KCO_WC_MIN_WC_VER', '3.9.0' );
  • klarna-checkout-for-woocommerce/tags/2.24.1/languages/klarna-checkout-for-woocommerce.pot

    r3767993 r3783345  
    99"Language-Team: Krokedil <info@krokedil.se>\n"
    1010"Last-Translator: Krokedil <info@krokedil.se>\n"
    11 "POT-Creation-Date: 2026-10-27 08:07+0000\n"
     11"POT-Creation-Date: 2026-11-04 07:59+0000\n"
    1212"Report-Msgid-Bugs-To: http://krokedil.se\n"
    1313"X-Poedit-Basepath: ..\n"
    … …  
    3535
    3636#. translators: Kustom order ID.
    37 #: ../classes/class-kco-api-callbacks.php:143, ../includes/kco-functions.php:696
     37#: ../classes/class-kco-api-callbacks.php:143, ../includes/kco-functions.php:697
    3838msgid "Kustom order is under review, order ID: %s."
    3939msgstr ""
    … …  
    4343msgstr ""
    4444
    45 #: ../classes/class-kco-api-callbacks.php:129, ../includes/kco-functions.php:681
     45#: ../classes/class-kco-api-callbacks.php:129, ../includes/kco-functions.php:682
    4646msgid "Payment via Kustom Checkout, order ID: %s"
    4747msgstr ""
    4848
    49 #: ../classes/class-kco-checkout.php:224
     49#: ../classes/class-kco-checkout.php:260
    5050msgid "The shipping methods have been changed during the checkout process. Please verify your selected shipping method and try again."
    5151msgstr ""
    … …  
    448448msgstr ""
    449449
    450 #: ../classes/class-kco-gateway.php:48, ../classes/class-kco-gateway.php:823, ../classes/class-kco-gateway.php:825, ../classes/class-kco-gateway.php:827, ../classes/class-kco-gateway.php:829, ../includes/admin/views/status-report.php:17
     450#: ../classes/class-kco-gateway.php:49, ../classes/class-kco-gateway.php:825, ../classes/class-kco-gateway.php:827, ../classes/class-kco-gateway.php:829, ../classes/class-kco-gateway.php:831, ../includes/admin/views/status-report.php:17
    451451msgid "Kustom Checkout"
    452452msgstr ""
    453453
    454 #: ../classes/class-kco-gateway.php:49
     454#: ../classes/class-kco-gateway.php:50
    455455msgid "The current Kustom Checkout replaces standard WooCommerce checkout page."
    456456msgstr ""
    457457
    458 #: ../classes/class-kco-gateway.php:142
     458#: ../classes/class-kco-gateway.php:143
    459459msgid "The Kustom order id could not be retrieved from the session. Please try again."
    460460msgstr ""
    461461
    462 #: ../classes/class-kco-gateway.php:149
     462#: ../classes/class-kco-gateway.php:150
    463463msgid "The Kustom order could not be retrieved from the session. Please try again."
    464464msgstr ""
    465465
    466466#. translators: %s is the field name.
    467 #: ../classes/class-kco-gateway.php:210
     467#: ../classes/class-kco-gateway.php:211
    468468msgid "Billing %s does not match Kustom order."
    469469msgstr ""
    470470
    471471#. translators: %s is the field name.
    472 #: ../classes/class-kco-gateway.php:222
     472#: ../classes/class-kco-gateway.php:223
    473473msgid "Shipping %s does not match Kustom order."
    474474msgstr ""
    475475
    476 #: ../classes/class-kco-gateway.php:322
     476#: ../classes/class-kco-gateway.php:323
    477477msgid "Could not load the enhanced settings page. Showing the standard settings instead."
    478478msgstr ""
    479479
    480 #: ../classes/class-kco-gateway.php:451
     480#: ../classes/class-kco-gateway.php:453
    481481msgid "Please fill in all required checkout fields."
    482482msgstr ""
    483483
    484 #: ../classes/class-kco-gateway.php:454
     484#: ../classes/class-kco-gateway.php:456
    485485msgid "Please try again, something went wrong with processing your order."
    486486msgstr ""
    487487
    488 #: ../classes/class-kco-gateway.php:562
     488#: ../classes/class-kco-gateway.php:564
    489489msgid "Order address should not be changed and any changes you make will not be reflected in Kustom system."
    490490msgstr ""
    491491
    492 #: ../classes/class-kco-gateway.php:621
     492#: ../classes/class-kco-gateway.php:623
    493493msgid "Organisation number:"
    494494msgstr ""
    495495
    496 #: ../classes/class-kco-gateway.php:643, ../classes/class-kco-gateway.php:665
     496#: ../classes/class-kco-gateway.php:645, ../classes/class-kco-gateway.php:667
    497497msgid "Reference:"
    498498msgstr ""
    499499
    500 #: ../classes/class-kco-gateway.php:730
     500#: ../classes/class-kco-gateway.php:732
    501501msgid "Kustom did not accept the new order amount, the order has not been updated"
    502502msgstr ""
    … …  
    547547msgstr ""
    548548
    549 #: ../includes/kco-functions.php:707
     549#: ../includes/kco-functions.php:708
    550550msgid "Waiting for verification from Kustom's push notification"
    551551msgstr ""
    552552
    553 #: ../includes/kco-functions.php:702
     553#: ../includes/kco-functions.php:703
    554554msgid "Kustom Checkout order was rejected"
    555555msgstr ""
    556556
    557557#. translators: 1: Kustom order total, 2: WooCommerce order total.
    558 #: ../includes/kco-functions.php:752
     558#: ../includes/kco-functions.php:753
    559559msgid "Kustom order total (%1$s) does not match WooCommerce order total (%2$s). Please verify the order with Kustom before processing."
    560560msgstr ""
    561561
    562 #: ../includes/kco-functions.php:782
     562#: ../includes/kco-functions.php:783
    563563msgid "A mismatch between the WooCommerce and Kustom orders was identified. Please verify the order in the Kustom merchant portal before processing."
    564564msgstr ""
    565565
    566566#. translators: %1$s: Product name, %2$d: Expected quantity, %3$d: Found quantity.
    567 #: ../includes/kco-functions.php:833
     567#: ../includes/kco-functions.php:834
    568568msgid "The product \"%1$s\" has a quantity mismatch. Expected %2$d found %3$d."
    569569msgstr ""
    570570
    571571#. translators: %s: Product name.
    572 #: ../includes/kco-functions.php:843
     572#: ../includes/kco-functions.php:844
    573573msgid "The product \"%s\" was not found in the Kustom order."
    574574msgstr ""
  • klarna-checkout-for-woocommerce/tags/2.24.1/readme.txt

    r3767993 r3783345  
    88WC requires at least: 9.7.0
    99WC tested up to: 11.2.1
    10 Stable tag: 2.24.0
     10Stable tag: 2.24.1
    1111License: GPLv3 or later
    1212License URI: http://www.gnu.org/licenses/gpl-3.0.html
    … …  
    5151
    5252== Changelog ==
     53= 2026-11-04    - version 2.24.1 =
     54* Fix           - Fixed an issue where an incomplete address could be sent to Kustom during checkout, preventing the customer from completing their purchase.
     55* Fix           - Fixed fields added by other plugins to the block checkout, such as the WooCommerce Smart Coupons gift card form, being hidden and not savedto the order when Kustom is selected.
     56* Fix           - Fixed the checkout script stopping part-way through initialisation when another script on the page declares a global variable named "i".
     57* Fix           - Fixed the Kustom Checkout iframe showing an outdated order total when the cart total changed outside the iframe before the customer had entered an address, for example when shipping was changed or a coupon was applied.
     58* Fix           - Fixed the shipping option selected in Kustom not being applied to WooCommerce when the "Suppress third party discount plugins" setting in Woo Discount Rules was enabled. WooCommerce kept another shipping method, which caused order total mismatches with Kustom Shipping Assistant.
     59
    5360= 2026-10-27    - version 2.24.0 =
    5461* Feature       - Added support for adding Kustom express buttons to the cart, the block cart and checkout, product pages, and a new shortcode and block.
  • klarna-checkout-for-woocommerce/tags/2.24.1/vendor/composer/installed.php

    r3767993 r3783345  
    22    'root' => array(
    33        'name' => '__root__',
    4         'pretty_version' => '2.24.0',
    5         'version' => '2.24.0.0',
    6         'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d',
     4        'pretty_version' => '2.24.1',
     5        'version' => '2.24.1.0',
     6        'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1212    'versions' => array(
    1313        '__root__' => array(
    14             'pretty_version' => '2.24.0',
    15             'version' => '2.24.0.0',
    16             'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d',
     14            'pretty_version' => '2.24.1',
     15            'version' => '2.24.1.0',
     16            'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5',
    1717            'type' => 'library',
    1818            'install_path' => __DIR__ . '/../../',
  • klarna-checkout-for-woocommerce/trunk/assets/js/klarna-checkout-for-woocommerce.js

    r3743403 r3783345  
    3030                suspended: false,
    3131                // True once a shipping address is known (via shipping_address_change or change event).
    32                 // Prevents api.suspend from being called before Kustom has an address to fetch shipping for.
     32                // With Kustom Shipping Assistant, prevents api.suspend from being called before Kustom has an address to fetch shipping for.
    3333                shippingAddressKnown: false,
     34                lastOrderTotal: null,
    3435
    3536                redirectAttemptCount: 0,
    … …  
    116117                /**
    117118                 * Suspends the Kustom Iframe.
    118                  * Will not suspend again if already suspended, and will not suspend before a shipping
    119                  * address is known (to avoid triggering premature KSA external TMS shipping fetches).
     119                 * Will not suspend again if already suspended. With Kustom Shipping Assistant, will not suspend before
     120                 * a shipping address is known (to avoid triggering premature KSA external TMS shipping fetches).
     121                 * Without it, the iframe must always be suspended, since it only fetches the updated order on resume.
    120122                 * @param {boolean} autoResumeBool
    121                  */
    122                 kcoSuspend: function ( autoResumeBool ) {
    123                         if ( window._klarnaCheckout && ! kco_wc.validation && ! kco_wc.suspended && kco_wc.shippingAddressKnown ) {
     123                 * @param {boolean} ignoreAddress Suspend even if no shipping address is known yet.
     124                 */
     125                kcoSuspend: function ( autoResumeBool, ignoreAddress ) {
     126                        const waitForAddress = "yes" === kco_params.ksa_enabled && ! kco_wc.shippingAddressKnown && ! ignoreAddress
     127                        if ( window._klarnaCheckout && ! kco_wc.validation && ! kco_wc.suspended && ! waitForAddress ) {
    124128                                kco_wc.log( "kcoSuspend", autoResumeBool )
    125129                                window._klarnaCheckout( function ( api ) {
    … …  
    131135                                        } )
    132136                                } )
     137                        }
     138                },
     139
     140                /**
     141                 * Suspends the iframe after a cart total change so the next resume fetches the updated order.
     142                 * @param {Event} event
     143                 * @param {Object} data The update_order_review response.
     144                 */
     145                maybeSuspendOnTotalChange: function ( event, data ) {
     146                        const orderTotal = data && data.fragments ? data.fragments.kco_order_total : undefined
     147                        if ( undefined === orderTotal ) {
     148                                return
     149                        }
     150
     151                        const previousTotal = kco_wc.lastOrderTotal
     152                        kco_wc.lastOrderTotal = orderTotal
     153                        if ( null !== previousTotal && orderTotal !== previousTotal ) {
     154                                kco_wc.kcoSuspend( true, true )
    133155                        }
    134156                },
    … …  
    224246                        var form = $( 'form[name="checkout"] input, form[name="checkout"] select, textarea' )
    225247                        var checkout_add_ons_moved = false
    226                         for ( i = 0; i < form.length; i++ ) {
     248                        for ( let i = 0; i < form.length; i++ ) {
    227249                                var name = form[ i ].name.replace( "[]", "\\[\\]" ) // Escape any empty "array" keys to prevent errors.
    228250                                // Check if field is inside the order review.
    … …  
    603625                                kco_wc.kcoSuspend( true )
    604626                        } )
     627                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.maybeSuspendOnTotalChange )
    605628                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.kcoResume )
    606629                        kco_wc.bodyEl.on( "updated_checkout", kco_wc.maybeDisplayShippingPrice )
    … …  
    632655                                                                "given_name" in data && $( "#billing_first_name" ).val( data.given_name )
    633656                                                                "family_name" in data && $( "#billing_last_name" ).val( data.family_name )
     657                                                                "street_address" in data && $( "#billing_address_1" ).val( data.street_address )
     658                                                                "street_address2" in data && $( "#billing_address_2" ).val( data.street_address2 )
     659                                                                "city" in data && $( "#billing_city" ).val( data.city )
    634660                                                                "postal_code" in data && $( "#billing_postcode" ).val( data.postal_code )
    635661                                                                "country" in data && $( "#billing_country" ).val( country )
     662                                                                "phone" in data && $( "#billing_phone" ).val( data.phone )
    636663                                                                "email" in data && $( "#billing_email" ).val( data.email )
    637664                                                                $( "#billing_country" ).trigger( "change" )
    … …  
    646673                                                                "given_name" in data && $( "#shipping_first_name" ).val( data.given_name )
    647674                                                                "family_name" in data && $( "#shipping_last_name" ).val( data.family_name )
     675                                                                "street_address" in data && $( "#shipping_address_1" ).val( data.street_address )
     676                                                                "street_address2" in data && $( "#shipping_address_2" ).val( data.street_address2 )
     677                                                                "city" in data && $( "#shipping_city" ).val( data.city )
    648678                                                                "postal_code" in data && $( "#shipping_postcode" ).val( data.postal_code )
    649679                                                                "country" in data && $( "#shipping_country" ).val( country )
     680                                                                "phone" in data && $( "#shipping_phone" ).val( data.phone )
    650681                                                                $( "#shipping_country" ).trigger( "change" )
    651682
    … …  
    660691                                                        "given_name" in data && $( "#billing_first_name" ).val( data.given_name )
    661692                                                        "family_name" in data && $( "#billing_last_name" ).val( data.family_name )
     693                                                        "street_address" in data && $( "#billing_address_1" ).val( data.street_address )
     694                                                        "street_address2" in data && $( "#billing_address_2" ).val( data.street_address2 )
     695                                                        "city" in data && $( "#billing_city" ).val( data.city )
    662696                                                        "postal_code" in data && $( "#billing_postcode" ).val( data.postal_code )
    663697                                                        "country" in data && $( "#billing_country" ).val( country )
     698                                                        "phone" in data && $( "#billing_phone" ).val( data.phone )
    664699                                                        "email" in data && $( "#billing_email" ).val( data.email )
    665700                                                        $( "#billing_country" ).trigger( "change" )
  • klarna-checkout-for-woocommerce/trunk/assets/js/klarna-checkout-for-woocommerce.min.js

    r3743403 r3783345  
    1 jQuery(function(a){if("undefined"==typeof kco_params)return!1;var t={bodyEl:a("body"),checkoutFormSelector:a("form.checkout"),paymentMethodEl:a('input[name="payment_method"]'),paymentMethod:"",selectAnotherSelector:"#klarna-checkout-select-other",shippingUpdated:!1,validation:!1,preventPaymentMethodChange:!1,timeout:null,interval:null,klarnaUpdateNeeded:!1,shippingEmailExists:!1,suspended:!1,shippingAddressKnown:!1,redirectAttemptCount:0,documentReady:function(){if(0<t.paymentMethodEl.length)t.paymentMethod=t.paymentMethodEl.filter(":checked").val();else{if(!(0<a("ul.wc_payment_methods").length))return;t.paymentMethod="kco"}if("kco"===t.paymentMethod){t.log(kco_params),"kco"===t.paymentMethod&&a("#ship-to-different-address-checkbox").prop("checked",!0),kco_params.pay_for_order||(t.moveExtraCheckoutFields(),t.updateShipping(!1));let o=!1;new MutationObserver(function(e){e.forEach(function(e){"attributes"===e.type&&"class"===e.attributeName&&(a("html").hasClass("klarna-checkout-fso-open")?o=!0:o&&(e=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout",(e=a(e)).length&&e.find(".woocommerce-error").length&&a("html, body").not(":animated").animate({scrollTop:e.offset().top-100},1e3),t.unblock(),o=!1))})}).observe(document.querySelector("html"),{attributes:!0,attributeFilter:["class"]})}},unblock:function(){t.kcoSuspend(),t.checkoutFormSelector.removeClass("processing"),a(".woocommerce-checkout-review-order-table").unblock(),a(t.checkoutFormSelector).unblock(),t.kcoResume()},kcoSuspend:function(o){window._klarnaCheckout&&!t.validation&&!t.suspended&&t.shippingAddressKnown&&(t.log("kcoSuspend",o),window._klarnaCheckout(function(e){t.suspended=!0,e.suspend({autoResume:{enabled:o}})}))},kcoResume:function(){window._klarnaCheckout&&!t.validation&&t.suspended&&(t.suspended=!1,t.log("kcoResume"),window._klarnaCheckout(function(e){e.resume()}))},changeFromKco:function(e){e.preventDefault(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",dataType:"json",data:{kco:!1,nonce:kco_params.change_payment_method_nonce},url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})},maybeChangeToKco:function(){t.preventPaymentMethodChange||(t.log(a(this).val()),"kco"===a(this).val()&&(a(".woocommerce-info").remove(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",data:{kco:!0,nonce:kco_params.change_payment_method_nonce},dataType:"json",url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})))},moveExtraCheckoutFields:function(){a(".woocommerce-additional-fields").appendTo("#kco-extra-checkout-fields");var e=a('form[name="checkout"] input, form[name="checkout"] select, textarea'),o=!1;for(i=0;i<e.length;i++){var n=e[i].name.replace("[]","\\[\\]");a("table.woocommerce-checkout-review-order-table").find(e[i]).length||-1===a.inArray(n,kco_params.standard_woo_checkout_fields)&&("wc_checkout_add_ons"===a("p#"+n+"_field").parent().attr("id")?o||(o=!0,a("div#wc_checkout_add_ons").appendTo("#kco-extra-checkout-fields")):(0<a("p#"+n+"_field").length?("shipping_email"===n&&(t.shippingEmailExists=!0),a("p#"+n+"_field")):a('input[name="'+n+'"]').closest("p")).appendTo("#kco-extra-checkout-fields"))}a(".woocommerce-account-fields").insertAfter(a("#createaccount").closest("p"))},maybeDisplayShippingPrice:function(){var e;a(".kco-shipping").length||"kco"===t.paymentMethod&&"yes"===kco_params.shipping_methods_in_iframe&&"no"===kco_params.is_confirmation_page&&(1<a('#shipping_method input[type="radio"]').length?a('#shipping_method input[type="radio"]:checked').each(function(){var e=a(this).attr("id"),e=a('label[for="'+e+'"]').text();a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")}):1===a('#shipping_method input[type="hidden"]').length?(e=a('#shipping_method input[name="shipping_method[0]"]').attr("id"),e=a('label[for="'+e+'"]').text(),a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")):a(".woocommerce-shipping-totals td").html(kco_params.no_shipping_message))},updateCart:function(){t.kcoSuspend(!0),a.ajax({type:"POST",url:kco_params.update_cart_url,data:{checkout:a("form.checkout").serialize(),nonce:kco_params.update_cart_nonce},dataType:"json",success:function(e){},error:function(e){},complete:function(e){a("body").trigger("update_checkout"),t.kcoResume()}})},getKlarnaOrder:function(){return console.log("getKustomOrder"),t.preventPaymentMethodChange=!0,a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.get_klarna_order_url,data:{nonce:kco_params.get_klarna_order_nonce},dataType:"json",success:function(e){t.setCustomerData(e.data),0<a("form.checkout #terms").length&&a("form.checkout #terms").prop("checked",!0),console.log("success")},error:function(e){console.log("error"),window.location.reload()},complete:function(e){}})},setCustomerData:function(e){t.log("setCustomerData",e),"object"==typeof e&&null!==e&&("billing_address"in e&&null!==e.billing_address&&(a("#billing_first_name").val("given_name"in e.billing_address?e.billing_address.given_name:""),a("#billing_last_name").val("family_name"in e.billing_address?e.billing_address.family_name:""),a("#billing_company").val("organization_name"in e.billing_address?e.billing_address.organization_name:""),a("#billing_address_1").val("street_address"in e.billing_address?e.billing_address.street_address:""),a("#billing_address_2").val("street_address2"in e.billing_address?e.billing_address.street_address2:""),a("#billing_city").val("city"in e.billing_address?e.billing_address.city:""),a("#billing_postcode").val("postal_code"in e.billing_address?e.billing_address.postal_code:""),a("#billing_phone").val("phone"in e.billing_address?e.billing_address.phone:""),a("#billing_email").val("email"in e.billing_address?e.billing_address.email:""),a("#billing_country").val("country"in e.billing_address?e.billing_address.country.toUpperCase():""),a("#billing_state").val("region"in e.billing_address?e.billing_address.region:""),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur")),"shipping_address"in e)&&null!==e.shipping_address&&(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#shipping_first_name").val("given_name"in e.shipping_address?e.shipping_address.given_name:""),a("#shipping_last_name").val("family_name"in e.shipping_address?e.shipping_address.family_name:""),a("#shipping_company").val("organization_name"in e.shipping_address?e.shipping_address.organization_name:""),a("#shipping_address_1").val("street_address"in e.shipping_address?e.shipping_address.street_address:""),a("#shipping_address_2").val("street_address2"in e.shipping_address?e.shipping_address.street_address2:""),a("#shipping_city").val("city"in e.shipping_address?e.shipping_address.city:""),a("#shipping_postcode").val("postal_code"in e.shipping_address?e.shipping_address.postal_code:""),a("#shipping_country").val("country"in e.shipping_address?e.shipping_address.country.toUpperCase():""),a("#shipping_state").val("region"in e.shipping_address?e.shipping_address.region:""),a("#shipping_phone").val("phone"in e.shipping_address?e.shipping_address.phone:""),!0===t.shippingEmailExists)&&a("#shipping_email")&&a("#shipping_email").val("email"in e.shipping_address?e.shipping_address.email:"")},checkUrl:function(e){window.location.hash&&-1<window.location.hash.indexOf("#klarna-success")&&(t.logToFile("klarna-success hashtag detected in URL."),e({should_proceed:!0}),clearInterval(t.interval),clearTimeout(t.timeout),t.unblock())},failOrder:function(e,o,n){n({should_proceed:!1,message:a(o).text().trim()}),t.validation=!1;n=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout";a("body").trigger("update_checkout"),a(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),a(n).prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+o+"</div>"),a(n).removeClass("processing").unblock(),a(n).find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),a(document.body).trigger("checkout_error",[o])},logToFile:function(e){a.ajax({url:kco_params.log_to_file_url,type:"POST",dataType:"json",data:{message:"object"==typeof e?JSON.stringify(e):e,nonce:kco_params.log_to_file_nonce}})},log:function(...e){kco_params.logging&&console.log(...e)},updateShipping:function(e){var o=JSON.stringify(e);a("#kco_shipping_data").val()!==o&&(a("#kco_shipping_data").val(o),a("body").trigger("kco_shipping_option_changed",[e]),a("body").trigger("update_checkout"))},convertCountry:function(o){return Object.keys(kco_params.countries).find(e=>kco_params.countries[e]===o)},placeKlarnaOrder:function(n){t.getKlarnaOrder().done(function(e){e.success?(a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.submit_order,data:a("form.checkout").serialize(),dataType:"json",success:function(o){try{if("success"!==o.result)throw"Result failed";t.logToFile('Successfully placed order. Sending "should_proceed: true" to Kustom'),n({should_proceed:!0})}catch(e){o.messages?(t.logToFile({type:"checkout_error",message:o.messages}),t.failOrder("submission",o.messages,n)):(t.logToFile({type:"checkout_error",message:"No message"}),t.failOrder("submission",'<div class="woocommerce-error">Checkout error</div>',n))}},error:function(e){var o=(e.responseText||"").trimStart().startsWith("<");t.logToFile({type:"ajax_error",status:e.status,response:o?"[HTML body stripped]":e.responseText||""}),t.failOrder("ajax-error",'<div class="woocommerce-error">Internal Server Error</div>',n)}})):t.failOrder("get_order",'<div class="woocommerce-error">Failed to get the order from Kustom</div>',n),t.validation=!1})},update_checkout:a.Callbacks("unique stopOnFalse"),init:function(){"yes"!==kco_params.is_order_received_page&&(a(document).ready(t.documentReady),t.bodyEl.on("update_checkout",function(){t.kcoSuspend(!0)}),t.bodyEl.on("updated_checkout",t.kcoResume),t.bodyEl.on("updated_checkout",t.maybeDisplayShippingPrice),t.bodyEl.on("change","input.qty",t.updateCart),t.bodyEl.on("change",'input[name="payment_method"]',t.maybeChangeToKco),t.bodyEl.on("click",t.selectAnotherSelector,t.changeFromKco),t.update_checkout.add(function(){return t.log("fire update_checkout"),a("form.checkout").trigger("update_checkout"),!1}),"function"==typeof window._klarnaCheckout)&&window._klarnaCheckout(function(e){e.on({shipping_address_change:function(e){t.log("shipping_address_change",e),t.shippingAddressKnown=!0;var o=t.convertCountry(e.country.toUpperCase());"billing_only"===kco_params.woocommerce_ship_to_destination?("given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()):(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#ship-to-different-address-checkbox").trigger("change"),a("#ship-to-different-address-checkbox").trigger("blur"),"given_name"in e&&a("#shipping_first_name").val(e.given_name),"family_name"in e&&a("#shipping_last_name").val(e.family_name),"postal_code"in e&&a("#shipping_postcode").val(e.postal_code),"country"in e&&a("#shipping_country").val(o),a("#shipping_country").trigger("change"),a("form.checkout").trigger("update_checkout"))},billing_address_change:function(e){t.log("billing_address_change",e);var o=t.convertCountry(e.country.toUpperCase());"given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()},change:function(e){t.log("change",e),e.country&&e.postal_code&&(t.shippingAddressKnown=!0)},order_total_change:function(e){t.log("order_total_change",e)},shipping_option_change:function(e){t.log("shipping_option_change",e),t.log(e),t.updateShipping(e)},can_not_complete_order:function(e){t.log("can_not_complete_order",e)},validation_callback:function(e,o){t.validation=!0,t.logToFile("validation_callback from Kustom triggered"),kco_params.pay_for_order?o({should_proceed:!0}):t.placeKlarnaOrder(o)},customer:function(e){e="person"===e.type?"b2c":"b2b";a.ajax({url:kco_params.customer_type_changed_url,type:"POST",data:{nonce:kco_params.customer_type_changed_nonce,customer_type:e}})},checkbox_change:e=>{var{key:e,checked:o}=e;a.ajax({url:kco_params.checkbox_changed_url,type:"POST",data:{nonce:kco_params.checkbox_changed_nonce,key:e,checked:o},success:e=>{e.data.refresh_checkout&&(a(document.body).trigger("wc_fragment_refresh"),a(document.body).trigger("update_checkout"))}})},redirect_initiated:e=>{t.log("redirect_initiated",e),1<=t.redirectAttemptCount?t.logToFile(`Redirect was initiated by Kustom, but the user was not redirected. This is attempt ${redirectAttemptCount}.`):t.logToFile("Redirect initiated by Kustom, the user is about to be redirected to the confirmation page."),t.redirectAttemptCount+=1}})})}};t.init()});
     1jQuery(function(a){if("undefined"==typeof kco_params)return!1;var t={bodyEl:a("body"),checkoutFormSelector:a("form.checkout"),paymentMethodEl:a('input[name="payment_method"]'),paymentMethod:"",selectAnotherSelector:"#klarna-checkout-select-other",shippingUpdated:!1,validation:!1,preventPaymentMethodChange:!1,timeout:null,interval:null,klarnaUpdateNeeded:!1,shippingEmailExists:!1,suspended:!1,shippingAddressKnown:!1,lastOrderTotal:null,redirectAttemptCount:0,documentReady:function(){if(0<t.paymentMethodEl.length)t.paymentMethod=t.paymentMethodEl.filter(":checked").val();else{if(!(0<a("ul.wc_payment_methods").length))return;t.paymentMethod="kco"}if("kco"===t.paymentMethod){t.log(kco_params),"kco"===t.paymentMethod&&a("#ship-to-different-address-checkbox").prop("checked",!0),kco_params.pay_for_order||(t.moveExtraCheckoutFields(),t.updateShipping(!1));let o=!1;new MutationObserver(function(e){e.forEach(function(e){"attributes"===e.type&&"class"===e.attributeName&&(a("html").hasClass("klarna-checkout-fso-open")?o=!0:o&&(e=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout",(e=a(e)).length&&e.find(".woocommerce-error").length&&a("html, body").not(":animated").animate({scrollTop:e.offset().top-100},1e3),t.unblock(),o=!1))})}).observe(document.querySelector("html"),{attributes:!0,attributeFilter:["class"]})}},unblock:function(){t.kcoSuspend(),t.checkoutFormSelector.removeClass("processing"),a(".woocommerce-checkout-review-order-table").unblock(),a(t.checkoutFormSelector).unblock(),t.kcoResume()},kcoSuspend:function(o,e){e="yes"===kco_params.ksa_enabled&&!t.shippingAddressKnown&&!e;!window._klarnaCheckout||t.validation||t.suspended||e||(t.log("kcoSuspend",o),window._klarnaCheckout(function(e){t.suspended=!0,e.suspend({autoResume:{enabled:o}})}))},maybeSuspendOnTotalChange:function(e,o){var n,o=o&&o.fragments?o.fragments.kco_order_total:void 0;void 0!==o&&(n=t.lastOrderTotal,t.lastOrderTotal=o,null!==n)&&o!==n&&t.kcoSuspend(!0,!0)},kcoResume:function(){window._klarnaCheckout&&!t.validation&&t.suspended&&(t.suspended=!1,t.log("kcoResume"),window._klarnaCheckout(function(e){e.resume()}))},changeFromKco:function(e){e.preventDefault(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",dataType:"json",data:{kco:!1,nonce:kco_params.change_payment_method_nonce},url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})},maybeChangeToKco:function(){t.preventPaymentMethodChange||(t.log(a(this).val()),"kco"===a(this).val()&&(a(".woocommerce-info").remove(),a(t.checkoutFormSelector).block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",data:{kco:!0,nonce:kco_params.change_payment_method_nonce},dataType:"json",url:kco_params.change_payment_method_url,success:function(e){},error:function(e){},complete:function(e){t.log(e.responseJSON),window.location.href=e.responseJSON.data.redirect}})))},moveExtraCheckoutFields:function(){a(".woocommerce-additional-fields").appendTo("#kco-extra-checkout-fields");var o=a('form[name="checkout"] input, form[name="checkout"] select, textarea'),n=!1;for(let e=0;e<o.length;e++){var i=o[e].name.replace("[]","\\[\\]");a("table.woocommerce-checkout-review-order-table").find(o[e]).length||-1===a.inArray(i,kco_params.standard_woo_checkout_fields)&&("wc_checkout_add_ons"===a("p#"+i+"_field").parent().attr("id")?n||(n=!0,a("div#wc_checkout_add_ons").appendTo("#kco-extra-checkout-fields")):(0<a("p#"+i+"_field").length?("shipping_email"===i&&(t.shippingEmailExists=!0),a("p#"+i+"_field")):a('input[name="'+i+'"]').closest("p")).appendTo("#kco-extra-checkout-fields"))}a(".woocommerce-account-fields").insertAfter(a("#createaccount").closest("p"))},maybeDisplayShippingPrice:function(){var e;a(".kco-shipping").length||"kco"===t.paymentMethod&&"yes"===kco_params.shipping_methods_in_iframe&&"no"===kco_params.is_confirmation_page&&(1<a('#shipping_method input[type="radio"]').length?a('#shipping_method input[type="radio"]:checked').each(function(){var e=a(this).attr("id"),e=a('label[for="'+e+'"]').text();a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")}):1===a('#shipping_method input[type="hidden"]').length?(e=a('#shipping_method input[name="shipping_method[0]"]').attr("id"),e=a('label[for="'+e+'"]').text(),a(".woocommerce-shipping-totals td").html(e),a(".woocommerce-shipping-totals td").addClass("kco-shipping")):a(".woocommerce-shipping-totals td").html(kco_params.no_shipping_message))},updateCart:function(){t.kcoSuspend(!0),a.ajax({type:"POST",url:kco_params.update_cart_url,data:{checkout:a("form.checkout").serialize(),nonce:kco_params.update_cart_nonce},dataType:"json",success:function(e){},error:function(e){},complete:function(e){a("body").trigger("update_checkout"),t.kcoResume()}})},getKlarnaOrder:function(){return console.log("getKustomOrder"),t.preventPaymentMethodChange=!0,a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.get_klarna_order_url,data:{nonce:kco_params.get_klarna_order_nonce},dataType:"json",success:function(e){t.setCustomerData(e.data),0<a("form.checkout #terms").length&&a("form.checkout #terms").prop("checked",!0),console.log("success")},error:function(e){console.log("error"),window.location.reload()},complete:function(e){}})},setCustomerData:function(e){t.log("setCustomerData",e),"object"==typeof e&&null!==e&&("billing_address"in e&&null!==e.billing_address&&(a("#billing_first_name").val("given_name"in e.billing_address?e.billing_address.given_name:""),a("#billing_last_name").val("family_name"in e.billing_address?e.billing_address.family_name:""),a("#billing_company").val("organization_name"in e.billing_address?e.billing_address.organization_name:""),a("#billing_address_1").val("street_address"in e.billing_address?e.billing_address.street_address:""),a("#billing_address_2").val("street_address2"in e.billing_address?e.billing_address.street_address2:""),a("#billing_city").val("city"in e.billing_address?e.billing_address.city:""),a("#billing_postcode").val("postal_code"in e.billing_address?e.billing_address.postal_code:""),a("#billing_phone").val("phone"in e.billing_address?e.billing_address.phone:""),a("#billing_email").val("email"in e.billing_address?e.billing_address.email:""),a("#billing_country").val("country"in e.billing_address?e.billing_address.country.toUpperCase():""),a("#billing_state").val("region"in e.billing_address?e.billing_address.region:""),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur")),"shipping_address"in e)&&null!==e.shipping_address&&(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#shipping_first_name").val("given_name"in e.shipping_address?e.shipping_address.given_name:""),a("#shipping_last_name").val("family_name"in e.shipping_address?e.shipping_address.family_name:""),a("#shipping_company").val("organization_name"in e.shipping_address?e.shipping_address.organization_name:""),a("#shipping_address_1").val("street_address"in e.shipping_address?e.shipping_address.street_address:""),a("#shipping_address_2").val("street_address2"in e.shipping_address?e.shipping_address.street_address2:""),a("#shipping_city").val("city"in e.shipping_address?e.shipping_address.city:""),a("#shipping_postcode").val("postal_code"in e.shipping_address?e.shipping_address.postal_code:""),a("#shipping_country").val("country"in e.shipping_address?e.shipping_address.country.toUpperCase():""),a("#shipping_state").val("region"in e.shipping_address?e.shipping_address.region:""),a("#shipping_phone").val("phone"in e.shipping_address?e.shipping_address.phone:""),!0===t.shippingEmailExists)&&a("#shipping_email")&&a("#shipping_email").val("email"in e.shipping_address?e.shipping_address.email:"")},checkUrl:function(e){window.location.hash&&-1<window.location.hash.indexOf("#klarna-success")&&(t.logToFile("klarna-success hashtag detected in URL."),e({should_proceed:!0}),clearInterval(t.interval),clearTimeout(t.timeout),t.unblock())},failOrder:function(e,o,n){n({should_proceed:!1,message:a(o).text().trim()}),t.validation=!1;n=kco_params.pay_for_order?"div.woocommerce-notices-wrapper":"form.checkout";a("body").trigger("update_checkout"),a(".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message").remove(),a(n).prepend('<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">'+o+"</div>"),a(n).removeClass("processing").unblock(),a(n).find(".input-text, select, input:checkbox").trigger("validate").trigger("blur"),a(document.body).trigger("checkout_error",[o])},logToFile:function(e){a.ajax({url:kco_params.log_to_file_url,type:"POST",dataType:"json",data:{message:"object"==typeof e?JSON.stringify(e):e,nonce:kco_params.log_to_file_nonce}})},log:function(...e){kco_params.logging&&console.log(...e)},updateShipping:function(e){var o=JSON.stringify(e);a("#kco_shipping_data").val()!==o&&(a("#kco_shipping_data").val(o),a("body").trigger("kco_shipping_option_changed",[e]),a("body").trigger("update_checkout"))},convertCountry:function(o){return Object.keys(kco_params.countries).find(e=>kco_params.countries[e]===o)},placeKlarnaOrder:function(n){t.getKlarnaOrder().done(function(e){e.success?(a(".woocommerce-checkout-review-order-table").block({message:null,overlayCSS:{background:"#fff",opacity:.6}}),a.ajax({type:"POST",url:kco_params.submit_order,data:a("form.checkout").serialize(),dataType:"json",success:function(o){try{if("success"!==o.result)throw"Result failed";t.logToFile('Successfully placed order. Sending "should_proceed: true" to Kustom'),n({should_proceed:!0})}catch(e){o.messages?(t.logToFile({type:"checkout_error",message:o.messages}),t.failOrder("submission",o.messages,n)):(t.logToFile({type:"checkout_error",message:"No message"}),t.failOrder("submission",'<div class="woocommerce-error">Checkout error</div>',n))}},error:function(e){var o=(e.responseText||"").trimStart().startsWith("<");t.logToFile({type:"ajax_error",status:e.status,response:o?"[HTML body stripped]":e.responseText||""}),t.failOrder("ajax-error",'<div class="woocommerce-error">Internal Server Error</div>',n)}})):t.failOrder("get_order",'<div class="woocommerce-error">Failed to get the order from Kustom</div>',n),t.validation=!1})},update_checkout:a.Callbacks("unique stopOnFalse"),init:function(){"yes"!==kco_params.is_order_received_page&&(a(document).ready(t.documentReady),t.bodyEl.on("update_checkout",function(){t.kcoSuspend(!0)}),t.bodyEl.on("updated_checkout",t.maybeSuspendOnTotalChange),t.bodyEl.on("updated_checkout",t.kcoResume),t.bodyEl.on("updated_checkout",t.maybeDisplayShippingPrice),t.bodyEl.on("change","input.qty",t.updateCart),t.bodyEl.on("change",'input[name="payment_method"]',t.maybeChangeToKco),t.bodyEl.on("click",t.selectAnotherSelector,t.changeFromKco),t.update_checkout.add(function(){return t.log("fire update_checkout"),a("form.checkout").trigger("update_checkout"),!1}),"function"==typeof window._klarnaCheckout)&&window._klarnaCheckout(function(e){e.on({shipping_address_change:function(e){t.log("shipping_address_change",e),t.shippingAddressKnown=!0;var o=t.convertCountry(e.country.toUpperCase());"billing_only"===kco_params.woocommerce_ship_to_destination?("given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"street_address"in e&&a("#billing_address_1").val(e.street_address),"street_address2"in e&&a("#billing_address_2").val(e.street_address2),"city"in e&&a("#billing_city").val(e.city),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"phone"in e&&a("#billing_phone").val(e.phone),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()):(a("#ship-to-different-address-checkbox").prop("checked",!0),a("#ship-to-different-address-checkbox").trigger("change"),a("#ship-to-different-address-checkbox").trigger("blur"),"given_name"in e&&a("#shipping_first_name").val(e.given_name),"family_name"in e&&a("#shipping_last_name").val(e.family_name),"street_address"in e&&a("#shipping_address_1").val(e.street_address),"street_address2"in e&&a("#shipping_address_2").val(e.street_address2),"city"in e&&a("#shipping_city").val(e.city),"postal_code"in e&&a("#shipping_postcode").val(e.postal_code),"country"in e&&a("#shipping_country").val(o),"phone"in e&&a("#shipping_phone").val(e.phone),a("#shipping_country").trigger("change"),a("form.checkout").trigger("update_checkout"))},billing_address_change:function(e){t.log("billing_address_change",e);var o=t.convertCountry(e.country.toUpperCase());"given_name"in e&&a("#billing_first_name").val(e.given_name),"family_name"in e&&a("#billing_last_name").val(e.family_name),"street_address"in e&&a("#billing_address_1").val(e.street_address),"street_address2"in e&&a("#billing_address_2").val(e.street_address2),"city"in e&&a("#billing_city").val(e.city),"postal_code"in e&&a("#billing_postcode").val(e.postal_code),"country"in e&&a("#billing_country").val(o),"phone"in e&&a("#billing_phone").val(e.phone),"email"in e&&a("#billing_email").val(e.email),a("#billing_country").trigger("change"),a("#billing_email").trigger("change"),a("#billing_email").trigger("blur"),t.update_checkout.fire()},change:function(e){t.log("change",e),e.country&&e.postal_code&&(t.shippingAddressKnown=!0)},order_total_change:function(e){t.log("order_total_change",e)},shipping_option_change:function(e){t.log("shipping_option_change",e),t.log(e),t.updateShipping(e)},can_not_complete_order:function(e){t.log("can_not_complete_order",e)},validation_callback:function(e,o){t.validation=!0,t.logToFile("validation_callback from Kustom triggered"),kco_params.pay_for_order?o({should_proceed:!0}):t.placeKlarnaOrder(o)},customer:function(e){e="person"===e.type?"b2c":"b2b";a.ajax({url:kco_params.customer_type_changed_url,type:"POST",data:{nonce:kco_params.customer_type_changed_nonce,customer_type:e}})},checkbox_change:e=>{var{key:e,checked:o}=e;a.ajax({url:kco_params.checkbox_changed_url,type:"POST",data:{nonce:kco_params.checkbox_changed_nonce,key:e,checked:o},success:e=>{e.data.refresh_checkout&&(a(document.body).trigger("wc_fragment_refresh"),a(document.body).trigger("update_checkout"))}})},redirect_initiated:e=>{t.log("redirect_initiated",e),1<=t.redirectAttemptCount?t.logToFile(`Redirect was initiated by Kustom, but the user was not redirected. This is attempt ${redirectAttemptCount}.`):t.logToFile("Redirect initiated by Kustom, the user is about to be redirected to the confirmation page."),t.redirectAttemptCount+=1}})})}};t.init()});
  • klarna-checkout-for-woocommerce/trunk/blocks/build/checkout.asset.php

    r3641654 r3783345  
    1 <?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-registry', 'wc-settings', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-polyfill'), 'version' => 'b6572d146d9a5337699f');
     1<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-registry', 'wc-settings', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-polyfill'), 'version' => '421df203be0c2da7bc3e');
  • klarna-checkout-for-woocommerce/trunk/blocks/build/checkout.js

    r3641654 r3783345  
    1 (()=>{"use strict";const e=window.React,t=window.wp.htmlEntities,n=window.wp.element,c=window.wc.wcBlocksRegistry,o=window.wc.wcSettings,r=window.wp.data,a=()=>{const e=(0,r.select)("wc/store/payment");if(!e)return!1;const t=Object.keys(e.getAvailablePaymentMethods()||{});return 1===t.length&&"kco"===t[0]},i=()=>{var e;return"kco"===(null===(e=document.querySelector('input[name="radio-control-wc-payment-method-options"]:checked'))||void 0===e?void 0:e.value)},l=window.wc.blocksCheckout;var u=function(e,t,n,c){return new(n||(n=Promise))(function(o,r){function a(e){try{l(c.next(e))}catch(e){r(e)}}function i(e){try{l(c.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(a,i)}l((c=c.apply(e,t||[])).next())})};const s=(0,o.getSetting)("kco_data",{}),d=(0,t.decodeEntities)(s.title||"Kustom Checkout"),p=(0,t.decodeEntities)(s.description||""),k=(0,t.decodeEntities)(s.iconUrl||""),h=s.features||[],m=t=>{const{activePaymentMethod:c,billing:o,cartData:r}=t,{isActive:d,suspendKCO:k,resumeKCO:h}=((e,t)=>{const[c,o]=(0,n.useState)(i()||"kco"===t),[r,s]=(0,n.useState)(null),[d,p]=(0,n.useState)(null),{snippet:k,shippingInIframe:h,countryCodes:m}=e,f=(e=>["#shipping-fields","#billing-fields","#contact-fields",".wc-block-components-checkout-place-order-button",".wp-block-woocommerce-checkout-terms-block",e?"#shipping-option":"",a()?".wc-block-checkout__payment-method":""])(h),w=(0,n.useRef)(),b=(0,n.useRef)(null),g=(0,n.useRef)(null),y=(0,n.useRef)({billing:null,shipping:null}),C=(0,n.useRef)(null),_=(0,n.useRef)(""),v=(0,n.useCallback)(()=>{const e=k.match(/<script.*?>([\s\S]*?)<\/script>/),t=e?e[1]:"";return{htmlContentText:k.replace(/<script.*<\/script>/,""),scriptContentText:t}},[k]),E=(0,n.useCallback)((e=!0)=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(t){t.suspend({autoResume:e})})},[]),x=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.resume()})},[]),O=(0,n.useCallback)(e=>Object.keys(m).find(t=>m[t]===e.toUpperCase())||"",[m]),S=(0,n.useCallback)(e=>Object.assign(Object.assign({},e),{country:(null==e?void 0:e.country)?O(e.country):""}),[O]),R=(0,n.useCallback)(()=>u(void 0,void 0,void 0,function*(){const{billing:e,shipping:t}=y.current;y.current={billing:null,shipping:null};const n=t||e;if(!n)return;const c={action:"address_changed",billing:e||{},shipping:n},o=JSON.stringify(c);if(o!==_.current)return _.current=o,(0,l.extensionCartUpdate)({namespace:"kco-block",data:c}).then(()=>{}).catch(e=>{_.current=""}).finally(()=>{});x()}),[x]),T=(0,n.useCallback)((e,t)=>{E(),y.current[e]=S(t),C.current&&clearTimeout(C.current),C.current=setTimeout(()=>{C.current=null,R()},100)},[E,S,R]),j=(0,n.useCallback)(e=>T("shipping",e),[T]),K=(0,n.useCallback)(e=>T("billing",e),[T]),P=(0,n.useCallback)(e=>u(void 0,void 0,void 0,function*(){return E(),(0,l.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"shipping_option_changed"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{x()})}),[E,x]),A=(0,n.useCallback)(e=>u(void 0,void 0,void 0,function*(){return E(),(0,l.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"load"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{x()})}),[E,x]);(0,n.useEffect)(()=>{const{htmlContentText:e,scriptContentText:t}=v();s(e),p(t)},[k,v]);const M=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.on({load:A,shipping_address_change:j,billing_address_change:K,shipping_option_change:P,change:e=>{},user_interacted:e=>{},customer:e=>{},shipping_address_update_error:e=>{},order_total_change:e=>{},checkbox_change:e=>{},can_not_complete_order:e=>{},network_error:e=>{},load_confirmation:e=>{},redirect_initiated:e=>{}})})},[j,K,P,A]);return(0,n.useEffect)(()=>()=>{C.current&&(clearTimeout(C.current),C.current=null)},[]),(0,n.useEffect)(()=>(c&&r&&!w.current&&(f.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: none;")}),b.current=(e=>{const t=document.createElement("div");t.id="kco-wrapper",t.className="wc-block-checkout__klarna-checkout wc-block-components-klarna-checkout-block",t.innerHTML=e;const n=document.querySelector(".wc-block-checkout__payment-method");return n&&n.after(t),t})(r),g.current=document.createElement("script"),g.current.textContent=d,document.body.appendChild(g.current),w.current=c),M(),()=>{i()||(b.current&&b.current.remove(),f.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: block;")}),document.body.removeChild(g.current),b.current=null,g.current=null,w.current=c)}),[c,r,d,f,M]),{isActive:c,elementsToHide:f,suspendKCO:E,resumeKCO:x}})(s,c);return(0,n.useEffect)(()=>{d&&(k(),h())},[o.cartTotalItems,d,h,k]),""===p?null:e.createElement("div",{className:"wc-block-components-klarna-checkout"},e.createElement("p",null,p))},f={name:"kco",label:e.createElement(()=>e.createElement("div",{style:{display:"flex",gap:16,width:"100%",justifyContent:"space-between",paddingRight:16}},e.createElement("span",null,d),e.createElement("img",{src:k,alt:d})),null),content:e.createElement(m,null),edit:e.createElement(m,null),placeOrderButtonLabel:"Pay with Kustom Checkout",canMakePayment:()=>(!s.error&&s.snippet||console.error("Failed to initialize Kustom Checkout: "+s.error),!0),ariaLabel:d,supports:{features:h}};(0,c.registerPaymentMethod)(f)})();
     1(()=>{"use strict";const e=window.React,t=window.wp.htmlEntities,n=window.wp.element,c=window.wc.wcBlocksRegistry,r=window.wc.wcSettings,o=window.wp.data,l=()=>{const e=(0,o.select)("wc/store/payment");if(!e)return!1;const t=Object.keys(e.getAvailablePaymentMethods()||{});return 1===t.length&&"kco"===t[0]},u=()=>{var e;return"kco"===(null===(e=document.querySelector('input[name="radio-control-wc-payment-method-options"]:checked'))||void 0===e?void 0:e.value)},i=window.wc.blocksCheckout;var a=function(e,t,n,c){return new(n||(n=Promise))(function(r,o){function l(e){try{i(c.next(e))}catch(e){o(e)}}function u(e){try{i(c.throw(e))}catch(e){o(e)}}function i(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(l,u)}i((c=c.apply(e,t||[])).next())})};const s=(e,t,c)=>{const[r,o]=(0,n.useState)(u()||"kco"===t),[s,d]=(0,n.useState)(null),[p,k]=(0,n.useState)(null),{snippet:m,shippingInIframe:h,countryCodes:f}=e,b=(e=>["#shipping-fields","#billing-fields","#contact",".wc-block-components-checkout-place-order-button",".wp-block-woocommerce-checkout-terms-block",e?"#shipping-option":"",l()?".wc-block-checkout__payment-method":""])(h),w=(0,n.useRef)(),v=(0,n.useRef)(null),y=(0,n.useRef)(null),g=(0,n.useRef)({billing:null,shipping:null}),C=(0,n.useRef)(null),_=(0,n.useRef)(""),E=(0,n.useRef)(""),x=(0,n.useRef)(null),O=(0,n.useRef)(null),S=(0,n.useRef)(!1),R=(0,n.useRef)(null),T=(0,n.useCallback)(()=>{const e=m.match(/<script.*?>([\s\S]*?)<\/script>/),t=e?e[1]:"";return{htmlContentText:m.replace(/<script.*<\/script>/,""),scriptContentText:t}},[m]),A=(0,n.useCallback)((e=!0)=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(t){t.suspend({autoResume:e})})},[]),K=(0,n.useCallback)(()=>{S.current||"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.resume()})},[]),j=(0,n.useCallback)(e=>Object.keys(f).find(t=>f[t]===e.toUpperCase())||"",[f]),q=(0,n.useCallback)(e=>Object.assign(Object.assign({},e),{country:(null==e?void 0:e.country)?j(e.country):""}),[j]),U=(0,n.useCallback)(()=>a(void 0,void 0,void 0,function*(){const{billing:e,shipping:t}=g.current;g.current={billing:null,shipping:null};const n=t||e;if(!n)return;const c={action:"address_changed",billing:e||{},shipping:n},r=JSON.stringify(c);if(r!==_.current)return _.current=r,(0,i.extensionCartUpdate)({namespace:"kco-block",data:c}).then(()=>{}).catch(e=>{_.current=""}).finally(()=>{});K()}),[K]),M=(0,n.useCallback)(()=>{var e,t,n,c,r,o,l;const u=window,i=null===(t=null===(e=null==u?void 0:u.wc)||void 0===e?void 0:e.wcBlocksData)||void 0===t?void 0:t.CHECKOUT_STORE_KEY;return i&&null!==(l=null===(o=null===(r=null===(c=null===(n=null==u?void 0:u.wp)||void 0===n?void 0:n.data)||void 0===c?void 0:c.select(i))||void 0===r?void 0:r.getExtensionData)||void 0===o?void 0:o.call(r))&&void 0!==l?l:{}},[]),P=(0,n.useCallback)(()=>a(void 0,void 0,void 0,function*(){O.current=null;const e=M(),t=JSON.stringify(e);if(t!==E.current){E.current=t;try{yield(0,i.extensionCartUpdate)({namespace:"kco-block",data:{action:"extension_data_changed",extensions:e}})}catch(e){E.current="",x.current=null}}S.current&&!O.current&&(S.current=!1,K())}),[M,K]),N=(0,n.useCallback)((e,t)=>{A(),g.current[e]=q(t),C.current&&clearTimeout(C.current),C.current=setTimeout(()=>{C.current=null,U()},100)},[A,q,U]),L=(0,n.useCallback)(e=>N("shipping",e),[N]),B=(0,n.useCallback)(e=>N("billing",e),[N]),D=(0,n.useCallback)(e=>a(void 0,void 0,void 0,function*(){return A(),(0,i.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"shipping_option_changed"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{K()})}),[A,K]),H=(0,n.useCallback)(e=>a(void 0,void 0,void 0,function*(){return A(),(0,i.extensionCartUpdate)({namespace:"kco-block",data:Object.assign({action:"load"},e)}).then(e=>{}).catch(e=>{}).finally(()=>{K()})}),[A,K]);(0,n.useEffect)(()=>{const{htmlContentText:e,scriptContentText:t}=T();d(e),k(t)},[m,T]);const I=(0,n.useCallback)(()=>{"function"==typeof window._klarnaCheckout&&window._klarnaCheckout(function(e){e.on({load:H,shipping_address_change:L,billing_address_change:B,shipping_option_change:D,change:e=>{},user_interacted:e=>{},customer:e=>{},shipping_address_update_error:e=>{},order_total_change:e=>{},checkbox_change:e=>{},can_not_complete_order:e=>{},network_error:e=>{},load_confirmation:e=>{},redirect_initiated:e=>{}})})},[L,B,D,H]);return(0,n.useEffect)(()=>()=>{C.current&&(clearTimeout(C.current),C.current=null)},[]),(0,n.useEffect)(()=>{var e,t;const n=window;if(!r||"function"!=typeof(null===(t=null===(e=null==n?void 0:n.wp)||void 0===e?void 0:e.data)||void 0===t?void 0:t.subscribe))return;const c=e=>{const t=M();t!==x.current&&(x.current=t,JSON.stringify(t)!==E.current&&(e&&!S.current&&(S.current=!0,A()),O.current&&clearTimeout(O.current),O.current=setTimeout(P,500)))},o=n.wp.data.subscribe(()=>c(!0));return c(!1),()=>{O.current&&(clearTimeout(O.current),O.current=null),x.current=null,S.current=!1,o()}},[r,M,P,A]),(0,n.useEffect)(()=>(r&&s&&!w.current&&(b.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: none;")}),R.current=(()=>{const e=document.querySelector("#contact-fields");if(!e)return()=>{};const t=()=>{const t=(e=>{var t;const n=e.querySelector(".wc-block-components-checkout-step__content");return Array.from(null!==(t=null==n?void 0:n.children)&&void 0!==t?t:[]).some(e=>"contact"!==e.id&&null!==e.querySelector("input, select, textarea"))})(e)?"display: block;":"display: none;";e.getAttribute("style")!==t&&e.setAttribute("style",t)};t();const n=new MutationObserver(t);return n.observe(e,{childList:!0,subtree:!0}),()=>{n.disconnect(),e.setAttribute("style","display: block;")}})(),v.current=(e=>{const t=document.createElement("div");t.id="kco-wrapper",t.className="wc-block-checkout__klarna-checkout wc-block-components-klarna-checkout-block",t.innerHTML=e;const n=document.querySelector(".wc-block-checkout__payment-method");return n&&n.after(t),t})(s),y.current=document.createElement("script"),y.current.textContent=p,document.body.appendChild(y.current),w.current=r),I(),()=>{var e;u()||(v.current&&v.current.remove(),b.forEach(e=>{if(""===e)return;const t=document.querySelector(e);t&&t.setAttribute("style","display: block;")}),null===(e=R.current)||void 0===e||e.call(R),R.current=null,document.body.removeChild(y.current),v.current=null,y.current=null,w.current=r)}),[r,s,p,b,I]),{isActive:r,elementsToHide:b,suspendKCO:A,resumeKCO:K}},d=(0,r.getSetting)("kco_data",{}),p=(0,t.decodeEntities)(d.title||"Kustom Checkout"),k=(0,t.decodeEntities)(d.description||""),m=(0,t.decodeEntities)(d.iconUrl||""),h=d.features||[],f=t=>{const{activePaymentMethod:c,billing:r,cartData:o}=t,{isActive:l,suspendKCO:u,resumeKCO:i}=s(d,c);return(0,n.useEffect)(()=>{l&&(u(),i())},[r.cartTotalItems,l,i,u]),""===k?null:e.createElement("div",{className:"wc-block-components-klarna-checkout"},e.createElement("p",null,k))},b={name:"kco",label:e.createElement(()=>e.createElement("div",{style:{display:"flex",gap:16,width:"100%",justifyContent:"space-between",paddingRight:16}},e.createElement("span",null,p),e.createElement("img",{src:m,alt:p})),null),content:e.createElement(f,null),edit:e.createElement(f,null),placeOrderButtonLabel:"Pay with Kustom Checkout",canMakePayment:()=>(!d.error&&d.snippet||console.error("Failed to initialize Kustom Checkout: "+d.error),!0),ariaLabel:p,supports:{features:h}};(0,c.registerPaymentMethod)(b)})();
  • klarna-checkout-for-woocommerce/trunk/blocks/src/BlockExtension.php

    r3767993 r3783345  
    127127                                kco_update_wc_shipping( $data );
    128128                                break;
     129                        case 'extension_data_changed':
     130                                $this->store_extension_data( $data );
     131                                break;
    129132                        case 'load':
    130133                                // No action needed here for now. We just want to trigger an update of the WooCommerce cart.
    … …  
    133136                                break;
    134137                }
     138        }
     139
     140        /**
     141         * Store the checkout block's extension data in the session.
     142         * Third party blocks keep it in the browser and expect it in the checkout POST, which we build
     143         * server side from the validation callback, so OrderValidation reads it back from here.
     144         *
     145         * @param array $data The data from the API.
     146         *
     147         * @return void
     148         */
     149        private function store_extension_data( $data ) {
     150                $extensions = $data['extensions'] ?? array();
     151
     152                if ( ! is_array( $extensions ) ) {
     153                        return;
     154                }
     155
     156                // An empty object means the shopper cleared everything, so drop what an earlier push stored.
     157                if ( empty( $extensions ) ) {
     158                        WC()->session->__unset( 'kco_wc_extension_data' );
     159                        return;
     160                }
     161
     162                WC()->session->set( 'kco_wc_extension_data', $extensions );
    135163        }
    136164
  • klarna-checkout-for-woocommerce/trunk/blocks/src/Checkout/hooks/useKcoIframe.tsx

    r3641654 r3783345  
    33        addIframe,
    44        getElementsToHide,
     5        hideContactStepWhenEmpty,
    56        hideElements,
    67        removeIframe,
    … …  
    2627 */
    2728const ADDRESS_UPDATE_DEBOUNCE_MS = 100;
     29
     30/**
     31 * How long to wait for the checkout data store to settle before sending extension data.
     32 * Typing in a third party field emits a store change per keystroke, and we only want one
     33 * cart update once the shopper stops.
     34 */
     35const EXTENSION_DATA_DEBOUNCE_MS = 500;
    2836
    2937/**
    … …  
    6674        // Signature of the last address update we sent, so an unchanged address is not sent twice.
    6775        const lastSentAddressRef = useRef<string>('');
     76        // Signature of the last extension data we sent, for the same reason. Starts unsent so the first
     77        // snapshot always goes out, even an empty one that clears what an earlier page stored.
     78        const lastSentExtensionDataRef = useRef<string>('');
     79        // The extension data object last seen in the store, and the push waiting to go out.
     80        const lastSeenExtensionDataRef = useRef<unknown>(null);
     81        const extensionUpdateTimerRef = useRef<ReturnType<
     82                typeof setTimeout
     83        > | null>(null);
     84        // Whether we suspended the iframe for an extension data push, so only we resume it.
     85        const extensionSuspendedRef = useRef<boolean>(false);
     86        // Stops watching the contact step for fields from other plugins.
     87        const stopContactStepRef = useRef<(() => void) | null>(null);
    6888
    6989        /**
    … …  
    103123         */
    104124        const resumeKCO = useCallback((): void => {
     125                // An extension data push is pending, sendExtensionData resumes once it is stored.
     126                if (extensionSuspendedRef.current) {
     127                        return;
     128                }
     129
    105130                // If the Kustom Checkout script hasn't loaded yet, do nothing.
    106131                if ('function' !== typeof window._klarnaCheckout) {
    … …  
    193218                return response;
    194219        }, [resumeKCO]);
     220
     221        /**
     222         * Read the extension data third party blocks keep in the checkout data store.
     223         *
     224         * @return {Record<string, unknown>} - The extension data, keyed by namespace.
     225         */
     226        const getExtensionData = useCallback((): Record<string, unknown> => {
     227                const globals = window as any;
     228                const checkoutStore = globals?.wc?.wcBlocksData?.CHECKOUT_STORE_KEY;
     229
     230                return checkoutStore
     231                        ? (globals?.wp?.data?.select(checkoutStore)?.getExtensionData?.() ??
     232                                        {})
     233                        : {};
     234        }, []);
     235
     236        /**
     237         * Send the checkout block's extension data to the WooCommerce session.
     238         * The Kustom order is submitted server side from the validation callback, which cannot read the
     239         * browser's checkout store, so the data has to be stored before the shopper pays.
     240         *
     241         * @return {Promise<void>}
     242         */
     243        const sendExtensionData = useCallback(async (): Promise<void> => {
     244                extensionUpdateTimerRef.current = null;
     245                const extensions = getExtensionData();
     246                const signature = JSON.stringify(extensions);
     247
     248                // Nothing changed since the last push, so skip the round trip.
     249                if (signature !== lastSentExtensionDataRef.current) {
     250                        lastSentExtensionDataRef.current = signature;
     251
     252                        try {
     253                                await extensionCartUpdate({
     254                                        namespace: 'kco-block',
     255                                        data: { action: 'extension_data_changed', extensions },
     256                                });
     257                        } catch (_error) {
     258                                // Send again on the next store change, since the session does not have this data.
     259                                lastSentExtensionDataRef.current = '';
     260                                lastSeenExtensionDataRef.current = null;
     261                        }
     262                }
     263
     264                // Let the shopper pay again, unless a newer change is already waiting to be sent.
     265                if (extensionSuspendedRef.current && !extensionUpdateTimerRef.current) {
     266                        extensionSuspendedRef.current = false;
     267                        resumeKCO();
     268                }
     269        }, [getExtensionData, resumeKCO]);
    195270
    196271        /**
    … …  
    388463
    389464        useEffect(() => {
     465                const globals = window as any;
     466
     467                if (!isActive || 'function' !== typeof globals?.wp?.data?.subscribe) {
     468                        return;
     469                }
     470
     471                /**
     472                 * Schedule a push when the extension data changed since it was last sent.
     473                 *
     474                 * @param {boolean} holdPayment - Whether to suspend the iframe until the push is stored.
     475                 * @return {void}
     476                 */
     477                const onStoreChange = (holdPayment: boolean): void => {
     478                        const extensions = getExtensionData();
     479
     480                        // The store returns the same object until something changes, so most calls stop here.
     481                        if (extensions === lastSeenExtensionDataRef.current) {
     482                                return;
     483                        }
     484                        lastSeenExtensionDataRef.current = extensions;
     485
     486                        if (
     487                                JSON.stringify(extensions) === lastSentExtensionDataRef.current
     488                        ) {
     489                                return;
     490                        }
     491
     492                        // The validation callback reads the session, so the shopper must not pay before this is stored.
     493                        if (holdPayment && !extensionSuspendedRef.current) {
     494                                extensionSuspendedRef.current = true;
     495                                suspendKCO();
     496                        }
     497
     498                        if (extensionUpdateTimerRef.current) {
     499                                clearTimeout(extensionUpdateTimerRef.current);
     500                        }
     501                        extensionUpdateTimerRef.current = setTimeout(
     502                                sendExtensionData,
     503                                EXTENSION_DATA_DEBOUNCE_MS
     504                        );
     505                };
     506
     507                // Third party fields write straight to the checkout data store, and there is no event to
     508                // listen for, so watch the store itself and push once the changes settle.
     509                const unsubscribe = globals.wp.data.subscribe(() =>
     510                        onStoreChange(true)
     511                );
     512
     513                // Send whatever was already filled in before the iframe was shown.
     514                onStoreChange(false);
     515
     516                return () => {
     517                        if (extensionUpdateTimerRef.current) {
     518                                clearTimeout(extensionUpdateTimerRef.current);
     519                                extensionUpdateTimerRef.current = null;
     520                        }
     521                        lastSeenExtensionDataRef.current = null;
     522                        extensionSuspendedRef.current = false;
     523                        unsubscribe();
     524                };
     525        }, [isActive, getExtensionData, sendExtensionData, suspendKCO]);
     526
     527        useEffect(() => {
    390528                // Only show the iframe if the Kustom Checkout is active, we have the content and it was not active before.
    391529                if (isActive && htmlContent && !prevIsActive.current) {
    392530                        hideElements(elementsToHide);
     531                        stopContactStepRef.current = hideContactStepWhenEmpty();
    393532                        // Add the iframe and script to the WooCommerce checkout page.
    394533                        kcoWrapperRef.current = addIframe(htmlContent);
    … …  
    409548
    410549                        showElements(elementsToHide);
     550                        stopContactStepRef.current?.();
     551                        stopContactStepRef.current = null;
    411552                        document.body.removeChild(scriptRef.current);
    412553                        kcoWrapperRef.current = null;
  • klarna-checkout-for-woocommerce/trunk/blocks/src/Checkout/lib.ts

    r3583083 r3783345  
    1414                '#shipping-fields', // Hide shipping fields since they are handled in the iframe.
    1515                '#billing-fields', // Hide billing fields since they are handled in the iframe.
    16                 '#contact-fields', // Hide contact fields since they are handled in the iframe.
     16                '#contact', // Hide the email field since it is handled in the iframe. The step itself is handled by hideContactStepWhenEmpty.
    1717                '.wc-block-components-checkout-place-order-button', // Hide the place order button since it is handled in the iframe.
    1818                '.wp-block-woocommerce-checkout-terms-block', // Hide the terms and conditions block since it is handled in the iframe.
    … …  
    5858                }
    5959        });
     60};
     61
     62/**
     63 * Test if the contact step holds fields from other plugins, such as the Smart Coupons gift form.
     64 * Checks for form controls rather than height, since nothing has a height while the step is hidden.
     65 *
     66 * @param {Element} step - The contact step element.
     67 * @return {boolean} - True if another block in the step has a form field, false otherwise.
     68 */
     69const contactStepHasOtherFields = (step: Element): boolean => {
     70        const content = step.querySelector(
     71                '.wc-block-components-checkout-step__content'
     72        );
     73
     74        return Array.from(content?.children ?? []).some(
     75                (child) =>
     76                        child.id !== 'contact' &&
     77                        child.querySelector('input, select, textarea') !== null
     78        );
     79};
     80
     81/**
     82 * Hide the contact step when the email field is all it holds, and show it again if another plugin's block mounts into it.
     83 * Other plugins can only place their blocks inside the step, so hiding it whole would hide their fields too.
     84 *
     85 * @return {() => void} - Stops watching the step and shows it again.
     86 */
     87export const hideContactStepWhenEmpty = (): (() => void) => {
     88        const step = document.querySelector('#contact-fields');
     89        if (!step) {
     90                return () => {};
     91        }
     92
     93        /**
     94         * Show or hide the step depending on what it currently holds.
     95         *
     96         * @return {void}
     97         */
     98        const sync = (): void => {
     99                const style = contactStepHasOtherFields(step)
     100                        ? 'display: block;'
     101                        : 'display: none;';
     102                if (step.getAttribute('style') !== style) {
     103                        step.setAttribute('style', style);
     104                }
     105        };
     106
     107        sync();
     108        const observer = new MutationObserver(sync);
     109        observer.observe(step, { childList: true, subtree: true });
     110
     111        return () => {
     112                observer.disconnect();
     113                step.setAttribute('style', 'display: block;');
     114        };
    60115};
    61116
  • klarna-checkout-for-woocommerce/trunk/blocks/src/OrderValidation.php

    r3767993 r3783345  
    249249                        throw new Exception( 'Order is already paid.', 400 );
    250250                }
     251        }
     252
     253        /**
     254         * Get the extension data the checkout block script stashed in the session.
     255         *
     256         * @param string $wc_cart_token The cart token from the Kustom order merchant data.
     257         *
     258         * @return array
     259         */
     260        private static function get_stashed_extension_data( $wc_cart_token ) {
     261                try {
     262                        $session = ExpressSession::open( $wc_cart_token );
     263                } catch ( Exception $e ) {
     264                        return array();
     265                }
     266
     267                $extensions = $session->get( 'kco_wc_extension_data', array() );
     268
     269                return is_array( $extensions ) ? $extensions : array();
    251270        }
    252271
    … …  
    326345                );
    327346
     347                // Pass on the extension data the checkout block collected in the browser. Not for express
     348                // orders, which never pass through the checkout page, so that data is not theirs.
     349                $extensions = $express_context ? array() : self::get_stashed_extension_data( $wc_cart_token );
     350                if ( ! empty( $extensions ) ) {
     351                        $body['extensions'] = $extensions;
     352                }
     353
    328354                // The order key is required by the Store API to pay for an existing order, and omitted for the create flow.
    329355                if ( $order ) {
  • klarna-checkout-for-woocommerce/trunk/classes/class-kco-checkout.php

    r3743403 r3783345  
    2222                add_filter( 'woocommerce_checkout_fields', array( $this, 'add_shipping_data_input' ) );
    2323                add_action( 'woocommerce_before_calculate_totals', array( $this, 'update_shipping_method' ), 9999 );
     24                add_filter( 'advanced_woo_discount_rules_exclude_hooks_from_removing', array( $this, 'keep_update_shipping_method_hook' ) );
    2425                add_action( 'woocommerce_after_calculate_totals', array( $this, 'update_klarna_order' ), 99999 );
     26                add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'add_order_total_fragment' ) );
    2527
    2628                // Handle potential shipping selection errors.
    … …  
    9799
    98100        /**
     101         * Keep the shipping method update when Woo Discount Rules suppresses third party discount plugins.
     102         *
     103         * That setting removes all other callbacks from woocommerce_before_calculate_totals, so the shipping option selected
     104         * in Kustom never reached WooCommerce and Kustom Shipping Assistant was replaced by another shipping method.
     105         *
     106         * @param array $allowed_hooks Callbacks to keep as 'Class|method', keyed by hook name.
     107         *
     108         * @return array
     109         */
     110        public function keep_update_shipping_method_hook( $allowed_hooks ) {
     111                $allowed_hooks['woocommerce_before_calculate_totals']   = (array) ( $allowed_hooks['woocommerce_before_calculate_totals'] ?? array() );
     112                $allowed_hooks['woocommerce_before_calculate_totals'][] = get_class( $this ) . '|update_shipping_method';
     113
     114                return $allowed_hooks;
     115        }
     116
     117        /**
    99118         * Update the Kustom order after calculations from WooCommerce has run.
    100119         *
    … …  
    135154                        }
    136155                }
     156        }
     157
     158        /**
     159         * Add the cart total to the checkout fragments.
     160         *
     161         * @param array $fragments The checkout fragments.
     162         *
     163         * @return array
     164         */
     165        public function add_order_total_fragment( $fragments ) {
     166                if ( 'kco' !== WC()->session->get( 'chosen_payment_method' ) ) {
     167                        return $fragments;
     168                }
     169
     170                $fragments['kco_order_total'] = (string) WC()->cart->get_total( 'edit' );
     171
     172                return $fragments;
    137173        }
    138174
  • klarna-checkout-for-woocommerce/trunk/classes/class-kco-gateway.php

    r3767993 r3783345  
    77
    88use Krokedil\KustomCheckout\CheckoutFlow\CheckoutFlow;
     9use Krokedil\KustomCheckout\ShippingAssistant\Settings as ShippingAssistantSettings;
    910use Krokedil\KustomCheckout\Utility\BlocksUtility;
    1011use Krokedil\KustomCheckout\Utility\SettingsUtility;
    … …  
    449450                                'is_order_received_page'          => is_order_received_page() ? 'yes' : 'no',
    450451                                'shipping_methods_in_iframe'      => $this->shipping_methods_in_iframe,
     452                                'ksa_enabled'                     => ShippingAssistantSettings::is_enabled() ? 'yes' : 'no',
    451453                                'required_fields_text'            => __( 'Please fill in all required checkout fields.', 'klarna-checkout-for-woocommerce' ),
    452454                                'email_exists'                    => $email_exists,
  • klarna-checkout-for-woocommerce/trunk/classes/requests/checkout/post/class-kco-request-update.php

    r3743403 r3783345  
    9191
    9292                if ( kco_wc_prefill_allowed() ) {
    93                         $request_body['billing_address'] = array(
    94                                 'email'             => WC()->checkout()->get_value( 'billing_email' ),
    95                                 'postal_code'       => WC()->checkout()->get_value( 'billing_postcode' ),
    96                                 'country'           => WC()->checkout()->get_value( 'billing_country' ),
    97                                 'phone'             => WC()->checkout()->get_value( 'billing_phone' ),
    98                                 'given_name'        => WC()->checkout()->get_value( 'billing_first_name' ),
    99                                 'family_name'       => WC()->checkout()->get_value( 'billing_last_name' ),
    100                                 'organization_name' => WC()->checkout()->get_value( 'billing_company' ),
    101                                 'street_address'    => WC()->checkout()->get_value( 'billing_address_1' ),
    102                                 'street_address2'   => WC()->checkout()->get_value( 'billing_address_2' ),
    103                                 'city'              => WC()->checkout()->get_value( 'billing_city' ),
    104                                 'region'            => WC()->checkout()->get_value( 'billing_state' ),
    105                         );
     93                        // Built the same way as when the order is created: only fields that have a value are sent, since Kustom keeps whatever it already stored for the fields we omit.
     94                        $billing_address = KCO_Request_Create::get_billing_address_from_customer();
    10695
    107                         $request_body['shipping_address'] = array(
    108                                 'postal_code'       => WC()->checkout()->get_value( 'shipping_postcode' ),
    109                                 'country'           => WC()->checkout()->get_value( 'shipping_country' ),
    110                                 'given_name'        => WC()->checkout()->get_value( 'shipping_first_name' ),
    111                                 'family_name'       => WC()->checkout()->get_value( 'shipping_last_name' ),
    112                                 'organization_name' => WC()->checkout()->get_value( 'shipping_company' ),
    113                                 'street_address'    => WC()->checkout()->get_value( 'shipping_address_1' ),
    114                                 'street_address2'   => WC()->checkout()->get_value( 'shipping_address_2' ),
    115                                 'city'              => WC()->checkout()->get_value( 'shipping_city' ),
    116                                 'region'            => WC()->checkout()->get_value( 'shipping_state' ),
    117                         );
     96                        if ( ! empty( $billing_address ) ) {
     97                                $request_body['billing_address'] = $billing_address;
     98                        }
    11899
    119                         $request_body['shipping_address'] = wp_parse_args( $request_body['billing_address'], $request_body['shipping_address'] ?? array() );
     100                        if ( 'yes' === ( $this->settings['allow_separate_shipping'] ?? 'no' ) ) {
     101                                $shipping_address = KCO_Request_Create::get_shipping_address_from_customer();
     102
     103                                if ( ! empty( $shipping_address ) ) {
     104                                        $request_body['shipping_address'] = $shipping_address;
     105                                }
     106                        } elseif ( ! empty( $billing_address ) ) {
     107                                $request_body['shipping_address'] = $billing_address;
     108                        }
    120109                }
    121110
  • klarna-checkout-for-woocommerce/trunk/composer-dependencies.json

    r3743403 r3783345  
    22    "require": {
    33        "php": ">=7.4",
    4         "krokedil/wp-api": "^1.2.0",
     4        "krokedil/wp-api": "1.2.0",
    55        "krokedil/woocommerce": "^1.0",
    66        "krokedil/shipping": "2.4.0",
    77        "krokedil/support": "1.0.4",
    8         "krokedil/settings-page": "^1.1.0"
     8        "krokedil/settings-page": "1.3.8"
    99    },
    1010    "config": {
  • klarna-checkout-for-woocommerce/trunk/composer-dependencies.lock

    r3743403 r3783345  
    55        "This file is @generated automatically"
    66    ],
    7     "content-hash": "e54adb7c33248f480bac51b2f22597b1",
     7    "content-hash": "b8aee8296192d0086586b33de8b773f8",
    88    "packages": [
    99        {
    1010            "name": "krokedil/settings-page",
    11             "version": "1.3.6",
     11            "version": "1.3.8",
    1212            "source": {
    1313                "type": "git",
    1414                "url": "https://github.com/krokedil/settings-page.git",
    15                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f"
    16             },
    17             "dist": {
    18                 "type": "zip",
    19                 "url": "https://api.github.com/repos/krokedil/settings-page/zipball/9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
    20                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
     15                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63"
     16            },
     17            "dist": {
     18                "type": "zip",
     19                "url": "https://api.github.com/repos/krokedil/settings-page/zipball/8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
     20                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
    2121                "shasum": ""
    2222            },
    … …  
    6262                    "./vendor/bin/phpstan analyse --memory-limit=2G"
    6363                ],
     64                "phpstan:baseline": [
     65                    "./vendor/bin/phpstan analyse --memory-limit=2G --generate-baseline"
     66                ],
    6467                "lint": [
    6568                    "vendor/bin/phpcs . --standard=phpcs.xml --extensions=php -q -s"
    … …  
    8689            "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    8790            "support": {
    88                 "source": "https://github.com/krokedil/settings-page/tree/1.3.6",
     91                "source": "https://github.com/krokedil/settings-page/tree/1.3.8",
    8992                "issues": "https://github.com/krokedil/settings-page/issues"
    9093            },
    91             "time": "2026-08-14T11:07:15+00:00"
     94            "time": "2026-10-29T09:53:20+00:00"
    9295        },
    9396        {
  • klarna-checkout-for-woocommerce/trunk/composer.lock

    r3767993 r3783345  
    73427342        "php": "8.0"
    73437343    },
    7344     "plugin-api-version": "2.6.0"
     7344    "plugin-api-version": "2.9.0"
    73457345}
  • klarna-checkout-for-woocommerce/trunk/dependencies/autoload.php

    r3743403 r3783345  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1::getLoader();
     22return ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8::getLoader();
  • klarna-checkout-for-woocommerce/trunk/dependencies/composer/autoload_real.php

    r3743403 r3783345  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1
     5class ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8
    66{
    77    private static $loader;
    … …  
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInite54adb7c33248f480bac51b2f22597b1', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInitb8aee8296192d0086586b33de8b773f8', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInite54adb7c33248f480bac51b2f22597b1::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInitb8aee8296192d0086586b33de8b773f8::getInitializer($loader));
    3333
    3434        $loader->register(true);
  • klarna-checkout-for-woocommerce/trunk/dependencies/composer/autoload_static.php

    r3743403 r3783345  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInite54adb7c33248f480bac51b2f22597b1
     7class ComposerStaticInitb8aee8296192d0086586b33de8b773f8
    88{
    99    public static $prefixLengthsPsr4 = array (
    … …  
    133133    {
    134134        return \Closure::bind(function () use ($loader) {
    135             $loader->prefixLengthsPsr4 = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$prefixLengthsPsr4;
    136             $loader->prefixDirsPsr4 = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$prefixDirsPsr4;
    137             $loader->classMap = ComposerStaticInite54adb7c33248f480bac51b2f22597b1::$classMap;
     135            $loader->prefixLengthsPsr4 = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$prefixLengthsPsr4;
     136            $loader->prefixDirsPsr4 = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$prefixDirsPsr4;
     137            $loader->classMap = ComposerStaticInitb8aee8296192d0086586b33de8b773f8::$classMap;
    138138
    139139        }, null, ClassLoader::class);
  • klarna-checkout-for-woocommerce/trunk/dependencies/composer/installed.json

    r3743403 r3783345  
    33        {
    44            "name": "krokedil\/settings-page",
    5             "version": "1.3.6",
    6             "version_normalized": "1.3.6.0",
     5            "version": "1.3.8",
     6            "version_normalized": "1.3.8.0",
    77            "source": {
    88                "type": "git",
    99                "url": "https:\/\/github.com\/krokedil\/settings-page.git",
    10                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f"
    11             },
    12             "dist": {
    13                 "type": "zip",
    14                 "url": "https:\/\/api.github.com\/repos\/krokedil\/settings-page\/zipball\/9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
    15                 "reference": "9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f",
     10                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63"
     11            },
     12            "dist": {
     13                "type": "zip",
     14                "url": "https:\/\/api.github.com\/repos\/krokedil\/settings-page\/zipball\/8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
     15                "reference": "8ba11d2e62dfc0b63d75ec295374ea183fcdac63",
    1616                "shasum": ""
    1717            },
    … …  
    2525                "wpackagist-theme\/storefront": "4.6.2"
    2626            },
    27             "time": "2026-08-14T11:07:15+00:00",
     27            "time": "2026-10-29T09:53:20+00:00",
    2828            "type": "library",
    2929            "extra": {
    … …  
    5959                    ".\/vendor\/bin\/phpstan analyse --memory-limit=2G"
    6060                ],
     61                "phpstan:baseline": [
     62                    ".\/vendor\/bin\/phpstan analyse --memory-limit=2G --generate-baseline"
     63                ],
    6164                "lint": [
    6265                    "vendor\/bin\/phpcs . --standard=phpcs.xml --extensions=php -q -s"
    … …  
    8386            "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    8487            "support": {
    85                 "source": "https:\/\/github.com\/krokedil\/settings-page\/tree\/1.3.6",
     88                "source": "https:\/\/github.com\/krokedil\/settings-page\/tree\/1.3.8",
    8689                "issues": "https:\/\/github.com\/krokedil\/settings-page\/issues"
    8790            },
  • klarna-checkout-for-woocommerce/trunk/dependencies/composer/installed.php

    r3767993 r3783345  
    33namespace KrokedilKlarnaCheckoutDeps;
    44
    5 return array('root' => array('name' => '__root__', 'pretty_version' => '2.24.0', 'version' => '2.24.0.0', 'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '2.24.0', 'version' => '2.24.0.0', 'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.6', 'version' => '1.3.6.0', 'reference' => '9269cc7fd1ab62acb2ba2ca459e53ca34dfad21f', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/shipping' => array('pretty_version' => '2.4.0', 'version' => '2.4.0.0', 'reference' => '12c7e30742725174ae8cdb2839b873aa40a29817', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/shipping', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.4', 'version' => '1.0.4.0', 'reference' => '96da75792434a2553c6af9e891e646705fd33e7c', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/woocommerce' => array('pretty_version' => '1.9.2', 'version' => '1.9.2.0', 'reference' => '6c38cf569df5eeb3598f206d449eca86ae9ac402', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/woocommerce', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/wp-api' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '3473dd2fb6b31ed5060ecd69877c98b5287ebe48', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/wp-api', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '707984727bd5b2b670e59559d3ed2500240cf875', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(0 => '2.0.x-dev'), 'dev_requirement' => \false)));
     5return array('root' => array('name' => '__root__', 'pretty_version' => '2.24.1', 'version' => '2.24.1.0', 'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '2.24.1', 'version' => '2.24.1.0', 'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.8', 'version' => '1.3.8.0', 'reference' => '8ba11d2e62dfc0b63d75ec295374ea183fcdac63', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/shipping' => array('pretty_version' => '2.4.0', 'version' => '2.4.0.0', 'reference' => '12c7e30742725174ae8cdb2839b873aa40a29817', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/shipping', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.4', 'version' => '1.0.4.0', 'reference' => '96da75792434a2553c6af9e891e646705fd33e7c', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/woocommerce' => array('pretty_version' => '1.9.2', 'version' => '1.9.2.0', 'reference' => '6c38cf569df5eeb3598f206d449eca86ae9ac402', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/woocommerce', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/wp-api' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '3473dd2fb6b31ed5060ecd69877c98b5287ebe48', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/wp-api', 'aliases' => array(), 'dev_requirement' => \false), 'psr/container' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '707984727bd5b2b670e59559d3ed2500240cf875', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(0 => '2.0.x-dev'), 'dev_requirement' => \false)));
  • klarna-checkout-for-woocommerce/trunk/dependencies/krokedil/settings-page/assets/js/support.js

    r3454335 r3783345  
    66      params: {
    77        beaconId: "",
    8         systemReport: {},
    98      },
    109      init: function () {
    … …  
    3938        }
    4039
    41         if (!this.params.systemReport) {
     40
     41        const systemReport = this.generateReport();
     42        if (!systemReport) {
    4243          return;
    4344        }
    4445
    45         const systemReportFile = this.objToFile(
    46           this.params.systemReport,
    47           "system-report.json"
    48         );
     46        const systemReportFile = new File([systemReport], "system-report.txt", {
     47          type: "text/plain",
     48          lastModified: Date.now(),
     49        });
    4950
    5051        window.Beacon("prefill", {
    … …  
    6970      },
    7071
    71       objToFile: function (obj, fileName) {
    72         const stringVal = JSON.stringify(obj);
     72      // Port of WooCommerce's generateReport (assets/js/admin/system-status.js), run on the hidden status report.
     73      generateReport: function () {
     74        let report = "";
    7375
    74         return new File([stringVal], fileName, {
    75           type: "application/json",
    76           lastModified: Date.now(),
     76        $("#krokedil-status-report .wc_status_table thead, #krokedil-status-report .wc_status_table tbody").each(function () {
     77          if ($(this).is("thead")) {
     78            const label = $(this).find("th:eq(0)").data("exportLabel") || $(this).text();
     79            report = report + "\n### " + label.trim() + " ###\n\n";
     80            return;
     81          }
     82
     83          $("tr", $(this)).each(function () {
     84            const label = $(this).find("td:eq(0)").data("exportLabel") || $(this).find("td:eq(0)").text();
     85            const the_name = label.trim().replace(/(<([^>]+)>)/gi, ""); // Remove HTML.
     86
     87            const $value_html = $(this).find("td:eq(2)").clone();
     88            $value_html.find(".private").remove();
     89            $value_html.find(".dashicons-yes").replaceWith("&#10004;");
     90            $value_html.find(".dashicons-no-alt, .dashicons-warning").replaceWith("&#10060;");
     91
     92            let the_value = $value_html.text().trim();
     93            const value_array = the_value.split(", ");
     94
     95            // Put each item of a comma separated list (e.g. plugins) on its own line.
     96            if (value_array.length > 1) {
     97              the_value = value_array.join("\n") + "\n";
     98            }
     99
     100            if (the_name || the_value) {
     101              report = report + the_name + ": " + the_value + "\n";
     102            } else {
     103              report = report + "\n";
     104            }
     105          });
    77106        });
     107
     108        return report;
    78109      },
    79110
  • klarna-checkout-for-woocommerce/trunk/dependencies/krokedil/settings-page/changelog.md

    r3696507 r3783345  
    99
    1010------------------
     11## [1.3.8] - 2026-10-29
     12### Changed
     13
     14* The support ticket now attaches the WooCommerce system status report as text (`system-report.txt`), the same report as WooCommerce's "Get system report" button, including sections added by other plugins. It replaces the JSON export from the `/wc/v3/system_status` REST endpoint.
     15
     16## [1.3.7] - 2026-09-28
     17### Fixed
     18
     19* Fixed an "Undefined array key" PHP warning that could occur with certain settings configurations.
     20
    1121## [1.3.6] - 2026-08-14
    1222### Fixed
  • klarna-checkout-for-woocommerce/trunk/dependencies/krokedil/settings-page/composer.json

    r3696507 r3783345  
    22    "name": "krokedil\/settings-page",
    33    "description": "A package to help setup settings pages in WordPress and WooCommerce for Krokedil plugins to add the Addons and Support tabs",
    4     "version": "1.3.6",
     4    "version": "1.3.8",
    55    "type": "library",
    66    "require-dev": {
    … …  
    6363        "makepot": "wp --allow-root i18n make-pot .\/src .\/languages\/krokedil-settings.pot --domain=krokedil-settings",
    6464        "phpstan": ".\/vendor\/bin\/phpstan analyse --memory-limit=2G",
     65        "phpstan:baseline": ".\/vendor\/bin\/phpstan analyse --memory-limit=2G --generate-baseline",
    6566        "lint": "vendor\/bin\/phpcs . --standard=phpcs.xml --extensions=php -q -s",
    6667        "lint:fix": "vendor\/bin\/phpcbf . --standard=phpcs.xml --extensions=php -q -s",
    6768        "lint:changes": "git diff --name-only HEAD~1 | grep '\\.php$' | xargs vendor\/bin\/phpcs --standard=phpcs.xml --extensions=php -q -s",
    6869        "lint:fix:changes": "git diff --name-only HEAD~1 | grep '\\.php$' | xargs vendor\/bin\/phpcbf --standard=phpcs.xml --extensions=php -q -s"
     70    },
     71    "scripts-descriptions": {
     72        "phpstan": "Run PHPStan static analysis at the level set in phpstan.neon. Findings that predate the analysis are suppressed by phpstan-baseline.neon, so a failure means new code introduced it.",
     73        "phpstan:baseline": "Regenerate phpstan-baseline.neon from the current findings. Only run this when intentionally accepting new suppressions, otherwise fix the reported errors instead."
    6974    }
    7075}
  • klarna-checkout-for-woocommerce/trunk/dependencies/krokedil/settings-page/src/Addons.php

    r3696507 r3783345  
    119119        add_thickbox();
    120120        // Required for the plugin installer to work.
    121         $addons = $this->addons['items'];
    122         $content = $this->addons['content'];
     121        $addons = $this->addons['items'] ?? array();
     122        $content = $this->addons['content'] ?? array();
    123123        ?>
    124124                <div class="krokedil_addons">
    125                 <div class="krokedil_addons__info">
    126                                 <?php
    127         foreach ($content as $item) {
    128             ?>
     125                        <?php
     126        if (!empty($content)) {
     127            ?>
     128                        <div class="krokedil_addons__info">
     129                                <?php
     130            foreach ($content as $item) {
     131                ?>
    129132                                        <?php
    130             echo wp_kses_post(self::print_content($item));
    131             ?>
    132                                 <?php
    133         }
    134         ?>
    135                         </div>
     133                echo wp_kses_post(self::print_content($item));
     134                ?>
     135                                <?php
     136            }
     137            ?>
     138                        </div>
     139                        <?php
     140        }
     141        ?>
    136142
    137143                        <?php
    138144        // translators: %s is the plugin name.
    139145        ?>
     146                        <?php
     147        if (!empty($addons)) {
     148            ?>
    140149                        <div class='krokedil_addons__cards'>
    141150                                <?php
    142         foreach ($addons as $addon) {
    143             ?>
     151            foreach ($addons as $addon) {
     152                ?>
    144153                                        <?php
    145             $this->print_addon_card($addon);
    146             ?>
    147                                 <?php
    148         }
    149         ?>
    150                         </div>
     154                $this->print_addon_card($addon);
     155                ?>
     156                                <?php
     157            }
     158            ?>
     159                        </div>
     160                        <?php
     161        }
     162        ?>
    151163                </div>
    152164                <?php
  • klarna-checkout-for-woocommerce/trunk/dependencies/krokedil/settings-page/src/Support.php

    r3696507 r3783345  
    6161        // Load CSS.
    6262        wp_enqueue_style('krokedil-support-page');
    63         // If the WC Version is 9.0 or above, get the container for the RestAPiUtil, else us the WC()->api class property.
    64         // The deprecation notice says 9.1.0, but the WC()->api property is not set in 9.0.0.
    65         // @see https://github.com/woocommerce/woocommerce/blob/5690850e47284b3a9afd4e61dec01121159ca9e8/plugins/woocommerce/src/Internal/Utilities/LegacyRestApiStub.php#L183-L187.
    66         $legacy_wc = \version_compare(WC_VERSION, '9.0', '<=');
    67         $system_report = '';
    68         if ($legacy_wc) {
    69             $system_report = WC()->api->get_endpoint_data('/wc/v3/system_status');
    70         } elseif (\class_exists(\Automattic\WooCommerce\Utilities\RestApiUtil::class)) {
    71             $system_report = wc_get_container()->get(\Automattic\WooCommerce\Utilities\RestApiUtil::class)->get_endpoint_data('/wc/v3/system_status');
    72         }
    7363        $beacon_id = '9c22f83e-3611-42aa-a148-1ca06de53566';
    7464        // Localize the support scrip.
    75         wp_localize_script('krokedil-support-page', 'krokedil_support_params', array('systemReport' => $system_report, 'beaconId' => $beacon_id));
     65        wp_localize_script('krokedil-support-page', 'krokedil_support_params', array('beaconId' => $beacon_id));
    7666        // Load JS. Only add the inline script if there is one, since wp_add_inline_script does not accept empty data.
    7767        $beacon_script = self::hs_beacon_script($this->support['use_helpscout'] ?? 'yes');
    … …  
    113103            ?></button>
    114104                                        <?php
     105            // Hidden WooCommerce status report, turned into the text report by support.js and attached to the Beacon.
     106            ?>
     107                                        <div id="krokedil-status-report" hidden>
     108                                                <?php
     109            if (\class_exists(\WC_Admin_Status::class)) {
     110                \WC_Admin_Status::status_report();
     111            }
     112            ?>
     113                                        </div>
     114                                        <?php
    115115        }
    116116        ?>
  • klarna-checkout-for-woocommerce/trunk/includes/kco-functions.php

    r3767993 r3783345  
    609609        WC()->session->__unset( 'kco_wc_prefill_consent' );
    610610        WC()->session->__unset( 'kco_wc_order_id' );
     611        WC()->session->__unset( 'kco_wc_extension_data' );
    611612}
    612613
  • klarna-checkout-for-woocommerce/trunk/klarna-checkout-for-woocommerce.php

    r3767993 r3783345  
    66 * Author: Kustom
    77 * Author URI: https://klarna.com/
    8  * Version: 2.24.0
     8 * Version: 2.24.1
    99 * Text Domain: klarna-checkout-for-woocommerce
    1010 * Domain Path: /languages
    … …  
    4545 * Required minimums and constants
    4646 */
    47 define( 'KCO_WC_VERSION', '2.24.0' );
     47define( 'KCO_WC_VERSION', '2.24.1' );
    4848define( 'KCO_WC_MIN_PHP_VER', '5.6.0' );
    4949define( 'KCO_WC_MIN_WC_VER', '3.9.0' );
  • klarna-checkout-for-woocommerce/trunk/languages/klarna-checkout-for-woocommerce.pot

    r3767993 r3783345  
    99"Language-Team: Krokedil <info@krokedil.se>\n"
    1010"Last-Translator: Krokedil <info@krokedil.se>\n"
    11 "POT-Creation-Date: 2026-10-27 08:07+0000\n"
     11"POT-Creation-Date: 2026-11-04 07:59+0000\n"
    1212"Report-Msgid-Bugs-To: http://krokedil.se\n"
    1313"X-Poedit-Basepath: ..\n"
    … …  
    3535
    3636#. translators: Kustom order ID.
    37 #: ../classes/class-kco-api-callbacks.php:143, ../includes/kco-functions.php:696
     37#: ../classes/class-kco-api-callbacks.php:143, ../includes/kco-functions.php:697
    3838msgid "Kustom order is under review, order ID: %s."
    3939msgstr ""
    … …  
    4343msgstr ""
    4444
    45 #: ../classes/class-kco-api-callbacks.php:129, ../includes/kco-functions.php:681
     45#: ../classes/class-kco-api-callbacks.php:129, ../includes/kco-functions.php:682
    4646msgid "Payment via Kustom Checkout, order ID: %s"
    4747msgstr ""
    4848
    49 #: ../classes/class-kco-checkout.php:224
     49#: ../classes/class-kco-checkout.php:260
    5050msgid "The shipping methods have been changed during the checkout process. Please verify your selected shipping method and try again."
    5151msgstr ""
    … …  
    448448msgstr ""
    449449
    450 #: ../classes/class-kco-gateway.php:48, ../classes/class-kco-gateway.php:823, ../classes/class-kco-gateway.php:825, ../classes/class-kco-gateway.php:827, ../classes/class-kco-gateway.php:829, ../includes/admin/views/status-report.php:17
     450#: ../classes/class-kco-gateway.php:49, ../classes/class-kco-gateway.php:825, ../classes/class-kco-gateway.php:827, ../classes/class-kco-gateway.php:829, ../classes/class-kco-gateway.php:831, ../includes/admin/views/status-report.php:17
    451451msgid "Kustom Checkout"
    452452msgstr ""
    453453
    454 #: ../classes/class-kco-gateway.php:49
     454#: ../classes/class-kco-gateway.php:50
    455455msgid "The current Kustom Checkout replaces standard WooCommerce checkout page."
    456456msgstr ""
    457457
    458 #: ../classes/class-kco-gateway.php:142
     458#: ../classes/class-kco-gateway.php:143
    459459msgid "The Kustom order id could not be retrieved from the session. Please try again."
    460460msgstr ""
    461461
    462 #: ../classes/class-kco-gateway.php:149
     462#: ../classes/class-kco-gateway.php:150
    463463msgid "The Kustom order could not be retrieved from the session. Please try again."
    464464msgstr ""
    465465
    466466#. translators: %s is the field name.
    467 #: ../classes/class-kco-gateway.php:210
     467#: ../classes/class-kco-gateway.php:211
    468468msgid "Billing %s does not match Kustom order."
    469469msgstr ""
    470470
    471471#. translators: %s is the field name.
    472 #: ../classes/class-kco-gateway.php:222
     472#: ../classes/class-kco-gateway.php:223
    473473msgid "Shipping %s does not match Kustom order."
    474474msgstr ""
    475475
    476 #: ../classes/class-kco-gateway.php:322
     476#: ../classes/class-kco-gateway.php:323
    477477msgid "Could not load the enhanced settings page. Showing the standard settings instead."
    478478msgstr ""
    479479
    480 #: ../classes/class-kco-gateway.php:451
     480#: ../classes/class-kco-gateway.php:453
    481481msgid "Please fill in all required checkout fields."
    482482msgstr ""
    483483
    484 #: ../classes/class-kco-gateway.php:454
     484#: ../classes/class-kco-gateway.php:456
    485485msgid "Please try again, something went wrong with processing your order."
    486486msgstr ""
    487487
    488 #: ../classes/class-kco-gateway.php:562
     488#: ../classes/class-kco-gateway.php:564
    489489msgid "Order address should not be changed and any changes you make will not be reflected in Kustom system."
    490490msgstr ""
    491491
    492 #: ../classes/class-kco-gateway.php:621
     492#: ../classes/class-kco-gateway.php:623
    493493msgid "Organisation number:"
    494494msgstr ""
    495495
    496 #: ../classes/class-kco-gateway.php:643, ../classes/class-kco-gateway.php:665
     496#: ../classes/class-kco-gateway.php:645, ../classes/class-kco-gateway.php:667
    497497msgid "Reference:"
    498498msgstr ""
    499499
    500 #: ../classes/class-kco-gateway.php:730
     500#: ../classes/class-kco-gateway.php:732
    501501msgid "Kustom did not accept the new order amount, the order has not been updated"
    502502msgstr ""
    … …  
    547547msgstr ""
    548548
    549 #: ../includes/kco-functions.php:707
     549#: ../includes/kco-functions.php:708
    550550msgid "Waiting for verification from Kustom's push notification"
    551551msgstr ""
    552552
    553 #: ../includes/kco-functions.php:702
     553#: ../includes/kco-functions.php:703
    554554msgid "Kustom Checkout order was rejected"
    555555msgstr ""
    556556
    557557#. translators: 1: Kustom order total, 2: WooCommerce order total.
    558 #: ../includes/kco-functions.php:752
     558#: ../includes/kco-functions.php:753
    559559msgid "Kustom order total (%1$s) does not match WooCommerce order total (%2$s). Please verify the order with Kustom before processing."
    560560msgstr ""
    561561
    562 #: ../includes/kco-functions.php:782
     562#: ../includes/kco-functions.php:783
    563563msgid "A mismatch between the WooCommerce and Kustom orders was identified. Please verify the order in the Kustom merchant portal before processing."
    564564msgstr ""
    565565
    566566#. translators: %1$s: Product name, %2$d: Expected quantity, %3$d: Found quantity.
    567 #: ../includes/kco-functions.php:833
     567#: ../includes/kco-functions.php:834
    568568msgid "The product \"%1$s\" has a quantity mismatch. Expected %2$d found %3$d."
    569569msgstr ""
    570570
    571571#. translators: %s: Product name.
    572 #: ../includes/kco-functions.php:843
     572#: ../includes/kco-functions.php:844
    573573msgid "The product \"%s\" was not found in the Kustom order."
    574574msgstr ""
  • klarna-checkout-for-woocommerce/trunk/readme.txt

    r3767993 r3783345  
    88WC requires at least: 9.7.0
    99WC tested up to: 11.2.1
    10 Stable tag: 2.24.0
     10Stable tag: 2.24.1
    1111License: GPLv3 or later
    1212License URI: http://www.gnu.org/licenses/gpl-3.0.html
    … …  
    5151
    5252== Changelog ==
     53= 2026-11-04    - version 2.24.1 =
     54* Fix           - Fixed an issue where an incomplete address could be sent to Kustom during checkout, preventing the customer from completing their purchase.
     55* Fix           - Fixed fields added by other plugins to the block checkout, such as the WooCommerce Smart Coupons gift card form, being hidden and not savedto the order when Kustom is selected.
     56* Fix           - Fixed the checkout script stopping part-way through initialisation when another script on the page declares a global variable named "i".
     57* Fix           - Fixed the Kustom Checkout iframe showing an outdated order total when the cart total changed outside the iframe before the customer had entered an address, for example when shipping was changed or a coupon was applied.
     58* Fix           - Fixed the shipping option selected in Kustom not being applied to WooCommerce when the "Suppress third party discount plugins" setting in Woo Discount Rules was enabled. WooCommerce kept another shipping method, which caused order total mismatches with Kustom Shipping Assistant.
     59
    5360= 2026-10-27    - version 2.24.0 =
    5461* Feature       - Added support for adding Kustom express buttons to the cart, the block cart and checkout, product pages, and a new shortcode and block.
  • klarna-checkout-for-woocommerce/trunk/vendor/composer/installed.php

    r3767993 r3783345  
    22    'root' => array(
    33        'name' => '__root__',
    4         'pretty_version' => '2.24.0',
    5         'version' => '2.24.0.0',
    6         'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d',
     4        'pretty_version' => '2.24.1',
     5        'version' => '2.24.1.0',
     6        'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1212    'versions' => array(
    1313        '__root__' => array(
    14             'pretty_version' => '2.24.0',
    15             'version' => '2.24.0.0',
    16             'reference' => 'd70fe31cf6df93ea245529852d2b8cd1efdd427d',
     14            'pretty_version' => '2.24.1',
     15            'version' => '2.24.1.0',
     16            'reference' => 'e210b713ccf1232d0758ec22127f6b30ba3560d5',
    1717            'type' => 'library',
    1818            'install_path' => __DIR__ . '/../../',
Note: See TracChangeset for help on using the changeset viewer.