Plugin Directory

Changeset 3705285


Ignore:
Timestamp:
09/21/2026 09:49:07 AM (8 weeks ago)
Author:
swedbankpay
Message:

Update to version 4.6.2 from GitHub

Location:
swedbank-pay-payment-menu
Files:
150 added
20 deleted
32 edited
1 copied

Legend:

Unmodified
Added
Removed
  • swedbank-pay-payment-menu/tags/4.6.2/assets/js/wc-intl-tel.js

    r3057342 r3705285  
    1 jQuery(document).ready(function ($) {
    2     $(document.body).on('update_checkout', function () {
    3         initTelInput();
    4     });
     1/**
     2 * Enhances the checkout billing phone field with intl-tel-input.
     3 *
     4 * This file is loaded as an ES module (see Swedbank_Intl_Tel::script_loader_tag)
     5 * and pulls the library in with a dynamic import. That is deliberate: the
     6 * library's classic build declares a top-level `var intlTelInput`, which lands
     7 * on `window`, so two plugins shipping different versions would clobber each
     8 * other. An imported binding is module-scoped, so nothing here reads or writes
     9 * the global and we cannot collide with anyone else's copy.
     10 */
     11( function () {
     12        'use strict';
    513
    6     initTelInput();
     14        var config = window.WC_Gateway_Swedbank_Pay_Intl_Tel;
    715
    8     function initTelInput() {
    9         const telInput = document.querySelector("#billing_phone");
     16        if ( ! config || ! config.lib_script ) {
     17                return;
     18        }
    1019
    11         var iti = window.intlTelInput(telInput, {
    12                 utilsScript: WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,
    13                 preferredCountries: [WC_Gateway_Swedbank_Pay_Intl_Tel.country, 'SE', 'NO', 'FI', 'DK'],
    14                 defaultToFirstCountry: true,
    15                 nationalMode: false,
    16                 formatOnDisplay: true,
    17                 customContainer: 'form-row-wide'
    18             }
    19         );
     20        /**
     21         * Country name translation goes through Intl.DisplayNames, which throws on a
     22         * malformed tag. The library catches that and then blanks every country
     23         * name, so validate before handing the tag over.
     24         *
     25         * @param {string} tag Locale tag.
     26         * @return {string} A usable locale tag.
     27         */
     28        function safeLocale( tag ) {
     29                try {
     30                        return Intl.getCanonicalLocales( tag ).length ? tag : 'en';
     31                } catch ( e ) {
     32                        return 'en';
     33                }
     34        }
    2035
    21         telInput.addEventListener('keyup', formatIntlTelInput);
    22         telInput.addEventListener('change', formatIntlTelInput);
     36        /**
     37         * Load the translated interface strings, if we ship any for this site's
     38         * language. A failure here must not stop the field from initialising.
     39         *
     40         * @return {Promise<Object>} Translations, or an empty object.
     41         */
     42        function loadTranslations() {
     43                if ( ! config.locale_script ) {
     44                        return Promise.resolve( {} );
     45                }
    2346
    24         function formatIntlTelInput() {
    25             if (typeof intlTelInputUtils !== 'undefined') { // utils are lazy loaded, so must check
    26                 var currentText = iti.getNumber(intlTelInputUtils.numberFormat.E164);
    27                 if (typeof currentText === 'string') { // sometimes the currentText is an object :)
    28                     iti.setNumber(currentText); // will autoformat because of formatOnDisplay=true
    29                 }
    30             }
    31         }
    32     }
    33 });
     47                return import( config.locale_script )
     48                        .then( function ( module ) {
     49                                return module.default || {};
     50                        } )
     51                        .catch( function () {
     52                                return {};
     53                        } );
     54        }
     55
     56        var enhanced = [];
     57
     58        /**
     59         * Tear down instances whose field has been removed from the page. The
     60         * library holds every instance in a map of its own, so a checkout plugin
     61         * that re-renders the address fields would otherwise pile them up.
     62         */
     63        function dropDetached() {
     64                enhanced = enhanced.filter(
     65                        function ( element ) {
     66                                if ( document.contains( element ) ) {
     67                                        return true;
     68                                }
     69
     70                                if ( element.iti ) {
     71                                        element.iti.destroy();
     72                                }
     73
     74                                return false;
     75                        }
     76                );
     77        }
     78
     79        /**
     80         * Initialise the field, unless it is already initialised. The library keeps
     81         * its instance on the element itself, so that doubles as the guard.
     82         *
     83         * @param {Function} intlTelInput The library.
     84         * @param {Object}   translations Interface translations.
     85         */
     86        function init( intlTelInput, translations ) {
     87                dropDetached();
     88
     89                var input = document.querySelector( '#billing_phone' );
     90
     91                if ( ! input || input.iti ) {
     92                        return;
     93                }
     94
     95                var iti = intlTelInput(
     96                        input,
     97                        {
     98                                initialCountry: config.country || '',
     99                                countryOrder: config.country_order || null,
     100                                countryNameLocale: safeLocale( config.name_locale || 'en' ),
     101                                uiTranslations: translations,
     102
     103                                separateDialCode: false,
     104                                numberDisplayFormat: 'INTERNATIONAL',
     105
     106                                // A scope class of our own, so our instances stay addressable if
     107                                // another plugin's intl-tel-input stylesheet ever bleeds in. The
     108                                // library applies it to the detached mobile selector too.
     109                                containerClass: 'form-row-wide swedbank-pay-iti',
     110
     111                                loadUtils: function () {
     112                                        return import( config.utils_script );
     113                                },
     114                        }
     115                );
     116
     117                enhanced.push( input );
     118
     119                /**
     120                 * Normalise the phone number to E.164 format.
     121                 */
     122                function normalise() {
     123                        if ( ! intlTelInput.utils ) {
     124                                return;
     125                        }
     126
     127                        var number = iti.getNumber( 'E164' );
     128
     129                        // Compared the way wc_sanitize_phone_number() will.
     130                        if ( number && 0 === number.indexOf( '+' ) && number !== input.value.replace( /[^\d+]/g, '' ) ) {
     131                                iti.setNumber( number );
     132                        }
     133                }
     134
     135                input.addEventListener( 'countrychange', normalise );
     136                input.addEventListener( 'change', normalise );
     137                input.addEventListener( 'blur', normalise );
     138
     139                // Keep the selected country in step with the billing country, so the
     140                // number the customer types is interpreted the same way the server will
     141                // interpret it.
     142                var billingCountry = document.querySelector( '#billing_country' );
     143                if ( billingCountry ) {
     144                        billingCountry.addEventListener(
     145                                'change',
     146                                function () {
     147                                        if ( ! input.value && billingCountry.value ) {
     148                                                iti.setSelectedCountry( billingCountry.value.toLowerCase() );
     149                                        }
     150                                }
     151                        );
     152                }
     153        }
     154
     155        Promise.all( [ import( config.lib_script ), loadTranslations() ] )
     156                .then(
     157                        function ( results ) {
     158                                var intlTelInput = results[0].default;
     159                                var translations = results[1];
     160
     161                                init( intlTelInput, translations );
     162
     163                                // Some checkout plugins re-render the address fields. The
     164                                // `input.iti` guard above makes this idempotent. Note that
     165                                // `updated_checkout` is synthesised by jQuery and so never
     166                                // reaches addEventListener().
     167                                if ( window.jQuery ) {
     168                                        window.jQuery( document.body ).on(
     169                                                'updated_checkout',
     170                                                function () {
     171                                                        init( intlTelInput, translations );
     172                                                }
     173                                        );
     174                                }
     175                        }
     176                )
     177                .catch(
     178                        function ( error ) {
     179                                // A CDN plugin rewriting plugins_url() to a host without CORS
     180                                // headers is the likely cause -- module imports are fetched in
     181                                // CORS mode, unlike classic scripts. Leave the plain field in
     182                                // place rather than failing silently.
     183                                window.console.warn( 'Swedbank Pay: could not load intl-tel-input.', error );
     184                        }
     185                );
     186}() );
  • swedbank-pay-payment-menu/tags/4.6.2/assets/js/wc-intl-tel.min.js

    r3407993 r3705285  
    1 jQuery(document).ready(function(t){function e(){const t=document.querySelector("#billing_phone");var e=window.intlTelInput(t,{utilsScript:WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,preferredCountries:[WC_Gateway_Swedbank_Pay_Intl_Tel.country,"SE","NO","FI","DK"],defaultToFirstCountry:!0,nationalMode:!1,formatOnDisplay:!0,customContainer:"form-row-wide"});function n(){if("undefined"!=typeof intlTelInputUtils){var t=e.getNumber(intlTelInputUtils.numberFormat.E164);"string"==typeof t&&e.setNumber(t)}}t.addEventListener("keyup",n),t.addEventListener("change",n)}t(document.body).on("update_checkout",function(){e()}),e()});
     1!function(){"use strict";var e=window.WC_Gateway_Swedbank_Pay_Intl_Tel;if(e&&e.lib_script){var n=[];Promise.all([import(e.lib_script),e.locale_script?import(e.locale_script).then(function(e){return e.default||{}}).catch(function(){return{}}):Promise.resolve({})]).then(function(e){var n=e[0].default,t=e[1];r(n,t),window.jQuery&&window.jQuery(document.body).on("updated_checkout",function(){r(n,t)})}).catch(function(e){window.console.warn("Swedbank Pay: could not load intl-tel-input.",e)})}function t(e){try{return Intl.getCanonicalLocales(e).length?e:"en"}catch(e){return"en"}}function r(r,i){n=n.filter(function(e){return!!document.contains(e)||(e.iti&&e.iti.destroy(),!1)});var o=document.querySelector("#billing_phone");if(o&&!o.iti){var a=r(o,{initialCountry:e.country||"",countryOrder:e.country_order||null,countryNameLocale:t(e.name_locale||"en"),uiTranslations:i,separateDialCode:!1,numberDisplayFormat:"INTERNATIONAL",containerClass:"form-row-wide swedbank-pay-iti",loadUtils:function(){return import(e.utils_script)}});n.push(o),o.addEventListener("countrychange",c),o.addEventListener("change",c),o.addEventListener("blur",c);var u=document.querySelector("#billing_country");u&&u.addEventListener("change",function(){!o.value&&u.value&&a.setSelectedCountry(u.value.toLowerCase())})}function c(){if(r.utils){var e=a.getNumber("E164");e&&0===e.indexOf("+")&&e!==o.value.replace(/[^\d+]/g,"")&&a.setNumber(e)}}}}();
    22//# sourceMappingURL=wc-intl-tel.min.js.map
  • swedbank-pay-payment-menu/tags/4.6.2/assets/js/wc-intl-tel.min.js.map

    r3407993 r3705285  
    1 {"version":3,"file":"wc-intl-tel.min.js","names":["jQuery","document","ready","$","initTelInput","telInput","querySelector","iti","window","intlTelInput","utilsScript","WC_Gateway_Swedbank_Pay_Intl_Tel","utils_script","preferredCountries","country","defaultToFirstCountry","nationalMode","formatOnDisplay","customContainer","formatIntlTelInput","intlTelInputUtils","currentText","getNumber","numberFormat","E164","setNumber","addEventListener","body","on"],"sources":["wc-intl-tel.js"],"sourcesContent":["jQuery(document).ready(function ($) {\n    $(document.body).on('update_checkout', function () {\n        initTelInput();\n    });\n\n    initTelInput();\n\n    function initTelInput() {\n        const telInput = document.querySelector(\"#billing_phone\");\n\n        var iti = window.intlTelInput(telInput, {\n                utilsScript: WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,\n                preferredCountries: [WC_Gateway_Swedbank_Pay_Intl_Tel.country, 'SE', 'NO', 'FI', 'DK'],\n                defaultToFirstCountry: true,\n                nationalMode: false,\n                formatOnDisplay: true,\n                customContainer: 'form-row-wide'\n            }\n        );\n\n        telInput.addEventListener('keyup', formatIntlTelInput);\n        telInput.addEventListener('change', formatIntlTelInput);\n\n        function formatIntlTelInput() {\n            if (typeof intlTelInputUtils !== 'undefined') { // utils are lazy loaded, so must check\n                var currentText = iti.getNumber(intlTelInputUtils.numberFormat.E164);\n                if (typeof currentText === 'string') { // sometimes the currentText is an object :)\n                    iti.setNumber(currentText); // will autoformat because of formatOnDisplay=true\n                }\n            }\n        }\n    }\n});\n"],"mappings":"AAAAA,OAAOC,UAAUC,MAAM,SAAUC,GAO7B,SAASC,IACL,MAAMC,EAAWJ,SAASK,cAAc,kBAExC,IAAIC,EAAMC,OAAOC,aAAaJ,EAAU,CAChCK,YAAaC,iCAAiCC,aAC9CC,mBAAoB,CAACF,iCAAiCG,QAAS,KAAM,KAAM,KAAM,MACjFC,uBAAuB,EACvBC,cAAc,EACdC,iBAAiB,EACjBC,gBAAiB,kBAOzB,SAASC,IACL,GAAiC,oBAAtBC,kBAAmC,CAC1C,IAAIC,EAAcd,EAAIe,UAAUF,kBAAkBG,aAAaC,MACpC,iBAAhBH,GACPd,EAAIkB,UAAUJ,EAEtB,CACJ,CAVAhB,EAASqB,iBAAiB,QAASP,GACnCd,EAASqB,iBAAiB,SAAUP,EAUxC,CA9BAhB,EAAEF,SAAS0B,MAAMC,GAAG,kBAAmB,WACnCxB,GACJ,GAEAA,GA2BJ","ignoreList":[]}
     1{"version":3,"file":"wc-intl-tel.min.js","names":["config","window","WC_Gateway_Swedbank_Pay_Intl_Tel","lib_script","enhanced","Promise","all","import","locale_script","then","module","default","catch","resolve","results","intlTelInput","translations","init","jQuery","document","body","on","error","console","warn","safeLocale","tag","Intl","getCanonicalLocales","length","e","filter","element","contains","iti","destroy","input","querySelector","initialCountry","country","countryOrder","country_order","countryNameLocale","name_locale","uiTranslations","separateDialCode","numberDisplayFormat","containerClass","loadUtils","utils_script","push","addEventListener","normalise","billingCountry","value","setSelectedCountry","toLowerCase","utils","number","getNumber","indexOf","replace","setNumber"],"sources":["wc-intl-tel.js"],"sourcesContent":["/**\n * Enhances the checkout billing phone field with intl-tel-input.\n *\n * This file is loaded as an ES module (see Swedbank_Intl_Tel::script_loader_tag)\n * and pulls the library in with a dynamic import. That is deliberate: the\n * library's classic build declares a top-level `var intlTelInput`, which lands\n * on `window`, so two plugins shipping different versions would clobber each\n * other. An imported binding is module-scoped, so nothing here reads or writes\n * the global and we cannot collide with anyone else's copy.\n */\n( function () {\n\t'use strict';\n\n\tvar config = window.WC_Gateway_Swedbank_Pay_Intl_Tel;\n\n\tif ( ! config || ! config.lib_script ) {\n\t\treturn;\n\t}\n\n\t/**\n\t * Country name translation goes through Intl.DisplayNames, which throws on a\n\t * malformed tag. The library catches that and then blanks every country\n\t * name, so validate before handing the tag over.\n\t *\n\t * @param {string} tag Locale tag.\n\t * @return {string} A usable locale tag.\n\t */\n\tfunction safeLocale( tag ) {\n\t\ttry {\n\t\t\treturn Intl.getCanonicalLocales( tag ).length ? tag : 'en';\n\t\t} catch ( e ) {\n\t\t\treturn 'en';\n\t\t}\n\t}\n\n\t/**\n\t * Load the translated interface strings, if we ship any for this site's\n\t * language. A failure here must not stop the field from initialising.\n\t *\n\t * @return {Promise<Object>} Translations, or an empty object.\n\t */\n\tfunction loadTranslations() {\n\t\tif ( ! config.locale_script ) {\n\t\t\treturn Promise.resolve( {} );\n\t\t}\n\n\t\treturn import( config.locale_script )\n\t\t\t.then( function ( module ) {\n\t\t\t\treturn module.default || {};\n\t\t\t} )\n\t\t\t.catch( function () {\n\t\t\t\treturn {};\n\t\t\t} );\n\t}\n\n\tvar enhanced = [];\n\n\t/**\n\t * Tear down instances whose field has been removed from the page. The\n\t * library holds every instance in a map of its own, so a checkout plugin\n\t * that re-renders the address fields would otherwise pile them up.\n\t */\n\tfunction dropDetached() {\n\t\tenhanced = enhanced.filter(\n\t\t\tfunction ( element ) {\n\t\t\t\tif ( document.contains( element ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif ( element.iti ) {\n\t\t\t\t\telement.iti.destroy();\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Initialise the field, unless it is already initialised. The library keeps\n\t * its instance on the element itself, so that doubles as the guard.\n\t *\n\t * @param {Function} intlTelInput The library.\n\t * @param {Object}   translations Interface translations.\n\t */\n\tfunction init( intlTelInput, translations ) {\n\t\tdropDetached();\n\n\t\tvar input = document.querySelector( '#billing_phone' );\n\n\t\tif ( ! input || input.iti ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar iti = intlTelInput(\n\t\t\tinput,\n\t\t\t{\n\t\t\t\tinitialCountry: config.country || '',\n\t\t\t\tcountryOrder: config.country_order || null,\n\t\t\t\tcountryNameLocale: safeLocale( config.name_locale || 'en' ),\n\t\t\t\tuiTranslations: translations,\n\n\t\t\t\tseparateDialCode: false,\n\t\t\t\tnumberDisplayFormat: 'INTERNATIONAL',\n\n\t\t\t\t// A scope class of our own, so our instances stay addressable if\n\t\t\t\t// another plugin's intl-tel-input stylesheet ever bleeds in. The\n\t\t\t\t// library applies it to the detached mobile selector too.\n\t\t\t\tcontainerClass: 'form-row-wide swedbank-pay-iti',\n\n\t\t\t\tloadUtils: function () {\n\t\t\t\t\treturn import( config.utils_script );\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\tenhanced.push( input );\n\n\t\t/**\n\t\t * Normalise the phone number to E.164 format.\n\t\t */\n\t\tfunction normalise() {\n\t\t\tif ( ! intlTelInput.utils ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar number = iti.getNumber( 'E164' );\n\n\t\t\t// Compared the way wc_sanitize_phone_number() will.\n\t\t\tif ( number && 0 === number.indexOf( '+' ) && number !== input.value.replace( /[^\\d+]/g, '' ) ) {\n\t\t\t\titi.setNumber( number );\n\t\t\t}\n\t\t}\n\n\t\tinput.addEventListener( 'countrychange', normalise );\n\t\tinput.addEventListener( 'change', normalise );\n\t\tinput.addEventListener( 'blur', normalise );\n\n\t\t// Keep the selected country in step with the billing country, so the\n\t\t// number the customer types is interpreted the same way the server will\n\t\t// interpret it.\n\t\tvar billingCountry = document.querySelector( '#billing_country' );\n\t\tif ( billingCountry ) {\n\t\t\tbillingCountry.addEventListener(\n\t\t\t\t'change',\n\t\t\t\tfunction () {\n\t\t\t\t\tif ( ! input.value && billingCountry.value ) {\n\t\t\t\t\t\titi.setSelectedCountry( billingCountry.value.toLowerCase() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\tPromise.all( [ import( config.lib_script ), loadTranslations() ] )\n\t\t.then(\n\t\t\tfunction ( results ) {\n\t\t\t\tvar intlTelInput = results[0].default;\n\t\t\t\tvar translations = results[1];\n\n\t\t\t\tinit( intlTelInput, translations );\n\n\t\t\t\t// Some checkout plugins re-render the address fields. The\n\t\t\t\t// `input.iti` guard above makes this idempotent. Note that\n\t\t\t\t// `updated_checkout` is synthesised by jQuery and so never\n\t\t\t\t// reaches addEventListener().\n\t\t\t\tif ( window.jQuery ) {\n\t\t\t\t\twindow.jQuery( document.body ).on(\n\t\t\t\t\t\t'updated_checkout',\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\tinit( intlTelInput, translations );\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.catch(\n\t\t\tfunction ( error ) {\n\t\t\t\t// A CDN plugin rewriting plugins_url() to a host without CORS\n\t\t\t\t// headers is the likely cause -- module imports are fetched in\n\t\t\t\t// CORS mode, unlike classic scripts. Leave the plain field in\n\t\t\t\t// place rather than failing silently.\n\t\t\t\twindow.console.warn( 'Swedbank Pay: could not load intl-tel-input.', error );\n\t\t\t}\n\t\t);\n}() );\n"],"mappings":"CAUE,WACD,aAEA,IAAIA,EAASC,OAAOC,iCAEpB,GAAOF,GAAYA,EAAOG,WAA1B,CAwCA,IAAIC,EAAW,GAmGfC,QAAQC,IAAK,CAAEC,OAAQP,EAAOG,YAhHtBH,EAAOQ,cAIPD,OAAQP,EAAOQ,eACpBC,KAAM,SAAWC,GACjB,OAAOA,EAAOC,SAAW,CAAC,CAC3B,GACCC,MAAO,WACP,MAAO,CAAC,CACT,GATOP,QAAQQ,QAAS,CAAC,KAgHzBJ,KACA,SAAWK,GACV,IAAIC,EAAeD,EAAQ,GAAGH,QAC1BK,EAAeF,EAAQ,GAE3BG,EAAMF,EAAcC,GAMff,OAAOiB,QACXjB,OAAOiB,OAAQC,SAASC,MAAOC,GAC9B,mBACA,WACCJ,EAAMF,EAAcC,EACrB,EAGH,GAEAJ,MACA,SAAWU,GAKVrB,OAAOsB,QAAQC,KAAM,+CAAgDF,EACtE,EAtKF,CAUA,SAASG,EAAYC,GACpB,IACC,OAAOC,KAAKC,oBAAqBF,GAAMG,OAASH,EAAM,IACvD,CAAE,MAAQI,GACT,MAAO,IACR,CACD,CAoDA,SAASb,EAAMF,EAAcC,GAtB5BZ,EAAWA,EAAS2B,OACnB,SAAWC,GACV,QAAKb,SAASc,SAAUD,KAInBA,EAAQE,KACZF,EAAQE,IAAIC,WAGN,EACR,GAcD,IAAIC,EAAQjB,SAASkB,cAAe,kBAEpC,GAAOD,IAASA,EAAMF,IAAtB,CAIA,IAAIA,EAAMnB,EACTqB,EACA,CACCE,eAAgBtC,EAAOuC,SAAW,GAClCC,aAAcxC,EAAOyC,eAAiB,KACtCC,kBAAmBjB,EAAYzB,EAAO2C,aAAe,MACrDC,eAAgB5B,EAEhB6B,kBAAkB,EAClBC,oBAAqB,gBAKrBC,eAAgB,iCAEhBC,UAAW,WACV,OAAOzC,OAAQP,EAAOiD,aACvB,IAIF7C,EAAS8C,KAAMd,GAkBfA,EAAMe,iBAAkB,gBAAiBC,GACzChB,EAAMe,iBAAkB,SAAUC,GAClChB,EAAMe,iBAAkB,OAAQC,GAKhC,IAAIC,EAAiBlC,SAASkB,cAAe,oBACxCgB,GACJA,EAAeF,iBACd,SACA,YACQf,EAAMkB,OAASD,EAAeC,OACpCpB,EAAIqB,mBAAoBF,EAAeC,MAAME,cAE/C,EAzDF,CA6BA,SAASJ,IACR,GAAOrC,EAAa0C,MAApB,CAIA,IAAIC,EAASxB,EAAIyB,UAAW,QAGvBD,GAAU,IAAMA,EAAOE,QAAS,MAASF,IAAWtB,EAAMkB,MAAMO,QAAS,UAAW,KACxF3B,EAAI4B,UAAWJ,EANhB,CAQD,CAoBD,CAiCD,CA/KA","ignoreList":[]}
  • swedbank-pay-payment-menu/tags/4.6.2/changelog.txt

    r3652908 r3705285  
     1Version 4.6.2
     2* Enhancement   - Added a new `swedbank_pay_culture` filter for overriding the checkout language.
     3* Fix           - Fixed an issue in the inline embedded checkout where placing an order could abort a payment that was already in progress, leaving the order on Pending payment after the customer had paid.
     4* Fix           - Fixed an issue where capturing, cancelling or refunding an order paid with a separate instrument stopped working after the checkout flow was changed to Seamless Menu, leaving the order status change unprocessed without any error.
     5* Fix           - Fixed an issue where the callback for a captured or refunded payment was logged as a failure, because the payment was looked up by its authorization instead of by the transaction the callback was about.
     6* Fix           - Fixed an issue where cancelling an order added an order note that ended in an empty transaction number, making the cancellation harder to match against the merchant portal.
     7* Fix           - Fixed an issue where a failed API request logged only the base URL and an empty response.
     8
    19Version 4.6.1
    210* Tweak         - Updated the link in the WooCommerce order admin leading to the payment order in the Swedbank Pay merchant portal.
  • swedbank-pay-payment-menu/tags/4.6.2/includes/class-swedbank-pay-admin.php

    r3488799 r3705285  
    3737                add_action( 'add_meta_boxes', __CLASS__ . '::add_meta_boxes', 10, 2 );
    3838
    39                 // Add action buttons
    40                 add_action( 'woocommerce_order_item_add_action_buttons', __CLASS__ . '::add_action_buttons', 10, 1 );
    41 
    4239                // Add scripts and styles for admin
    4340                add_action( 'admin_enqueue_scripts', __CLASS__ . '::admin_enqueue_scripts' );
    … …  
    174171
    175172        /**
    176          * Add action buttons to Order view
    177          *
    178          * @param WC_Order $order
    179          */
    180         public static function add_action_buttons( $order ) {
    181                 if ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order ) ) {
    182                         // Buttons are available for orders only
    183                         return;
    184                 }
    185 
    186                 // Get Payment Gateway
    187                 if ( swedbank_pay_is_payment_swedbank_method( $order->get_payment_method() ) ) {
    188                         // Get Payment Gateway
    189                         $gateway = swedbank_pay_get_payment_method( $order );
    190                         if ( ! $gateway ) {
    191                                 return;
    192                         }
    193 
    194                         /** @var \Swedbank_Pay_Payment_Gateway_Checkout $gateway */
    195                         wc_get_template(
    196                                 'admin/action-buttons.php',
    197                                 array(
    198                                         'gateway' => $gateway,
    199                                         'order'   => $order,
    200                                 ),
    201                                 '',
    202                                 __DIR__ . '/../templates/'
    203                         );
    204                 }
    205         }
    206 
    207         /**
    208173         * Enqueue Scripts in admin
    209174         *
    … …  
    232197                        );
    233198
     199                        wp_register_style(
     200                                'swedbank-pay-admin-css',
     201                                plugin_dir_url( __FILE__ ) . '../assets/css/admin.css',
     202                                array( 'dashicons' ),
     203                                SWEDBANK_PAY_VERSION
     204                        );
     205
    234206                        // Localize the script.
    235207                        $translation_array = array(
    … …  
    242214
    243215                        // Enqueued script with localized data.
     216                        wp_enqueue_style( 'swedbank-pay-admin-css' );
    244217                        wp_enqueue_script( 'swedbank-pay-admin-js' );
    245218                }
    … …  
    502475                        'payment_order_id' => $payment_order_id,
    503476                );
     477
     478                if ( empty( $gateway ) ) {
     479                        Swedbank_Pay()->logger()->error(
     480                                "[ORDER MANAGEMENT]: Unable to resolve the payment gateway for order #{$order->get_order_number()}. The '{$old_status}->{$new_status}' status change was not forwarded to Swedbank Pay.",
     481                                $context
     482                        );
     483
     484                        return;
     485                }
    504486
    505487                try {
  • swedbank-pay-payment-menu/tags/4.6.2/includes/class-swedbank-pay-api.php

    r3652908 r3705285  
    347347         */
    348348        public function get_embedded_purchase() {
    349                 $payment_order_id  = explode( '/', WC()->session->get( 'swedbank_pay_paymentorder_id' ) );
    350                 $payment_order_id  = array_pop( $payment_order_id );
     349                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     350                if ( empty( $payment_order_id ) ) {
     351                        return new WP_Error( 'no_payment_order', 'No payment session in progress.' );
     352                }
     353
     354                $parts             = explode( '/', $payment_order_id );
     355                $short_id          = array_pop( $parts );
    351356                $context           = array(
    352                         'payment_order_id' => $payment_order_id,
    353                 );
    354                 LogUtility::$title = "[CHECKOUT]: Get embedded checkout for payment order ID #{$context['payment_order_id']}";
     357                        'payment_order_id' => $short_id,
     358                );
     359                LogUtility::$title = "[CHECKOUT]: Get embedded checkout for payment order ID #{$short_id}";
    355360
    356361                $view_session_url = WC()->session->get( 'swedbank_pay_view_session_url' );
    … …  
    359364                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $result->get_error_message() );
    360365                        Swedbank_Pay()->logger()->error(
    361                                 "[CHECKOUT]: Get embedded checkout for payment order ID #{$context['payment_order_id']}",
     366                                "[CHECKOUT]: Get embedded checkout for payment order ID #{$short_id}",
    362367                                $context
    363368                        );
    … …  
    372377         * Update a embedded payment.
    373378         *
    374          * @param string|null $instrument The instrument to use for the payment, e.g. 'CreditCard'. This is optional and may not be needed for all flows or gateways.
     379         * @param string|null   $instrument The instrument to use for the payment, e.g. 'CreditCard'. This is optional and may not be needed for all flows or gateways.
    375380         * @param WC_Order|null $order The order object to get the order number from if it exists.
    376381         *
    … …  
    378383         */
    379384        public function update_embedded_purchase( $instrument = null, $order = null ) {
     385                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     386                if ( empty( $payment_order_id ) ) {
     387                        return new WP_Error( 'no_payment_order', 'No payment session in progress.' );
     388                }
     389
    380390                $update_payment_url = WC()->session->get( 'swedbank_pay_update_order_url' );
    381391                $helper             = new Cart();
    … …  
    391401                $payment_order_object->setPaymentorder( $payment_order );
    392402
    393                 $payment_order_id = explode( '/', WC()->session->get( 'swedbank_pay_paymentorder_id' ) );
    394                 $payment_order_id = array_pop( $payment_order_id );
     403                $parts    = explode( '/', $payment_order_id );
     404                $short_id = array_pop( $parts );
    395405
    396406                $context = array(
    397                         'payment_order_id' => $payment_order_id,
    398                 );
    399 
    400                 LogUtility::$title = "[CHECKOUT]: Update embedded checkout for payment order ID #{$context['payment_order_id']}";
     407                        'payment_order_id' => $short_id,
     408                );
     409
     410                LogUtility::$title = "[CHECKOUT]: Update embedded checkout for payment order ID #{$short_id}";
    401411                $result            = $this->request( 'PATCH', $update_payment_url, $payment_order_object );
    402412                if ( is_wp_error( Swedbank_Pay()->system_report()->request( $result ) ) ) {
    403413                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $result->get_error_message() );
    404414                        Swedbank_Pay()->logger()->error(
    405                                 "[CHECKOUT]: Update embedded purchase for payment order ID #{$context['payment_order_id']}",
     415                                "[CHECKOUT]: Update embedded purchase for payment order ID #{$short_id}",
    406416                                $context
    407417                        );
    … …  
    496506                );
    497507
    498                 $start = microtime( true );
     508                $start  = microtime( true );
     509                $client = self::get_client();
    499510
    500511                try {
    501                         $client        = self::get_client()->request( $method, $url, $params );
     512                        $client->request( $method, $url, $params );
    502513                        $response_body = $client->getResponseBody();
    503514                        $result        = json_decode( $response_body, true );
    … …  
    509520                        return $result;
    510521                } catch ( \KrokedilSwedbankPayDeps\SwedbankPay\Api\Client\Exception $exception ) {
    511                         $http_code = (int) self::get_client()->getResponseCode();
     522                        $http_code = (int) $client->getResponseCode();
    512523                        $time      = microtime( true ) - $start;
    513524
    … …  
    515526                                '[%.4F] Client Exception. Check debug info: %s',
    516527                                $time,
    517                                 self::get_client()->getDebugInfo()
    518                         );
    519                         $client           = empty( $client ) ? self::get_client() : $client;
     528                                $client->getDebugInfo()
     529                        );
    520530                        LogUtility::log_request( '', $client, WC_Log_Levels::ERROR, $context );
    521531
    522532                        // https://tools.ietf.org/html/rfc7807 .
    523                         $response_body = self::get_client()->getResponseBody() ?? '{}';
     533                        $response_body = $client->getResponseBody() ?? '{}';
    524534                        $data          = json_decode( $response_body, true );
    525535                        if ( json_last_error() === JSON_ERROR_NONE &&
    … …  
    890900                );
    891901
    892                 Swedbank_Pay()->logger()->info( "[UPDATE STATUS]: Update order #{$context['order_number']} status to '{$context['status']}' with transaction ID: {$context['transaction_id']}'", $context );
     902                Swedbank_Pay()->logger()->info( "[UPDATE STATUS]: Update order #{$context['order_number']} status to '{$context['status']}' with transaction ID: '{$context['transaction_id']}'", $context );
    893903
    894904                switch ( $status ) {
    … …  
    11961206                        ->setClient( self::get_client() )
    11971207                        ->setPaymentOrderId( $payment_order_id )
    1198                         ->setExpands( array( 'financialtransactions', 'paid' ) );
     1208                        ->setExpands( array( 'financialtransactions', 'paid', 'cancelled' ) );
    11991209
    12001210                try {
    … …  
    12431253                        }
    12441254
    1245                         $transaction_id = $payment_order->getNumber();
    1246 
    1247                         $this->update_order_status(
    1248                                 $order,
    1249                                 'cancelled',
    1250                                 $transaction_id,
     1255                        // The number belongs to the cancelled sub-resource, not to the payment
     1256                        // order. The status above already confirms the cancellation without it.
     1257                        $cancelled      = $payment_order->getCancelled();
     1258                        $transaction_id = empty( $cancelled ) ? null : $cancelled->offsetGet( 'number' );
     1259
     1260                        $message = empty( $transaction_id )
     1261                                ? __( 'Payment has been cancelled.', 'swedbank-pay-payment-menu' )
    12511262                                // translators: 1: transaction ID.
    1252                                 sprintf( __( 'Payment has been cancelled. Transaction: %s', 'swedbank-pay-payment-menu' ), $transaction_id )
    1253                         );
     1263                                : sprintf( __( 'Payment has been cancelled. Transaction: %s', 'swedbank-pay-payment-menu' ), $transaction_id );
     1264
     1265                        $this->update_order_status( $order, 'cancelled', $transaction_id, $message );
    12541266
    12551267                        return array(
    … …  
    14081420
    14091421                        LogUtility::log_request(
    1410                                 '[ORDER MANAGEMENT]: refund amount',
     1422                                '[ORDER MANAGEMENT]: refund checkout',
    14111423                                $request_service->getClient(),
    14121424                                WC_Log_Levels::DEBUG,
    … …  
    14211433                                $context['error'] = $transaction->get_error_message();
    14221434                                LogUtility::log_request(
    1423                                         '[ORDER MANAGEMENT]: refund amount',
     1435                                        '[ORDER MANAGEMENT]: refund checkout',
    14241436                                        $request_service->getClient(),
    14251437                                        WC_Log_Levels::ERROR,
    … …  
    14361448                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $e->getMessage() );
    14371449                        LogUtility::log_request(
    1438                                 '[ORDER MANAGEMENT]: refund amount',
     1450                                '[ORDER MANAGEMENT]: refund checkout',
    14391451                                $request_service->getClient(),
    14401452                                WC_Log_Levels::ERROR,
  • swedbank-pay-payment-menu/tags/4.6.2/includes/class-swedbank-pay-intl-tel.php

    r3458960 r3705285  
    11<?php
     2/**
     3 * International Telephone Input for the checkout phone field.
     4 *
     5 * @package SwedbankPay\Checkout\WooCommerce
     6 */
    27
    38namespace SwedbankPay\Checkout\WooCommerce;
    49
     10use Krokedil\Swedbank\Pay\Utility\BlocksUtility;
     11
    512defined( 'ABSPATH' ) || exit;
    613
     14/**
     15 * Enhances the checkout phone field with the intl-tel-input library.
     16 */
    717class Swedbank_Intl_Tel {
     18        /**
     19         * Version of the bundled intl-tel-input library.
     20         *
     21         * Keep in sync with the pinned version in package.json; run
     22         * `npm run build:vendor` after changing it.
     23         *
     24         * @var string
     25         */
     26        const LIB_VERSION = '29.2.3';
     27
     28        /**
     29         * Script handle for the checkout wrapper.
     30         *
     31         * @var string
     32         */
     33        const HANDLE = 'swedbank-wc-intl-tel-js';
     34
     35        /**
     36         * Locale overrides for the intl-tel-input library.
     37         *
     38         * @var array<string, string>
     39         */
     40        private const LOCALE_OVERRIDES = array(
     41                'nb_NO' => 'no',
     42                'nn_NO' => 'no',
     43                'zh_HK' => 'zh-hk',
     44                'tl'    => 'fil',
     45        );
     46
     47        /**
     48         * Constructor.
     49         */
    850        public function __construct() {
    9                 // JS Scrips
     51                // JS Scripts.
    1052                add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
    1153
    12                 // Add settings
     54                // Load the wrapper as an ES module. See scripts() for why.
     55                add_filter( 'script_loader_tag', array( $this, 'script_loader_tag' ), 10, 3 );
     56
     57                // Add settings.
    1358                add_action( 'woocommerce_after_register_post_type', array( $this, 'woocommerce_init' ), 100 );
    1459        }
    … …  
    3075         * Add settings
    3176         *
    32          * @param $form_fields
    33          *
    34          * @return mixed
     77         * @param array $form_fields The gateway's form fields.
     78         *
     79         * @return array
    3580         */
    3681        public function add_settings( $form_fields ) {
    … …  
    4792        }
    4893
     94        /**
     95         * Whether the phone field should be enhanced on the current request.
     96         *
     97         * @return bool
     98         */
     99        private function is_enabled() {
     100
     101                if ( ! is_checkout() || is_order_received_page() || is_checkout_pay_page() ) {
     102                        return false;
     103                }
     104
     105                if ( BlocksUtility::is_checkout_block_enabled() ) {
     106                        return false;
     107                }
     108
     109                $settings = get_option( 'woocommerce_payex_checkout_settings', array() );
     110
     111                if ( ! wc_string_to_bool( $settings['enabled'] ?? 'no' ) ) {
     112                        return false;
     113                }
     114
     115                return wc_string_to_bool( $settings['enable_intl_tel'] ?? 'no' );
     116        }
     117
     118        /**
     119         * Enqueue the checkout assets.
     120         *
     121         * @return void
     122         */
    49123        public function scripts() {
    50                 if ( ! is_checkout() ) {
    51                         return;
    52                 }
    53 
    54                 $settings = get_option( 'woocommerce_payex_checkout_settings', array( 'enable_intl_tel' => 'no' ) );
    55                 if ( ! isset( $settings['enable_intl_tel'] ) ) {
    56                         $settings['enable_intl_tel'] = 'no';
    57                 }
    58 
    59                 if ( 'no' === $settings['enable_intl_tel'] ) {
     124                if ( ! $this->is_enabled() ) {
    60125                        return;
    61126                }
    … …  
    65130                wp_enqueue_style(
    66131                        'swedbank-intl-tel-css',
    67                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/css/intlTelInput' . $suffix . '.css',
     132                        $this->vendor_url( "css/intlTelInput{$suffix}.css" ),
    68133                        array(),
    69                         '17.0.3',
     134                        self::LIB_VERSION,
    70135                        'all'
    71136                );
    72137
    73138                wp_register_script(
    74                         'swedbank-intl-tel-js',
    75                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/intlTelInput' . $suffix . '.js',
    76                         array(
    77                                 'jquery',
    78                                 'wc-checkout',
    79                         ),
    80                         '17.0.3',
    81                         true
    82                 );
    83 
    84                 wp_register_script(
    85                         'swedbank-wc-intl-tel-js',
    86                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/wc-intl-tel' . $suffix . '.js',
    87                         array(
    88                                 'swedbank-intl-tel-js',
    89                         ),
     139                        self::HANDLE,
     140                        SWEDBANK_PAY_PLUGIN_URL . "/assets/js/wc-intl-tel{$suffix}.js",
     141                        array( 'jquery' ),
    90142                        SWEDBANK_PAY_VERSION,
    91143                        true
    92144                );
    93145
    94                 wp_localize_script(
    95                         'swedbank-intl-tel-js',
    96                         'WC_Gateway_Swedbank_Pay_Intl_Tel',
    97                         array(
    98                                 'utils_script' => untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/utils' . $suffix . '.js',
    99                                 'country'      => $this->get_country(),
    100                         )
    101                 );
    102 
    103                 // Enqueued script with localized data.
    104                 wp_enqueue_script( 'swedbank-intl-tel-js' );
    105                 wp_enqueue_script( 'swedbank-wc-intl-tel-js' );
    106         }
    107 
    108         /**
    109          * Get the country ISO code based on the IP address of the client.
     146                wp_localize_script( self::HANDLE, 'WC_Gateway_Swedbank_Pay_Intl_Tel', $this->get_params( $suffix ) );
     147
     148                wp_enqueue_script( self::HANDLE );
     149        }
     150
     151        /**
     152         * Data handed to the wrapper script.
     153         *
     154         * @param string $suffix Minified file suffix.
     155         *
     156         * @return array
     157         */
     158        private function get_params( $suffix ) {
     159                $locale = $this->get_locale_file();
     160
     161                $params = array(
     162                        'lib_script'    => $this->vendor_url( "js/intlTelInput{$suffix}.js" ),
     163                        'utils_script'  => $this->vendor_url( 'js/utils.js' ),
     164                        'locale_script' => $locale ? $this->vendor_url( "js/locale/{$locale}.js" ) : '',
     165                        'name_locale'   => $this->get_country_name_locale(),
     166                        'country'       => $this->get_country(),
     167                        'country_order' => $this->get_country_order(),
     168                );
     169
     170                /**
     171                 * Filter the options handed to intl-tel-input on the checkout.
     172                 *
     173                 * @param array $params
     174                 */
     175                return apply_filters( 'swedbank_pay_intl_tel_params', $params );
     176        }
     177
     178        /**
     179         * Build a URL to a bundled third-party asset, carrying the library version.
     180         *
     181         * @param string $path Path relative to the intl-tel-input vendor directory.
     182         *
     183         * @return string
     184         */
     185        private function vendor_url( $path ) {
     186                return add_query_arg(
     187                        'ver',
     188                        self::LIB_VERSION,
     189                        SWEDBANK_PAY_PLUGIN_URL . '/assets/vendor/intl-tel-input/' . $path
     190                );
     191        }
     192
     193        /**
     194         * Load the wrapper as an ES module so it can import the library.
     195         *
     196         * @param string $tag    The script tag.
     197         * @param string $handle Script handle.
     198         * @param string $src    Script source.
     199         *
     200         * @return string
     201         */
     202        public function script_loader_tag( $tag, $handle, $src ) {
     203                if ( self::HANDLE !== $handle ) {
     204                        return $tag;
     205                }
     206
     207                // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript -- This rewrites the tag of an already enqueued script.
     208                return sprintf( '<script type="module" src="%s" id="%s-js"></script>' . "\n", esc_url( $src ), esc_attr( $handle ) );
     209        }
     210
     211        /**
     212         * Get the locale file name for the current site language, or null if none exists.
     213         *
     214         * @return string|null
     215         */
     216        private function get_locale_file() {
     217                $locale = get_locale();
     218                $name   = self::LOCALE_OVERRIDES[ $locale ] ?? strtolower( strtok( $locale, '_-' ) );
     219
     220                if ( ! preg_match( '/^[a-z-]{2,5}$/', $name ) ) {
     221                        return null;
     222                }
     223
     224                $path = SWEDBANK_PAY_PLUGIN_PATH . '/assets/vendor/intl-tel-input/js/locale/' . $name . '.js';
     225
     226                return file_exists( $path ) ? $name : null;
     227        }
     228
     229        /**
     230         * Locale used to translate the country names via Intl.DisplayNames.
     231         *
     232         * @return string
     233         */
     234        private function get_country_name_locale() {
     235                $locale = str_replace( '_', '-', get_locale() );
     236                $parts  = explode( '-', $locale );
     237                $tag    = strtolower( $parts[0] );
     238
     239                if ( isset( $parts[1] ) && 2 === strlen( $parts[1] ) ) {
     240                        $tag .= '-' . strtoupper( $parts[1] );
     241                }
     242
     243                return preg_match( '/^[a-z]{2,3}(-[A-Z]{2})?$/', $tag ) ? $tag : 'en';
     244        }
     245
     246        /**
     247         * Countries to float to the top of the list.
     248         *
     249         * @return array
     250         */
     251        private function get_country_order() {
     252                $countries = array_merge( array( $this->get_country() ), array( 'SE', 'NO', 'FI', 'DK' ) );
     253
     254                return array_values( array_unique( array_filter( $countries ) ) );
     255        }
     256
     257        /**
     258         * Get the country ISO code to preselect in the country dropdown.
    110259         *
    111260         * @return string The country ISO code.
    112261         */
    113262        private function get_country() {
    114                 return function_exists( 'geoip_detect2_get_info_from_ip' ) ?
    115                         geoip_detect2_get_info_from_ip( geoip_detect2_get_client_ip() )->country->isoCode :
    116                         \WC_Geolocation::geolocate_ip()['country'];
     263                if ( function_exists( 'geoip_detect2_get_info_from_ip' ) ) {
     264                        return geoip_detect2_get_info_from_ip( geoip_detect2_get_client_ip() )->country->isoCode;
     265                }
     266
     267                $country = \WC_Geolocation::geolocate_ip()['country'];
     268
     269                // Fall back to the store's default customer location.
     270                return ! empty( $country ) ? $country : wc_get_customer_default_location()['country'];
    117271        }
    118272}
  • swedbank-pay-payment-menu/tags/4.6.2/includes/class-swedbank-pay-payment-gateway-checkout.php

    r3652908 r3705285  
    230230        public static function locale_to_culture() {
    231231                $locale = get_locale();
     232                $mapped = $locale;
    232233
    233234                // Format exceptions for locales that do not match the expected format, e.g. fi_FI for Finnish in Finland.
    234                 switch ( $locale ) {
     235                switch ( $mapped ) {
    235236                        case 'fi':
    236                                 $locale = 'fi_FI';
     237                                $mapped = 'fi_FI';
    237238                                break;
    238239                        case 'et':
    239                                 $locale = 'et_EE';
     240                                $mapped = 'et_EE';
    240241                                break;
    241242                        case 'lv':
    242                                 $locale = 'lv_LV';
     243                                $mapped = 'lv_LV';
    243244                                break;
    244245                        default:
    … …  
    246247                }
    247248
    248                 return substr( str_replace( '_', '-', $locale ), 0, 5 );
     249                $culture = substr( str_replace( '_', '-', $mapped ), 0, 5 );
     250
     251                return apply_filters( 'swedbank_pay_culture', $culture, $locale );
    249252        }
    250253
    … …  
    604607                $this->access_token = isset( $this->settings['access_token'] ) ? $this->settings['access_token'] : $this->access_token; // phpcs:ignore
    605608                $this->payee_id     = isset( $this->settings['payee_id'] ) ? $this->settings['payee_id'] : $this->payee_id;
     609                $this->testmode     = isset( $this->settings['testmode'] ) ? $this->settings['testmode'] : $this->testmode;
    606610
    607611                // Test API Credentials.
  • swedbank-pay-payment-menu/tags/4.6.2/includes/class-swedbank-pay-scheduler.php

    r3568448 r3705285  
    112112                }
    113113
    114                 // v3.1 callbacks no longer carry a transaction.number; finalize_payment falls back
    115                 // to the paymentOrder's `paid` resource to discover the right transaction.
    116                 // process_transaction() dedupes by financial transaction id internally.
     114                // The callback names the transaction it is about. `paid` keeps reporting the
     115                // authorization, which is absent from the transactions list after a capture.
    117116                Swedbank_Pay()->logger()->info( "[SCHEDULER]: Attempting to finalize payment for order #{$context['order_number']} with payment number #{$context['payment_number']}.", $context );
    118                 $result = $gateway->api->finalize_payment( $order );
     117                $result = $gateway->api->finalize_payment( $order, $payment_number );
    119118                if ( is_wp_error( Swedbank_Pay()->system_report()->request( $result ) ) ) {
    120119                        $context['error'] = join( '; ', $result->get_error_messages() );
  • swedbank-pay-payment-menu/tags/4.6.2/includes/functions.php

    r3652908 r3705285  
    5858 */
    5959function swedbank_pay_get_payment_method( WC_Order $order, bool $use_base_gateway = true ) {
    60         // Get Payment Gateway
     60        $payment_method = $order->get_payment_method();
     61
     62        // The split instrument gateways only exist in the redirect flow, so an order
     63        // paid with one has no registered gateway once the flow changes.
     64        if ( $use_base_gateway && swedbank_pay_is_payment_swedbank_method( $payment_method ) ) {
     65                return swedbank_pay_get_payment_method_by_id();
     66        }
     67
    6168        $gateways = WC()->payment_gateways()->payment_gateways();
    62         if ( ! isset( $gateways[ $order->get_payment_method() ] ) ) {
    63                 return null;
    64         }
    65 
    66         /** @var \WC_Payment_Gateway $gateway */
    67         $gateway = $gateways[ $order->get_payment_method() ];
    68 
    69         if ( $use_base_gateway && swedbank_pay_is_payment_swedbank_method( $gateway->id ) ) {
    70                 $gateway = swedbank_pay_get_payment_method_by_id();
    71         }
    72 
    73         return $gateway;
     69
     70        return $gateways[ $payment_method ] ?? null;
    7471}
    7572
  • swedbank-pay-payment-menu/tags/4.6.2/readme.txt

    r3652908 r3705285  
    66Requires PHP: 7.4
    77WC requires at least: 5.5.1
    8 WC tested up to: 11.0.1
    9 Stable tag: 4.6.1
     8WC tested up to: 11.1.1
     9Stable tag: 4.6.2
    1010License: Apache License 2.0
    1111License URI: http://www.apache.org/licenses/LICENSE-2.0
    … …  
    9696
    9797== Changelog ==
     98= 2026.09.21    - version 4.6.2 =
     99* Enhancement   - Added a new `swedbank_pay_culture` filter for overriding the checkout language.
     100* Fix           - Fixed an issue in the inline embedded checkout where placing an order could abort a payment that was already in progress, leaving the order on Pending payment after the customer had paid.
     101* Fix           - Fixed an issue where capturing, cancelling or refunding an order paid with a separate instrument stopped working after the checkout flow was changed to Seamless Menu, leaving the order status change unprocessed without any error.
     102* Fix           - Fixed an issue where the callback for a captured or refunded payment was logged as a failure, because the payment was looked up by its authorization instead of by the transaction the callback was about.
     103* Fix           - Fixed an issue where cancelling an order added an order note that ended in an empty transaction number, making the cancellation harder to match against the merchant portal.
     104* Fix           - Fixed an issue where a failed API request logged only the base URL and an empty response.
     105
    98106= 2026.08.18    - version 4.6.1 =
    99107* Tweak         - Updated the link in the WooCommerce order admin leading to the payment order in the Swedbank Pay merchant portal.
  • swedbank-pay-payment-menu/tags/4.6.2/src/CheckoutFlow/InlineEmbedded.php

    r3652908 r3705285  
    5555         */
    5656        protected function init() {
     57                // Only when rendering the checkout page, since process() manages the payment order itself.
     58                if ( null !== $this->order ) {
     59                        return;
     60                }
     61
    5762                $this->set_is_payment_complete();
    5863                if ( ! $this->is_payment_complete ) {
    … …  
    175180                                }
    176181
    177                                 // A verify operation cannot be updated which is the case for all zero amount order.
     182                                // A verify operation cannot be updated which is the case for all zero amount orders.
    178183                                if ( PaymentDataHelper::OPERATION_VERIFY === $session_operation ) {
    179184                                        return array();
    … …  
    247252
    248253        /**
     254         * Update the payment order with the WooCommerce order number before it is paid.
     255         *
     256         * Unlike create_or_update_embedded_purchase(), the payment order is never
     257         * aborted and the session is never cleared when the update fails. The shopper
     258         * may already have a payment in flight by the time process() runs, e.g. Apple
     259         * Pay authorizing during the place order request, and Swedbank Pay refuses to
     260         * update a payment order while that is the case. Losing the order reference in
     261         * the merchant portal is preferable to orphaning an ongoing payment.
     262         *
     263         * @param \WC_Order $order The WooCommerce order to be processed.
     264         *
     265         * @return void
     266         */
     267        private function maybe_update_order_reference( $order ) {
     268                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     269                if ( empty( $payment_order_id ) ) {
     270                        return;
     271                }
     272
     273                // A verify operation cannot be updated which is the case for all zero amount orders.
     274                if ( PaymentDataHelper::OPERATION_VERIFY === WC()->session->get( 'swedbank_pay_operation' ) ) {
     275                        return;
     276                }
     277
     278                $result = $this->api->update_embedded_purchase( null, $order );
     279                if ( is_wp_error( $result ) ) {
     280                        Swedbank_Pay()->logger()->warning(
     281                                sprintf(
     282                                        '[PROCESS PAYMENT]: Failed to update the order reference for order #%s, continuing without it: %s',
     283                                        $this->get_order_number( $order ),
     284                                        $result->get_error_message()
     285                                ),
     286                                array( 'order_id' => $order->get_id() )
     287                        );
     288                }
     289        }
     290
     291        /**
    249292         * Process the payment for the WooCommerce order.
    250293         *
    … …  
    260303                        throw new \Exception( 'Zero order is not supported.' );
    261304                }
     305
     306                $this->maybe_update_order_reference( $order );
    262307
    263308                // Initiate Payment Order.
  • swedbank-pay-payment-menu/tags/4.6.2/swedbank-pay-payment-menu.php

    r3652908 r3705285  
    88 * License: Apache License 2.0
    99 * License URI: http://www.apache.org/licenses/LICENSE-2.0
    10  * Version: 4.6.1
     10 * Version: 4.6.2
    1111 * Text Domain: swedbank-pay-payment-menu
    1212 * Domain Path: /languages
    1313 *
    1414 * WC requires at least: 5.5.1
    15  * WC tested up to: 11.0.1
     15 * WC tested up to: 11.1.1
    1616 * Requires Plugins: woocommerce
    1717 *
    … …  
    2828
    2929defined( 'ABSPATH' ) || exit;
    30 define( 'SWEDBANK_PAY_VERSION', '4.6.1' );
     30define( 'SWEDBANK_PAY_VERSION', '4.6.2' );
    3131define( 'SWEDBANK_PAY_MAIN_FILE', __FILE__ );
    3232define( 'SWEDBANK_PAY_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
  • swedbank-pay-payment-menu/tags/4.6.2/templates/admin/payment-actions.php

    r3516255 r3705285  
    1010?>
    1111<div>
    12         <strong><?php esc_html_e( 'Payment Info', 'swedbank-pay-payment-menu' ); ?></strong>
    13         <br />
     12        <?php $transaction_url = $gateway->get_transaction_url( $order ); ?>
    1413        <?php if ( isset( $info['paid']['number'] ) ) : ?>
    15                 <strong><?php esc_html_e( 'Number', 'swedbank-pay-payment-menu' ); ?>
    16                         :</strong> <?php echo esc_html( $info['paid']['number'] ); ?>
    17                 <br/>
     14                <p>
     15                        <strong><?php esc_html_e( 'Number', 'swedbank-pay-payment-menu' ); ?></strong>
     16                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The payment number assigned by Swedbank Pay. Use it when referring to the payment in the Merchant Portal or in support requests.', 'swedbank-pay-payment-menu' ) ) ); ?>
     17                        <br/>
     18                        <?php if ( $transaction_url ) : ?>
     19                                <a href="<?php echo esc_url( $transaction_url ); ?>"
     20                                        target="_blank"
     21                                        rel="noopener noreferrer"
     22                                        class="swedbank-pay-transaction-link">
     23                                        <?php echo esc_html( $info['paid']['number'] ); ?>
     24                                        <span class="screen-reader-text"><?php esc_html_e( '(opens the payment in the Merchant Portal in a new tab)', 'swedbank-pay-payment-menu' ); ?></span>
     25                                </a>
     26                                <span class="dashicons dashicons-external" aria-hidden="true"></span>
     27                        <?php else : ?>
     28                                <?php echo esc_html( $info['paid']['number'] ); ?>
     29                        <?php endif; ?>
     30                </p>
    1831        <?php endif; ?>
    1932        <?php if ( isset( $info['paid']['instrument'] ) ) : ?>
    20                 <strong><?php esc_html_e( 'Instrument', 'swedbank-pay-payment-menu' ); ?>
    21                         : </strong> <?php echo esc_html( $info['paid']['instrument'] ); ?>
    22                 <br/>
     33                <p>
     34                        <strong><?php esc_html_e( 'Instrument', 'swedbank-pay-payment-menu' ); ?></strong>
     35                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The payment instrument the customer paid with, for example Card, Swish or Invoice.', 'swedbank-pay-payment-menu' ) ) ); ?>
     36                        <br/>
     37                        <?php echo esc_html( $info['paid']['instrument'] ); ?>
     38                </p>
    2339        <?php endif; ?>
    2440        <?php if ( isset( $info['paid']['transactionType'] ) ) : ?>
    25                 <strong><?php esc_html_e( 'Transaction type', 'swedbank-pay-payment-menu' ); ?>
    26                         : </strong> <?php echo esc_html( $info['paid']['transactionType'] ); ?>
    27                 <br/>
     41                <p>
     42                        <strong><?php esc_html_e( 'Transaction type', 'swedbank-pay-payment-menu' ); ?></strong>
     43                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The type of transaction performed on the payment, for example Authorization or Sale.', 'swedbank-pay-payment-menu' ) ) ); ?>
     44                        <br/>
     45                        <?php echo esc_html( $info['paid']['transactionType'] ); ?>
     46                </p>
    2847        <?php endif; ?>
    2948        <?php if ( isset( $info['paid']['payeeReference'] ) ) : ?>
    30                 <strong><?php esc_html_e( 'Payee Reference', 'swedbank-pay-payment-menu' ); ?>
    31                         : </strong> <?php echo esc_html( $info['paid']['payeeReference'] ); ?>
    32                 <br/>
     49                <p>
     50                        <strong><?php esc_html_e( 'Payee Reference', 'swedbank-pay-payment-menu' ); ?></strong>
     51                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The unique reference sent to Swedbank Pay for this payment. It ties the order in the store to the payment at Swedbank Pay.', 'swedbank-pay-payment-menu' ) ) ); ?>
     52                        <br/>
     53                        <?php echo esc_html( $info['paid']['payeeReference'] ); ?>
     54                </p>
    3355        <?php endif; ?>
    34         <?php if ( $gateway->api->can_capture( $order ) ) : ?>
    35                 <button id="swedbank_pay_capture"
    36                                 data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
    37                                 data-order-id="<?php echo esc_html( $order->get_id() ); ?>">
    38                         <?php esc_html_e( 'Capture Payment', 'swedbank-pay-payment-menu' ); ?>
    39                 </button>
    40         <?php endif; ?>
     56        <?php
     57        $can_capture = $gateway->api->can_capture( $order );
     58        $can_cancel  = $gateway->api->can_cancel( $order );
     59        ?>
     60        <?php if ( $can_capture || $can_cancel ) : ?>
     61                <details class="swedbank-pay-advanced">
     62                        <summary class="swedbank-pay-advanced__summary">
     63                                <?php esc_html_e( 'Advanced', 'swedbank-pay-payment-menu' ); ?>
     64                        </summary>
     65                        <div class="swedbank-pay-advanced__content">
     66                                <?php if ( $can_capture ) : ?>
     67                                        <p class="swedbank-pay-advanced__action">
     68                                                <button id="swedbank_pay_capture"
     69                                                                type="button" class="button"
     70                                                                data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
     71                                                                data-order-id="<?php echo esc_attr( $order->get_id() ); ?>">
     72                                                        <?php esc_html_e( 'Capture Payment', 'swedbank-pay-payment-menu' ); ?>
     73                                                </button>
     74                                        </p>
     75                                <?php endif; ?>
    4176
    42         <?php if ( $gateway->api->can_cancel( $order ) ) : ?>
    43                 <button id="swedbank_pay_cancel"
    44                                 data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
    45                                 data-order-id="<?php echo esc_html( $order->get_id() ); ?>">
    46                         <?php esc_html_e( 'Cancel Payment', 'swedbank-pay-payment-menu' ); ?>
    47                 </button>
     77                                <?php if ( $can_cancel ) : ?>
     78                                        <p class="swedbank-pay-advanced__action">
     79                                                <button id="swedbank_pay_cancel"
     80                                                                type="button" class="button"
     81                                                                data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
     82                                                                data-order-id="<?php echo esc_attr( $order->get_id() ); ?>">
     83                                                        <?php esc_html_e( 'Cancel Payment', 'swedbank-pay-payment-menu' ); ?>
     84                                                </button>
     85                                        </p>
     86                                <?php endif; ?>
     87                        </div>
     88                </details>
    4889        <?php endif; ?>
    4990</div>
  • swedbank-pay-payment-menu/tags/4.6.2/vendor/composer/installed.php

    r3652908 r3705285  
    22    'root' => array(
    33        'name' => 'swedbank-pay/woocommerce-payment-menu',
    4         'pretty_version' => '4.6.1',
    5         'version' => '4.6.1.0',
    6         'reference' => '79901a987e2c97b14b429e258739489773e7e0ed',
     4        'pretty_version' => '4.6.2',
     5        'version' => '4.6.2.0',
     6        'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1212    'versions' => array(
    1313        'swedbank-pay/woocommerce-payment-menu' => array(
    14             'pretty_version' => '4.6.1',
    15             'version' => '4.6.1.0',
    16             'reference' => '79901a987e2c97b14b429e258739489773e7e0ed',
     14            'pretty_version' => '4.6.2',
     15            'version' => '4.6.2.0',
     16            'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
  • swedbank-pay-payment-menu/tags/4.6.2/vendor/dependencies/composer/installed.php

    r3652908 r3705285  
    33namespace KrokedilSwedbankPayDeps;
    44
    5 return array('root' => array('name' => '__root__', 'pretty_version' => '4.6.1', 'version' => '4.6.1.0', 'reference' => '79901a987e2c97b14b429e258739489773e7e0ed', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '4.6.1', 'version' => '4.6.1.0', 'reference' => '79901a987e2c97b14b429e258739489773e7e0ed', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.5', 'version' => '1.3.5.0', 'reference' => 'e8f015fefcc42599b40fc0953a27f788ac24a853', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.2', 'version' => '1.0.2.0', 'reference' => '99059b1b27cc4ed7667c1d04968aec45413fe533', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/random_compat' => array('pretty_version' => 'v9.99.100', 'version' => '9.99.100.0', 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/random_compat', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '3.9.7', 'version' => '3.9.7.0', 'reference' => 'dc75aa439eb4c1b77f5379fd958b3dc0e6014178', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '3.9.7')), 'swedbank-pay/swedbank-pay-sdk-php' => array('pretty_version' => '6.3.0', 'version' => '6.3.0.0', 'reference' => '1a85aa5d724954f6b8852a982f8f7cb02c68ebca', 'type' => 'library', 'install_path' => __DIR__ . '/../swedbank-pay/swedbank-pay-sdk-php', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false)));
     5return array('root' => array('name' => '__root__', 'pretty_version' => '4.6.2', 'version' => '4.6.2.0', 'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '4.6.2', 'version' => '4.6.2.0', 'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.5', 'version' => '1.3.5.0', 'reference' => 'e8f015fefcc42599b40fc0953a27f788ac24a853', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.2', 'version' => '1.0.2.0', 'reference' => '99059b1b27cc4ed7667c1d04968aec45413fe533', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/random_compat' => array('pretty_version' => 'v9.99.100', 'version' => '9.99.100.0', 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/random_compat', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '3.9.7', 'version' => '3.9.7.0', 'reference' => 'dc75aa439eb4c1b77f5379fd958b3dc0e6014178', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '3.9.7')), 'swedbank-pay/swedbank-pay-sdk-php' => array('pretty_version' => '6.3.0', 'version' => '6.3.0.0', 'reference' => '1a85aa5d724954f6b8852a982f8f7cb02c68ebca', 'type' => 'library', 'install_path' => __DIR__ . '/../swedbank-pay/swedbank-pay-sdk-php', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false)));
  • swedbank-pay-payment-menu/trunk/assets/js/wc-intl-tel.js

    r3057342 r3705285  
    1 jQuery(document).ready(function ($) {
    2     $(document.body).on('update_checkout', function () {
    3         initTelInput();
    4     });
     1/**
     2 * Enhances the checkout billing phone field with intl-tel-input.
     3 *
     4 * This file is loaded as an ES module (see Swedbank_Intl_Tel::script_loader_tag)
     5 * and pulls the library in with a dynamic import. That is deliberate: the
     6 * library's classic build declares a top-level `var intlTelInput`, which lands
     7 * on `window`, so two plugins shipping different versions would clobber each
     8 * other. An imported binding is module-scoped, so nothing here reads or writes
     9 * the global and we cannot collide with anyone else's copy.
     10 */
     11( function () {
     12        'use strict';
    513
    6     initTelInput();
     14        var config = window.WC_Gateway_Swedbank_Pay_Intl_Tel;
    715
    8     function initTelInput() {
    9         const telInput = document.querySelector("#billing_phone");
     16        if ( ! config || ! config.lib_script ) {
     17                return;
     18        }
    1019
    11         var iti = window.intlTelInput(telInput, {
    12                 utilsScript: WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,
    13                 preferredCountries: [WC_Gateway_Swedbank_Pay_Intl_Tel.country, 'SE', 'NO', 'FI', 'DK'],
    14                 defaultToFirstCountry: true,
    15                 nationalMode: false,
    16                 formatOnDisplay: true,
    17                 customContainer: 'form-row-wide'
    18             }
    19         );
     20        /**
     21         * Country name translation goes through Intl.DisplayNames, which throws on a
     22         * malformed tag. The library catches that and then blanks every country
     23         * name, so validate before handing the tag over.
     24         *
     25         * @param {string} tag Locale tag.
     26         * @return {string} A usable locale tag.
     27         */
     28        function safeLocale( tag ) {
     29                try {
     30                        return Intl.getCanonicalLocales( tag ).length ? tag : 'en';
     31                } catch ( e ) {
     32                        return 'en';
     33                }
     34        }
    2035
    21         telInput.addEventListener('keyup', formatIntlTelInput);
    22         telInput.addEventListener('change', formatIntlTelInput);
     36        /**
     37         * Load the translated interface strings, if we ship any for this site's
     38         * language. A failure here must not stop the field from initialising.
     39         *
     40         * @return {Promise<Object>} Translations, or an empty object.
     41         */
     42        function loadTranslations() {
     43                if ( ! config.locale_script ) {
     44                        return Promise.resolve( {} );
     45                }
    2346
    24         function formatIntlTelInput() {
    25             if (typeof intlTelInputUtils !== 'undefined') { // utils are lazy loaded, so must check
    26                 var currentText = iti.getNumber(intlTelInputUtils.numberFormat.E164);
    27                 if (typeof currentText === 'string') { // sometimes the currentText is an object :)
    28                     iti.setNumber(currentText); // will autoformat because of formatOnDisplay=true
    29                 }
    30             }
    31         }
    32     }
    33 });
     47                return import( config.locale_script )
     48                        .then( function ( module ) {
     49                                return module.default || {};
     50                        } )
     51                        .catch( function () {
     52                                return {};
     53                        } );
     54        }
     55
     56        var enhanced = [];
     57
     58        /**
     59         * Tear down instances whose field has been removed from the page. The
     60         * library holds every instance in a map of its own, so a checkout plugin
     61         * that re-renders the address fields would otherwise pile them up.
     62         */
     63        function dropDetached() {
     64                enhanced = enhanced.filter(
     65                        function ( element ) {
     66                                if ( document.contains( element ) ) {
     67                                        return true;
     68                                }
     69
     70                                if ( element.iti ) {
     71                                        element.iti.destroy();
     72                                }
     73
     74                                return false;
     75                        }
     76                );
     77        }
     78
     79        /**
     80         * Initialise the field, unless it is already initialised. The library keeps
     81         * its instance on the element itself, so that doubles as the guard.
     82         *
     83         * @param {Function} intlTelInput The library.
     84         * @param {Object}   translations Interface translations.
     85         */
     86        function init( intlTelInput, translations ) {
     87                dropDetached();
     88
     89                var input = document.querySelector( '#billing_phone' );
     90
     91                if ( ! input || input.iti ) {
     92                        return;
     93                }
     94
     95                var iti = intlTelInput(
     96                        input,
     97                        {
     98                                initialCountry: config.country || '',
     99                                countryOrder: config.country_order || null,
     100                                countryNameLocale: safeLocale( config.name_locale || 'en' ),
     101                                uiTranslations: translations,
     102
     103                                separateDialCode: false,
     104                                numberDisplayFormat: 'INTERNATIONAL',
     105
     106                                // A scope class of our own, so our instances stay addressable if
     107                                // another plugin's intl-tel-input stylesheet ever bleeds in. The
     108                                // library applies it to the detached mobile selector too.
     109                                containerClass: 'form-row-wide swedbank-pay-iti',
     110
     111                                loadUtils: function () {
     112                                        return import( config.utils_script );
     113                                },
     114                        }
     115                );
     116
     117                enhanced.push( input );
     118
     119                /**
     120                 * Normalise the phone number to E.164 format.
     121                 */
     122                function normalise() {
     123                        if ( ! intlTelInput.utils ) {
     124                                return;
     125                        }
     126
     127                        var number = iti.getNumber( 'E164' );
     128
     129                        // Compared the way wc_sanitize_phone_number() will.
     130                        if ( number && 0 === number.indexOf( '+' ) && number !== input.value.replace( /[^\d+]/g, '' ) ) {
     131                                iti.setNumber( number );
     132                        }
     133                }
     134
     135                input.addEventListener( 'countrychange', normalise );
     136                input.addEventListener( 'change', normalise );
     137                input.addEventListener( 'blur', normalise );
     138
     139                // Keep the selected country in step with the billing country, so the
     140                // number the customer types is interpreted the same way the server will
     141                // interpret it.
     142                var billingCountry = document.querySelector( '#billing_country' );
     143                if ( billingCountry ) {
     144                        billingCountry.addEventListener(
     145                                'change',
     146                                function () {
     147                                        if ( ! input.value && billingCountry.value ) {
     148                                                iti.setSelectedCountry( billingCountry.value.toLowerCase() );
     149                                        }
     150                                }
     151                        );
     152                }
     153        }
     154
     155        Promise.all( [ import( config.lib_script ), loadTranslations() ] )
     156                .then(
     157                        function ( results ) {
     158                                var intlTelInput = results[0].default;
     159                                var translations = results[1];
     160
     161                                init( intlTelInput, translations );
     162
     163                                // Some checkout plugins re-render the address fields. The
     164                                // `input.iti` guard above makes this idempotent. Note that
     165                                // `updated_checkout` is synthesised by jQuery and so never
     166                                // reaches addEventListener().
     167                                if ( window.jQuery ) {
     168                                        window.jQuery( document.body ).on(
     169                                                'updated_checkout',
     170                                                function () {
     171                                                        init( intlTelInput, translations );
     172                                                }
     173                                        );
     174                                }
     175                        }
     176                )
     177                .catch(
     178                        function ( error ) {
     179                                // A CDN plugin rewriting plugins_url() to a host without CORS
     180                                // headers is the likely cause -- module imports are fetched in
     181                                // CORS mode, unlike classic scripts. Leave the plain field in
     182                                // place rather than failing silently.
     183                                window.console.warn( 'Swedbank Pay: could not load intl-tel-input.', error );
     184                        }
     185                );
     186}() );
  • swedbank-pay-payment-menu/trunk/assets/js/wc-intl-tel.min.js

    r3407993 r3705285  
    1 jQuery(document).ready(function(t){function e(){const t=document.querySelector("#billing_phone");var e=window.intlTelInput(t,{utilsScript:WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,preferredCountries:[WC_Gateway_Swedbank_Pay_Intl_Tel.country,"SE","NO","FI","DK"],defaultToFirstCountry:!0,nationalMode:!1,formatOnDisplay:!0,customContainer:"form-row-wide"});function n(){if("undefined"!=typeof intlTelInputUtils){var t=e.getNumber(intlTelInputUtils.numberFormat.E164);"string"==typeof t&&e.setNumber(t)}}t.addEventListener("keyup",n),t.addEventListener("change",n)}t(document.body).on("update_checkout",function(){e()}),e()});
     1!function(){"use strict";var e=window.WC_Gateway_Swedbank_Pay_Intl_Tel;if(e&&e.lib_script){var n=[];Promise.all([import(e.lib_script),e.locale_script?import(e.locale_script).then(function(e){return e.default||{}}).catch(function(){return{}}):Promise.resolve({})]).then(function(e){var n=e[0].default,t=e[1];r(n,t),window.jQuery&&window.jQuery(document.body).on("updated_checkout",function(){r(n,t)})}).catch(function(e){window.console.warn("Swedbank Pay: could not load intl-tel-input.",e)})}function t(e){try{return Intl.getCanonicalLocales(e).length?e:"en"}catch(e){return"en"}}function r(r,i){n=n.filter(function(e){return!!document.contains(e)||(e.iti&&e.iti.destroy(),!1)});var o=document.querySelector("#billing_phone");if(o&&!o.iti){var a=r(o,{initialCountry:e.country||"",countryOrder:e.country_order||null,countryNameLocale:t(e.name_locale||"en"),uiTranslations:i,separateDialCode:!1,numberDisplayFormat:"INTERNATIONAL",containerClass:"form-row-wide swedbank-pay-iti",loadUtils:function(){return import(e.utils_script)}});n.push(o),o.addEventListener("countrychange",c),o.addEventListener("change",c),o.addEventListener("blur",c);var u=document.querySelector("#billing_country");u&&u.addEventListener("change",function(){!o.value&&u.value&&a.setSelectedCountry(u.value.toLowerCase())})}function c(){if(r.utils){var e=a.getNumber("E164");e&&0===e.indexOf("+")&&e!==o.value.replace(/[^\d+]/g,"")&&a.setNumber(e)}}}}();
    22//# sourceMappingURL=wc-intl-tel.min.js.map
  • swedbank-pay-payment-menu/trunk/assets/js/wc-intl-tel.min.js.map

    r3407993 r3705285  
    1 {"version":3,"file":"wc-intl-tel.min.js","names":["jQuery","document","ready","$","initTelInput","telInput","querySelector","iti","window","intlTelInput","utilsScript","WC_Gateway_Swedbank_Pay_Intl_Tel","utils_script","preferredCountries","country","defaultToFirstCountry","nationalMode","formatOnDisplay","customContainer","formatIntlTelInput","intlTelInputUtils","currentText","getNumber","numberFormat","E164","setNumber","addEventListener","body","on"],"sources":["wc-intl-tel.js"],"sourcesContent":["jQuery(document).ready(function ($) {\n    $(document.body).on('update_checkout', function () {\n        initTelInput();\n    });\n\n    initTelInput();\n\n    function initTelInput() {\n        const telInput = document.querySelector(\"#billing_phone\");\n\n        var iti = window.intlTelInput(telInput, {\n                utilsScript: WC_Gateway_Swedbank_Pay_Intl_Tel.utils_script,\n                preferredCountries: [WC_Gateway_Swedbank_Pay_Intl_Tel.country, 'SE', 'NO', 'FI', 'DK'],\n                defaultToFirstCountry: true,\n                nationalMode: false,\n                formatOnDisplay: true,\n                customContainer: 'form-row-wide'\n            }\n        );\n\n        telInput.addEventListener('keyup', formatIntlTelInput);\n        telInput.addEventListener('change', formatIntlTelInput);\n\n        function formatIntlTelInput() {\n            if (typeof intlTelInputUtils !== 'undefined') { // utils are lazy loaded, so must check\n                var currentText = iti.getNumber(intlTelInputUtils.numberFormat.E164);\n                if (typeof currentText === 'string') { // sometimes the currentText is an object :)\n                    iti.setNumber(currentText); // will autoformat because of formatOnDisplay=true\n                }\n            }\n        }\n    }\n});\n"],"mappings":"AAAAA,OAAOC,UAAUC,MAAM,SAAUC,GAO7B,SAASC,IACL,MAAMC,EAAWJ,SAASK,cAAc,kBAExC,IAAIC,EAAMC,OAAOC,aAAaJ,EAAU,CAChCK,YAAaC,iCAAiCC,aAC9CC,mBAAoB,CAACF,iCAAiCG,QAAS,KAAM,KAAM,KAAM,MACjFC,uBAAuB,EACvBC,cAAc,EACdC,iBAAiB,EACjBC,gBAAiB,kBAOzB,SAASC,IACL,GAAiC,oBAAtBC,kBAAmC,CAC1C,IAAIC,EAAcd,EAAIe,UAAUF,kBAAkBG,aAAaC,MACpC,iBAAhBH,GACPd,EAAIkB,UAAUJ,EAEtB,CACJ,CAVAhB,EAASqB,iBAAiB,QAASP,GACnCd,EAASqB,iBAAiB,SAAUP,EAUxC,CA9BAhB,EAAEF,SAAS0B,MAAMC,GAAG,kBAAmB,WACnCxB,GACJ,GAEAA,GA2BJ","ignoreList":[]}
     1{"version":3,"file":"wc-intl-tel.min.js","names":["config","window","WC_Gateway_Swedbank_Pay_Intl_Tel","lib_script","enhanced","Promise","all","import","locale_script","then","module","default","catch","resolve","results","intlTelInput","translations","init","jQuery","document","body","on","error","console","warn","safeLocale","tag","Intl","getCanonicalLocales","length","e","filter","element","contains","iti","destroy","input","querySelector","initialCountry","country","countryOrder","country_order","countryNameLocale","name_locale","uiTranslations","separateDialCode","numberDisplayFormat","containerClass","loadUtils","utils_script","push","addEventListener","normalise","billingCountry","value","setSelectedCountry","toLowerCase","utils","number","getNumber","indexOf","replace","setNumber"],"sources":["wc-intl-tel.js"],"sourcesContent":["/**\n * Enhances the checkout billing phone field with intl-tel-input.\n *\n * This file is loaded as an ES module (see Swedbank_Intl_Tel::script_loader_tag)\n * and pulls the library in with a dynamic import. That is deliberate: the\n * library's classic build declares a top-level `var intlTelInput`, which lands\n * on `window`, so two plugins shipping different versions would clobber each\n * other. An imported binding is module-scoped, so nothing here reads or writes\n * the global and we cannot collide with anyone else's copy.\n */\n( function () {\n\t'use strict';\n\n\tvar config = window.WC_Gateway_Swedbank_Pay_Intl_Tel;\n\n\tif ( ! config || ! config.lib_script ) {\n\t\treturn;\n\t}\n\n\t/**\n\t * Country name translation goes through Intl.DisplayNames, which throws on a\n\t * malformed tag. The library catches that and then blanks every country\n\t * name, so validate before handing the tag over.\n\t *\n\t * @param {string} tag Locale tag.\n\t * @return {string} A usable locale tag.\n\t */\n\tfunction safeLocale( tag ) {\n\t\ttry {\n\t\t\treturn Intl.getCanonicalLocales( tag ).length ? tag : 'en';\n\t\t} catch ( e ) {\n\t\t\treturn 'en';\n\t\t}\n\t}\n\n\t/**\n\t * Load the translated interface strings, if we ship any for this site's\n\t * language. A failure here must not stop the field from initialising.\n\t *\n\t * @return {Promise<Object>} Translations, or an empty object.\n\t */\n\tfunction loadTranslations() {\n\t\tif ( ! config.locale_script ) {\n\t\t\treturn Promise.resolve( {} );\n\t\t}\n\n\t\treturn import( config.locale_script )\n\t\t\t.then( function ( module ) {\n\t\t\t\treturn module.default || {};\n\t\t\t} )\n\t\t\t.catch( function () {\n\t\t\t\treturn {};\n\t\t\t} );\n\t}\n\n\tvar enhanced = [];\n\n\t/**\n\t * Tear down instances whose field has been removed from the page. The\n\t * library holds every instance in a map of its own, so a checkout plugin\n\t * that re-renders the address fields would otherwise pile them up.\n\t */\n\tfunction dropDetached() {\n\t\tenhanced = enhanced.filter(\n\t\t\tfunction ( element ) {\n\t\t\t\tif ( document.contains( element ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif ( element.iti ) {\n\t\t\t\t\telement.iti.destroy();\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Initialise the field, unless it is already initialised. The library keeps\n\t * its instance on the element itself, so that doubles as the guard.\n\t *\n\t * @param {Function} intlTelInput The library.\n\t * @param {Object}   translations Interface translations.\n\t */\n\tfunction init( intlTelInput, translations ) {\n\t\tdropDetached();\n\n\t\tvar input = document.querySelector( '#billing_phone' );\n\n\t\tif ( ! input || input.iti ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar iti = intlTelInput(\n\t\t\tinput,\n\t\t\t{\n\t\t\t\tinitialCountry: config.country || '',\n\t\t\t\tcountryOrder: config.country_order || null,\n\t\t\t\tcountryNameLocale: safeLocale( config.name_locale || 'en' ),\n\t\t\t\tuiTranslations: translations,\n\n\t\t\t\tseparateDialCode: false,\n\t\t\t\tnumberDisplayFormat: 'INTERNATIONAL',\n\n\t\t\t\t// A scope class of our own, so our instances stay addressable if\n\t\t\t\t// another plugin's intl-tel-input stylesheet ever bleeds in. The\n\t\t\t\t// library applies it to the detached mobile selector too.\n\t\t\t\tcontainerClass: 'form-row-wide swedbank-pay-iti',\n\n\t\t\t\tloadUtils: function () {\n\t\t\t\t\treturn import( config.utils_script );\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\tenhanced.push( input );\n\n\t\t/**\n\t\t * Normalise the phone number to E.164 format.\n\t\t */\n\t\tfunction normalise() {\n\t\t\tif ( ! intlTelInput.utils ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar number = iti.getNumber( 'E164' );\n\n\t\t\t// Compared the way wc_sanitize_phone_number() will.\n\t\t\tif ( number && 0 === number.indexOf( '+' ) && number !== input.value.replace( /[^\\d+]/g, '' ) ) {\n\t\t\t\titi.setNumber( number );\n\t\t\t}\n\t\t}\n\n\t\tinput.addEventListener( 'countrychange', normalise );\n\t\tinput.addEventListener( 'change', normalise );\n\t\tinput.addEventListener( 'blur', normalise );\n\n\t\t// Keep the selected country in step with the billing country, so the\n\t\t// number the customer types is interpreted the same way the server will\n\t\t// interpret it.\n\t\tvar billingCountry = document.querySelector( '#billing_country' );\n\t\tif ( billingCountry ) {\n\t\t\tbillingCountry.addEventListener(\n\t\t\t\t'change',\n\t\t\t\tfunction () {\n\t\t\t\t\tif ( ! input.value && billingCountry.value ) {\n\t\t\t\t\t\titi.setSelectedCountry( billingCountry.value.toLowerCase() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\tPromise.all( [ import( config.lib_script ), loadTranslations() ] )\n\t\t.then(\n\t\t\tfunction ( results ) {\n\t\t\t\tvar intlTelInput = results[0].default;\n\t\t\t\tvar translations = results[1];\n\n\t\t\t\tinit( intlTelInput, translations );\n\n\t\t\t\t// Some checkout plugins re-render the address fields. The\n\t\t\t\t// `input.iti` guard above makes this idempotent. Note that\n\t\t\t\t// `updated_checkout` is synthesised by jQuery and so never\n\t\t\t\t// reaches addEventListener().\n\t\t\t\tif ( window.jQuery ) {\n\t\t\t\t\twindow.jQuery( document.body ).on(\n\t\t\t\t\t\t'updated_checkout',\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\tinit( intlTelInput, translations );\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t\t.catch(\n\t\t\tfunction ( error ) {\n\t\t\t\t// A CDN plugin rewriting plugins_url() to a host without CORS\n\t\t\t\t// headers is the likely cause -- module imports are fetched in\n\t\t\t\t// CORS mode, unlike classic scripts. Leave the plain field in\n\t\t\t\t// place rather than failing silently.\n\t\t\t\twindow.console.warn( 'Swedbank Pay: could not load intl-tel-input.', error );\n\t\t\t}\n\t\t);\n}() );\n"],"mappings":"CAUE,WACD,aAEA,IAAIA,EAASC,OAAOC,iCAEpB,GAAOF,GAAYA,EAAOG,WAA1B,CAwCA,IAAIC,EAAW,GAmGfC,QAAQC,IAAK,CAAEC,OAAQP,EAAOG,YAhHtBH,EAAOQ,cAIPD,OAAQP,EAAOQ,eACpBC,KAAM,SAAWC,GACjB,OAAOA,EAAOC,SAAW,CAAC,CAC3B,GACCC,MAAO,WACP,MAAO,CAAC,CACT,GATOP,QAAQQ,QAAS,CAAC,KAgHzBJ,KACA,SAAWK,GACV,IAAIC,EAAeD,EAAQ,GAAGH,QAC1BK,EAAeF,EAAQ,GAE3BG,EAAMF,EAAcC,GAMff,OAAOiB,QACXjB,OAAOiB,OAAQC,SAASC,MAAOC,GAC9B,mBACA,WACCJ,EAAMF,EAAcC,EACrB,EAGH,GAEAJ,MACA,SAAWU,GAKVrB,OAAOsB,QAAQC,KAAM,+CAAgDF,EACtE,EAtKF,CAUA,SAASG,EAAYC,GACpB,IACC,OAAOC,KAAKC,oBAAqBF,GAAMG,OAASH,EAAM,IACvD,CAAE,MAAQI,GACT,MAAO,IACR,CACD,CAoDA,SAASb,EAAMF,EAAcC,GAtB5BZ,EAAWA,EAAS2B,OACnB,SAAWC,GACV,QAAKb,SAASc,SAAUD,KAInBA,EAAQE,KACZF,EAAQE,IAAIC,WAGN,EACR,GAcD,IAAIC,EAAQjB,SAASkB,cAAe,kBAEpC,GAAOD,IAASA,EAAMF,IAAtB,CAIA,IAAIA,EAAMnB,EACTqB,EACA,CACCE,eAAgBtC,EAAOuC,SAAW,GAClCC,aAAcxC,EAAOyC,eAAiB,KACtCC,kBAAmBjB,EAAYzB,EAAO2C,aAAe,MACrDC,eAAgB5B,EAEhB6B,kBAAkB,EAClBC,oBAAqB,gBAKrBC,eAAgB,iCAEhBC,UAAW,WACV,OAAOzC,OAAQP,EAAOiD,aACvB,IAIF7C,EAAS8C,KAAMd,GAkBfA,EAAMe,iBAAkB,gBAAiBC,GACzChB,EAAMe,iBAAkB,SAAUC,GAClChB,EAAMe,iBAAkB,OAAQC,GAKhC,IAAIC,EAAiBlC,SAASkB,cAAe,oBACxCgB,GACJA,EAAeF,iBACd,SACA,YACQf,EAAMkB,OAASD,EAAeC,OACpCpB,EAAIqB,mBAAoBF,EAAeC,MAAME,cAE/C,EAzDF,CA6BA,SAASJ,IACR,GAAOrC,EAAa0C,MAApB,CAIA,IAAIC,EAASxB,EAAIyB,UAAW,QAGvBD,GAAU,IAAMA,EAAOE,QAAS,MAASF,IAAWtB,EAAMkB,MAAMO,QAAS,UAAW,KACxF3B,EAAI4B,UAAWJ,EANhB,CAQD,CAoBD,CAiCD,CA/KA","ignoreList":[]}
  • swedbank-pay-payment-menu/trunk/changelog.txt

    r3652908 r3705285  
     1Version 4.6.2
     2* Enhancement   - Added a new `swedbank_pay_culture` filter for overriding the checkout language.
     3* Fix           - Fixed an issue in the inline embedded checkout where placing an order could abort a payment that was already in progress, leaving the order on Pending payment after the customer had paid.
     4* Fix           - Fixed an issue where capturing, cancelling or refunding an order paid with a separate instrument stopped working after the checkout flow was changed to Seamless Menu, leaving the order status change unprocessed without any error.
     5* Fix           - Fixed an issue where the callback for a captured or refunded payment was logged as a failure, because the payment was looked up by its authorization instead of by the transaction the callback was about.
     6* Fix           - Fixed an issue where cancelling an order added an order note that ended in an empty transaction number, making the cancellation harder to match against the merchant portal.
     7* Fix           - Fixed an issue where a failed API request logged only the base URL and an empty response.
     8
    19Version 4.6.1
    210* Tweak         - Updated the link in the WooCommerce order admin leading to the payment order in the Swedbank Pay merchant portal.
  • swedbank-pay-payment-menu/trunk/includes/class-swedbank-pay-admin.php

    r3488799 r3705285  
    3737                add_action( 'add_meta_boxes', __CLASS__ . '::add_meta_boxes', 10, 2 );
    3838
    39                 // Add action buttons
    40                 add_action( 'woocommerce_order_item_add_action_buttons', __CLASS__ . '::add_action_buttons', 10, 1 );
    41 
    4239                // Add scripts and styles for admin
    4340                add_action( 'admin_enqueue_scripts', __CLASS__ . '::admin_enqueue_scripts' );
    … …  
    174171
    175172        /**
    176          * Add action buttons to Order view
    177          *
    178          * @param WC_Order $order
    179          */
    180         public static function add_action_buttons( $order ) {
    181                 if ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order ) ) {
    182                         // Buttons are available for orders only
    183                         return;
    184                 }
    185 
    186                 // Get Payment Gateway
    187                 if ( swedbank_pay_is_payment_swedbank_method( $order->get_payment_method() ) ) {
    188                         // Get Payment Gateway
    189                         $gateway = swedbank_pay_get_payment_method( $order );
    190                         if ( ! $gateway ) {
    191                                 return;
    192                         }
    193 
    194                         /** @var \Swedbank_Pay_Payment_Gateway_Checkout $gateway */
    195                         wc_get_template(
    196                                 'admin/action-buttons.php',
    197                                 array(
    198                                         'gateway' => $gateway,
    199                                         'order'   => $order,
    200                                 ),
    201                                 '',
    202                                 __DIR__ . '/../templates/'
    203                         );
    204                 }
    205         }
    206 
    207         /**
    208173         * Enqueue Scripts in admin
    209174         *
    … …  
    232197                        );
    233198
     199                        wp_register_style(
     200                                'swedbank-pay-admin-css',
     201                                plugin_dir_url( __FILE__ ) . '../assets/css/admin.css',
     202                                array( 'dashicons' ),
     203                                SWEDBANK_PAY_VERSION
     204                        );
     205
    234206                        // Localize the script.
    235207                        $translation_array = array(
    … …  
    242214
    243215                        // Enqueued script with localized data.
     216                        wp_enqueue_style( 'swedbank-pay-admin-css' );
    244217                        wp_enqueue_script( 'swedbank-pay-admin-js' );
    245218                }
    … …  
    502475                        'payment_order_id' => $payment_order_id,
    503476                );
     477
     478                if ( empty( $gateway ) ) {
     479                        Swedbank_Pay()->logger()->error(
     480                                "[ORDER MANAGEMENT]: Unable to resolve the payment gateway for order #{$order->get_order_number()}. The '{$old_status}->{$new_status}' status change was not forwarded to Swedbank Pay.",
     481                                $context
     482                        );
     483
     484                        return;
     485                }
    504486
    505487                try {
  • swedbank-pay-payment-menu/trunk/includes/class-swedbank-pay-api.php

    r3652908 r3705285  
    347347         */
    348348        public function get_embedded_purchase() {
    349                 $payment_order_id  = explode( '/', WC()->session->get( 'swedbank_pay_paymentorder_id' ) );
    350                 $payment_order_id  = array_pop( $payment_order_id );
     349                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     350                if ( empty( $payment_order_id ) ) {
     351                        return new WP_Error( 'no_payment_order', 'No payment session in progress.' );
     352                }
     353
     354                $parts             = explode( '/', $payment_order_id );
     355                $short_id          = array_pop( $parts );
    351356                $context           = array(
    352                         'payment_order_id' => $payment_order_id,
    353                 );
    354                 LogUtility::$title = "[CHECKOUT]: Get embedded checkout for payment order ID #{$context['payment_order_id']}";
     357                        'payment_order_id' => $short_id,
     358                );
     359                LogUtility::$title = "[CHECKOUT]: Get embedded checkout for payment order ID #{$short_id}";
    355360
    356361                $view_session_url = WC()->session->get( 'swedbank_pay_view_session_url' );
    … …  
    359364                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $result->get_error_message() );
    360365                        Swedbank_Pay()->logger()->error(
    361                                 "[CHECKOUT]: Get embedded checkout for payment order ID #{$context['payment_order_id']}",
     366                                "[CHECKOUT]: Get embedded checkout for payment order ID #{$short_id}",
    362367                                $context
    363368                        );
    … …  
    372377         * Update a embedded payment.
    373378         *
    374          * @param string|null $instrument The instrument to use for the payment, e.g. 'CreditCard'. This is optional and may not be needed for all flows or gateways.
     379         * @param string|null   $instrument The instrument to use for the payment, e.g. 'CreditCard'. This is optional and may not be needed for all flows or gateways.
    375380         * @param WC_Order|null $order The order object to get the order number from if it exists.
    376381         *
    … …  
    378383         */
    379384        public function update_embedded_purchase( $instrument = null, $order = null ) {
     385                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     386                if ( empty( $payment_order_id ) ) {
     387                        return new WP_Error( 'no_payment_order', 'No payment session in progress.' );
     388                }
     389
    380390                $update_payment_url = WC()->session->get( 'swedbank_pay_update_order_url' );
    381391                $helper             = new Cart();
    … …  
    391401                $payment_order_object->setPaymentorder( $payment_order );
    392402
    393                 $payment_order_id = explode( '/', WC()->session->get( 'swedbank_pay_paymentorder_id' ) );
    394                 $payment_order_id = array_pop( $payment_order_id );
     403                $parts    = explode( '/', $payment_order_id );
     404                $short_id = array_pop( $parts );
    395405
    396406                $context = array(
    397                         'payment_order_id' => $payment_order_id,
    398                 );
    399 
    400                 LogUtility::$title = "[CHECKOUT]: Update embedded checkout for payment order ID #{$context['payment_order_id']}";
     407                        'payment_order_id' => $short_id,
     408                );
     409
     410                LogUtility::$title = "[CHECKOUT]: Update embedded checkout for payment order ID #{$short_id}";
    401411                $result            = $this->request( 'PATCH', $update_payment_url, $payment_order_object );
    402412                if ( is_wp_error( Swedbank_Pay()->system_report()->request( $result ) ) ) {
    403413                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $result->get_error_message() );
    404414                        Swedbank_Pay()->logger()->error(
    405                                 "[CHECKOUT]: Update embedded purchase for payment order ID #{$context['payment_order_id']}",
     415                                "[CHECKOUT]: Update embedded purchase for payment order ID #{$short_id}",
    406416                                $context
    407417                        );
    … …  
    496506                );
    497507
    498                 $start = microtime( true );
     508                $start  = microtime( true );
     509                $client = self::get_client();
    499510
    500511                try {
    501                         $client        = self::get_client()->request( $method, $url, $params );
     512                        $client->request( $method, $url, $params );
    502513                        $response_body = $client->getResponseBody();
    503514                        $result        = json_decode( $response_body, true );
    … …  
    509520                        return $result;
    510521                } catch ( \KrokedilSwedbankPayDeps\SwedbankPay\Api\Client\Exception $exception ) {
    511                         $http_code = (int) self::get_client()->getResponseCode();
     522                        $http_code = (int) $client->getResponseCode();
    512523                        $time      = microtime( true ) - $start;
    513524
    … …  
    515526                                '[%.4F] Client Exception. Check debug info: %s',
    516527                                $time,
    517                                 self::get_client()->getDebugInfo()
    518                         );
    519                         $client           = empty( $client ) ? self::get_client() : $client;
     528                                $client->getDebugInfo()
     529                        );
    520530                        LogUtility::log_request( '', $client, WC_Log_Levels::ERROR, $context );
    521531
    522532                        // https://tools.ietf.org/html/rfc7807 .
    523                         $response_body = self::get_client()->getResponseBody() ?? '{}';
     533                        $response_body = $client->getResponseBody() ?? '{}';
    524534                        $data          = json_decode( $response_body, true );
    525535                        if ( json_last_error() === JSON_ERROR_NONE &&
    … …  
    890900                );
    891901
    892                 Swedbank_Pay()->logger()->info( "[UPDATE STATUS]: Update order #{$context['order_number']} status to '{$context['status']}' with transaction ID: {$context['transaction_id']}'", $context );
     902                Swedbank_Pay()->logger()->info( "[UPDATE STATUS]: Update order #{$context['order_number']} status to '{$context['status']}' with transaction ID: '{$context['transaction_id']}'", $context );
    893903
    894904                switch ( $status ) {
    … …  
    11961206                        ->setClient( self::get_client() )
    11971207                        ->setPaymentOrderId( $payment_order_id )
    1198                         ->setExpands( array( 'financialtransactions', 'paid' ) );
     1208                        ->setExpands( array( 'financialtransactions', 'paid', 'cancelled' ) );
    11991209
    12001210                try {
    … …  
    12431253                        }
    12441254
    1245                         $transaction_id = $payment_order->getNumber();
    1246 
    1247                         $this->update_order_status(
    1248                                 $order,
    1249                                 'cancelled',
    1250                                 $transaction_id,
     1255                        // The number belongs to the cancelled sub-resource, not to the payment
     1256                        // order. The status above already confirms the cancellation without it.
     1257                        $cancelled      = $payment_order->getCancelled();
     1258                        $transaction_id = empty( $cancelled ) ? null : $cancelled->offsetGet( 'number' );
     1259
     1260                        $message = empty( $transaction_id )
     1261                                ? __( 'Payment has been cancelled.', 'swedbank-pay-payment-menu' )
    12511262                                // translators: 1: transaction ID.
    1252                                 sprintf( __( 'Payment has been cancelled. Transaction: %s', 'swedbank-pay-payment-menu' ), $transaction_id )
    1253                         );
     1263                                : sprintf( __( 'Payment has been cancelled. Transaction: %s', 'swedbank-pay-payment-menu' ), $transaction_id );
     1264
     1265                        $this->update_order_status( $order, 'cancelled', $transaction_id, $message );
    12541266
    12551267                        return array(
    … …  
    14081420
    14091421                        LogUtility::log_request(
    1410                                 '[ORDER MANAGEMENT]: refund amount',
     1422                                '[ORDER MANAGEMENT]: refund checkout',
    14111423                                $request_service->getClient(),
    14121424                                WC_Log_Levels::DEBUG,
    … …  
    14211433                                $context['error'] = $transaction->get_error_message();
    14221434                                LogUtility::log_request(
    1423                                         '[ORDER MANAGEMENT]: refund amount',
     1435                                        '[ORDER MANAGEMENT]: refund checkout',
    14241436                                        $request_service->getClient(),
    14251437                                        WC_Log_Levels::ERROR,
    … …  
    14361448                        $context['error'] = sprintf( '%s: API Exception: %s', __METHOD__, $e->getMessage() );
    14371449                        LogUtility::log_request(
    1438                                 '[ORDER MANAGEMENT]: refund amount',
     1450                                '[ORDER MANAGEMENT]: refund checkout',
    14391451                                $request_service->getClient(),
    14401452                                WC_Log_Levels::ERROR,
  • swedbank-pay-payment-menu/trunk/includes/class-swedbank-pay-intl-tel.php

    r3458960 r3705285  
    11<?php
     2/**
     3 * International Telephone Input for the checkout phone field.
     4 *
     5 * @package SwedbankPay\Checkout\WooCommerce
     6 */
    27
    38namespace SwedbankPay\Checkout\WooCommerce;
    49
     10use Krokedil\Swedbank\Pay\Utility\BlocksUtility;
     11
    512defined( 'ABSPATH' ) || exit;
    613
     14/**
     15 * Enhances the checkout phone field with the intl-tel-input library.
     16 */
    717class Swedbank_Intl_Tel {
     18        /**
     19         * Version of the bundled intl-tel-input library.
     20         *
     21         * Keep in sync with the pinned version in package.json; run
     22         * `npm run build:vendor` after changing it.
     23         *
     24         * @var string
     25         */
     26        const LIB_VERSION = '29.2.3';
     27
     28        /**
     29         * Script handle for the checkout wrapper.
     30         *
     31         * @var string
     32         */
     33        const HANDLE = 'swedbank-wc-intl-tel-js';
     34
     35        /**
     36         * Locale overrides for the intl-tel-input library.
     37         *
     38         * @var array<string, string>
     39         */
     40        private const LOCALE_OVERRIDES = array(
     41                'nb_NO' => 'no',
     42                'nn_NO' => 'no',
     43                'zh_HK' => 'zh-hk',
     44                'tl'    => 'fil',
     45        );
     46
     47        /**
     48         * Constructor.
     49         */
    850        public function __construct() {
    9                 // JS Scrips
     51                // JS Scripts.
    1052                add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
    1153
    12                 // Add settings
     54                // Load the wrapper as an ES module. See scripts() for why.
     55                add_filter( 'script_loader_tag', array( $this, 'script_loader_tag' ), 10, 3 );
     56
     57                // Add settings.
    1358                add_action( 'woocommerce_after_register_post_type', array( $this, 'woocommerce_init' ), 100 );
    1459        }
    … …  
    3075         * Add settings
    3176         *
    32          * @param $form_fields
    33          *
    34          * @return mixed
     77         * @param array $form_fields The gateway's form fields.
     78         *
     79         * @return array
    3580         */
    3681        public function add_settings( $form_fields ) {
    … …  
    4792        }
    4893
     94        /**
     95         * Whether the phone field should be enhanced on the current request.
     96         *
     97         * @return bool
     98         */
     99        private function is_enabled() {
     100
     101                if ( ! is_checkout() || is_order_received_page() || is_checkout_pay_page() ) {
     102                        return false;
     103                }
     104
     105                if ( BlocksUtility::is_checkout_block_enabled() ) {
     106                        return false;
     107                }
     108
     109                $settings = get_option( 'woocommerce_payex_checkout_settings', array() );
     110
     111                if ( ! wc_string_to_bool( $settings['enabled'] ?? 'no' ) ) {
     112                        return false;
     113                }
     114
     115                return wc_string_to_bool( $settings['enable_intl_tel'] ?? 'no' );
     116        }
     117
     118        /**
     119         * Enqueue the checkout assets.
     120         *
     121         * @return void
     122         */
    49123        public function scripts() {
    50                 if ( ! is_checkout() ) {
    51                         return;
    52                 }
    53 
    54                 $settings = get_option( 'woocommerce_payex_checkout_settings', array( 'enable_intl_tel' => 'no' ) );
    55                 if ( ! isset( $settings['enable_intl_tel'] ) ) {
    56                         $settings['enable_intl_tel'] = 'no';
    57                 }
    58 
    59                 if ( 'no' === $settings['enable_intl_tel'] ) {
     124                if ( ! $this->is_enabled() ) {
    60125                        return;
    61126                }
    … …  
    65130                wp_enqueue_style(
    66131                        'swedbank-intl-tel-css',
    67                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/css/intlTelInput' . $suffix . '.css',
     132                        $this->vendor_url( "css/intlTelInput{$suffix}.css" ),
    68133                        array(),
    69                         '17.0.3',
     134                        self::LIB_VERSION,
    70135                        'all'
    71136                );
    72137
    73138                wp_register_script(
    74                         'swedbank-intl-tel-js',
    75                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/intlTelInput' . $suffix . '.js',
    76                         array(
    77                                 'jquery',
    78                                 'wc-checkout',
    79                         ),
    80                         '17.0.3',
    81                         true
    82                 );
    83 
    84                 wp_register_script(
    85                         'swedbank-wc-intl-tel-js',
    86                         untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/wc-intl-tel' . $suffix . '.js',
    87                         array(
    88                                 'swedbank-intl-tel-js',
    89                         ),
     139                        self::HANDLE,
     140                        SWEDBANK_PAY_PLUGIN_URL . "/assets/js/wc-intl-tel{$suffix}.js",
     141                        array( 'jquery' ),
    90142                        SWEDBANK_PAY_VERSION,
    91143                        true
    92144                );
    93145
    94                 wp_localize_script(
    95                         'swedbank-intl-tel-js',
    96                         'WC_Gateway_Swedbank_Pay_Intl_Tel',
    97                         array(
    98                                 'utils_script' => untrailingslashit( plugins_url( '/', __FILE__ ) ) . '/../assets/js/utils' . $suffix . '.js',
    99                                 'country'      => $this->get_country(),
    100                         )
    101                 );
    102 
    103                 // Enqueued script with localized data.
    104                 wp_enqueue_script( 'swedbank-intl-tel-js' );
    105                 wp_enqueue_script( 'swedbank-wc-intl-tel-js' );
    106         }
    107 
    108         /**
    109          * Get the country ISO code based on the IP address of the client.
     146                wp_localize_script( self::HANDLE, 'WC_Gateway_Swedbank_Pay_Intl_Tel', $this->get_params( $suffix ) );
     147
     148                wp_enqueue_script( self::HANDLE );
     149        }
     150
     151        /**
     152         * Data handed to the wrapper script.
     153         *
     154         * @param string $suffix Minified file suffix.
     155         *
     156         * @return array
     157         */
     158        private function get_params( $suffix ) {
     159                $locale = $this->get_locale_file();
     160
     161                $params = array(
     162                        'lib_script'    => $this->vendor_url( "js/intlTelInput{$suffix}.js" ),
     163                        'utils_script'  => $this->vendor_url( 'js/utils.js' ),
     164                        'locale_script' => $locale ? $this->vendor_url( "js/locale/{$locale}.js" ) : '',
     165                        'name_locale'   => $this->get_country_name_locale(),
     166                        'country'       => $this->get_country(),
     167                        'country_order' => $this->get_country_order(),
     168                );
     169
     170                /**
     171                 * Filter the options handed to intl-tel-input on the checkout.
     172                 *
     173                 * @param array $params
     174                 */
     175                return apply_filters( 'swedbank_pay_intl_tel_params', $params );
     176        }
     177
     178        /**
     179         * Build a URL to a bundled third-party asset, carrying the library version.
     180         *
     181         * @param string $path Path relative to the intl-tel-input vendor directory.
     182         *
     183         * @return string
     184         */
     185        private function vendor_url( $path ) {
     186                return add_query_arg(
     187                        'ver',
     188                        self::LIB_VERSION,
     189                        SWEDBANK_PAY_PLUGIN_URL . '/assets/vendor/intl-tel-input/' . $path
     190                );
     191        }
     192
     193        /**
     194         * Load the wrapper as an ES module so it can import the library.
     195         *
     196         * @param string $tag    The script tag.
     197         * @param string $handle Script handle.
     198         * @param string $src    Script source.
     199         *
     200         * @return string
     201         */
     202        public function script_loader_tag( $tag, $handle, $src ) {
     203                if ( self::HANDLE !== $handle ) {
     204                        return $tag;
     205                }
     206
     207                // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript -- This rewrites the tag of an already enqueued script.
     208                return sprintf( '<script type="module" src="%s" id="%s-js"></script>' . "\n", esc_url( $src ), esc_attr( $handle ) );
     209        }
     210
     211        /**
     212         * Get the locale file name for the current site language, or null if none exists.
     213         *
     214         * @return string|null
     215         */
     216        private function get_locale_file() {
     217                $locale = get_locale();
     218                $name   = self::LOCALE_OVERRIDES[ $locale ] ?? strtolower( strtok( $locale, '_-' ) );
     219
     220                if ( ! preg_match( '/^[a-z-]{2,5}$/', $name ) ) {
     221                        return null;
     222                }
     223
     224                $path = SWEDBANK_PAY_PLUGIN_PATH . '/assets/vendor/intl-tel-input/js/locale/' . $name . '.js';
     225
     226                return file_exists( $path ) ? $name : null;
     227        }
     228
     229        /**
     230         * Locale used to translate the country names via Intl.DisplayNames.
     231         *
     232         * @return string
     233         */
     234        private function get_country_name_locale() {
     235                $locale = str_replace( '_', '-', get_locale() );
     236                $parts  = explode( '-', $locale );
     237                $tag    = strtolower( $parts[0] );
     238
     239                if ( isset( $parts[1] ) && 2 === strlen( $parts[1] ) ) {
     240                        $tag .= '-' . strtoupper( $parts[1] );
     241                }
     242
     243                return preg_match( '/^[a-z]{2,3}(-[A-Z]{2})?$/', $tag ) ? $tag : 'en';
     244        }
     245
     246        /**
     247         * Countries to float to the top of the list.
     248         *
     249         * @return array
     250         */
     251        private function get_country_order() {
     252                $countries = array_merge( array( $this->get_country() ), array( 'SE', 'NO', 'FI', 'DK' ) );
     253
     254                return array_values( array_unique( array_filter( $countries ) ) );
     255        }
     256
     257        /**
     258         * Get the country ISO code to preselect in the country dropdown.
    110259         *
    111260         * @return string The country ISO code.
    112261         */
    113262        private function get_country() {
    114                 return function_exists( 'geoip_detect2_get_info_from_ip' ) ?
    115                         geoip_detect2_get_info_from_ip( geoip_detect2_get_client_ip() )->country->isoCode :
    116                         \WC_Geolocation::geolocate_ip()['country'];
     263                if ( function_exists( 'geoip_detect2_get_info_from_ip' ) ) {
     264                        return geoip_detect2_get_info_from_ip( geoip_detect2_get_client_ip() )->country->isoCode;
     265                }
     266
     267                $country = \WC_Geolocation::geolocate_ip()['country'];
     268
     269                // Fall back to the store's default customer location.
     270                return ! empty( $country ) ? $country : wc_get_customer_default_location()['country'];
    117271        }
    118272}
  • swedbank-pay-payment-menu/trunk/includes/class-swedbank-pay-payment-gateway-checkout.php

    r3652908 r3705285  
    230230        public static function locale_to_culture() {
    231231                $locale = get_locale();
     232                $mapped = $locale;
    232233
    233234                // Format exceptions for locales that do not match the expected format, e.g. fi_FI for Finnish in Finland.
    234                 switch ( $locale ) {
     235                switch ( $mapped ) {
    235236                        case 'fi':
    236                                 $locale = 'fi_FI';
     237                                $mapped = 'fi_FI';
    237238                                break;
    238239                        case 'et':
    239                                 $locale = 'et_EE';
     240                                $mapped = 'et_EE';
    240241                                break;
    241242                        case 'lv':
    242                                 $locale = 'lv_LV';
     243                                $mapped = 'lv_LV';
    243244                                break;
    244245                        default:
    … …  
    246247                }
    247248
    248                 return substr( str_replace( '_', '-', $locale ), 0, 5 );
     249                $culture = substr( str_replace( '_', '-', $mapped ), 0, 5 );
     250
     251                return apply_filters( 'swedbank_pay_culture', $culture, $locale );
    249252        }
    250253
    … …  
    604607                $this->access_token = isset( $this->settings['access_token'] ) ? $this->settings['access_token'] : $this->access_token; // phpcs:ignore
    605608                $this->payee_id     = isset( $this->settings['payee_id'] ) ? $this->settings['payee_id'] : $this->payee_id;
     609                $this->testmode     = isset( $this->settings['testmode'] ) ? $this->settings['testmode'] : $this->testmode;
    606610
    607611                // Test API Credentials.
  • swedbank-pay-payment-menu/trunk/includes/class-swedbank-pay-scheduler.php

    r3568448 r3705285  
    112112                }
    113113
    114                 // v3.1 callbacks no longer carry a transaction.number; finalize_payment falls back
    115                 // to the paymentOrder's `paid` resource to discover the right transaction.
    116                 // process_transaction() dedupes by financial transaction id internally.
     114                // The callback names the transaction it is about. `paid` keeps reporting the
     115                // authorization, which is absent from the transactions list after a capture.
    117116                Swedbank_Pay()->logger()->info( "[SCHEDULER]: Attempting to finalize payment for order #{$context['order_number']} with payment number #{$context['payment_number']}.", $context );
    118                 $result = $gateway->api->finalize_payment( $order );
     117                $result = $gateway->api->finalize_payment( $order, $payment_number );
    119118                if ( is_wp_error( Swedbank_Pay()->system_report()->request( $result ) ) ) {
    120119                        $context['error'] = join( '; ', $result->get_error_messages() );
  • swedbank-pay-payment-menu/trunk/includes/functions.php

    r3652908 r3705285  
    5858 */
    5959function swedbank_pay_get_payment_method( WC_Order $order, bool $use_base_gateway = true ) {
    60         // Get Payment Gateway
     60        $payment_method = $order->get_payment_method();
     61
     62        // The split instrument gateways only exist in the redirect flow, so an order
     63        // paid with one has no registered gateway once the flow changes.
     64        if ( $use_base_gateway && swedbank_pay_is_payment_swedbank_method( $payment_method ) ) {
     65                return swedbank_pay_get_payment_method_by_id();
     66        }
     67
    6168        $gateways = WC()->payment_gateways()->payment_gateways();
    62         if ( ! isset( $gateways[ $order->get_payment_method() ] ) ) {
    63                 return null;
    64         }
    65 
    66         /** @var \WC_Payment_Gateway $gateway */
    67         $gateway = $gateways[ $order->get_payment_method() ];
    68 
    69         if ( $use_base_gateway && swedbank_pay_is_payment_swedbank_method( $gateway->id ) ) {
    70                 $gateway = swedbank_pay_get_payment_method_by_id();
    71         }
    72 
    73         return $gateway;
     69
     70        return $gateways[ $payment_method ] ?? null;
    7471}
    7572
  • swedbank-pay-payment-menu/trunk/readme.txt

    r3652908 r3705285  
    66Requires PHP: 7.4
    77WC requires at least: 5.5.1
    8 WC tested up to: 11.0.1
    9 Stable tag: 4.6.1
     8WC tested up to: 11.1.1
     9Stable tag: 4.6.2
    1010License: Apache License 2.0
    1111License URI: http://www.apache.org/licenses/LICENSE-2.0
    … …  
    9696
    9797== Changelog ==
     98= 2026.09.21    - version 4.6.2 =
     99* Enhancement   - Added a new `swedbank_pay_culture` filter for overriding the checkout language.
     100* Fix           - Fixed an issue in the inline embedded checkout where placing an order could abort a payment that was already in progress, leaving the order on Pending payment after the customer had paid.
     101* Fix           - Fixed an issue where capturing, cancelling or refunding an order paid with a separate instrument stopped working after the checkout flow was changed to Seamless Menu, leaving the order status change unprocessed without any error.
     102* Fix           - Fixed an issue where the callback for a captured or refunded payment was logged as a failure, because the payment was looked up by its authorization instead of by the transaction the callback was about.
     103* Fix           - Fixed an issue where cancelling an order added an order note that ended in an empty transaction number, making the cancellation harder to match against the merchant portal.
     104* Fix           - Fixed an issue where a failed API request logged only the base URL and an empty response.
     105
    98106= 2026.08.18    - version 4.6.1 =
    99107* Tweak         - Updated the link in the WooCommerce order admin leading to the payment order in the Swedbank Pay merchant portal.
  • swedbank-pay-payment-menu/trunk/src/CheckoutFlow/InlineEmbedded.php

    r3652908 r3705285  
    5555         */
    5656        protected function init() {
     57                // Only when rendering the checkout page, since process() manages the payment order itself.
     58                if ( null !== $this->order ) {
     59                        return;
     60                }
     61
    5762                $this->set_is_payment_complete();
    5863                if ( ! $this->is_payment_complete ) {
    … …  
    175180                                }
    176181
    177                                 // A verify operation cannot be updated which is the case for all zero amount order.
     182                                // A verify operation cannot be updated which is the case for all zero amount orders.
    178183                                if ( PaymentDataHelper::OPERATION_VERIFY === $session_operation ) {
    179184                                        return array();
    … …  
    247252
    248253        /**
     254         * Update the payment order with the WooCommerce order number before it is paid.
     255         *
     256         * Unlike create_or_update_embedded_purchase(), the payment order is never
     257         * aborted and the session is never cleared when the update fails. The shopper
     258         * may already have a payment in flight by the time process() runs, e.g. Apple
     259         * Pay authorizing during the place order request, and Swedbank Pay refuses to
     260         * update a payment order while that is the case. Losing the order reference in
     261         * the merchant portal is preferable to orphaning an ongoing payment.
     262         *
     263         * @param \WC_Order $order The WooCommerce order to be processed.
     264         *
     265         * @return void
     266         */
     267        private function maybe_update_order_reference( $order ) {
     268                $payment_order_id = WC()->session->get( 'swedbank_pay_paymentorder_id' );
     269                if ( empty( $payment_order_id ) ) {
     270                        return;
     271                }
     272
     273                // A verify operation cannot be updated which is the case for all zero amount orders.
     274                if ( PaymentDataHelper::OPERATION_VERIFY === WC()->session->get( 'swedbank_pay_operation' ) ) {
     275                        return;
     276                }
     277
     278                $result = $this->api->update_embedded_purchase( null, $order );
     279                if ( is_wp_error( $result ) ) {
     280                        Swedbank_Pay()->logger()->warning(
     281                                sprintf(
     282                                        '[PROCESS PAYMENT]: Failed to update the order reference for order #%s, continuing without it: %s',
     283                                        $this->get_order_number( $order ),
     284                                        $result->get_error_message()
     285                                ),
     286                                array( 'order_id' => $order->get_id() )
     287                        );
     288                }
     289        }
     290
     291        /**
    249292         * Process the payment for the WooCommerce order.
    250293         *
    … …  
    260303                        throw new \Exception( 'Zero order is not supported.' );
    261304                }
     305
     306                $this->maybe_update_order_reference( $order );
    262307
    263308                // Initiate Payment Order.
  • swedbank-pay-payment-menu/trunk/swedbank-pay-payment-menu.php

    r3652908 r3705285  
    88 * License: Apache License 2.0
    99 * License URI: http://www.apache.org/licenses/LICENSE-2.0
    10  * Version: 4.6.1
     10 * Version: 4.6.2
    1111 * Text Domain: swedbank-pay-payment-menu
    1212 * Domain Path: /languages
    1313 *
    1414 * WC requires at least: 5.5.1
    15  * WC tested up to: 11.0.1
     15 * WC tested up to: 11.1.1
    1616 * Requires Plugins: woocommerce
    1717 *
    … …  
    2828
    2929defined( 'ABSPATH' ) || exit;
    30 define( 'SWEDBANK_PAY_VERSION', '4.6.1' );
     30define( 'SWEDBANK_PAY_VERSION', '4.6.2' );
    3131define( 'SWEDBANK_PAY_MAIN_FILE', __FILE__ );
    3232define( 'SWEDBANK_PAY_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
  • swedbank-pay-payment-menu/trunk/templates/admin/payment-actions.php

    r3516255 r3705285  
    1010?>
    1111<div>
    12         <strong><?php esc_html_e( 'Payment Info', 'swedbank-pay-payment-menu' ); ?></strong>
    13         <br />
     12        <?php $transaction_url = $gateway->get_transaction_url( $order ); ?>
    1413        <?php if ( isset( $info['paid']['number'] ) ) : ?>
    15                 <strong><?php esc_html_e( 'Number', 'swedbank-pay-payment-menu' ); ?>
    16                         :</strong> <?php echo esc_html( $info['paid']['number'] ); ?>
    17                 <br/>
     14                <p>
     15                        <strong><?php esc_html_e( 'Number', 'swedbank-pay-payment-menu' ); ?></strong>
     16                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The payment number assigned by Swedbank Pay. Use it when referring to the payment in the Merchant Portal or in support requests.', 'swedbank-pay-payment-menu' ) ) ); ?>
     17                        <br/>
     18                        <?php if ( $transaction_url ) : ?>
     19                                <a href="<?php echo esc_url( $transaction_url ); ?>"
     20                                        target="_blank"
     21                                        rel="noopener noreferrer"
     22                                        class="swedbank-pay-transaction-link">
     23                                        <?php echo esc_html( $info['paid']['number'] ); ?>
     24                                        <span class="screen-reader-text"><?php esc_html_e( '(opens the payment in the Merchant Portal in a new tab)', 'swedbank-pay-payment-menu' ); ?></span>
     25                                </a>
     26                                <span class="dashicons dashicons-external" aria-hidden="true"></span>
     27                        <?php else : ?>
     28                                <?php echo esc_html( $info['paid']['number'] ); ?>
     29                        <?php endif; ?>
     30                </p>
    1831        <?php endif; ?>
    1932        <?php if ( isset( $info['paid']['instrument'] ) ) : ?>
    20                 <strong><?php esc_html_e( 'Instrument', 'swedbank-pay-payment-menu' ); ?>
    21                         : </strong> <?php echo esc_html( $info['paid']['instrument'] ); ?>
    22                 <br/>
     33                <p>
     34                        <strong><?php esc_html_e( 'Instrument', 'swedbank-pay-payment-menu' ); ?></strong>
     35                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The payment instrument the customer paid with, for example Card, Swish or Invoice.', 'swedbank-pay-payment-menu' ) ) ); ?>
     36                        <br/>
     37                        <?php echo esc_html( $info['paid']['instrument'] ); ?>
     38                </p>
    2339        <?php endif; ?>
    2440        <?php if ( isset( $info['paid']['transactionType'] ) ) : ?>
    25                 <strong><?php esc_html_e( 'Transaction type', 'swedbank-pay-payment-menu' ); ?>
    26                         : </strong> <?php echo esc_html( $info['paid']['transactionType'] ); ?>
    27                 <br/>
     41                <p>
     42                        <strong><?php esc_html_e( 'Transaction type', 'swedbank-pay-payment-menu' ); ?></strong>
     43                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The type of transaction performed on the payment, for example Authorization or Sale.', 'swedbank-pay-payment-menu' ) ) ); ?>
     44                        <br/>
     45                        <?php echo esc_html( $info['paid']['transactionType'] ); ?>
     46                </p>
    2847        <?php endif; ?>
    2948        <?php if ( isset( $info['paid']['payeeReference'] ) ) : ?>
    30                 <strong><?php esc_html_e( 'Payee Reference', 'swedbank-pay-payment-menu' ); ?>
    31                         : </strong> <?php echo esc_html( $info['paid']['payeeReference'] ); ?>
    32                 <br/>
     49                <p>
     50                        <strong><?php esc_html_e( 'Payee Reference', 'swedbank-pay-payment-menu' ); ?></strong>
     51                        <?php echo wp_kses_post( wc_help_tip( esc_html__( 'The unique reference sent to Swedbank Pay for this payment. It ties the order in the store to the payment at Swedbank Pay.', 'swedbank-pay-payment-menu' ) ) ); ?>
     52                        <br/>
     53                        <?php echo esc_html( $info['paid']['payeeReference'] ); ?>
     54                </p>
    3355        <?php endif; ?>
    34         <?php if ( $gateway->api->can_capture( $order ) ) : ?>
    35                 <button id="swedbank_pay_capture"
    36                                 data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
    37                                 data-order-id="<?php echo esc_html( $order->get_id() ); ?>">
    38                         <?php esc_html_e( 'Capture Payment', 'swedbank-pay-payment-menu' ); ?>
    39                 </button>
    40         <?php endif; ?>
     56        <?php
     57        $can_capture = $gateway->api->can_capture( $order );
     58        $can_cancel  = $gateway->api->can_cancel( $order );
     59        ?>
     60        <?php if ( $can_capture || $can_cancel ) : ?>
     61                <details class="swedbank-pay-advanced">
     62                        <summary class="swedbank-pay-advanced__summary">
     63                                <?php esc_html_e( 'Advanced', 'swedbank-pay-payment-menu' ); ?>
     64                        </summary>
     65                        <div class="swedbank-pay-advanced__content">
     66                                <?php if ( $can_capture ) : ?>
     67                                        <p class="swedbank-pay-advanced__action">
     68                                                <button id="swedbank_pay_capture"
     69                                                                type="button" class="button"
     70                                                                data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
     71                                                                data-order-id="<?php echo esc_attr( $order->get_id() ); ?>">
     72                                                        <?php esc_html_e( 'Capture Payment', 'swedbank-pay-payment-menu' ); ?>
     73                                                </button>
     74                                        </p>
     75                                <?php endif; ?>
    4176
    42         <?php if ( $gateway->api->can_cancel( $order ) ) : ?>
    43                 <button id="swedbank_pay_cancel"
    44                                 data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
    45                                 data-order-id="<?php echo esc_html( $order->get_id() ); ?>">
    46                         <?php esc_html_e( 'Cancel Payment', 'swedbank-pay-payment-menu' ); ?>
    47                 </button>
     77                                <?php if ( $can_cancel ) : ?>
     78                                        <p class="swedbank-pay-advanced__action">
     79                                                <button id="swedbank_pay_cancel"
     80                                                                type="button" class="button"
     81                                                                data-nonce="<?php echo esc_attr( wp_create_nonce( 'swedbank_pay' ) ); ?>"
     82                                                                data-order-id="<?php echo esc_attr( $order->get_id() ); ?>">
     83                                                        <?php esc_html_e( 'Cancel Payment', 'swedbank-pay-payment-menu' ); ?>
     84                                                </button>
     85                                        </p>
     86                                <?php endif; ?>
     87                        </div>
     88                </details>
    4889        <?php endif; ?>
    4990</div>
  • swedbank-pay-payment-menu/trunk/vendor/composer/installed.php

    r3652908 r3705285  
    22    'root' => array(
    33        'name' => 'swedbank-pay/woocommerce-payment-menu',
    4         'pretty_version' => '4.6.1',
    5         'version' => '4.6.1.0',
    6         'reference' => '79901a987e2c97b14b429e258739489773e7e0ed',
     4        'pretty_version' => '4.6.2',
     5        'version' => '4.6.2.0',
     6        'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1212    'versions' => array(
    1313        'swedbank-pay/woocommerce-payment-menu' => array(
    14             'pretty_version' => '4.6.1',
    15             'version' => '4.6.1.0',
    16             'reference' => '79901a987e2c97b14b429e258739489773e7e0ed',
     14            'pretty_version' => '4.6.2',
     15            'version' => '4.6.2.0',
     16            'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
  • swedbank-pay-payment-menu/trunk/vendor/dependencies/composer/installed.php

    r3652908 r3705285  
    33namespace KrokedilSwedbankPayDeps;
    44
    5 return array('root' => array('name' => '__root__', 'pretty_version' => '4.6.1', 'version' => '4.6.1.0', 'reference' => '79901a987e2c97b14b429e258739489773e7e0ed', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '4.6.1', 'version' => '4.6.1.0', 'reference' => '79901a987e2c97b14b429e258739489773e7e0ed', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.5', 'version' => '1.3.5.0', 'reference' => 'e8f015fefcc42599b40fc0953a27f788ac24a853', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.2', 'version' => '1.0.2.0', 'reference' => '99059b1b27cc4ed7667c1d04968aec45413fe533', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/random_compat' => array('pretty_version' => 'v9.99.100', 'version' => '9.99.100.0', 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/random_compat', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '3.9.7', 'version' => '3.9.7.0', 'reference' => 'dc75aa439eb4c1b77f5379fd958b3dc0e6014178', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '3.9.7')), 'swedbank-pay/swedbank-pay-sdk-php' => array('pretty_version' => '6.3.0', 'version' => '6.3.0.0', 'reference' => '1a85aa5d724954f6b8852a982f8f7cb02c68ebca', 'type' => 'library', 'install_path' => __DIR__ . '/../swedbank-pay/swedbank-pay-sdk-php', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false)));
     5return array('root' => array('name' => '__root__', 'pretty_version' => '4.6.2', 'version' => '4.6.2.0', 'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \true), 'versions' => array('__root__' => array('pretty_version' => '4.6.2', 'version' => '4.6.2.0', 'reference' => 'ffffcb1b1ee1bc230eb5045a38eb9b6ffad58d02', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/settings-page' => array('pretty_version' => '1.3.5', 'version' => '1.3.5.0', 'reference' => 'e8f015fefcc42599b40fc0953a27f788ac24a853', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/settings-page', 'aliases' => array(), 'dev_requirement' => \false), 'krokedil/support' => array('pretty_version' => '1.0.2', 'version' => '1.0.2.0', 'reference' => '99059b1b27cc4ed7667c1d04968aec45413fe533', 'type' => 'library', 'install_path' => __DIR__ . '/../krokedil/support', 'aliases' => array(), 'dev_requirement' => \false), 'paragonie/random_compat' => array('pretty_version' => 'v9.99.100', 'version' => '9.99.100.0', 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/random_compat', 'aliases' => array(), 'dev_requirement' => \false), 'ramsey/uuid' => array('pretty_version' => '3.9.7', 'version' => '3.9.7.0', 'reference' => 'dc75aa439eb4c1b77f5379fd958b3dc0e6014178', 'type' => 'library', 'install_path' => __DIR__ . '/../ramsey/uuid', 'aliases' => array(), 'dev_requirement' => \false), 'rhumsaa/uuid' => array('dev_requirement' => \false, 'replaced' => array(0 => '3.9.7')), 'swedbank-pay/swedbank-pay-sdk-php' => array('pretty_version' => '6.3.0', 'version' => '6.3.0.0', 'reference' => '1a85aa5d724954f6b8852a982f8f7cb02c68ebca', 'type' => 'library', 'install_path' => __DIR__ . '/../swedbank-pay/swedbank-pay-sdk-php', 'aliases' => array(), 'dev_requirement' => \false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.37.0', 'version' => '1.37.0.0', 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => \false)));
Note: See TracChangeset for help on using the changeset viewer.