PluginProbe
Pay with Vipps and MobilePay for WooCommerce / 6.2.4
Pay with Vipps and MobilePay for WooCommerce v6.2.4
6.2.4 6.2.3 6.2.2 6.2.1 6.2.0 6.1.10 6.1.9 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1.0 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 5.4.3 5.4.2 5.4.1 All 186 releases
← All changes | payment/Vipps.class.php +354 -241 6.1.96.2.4 View file →
@@ -125,8 +125,13 @@
125 125 // Express Checkout and Checkout supports the new pickup_location shipping method, but the admin interface for this may
126 126 // not have loaded if the default checkout solution isn't the Checkout block. We'll load it anyway if the user has any local pickup locations
127 127 // stored in the database since we support this for both Vipps MobilePay checkokut and Express. IOK 2026-02-25
128 128 add_action('woocommerce_load_shipping_methods', array($Vipps, 'maybe_load_pickup_locations'), 90);
129 +
130 + // Vipps Checkout replaces the default checkout page, and currently uses its own page for this which needs to exist
131 + // Will also probably be used to maintain a real utility-page for Vipps actions later for themes where this
132 + // is important.
133 + add_filter('woocommerce_create_pages', array($Vipps, 'woocommerce_create_pages'), 50, 1);
129 134 }
130 135
131 136 // Register woocommerce store api endpoint to use in buy-now minicart block. LP 2026-02-10
132 137 public function woocommerce_blocks_loaded() {
@@ -280,8 +285,38 @@
280 285 }
281 286
282 287 // Set default button options, migrating any older setup IOK 2026-07-15
283 288 $this->init_button_options();
289 +
290 + /*
291 + From version 6.2.x we create a real physical page to handle the "special" vipps pages,
292 + where we earlier used just a fake page with no real page id, unless especially configured.
293 + We therefore need to add code to maintain this special page.
294 +
295 + woocommerce_loaded is too early for this because of maybe_create_vipps_pages which calls WC_Install::create_pages,
296 + and we hook unto this with woocommerce_create_pages. LP 2026-09-03
297 + */
298 +
299 + // Delete special page id option when its deleted or trashed, so that we dont have to load
300 + // in the post to check status in woocommerce_loaded when we ensure the special page exists. LP 2026-09-03
301 + $delete_special_page_id = function($post_id, $post = null) {
302 + if (static::get_special_page_id() === $post_id) {
303 + delete_option('woocommerce_vipps_special_page_page_id');
304 + }
305 + };
306 + add_action('delete_post', $delete_special_page_id, 10, 2);
307 + add_action('wp_trash_post', $delete_special_page_id, 10, 2);
308 +
309 + $this->ensure_special_page_exists();
310 +
311 +
312 + // We want this special page to have a certain title and maybe special scripts and so on,
313 + // this gets run in template redirect for these pages.
314 + add_action('woo_vipps_before_handling_special_page', array($this, 'pre_special_page_actions'));
315 +
316 + // Add an admin interface for this page as well IOK 2026-09-11
317 + add_action('woocommerce_settings_pages', array($this, 'woocommerce_settings_pages'));
318 +
284 319 }
285 320
286 321 public function admin_init () {
287 322 $gw = $this->gateway();
@@ -401,9 +436,77 @@
401 436 }
402 437 }
403 438 }
404 439
440 +
441 + /** Ensure we have a special page for payment flows
442 + *
443 + * woocommerce_loaded is too early for this because of maybe_create_vipps_pages which calls WC_Install::create_pages,
444 + * and we hook unto this with woocommerce_create_pages. LP 2026-09-03
445 + **/
446 + public function ensure_special_page_exists() {
447 + if (static::get_special_page_id()) return;
448 + $this->log(__('Missing id for special page, attempting to fix.', 'woo-vipps'), 'info');
405 449
450 + // If user had in previous version overriden the fake page with a real one: migrate this page to be the special page. LP 2026-09-01
451 + $old_special_page_id = $this->gateway()->get_option('vippsspecialpageid');
452 + if ($old_special_page_id && ($special_page = get_post($old_special_page_id)) && "trash" !== $special_page->post_status) {
453 + $this->log(__('Migrated old special page setting.', 'woo-vipps'), 'info');
454 + // there is no wc_set_page_id() so we update the option directly. LP 2026-09-01
455 + update_option('woocommerce_vipps_special_page_page_id', $old_special_page_id);
456 +
457 + // Ensure this page has the necessary shortcode. LP 2026-09-01
458 + if (!has_shortcode($special_page->post_content, 'vipps_special_page')) {
459 + $new_content = $special_page->post_content . "\n\n<!-- wp:shortcode -->[vipps_special_page]<!-- /wp:shortcode -->";
460 + wp_update_post([
461 + 'ID' => $old_special_page_id,
462 + 'post_content' => $new_content,
463 + ]);
464 + }
465 + } else {
466 + // Create special page if its missing. LP 2026-09-01
467 + $this->maybe_create_vipps_pages();
468 + }
469 + }
470 +
471 + // Admin interface for the special page on woo/advanced/pages
472 + public function woocommerce_settings_pages ($settings) {
473 + $i = -1;
474 + foreach($settings as $entry) {
475 + $i++;
476 + if ($entry['type'] == 'sectionend' && $entry['id'] == 'advanced_page_options') {
477 + break;
478 + }
479 + }
480 + if ($i > 0) {
481 + $vippspagesettings = array(
482 + array(
483 + 'title' => sprintf(__( '%1$s Page', 'woo-vipps' ), Vipps::CompanyName()),
484 + 'desc' => sprintf(__('This page is used for various special pages used by %1$s', 'woo-vipps'), Vipps::CompanyName()) . sprintf( __( 'Page contents: [%1$s]', 'woocommerce' ), 'vipps_special_page') ,
485 + 'id' => 'woocommerce_vipps_special_page_page_id',
486 + 'type' => 'single_select_page_with_search',
487 + 'default' => '',
488 + 'class' => 'wc-page-search',
489 + 'css' => 'min-width:300px;',
490 + 'args' => array(
491 + 'exclude' =>
492 + array(
493 + wc_get_page_id( 'myaccount' ),
494 + wc_get_page_id( 'checkout' ),
495 + wc_get_page_id( 'cart' ),
496 + ),
497 + ),
498 + 'desc_tip' => true,
499 + 'autoload' => false,
500 + ));
501 + array_splice($settings, $i, 0, $vippspagesettings);
502 + }
503 +
504 + return $settings;
505 + }
506 +
507 +
508 +
406 509 // Runs on init, adds the Vipps badge feature if activated
407 510 public function maybe_add_vipps_badge_feature () {
408 511 $badge_options = get_option('vipps_badge_options');
409 512 if (!$badge_options || !@$badge_options['badgeon']) return false;
@@ -1164,9 +1267,9 @@
1164 1267
1165 1268 // Update the preview web component's attributes. LP 2026-06-24
1166 1269 function updatePreview(event) {
1167 1270 const args = getPreviewArgs();
1168 - // LP FIXME: when i use get_customer_language() here it gives me my user language, but on frontend it gives the site language, i.e not the same value. So this preview will be wrong language. so use get_locale for now. LP 2026-07-02
1271 + // FIXME: when i use get_customer_language() here it gives me my user language, but on frontend it gives the site language, i.e not the same value. So this preview will be wrong language. so use get_locale for now. LP 2026-07-02
1169 1272 // if ('store' === args.language) args.language = '<?php echo $this->get_customer_language(); ?>';
1170 1273 if ('store' === args.language) args.language = '<?php echo substr(get_locale(), 0, 2); ?>';
1171 1274 const button = jQuery('#vipps-button-express-preview');
1172 1275 button.attr(args);
@@ -1704,8 +1807,11 @@
1704 1807 // New vipps-mobilepay-badge shortcode. LP 19.11.2024
1705 1808 add_shortcode('vipps-mobilepay-badge', array($this, 'vipps_mobilepay_badge_shortcode'));
1706 1809 // Legacy vipps-badge shortcode. LP 19.11.2024
1707 1810 add_shortcode('vipps-badge', array($this, 'vipps_badge_shortcode'));
1811 +
1812 + // special page handling, previously a fake page. LP 2026-08-25
1813 + add_shortcode('vipps_special_page', array($this, 'vipps_special_page_shortcode'));
1708 1814 }
1709 1815
1710 1816
1711 1817 public function log ($what,$type='info') {
@@ -1731,8 +1837,10 @@
1731 1837 }
1732 1838
1733 1839 // Show express button option on checkout form. LP 2026-03-23
1734 1840 public function checkout_before_customer_details_express () {
1841 + if (did_action('woo_vipps_checkout_before_customer_details_express')) return;
1842 + do_action('woo_vipps_checkout_before_customer_details_express');
1735 1843 $gw = $this->gateway();
1736 1844 if (!$gw->show_express_checkout()) return;
1737 1845 $this->express_checkout_section_html();
1738 1846 }
@@ -2518,77 +2626,87 @@
2518 2626 return null;
2519 2627 }
2520 2628 }
2521 2629
2630 + // Special pages, and some callbacks. IOK 2018-05-18
2631 + public function template_redirect() {
2522 2632
2523 - // If this is a special page, return true very early because we are handling this. IOK 2023-02-22
2524 - public function pre_handle_404($current, $query) {
2525 - if (!is_admin()) {
2526 - $special = $this->is_special_page();
2527 - if ($special) {
2528 - // Ensure very early on that Autooptimize does not try to optimize us (if installed) IOK 2023-03-04
2529 - add_filter( 'autoptimize_filter_noptimize', '__return_true');
2530 - return true;
2531 - }
2633 + // Handle legacy vipps-buy-now urls that auto-start express checkout for certain product - in QR codes etc IOK 2026-09-11
2634 + // We redirect these to the new location.
2635 + $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
2636 + if (( ($_GET['VippsSpecialPage'] ?? '') == 'vipps-buy-product') || ($path && preg_match("!/vipps-buy-product/?$!", $path)) ) {
2637 + $url = static::get_special_page_url();
2638 + $_GET['action'] = 'buy_product';
2639 + $q = build_query($_GET);
2640 + wp_redirect($url . "?" . $q, 302);
2641 + exit();
2532 2642 }
2533 - return $current;
2643 +
2644 + if (static::is_special_page()) {
2645 + // Legacy: Stop the canonical redirect here. Unclear if still necessary. IOK 2026-09-11
2646 + remove_filter('template_redirect', 'redirect_canonical', 10);
2647 + // dont cache special page. LP 2026-08-25
2648 + $this->nocache();
2649 + // Do the custom pre-load actions for these pages IOK 2026-09-11
2650 + do_action('woo_vipps_before_handling_special_page', ($_GET['action'] ?? ""));
2651 + }
2534 2652 }
2535 2653
2536 - // Special pages, and some callbacks. IOK 2018-05-18
2537 - public function template_redirect() {
2538 - global $post;
2539 - // Handle special callbacks
2540 - $special = $this->is_special_page() ;
2654 + // Ran in template redirect for the special page. IOK 2026-09-2
2655 + public function pre_special_page_actions ($action) {
2656 + // Change title dynamically depending on action. LP 2026-09-02
2657 + add_filter('the_title', [$this, 'vipps_special_page_endpoint_title'], 10, 2);
2541 2658
2542 - if ($special) {
2543 - remove_filter('template_redirect', 'redirect_canonical', 10);
2544 - do_action('woo_vipps_before_handling_special_page', $special);
2659 + // If we are handling the 'wait for payment' action, we need to poll the order status before
2660 + // we start producing content IOK 2026-09-21
2661 + if ($action == 'wait_for_payment') {
2662 + $this->handle_payment_poll_and_redirect();
2663 + }
2545 2664
2546 - // Allow above hook to actually handle special pages. It should probably call $Vipps->fakepage or a redirect; can be used
2547 - // to intercept express checkout etc. IOK 2022-03-18
2548 - if (! apply_filters('woo_vipps_special_page_handled', false, $special)) {
2549 - $this->$special();
2550 - }
2665 + // Some validation is required for this action
2666 + if ($action == 'do_express_checkout') {
2667 + $this->vipps_express_checkout_consistency_check();
2551 2668 }
2669 + }
2552 2670
2553 - $consentremoval = $this->is_consent_removal();
2554 - if ($consentremoval) {
2555 - remove_filter('template_redirect', 'redirect_canonical', 10);
2556 - do_action('woo_vipps_before_handling_special_page', 'consentremoval');
2557 - if (! apply_filters('woo_vipps_special_page_handled', false, 'consentremoval')) {
2558 - $this->vipps_consent_removal_callback($consentremoval);
2671 +
2672 + // Dynamic special page title depending on endpoint/action, only frontend. LP 2026-09-02
2673 + public function vipps_special_page_endpoint_title($title, $postid = 0) {
2674 + global $wp_query;
2675 + // Comment from woocommerce's wc_page_endpoint_title where this logic is from: LP 2026-09-02
2676 +
2677 + // In block themes the whole template (header, footer, content) renders inside the main
2678 + // loop, so `the_title` fires for any post title rendered on the page (e.g. a product in a
2679 + // server-rendered mini-cart) - not just the page's own heading. Only replace the title of
2680 + // the queried page so an earlier title doesn't consume this one-shot filter.
2681 + if ( ! is_null( $wp_query ) && ! is_admin() && is_main_query() && in_the_loop() && is_page() && $postid == static::get_special_page_id() ) {
2682 + switch ($_GET['action'] ?? '') {
2683 + case 'wait_for_payment':
2684 + $title = __('Processing order', 'woo-vipps');
2685 + break;
2686 + case 'do_express_checkout':
2687 + case 'buy_product':
2688 + $title = __('Express Checkout', 'woo-vipps');
2689 + break;
2559 2690 }
2560 2691 }
2692 + return $title;
2561 2693 }
2694 +
2562 2695 // Template handling for special pages. IOK 2018-11-21
2696 + // This is legacy - the special page is now a real page, so it can have a special template using standard WP methods. IOK 2026-09-11
2563 2697 public function template_include($template) {
2564 - $special = $this->is_special_page() ;
2565 - if ($special) {
2698 + if (static::is_special_page()) {
2566 2699 // Get any special template override from the options IOK 2020-02-18
2567 2700 $specific = $this->gateway()->get_option('vippsspecialpagetemplate');
2568 2701 $found = locate_template($specific,false,false);
2569 2702 if ($found) $template=$found;
2570 2703
2571 - return apply_filters('woo_vipps_special_page_template', $template, $special);
2704 + return apply_filters('woo_vipps_special_page_template', $template, $_GET['action'] ?? '');
2572 2705 }
2573 2706 return $template;
2574 2707 }
2575 2708
2576 -
2577 - // Can't use wc-api for this, as that does not support DELETE . IOK 2018-05-18
2578 - private function is_consent_removal () {
2579 -
2580 - if ($_SERVER['REQUEST_METHOD'] != 'DELETE') return false;
2581 - if ( !get_option('permalink_structure')) {
2582 - if (@$_REQUEST['vipps-consent-removal']) return @$_REQUEST['callback'];
2583 - return false;
2584 - }
2585 - if (preg_match("!/vipps-consent-removal/([^/]*)!", $_SERVER['REQUEST_URI'], $matches)) {
2586 - return @$_REQUEST['callback'];
2587 - }
2588 - return false;
2589 - }
2590 -
2591 2709 // On the thank you page, we have a completed order, so we need to restore any saved cart and possibly log in
2592 2710 // the user if using Express Checkout IOK 2020-10-09
2593 2711 public function woocommerce_before_thankyou ($orderid) {
2594 2712 $order = wc_get_order($orderid);
@@ -2656,9 +2774,8 @@
2656 2774
2657 2775 // Support adding pickup locations to any shipping rate using the 'woo_vipps_shipping_method_pickup_points' filter
2658 2776 // IOK 2025-11-19
2659 2777 add_filter('woo_vipps_modify_express_checkout_rate', array($this, 'express_add_pickup_location_options'), 10, 4);
2660 -
2661 2778 }
2662 2779
2663 2780 public function get_payment_method_name() {
2664 2781 return $this->gateway()->get_option('payment_method_name');
@@ -2683,9 +2800,8 @@
2683 2800 // Will also probably be used to maintain a real utility-page for Vipps actions later for themes where this
2684 2801 // is important.
2685 2802 add_filter('woocommerce_create_pages', array($this, 'woocommerce_create_pages'), 50, 1);
2686 2803
2687 -
2688 2804 // Callbacks use the Woo API IOK 2018-05-18
2689 2805 add_action( 'woocommerce_api_wc_gateway_vipps', array($this,'vipps_callback'));
2690 2806 add_action( 'woocommerce_api_vipps_shipping_details', array($this,'vipps_shipping_details_callback'));
2691 2807
@@ -2696,9 +2812,9 @@
2696 2812 add_action( 'woocommerce_cart_actions', array($this, 'cart_express_checkout_button'));
2697 2813 add_action( 'woocommerce_widget_shopping_cart_buttons', array($this, 'minicart_express_checkout_button'), 30);
2698 2814
2699 2815 // Previously we added an express html banner to the action 'woocommerce_before_checkout_form.',
2700 - // replaced by the new express buttons in manner more like Gutenberg. LP 2026-03-23
2816 + // replaced by the new express buttons in manner more like Gutenberg. for grepping: "express legacy checkout". LP 2026-03-23
2701 2817 add_action('woocommerce_checkout_before_customer_details', array($this, 'checkout_before_customer_details_express'), 5);
2702 2818
2703 2819 add_action('woocommerce_after_add_to_cart_button', array($this, 'single_product_buy_now_button'));
2704 2820 add_action('woocommerce_after_shop_loop_item', array($this, 'loop_single_product_buy_now_button'), 20);
@@ -2703,12 +2819,10 @@
2703 2819 add_action('woocommerce_after_add_to_cart_button', array($this, 'single_product_buy_now_button'));
2704 2820 add_action('woocommerce_after_shop_loop_item', array($this, 'loop_single_product_buy_now_button'), 20);
2705 2821
2706 2822
2707 - // Special pages and callbacks handled by template_redirect
2708 - // We must also notify WP and other plugins that we are handling this 404-like situation. IOK 2023-02-22
2823 + // Special pages and callbacks handled by template_redirect. IOK 2023-02-22
2709 2824 add_action('template_redirect', array($this,'template_redirect'),1);
2710 - add_action('pre_handle_404', array($this, 'pre_handle_404'), 1, 2);
2711 2825
2712 2826 // Allow overriding their templates
2713 2827 add_filter('template_include', array($this,'template_include'), 10, 1);
2714 2828
@@ -4120,17 +4234,8 @@
4120 4234 header("X-Accel-Expires: 0");
4121 4235 }
4122 4236
4123 4237
4124 -
4125 - // Handle DELETE on a vipps consent removal callback
4126 - public function vipps_consent_removal_callback ($callback) {
4127 - Vipps::nocache();
4128 - // Currently, no such requests will be posted, and as this code isn't sufficiently tested,we'll just have
4129 - // to escape here when the API is changed. IOK 2020-10-14
4130 - $this->log("Consent removal is non-functional pending API changes as of 2020-10-14"); print "1"; exit();
4131 - }
4132 -
4133 4238 public function woocommerce_payment_gateways($methods) {
4134 4239 require_once(dirname(__FILE__) . "/WC_Gateway_Vipps.class.php");
4135 4240 require_once(dirname(__FILE__) . "/WC_Gateway_VippsCard.class.php");
4136 4241 // Protect the singleton: Use the object instead of the class name IOK 2025-02-04
@@ -4155,9 +4260,11 @@
4155 4260 if ( empty($_REQUEST['add-to-cart']) || ! is_numeric($_REQUEST['add-to-cart']) || empty($_REQUEST['vipps_compat_mode']) || !$_REQUEST['vipps_compat_mode']) {
4156 4261 return $url;
4157 4262 }
4158 4263 $url = $this->express_checkout_url();
4159 - $url = wp_nonce_url($url,'express','sec');
4264 + // At this point, there is always a query argument here. IOK 2026-09-21
4265 + $nonce = wp_create_nonce('express');
4266 + $url = $url . "&sec=$nonce";
4160 4267
4161 4268 return $url;
4162 4269 }
4163 4270
@@ -4253,20 +4360,40 @@
4253 4360 }
4254 4361 }
4255 4362
4256 4363 public function activate () {
4257 - static::maybe_add_cron_event();
4258 - $gw = $this->gateway();
4364 + static::maybe_add_cron_event();
4365 + $gw = $this->gateway();
4259 4366
4260 - // If store is using the default "Woo" orderprefix, generate a new one, this time using the stores' sitename if possible. IOK 2020-05-19
4261 - if ($gw->get_option('orderprefix') == 'Woo') {
4262 - $gw->update_option('orderprefix', $this->generate_order_prefix());
4263 - }
4264 - // IOK 2023-12-20 for the epayment api, we need to re-initialize webhooks at this point.
4265 - $gw->initialize_webhooks();
4266 - $this->payment_method_name = $gw->get_option('payment_method_name');
4267 - }
4367 + // If store is using the default "Woo" orderprefix, generate a new one, this time using the stores' sitename if possible. IOK 2020-05-19
4368 + if ($gw->get_option('orderprefix') == 'Woo') {
4369 + $gw->update_option('orderprefix', $this->generate_order_prefix());
4370 + }
4371 + // IOK 2023-12-20 for the epayment api, we need to re-initialize webhooks at this point.
4372 + $gw->initialize_webhooks();
4373 + $this->payment_method_name = $gw->get_option('payment_method_name');
4268 4374
4375 +
4376 + // Check if the special page is noted and actually does exist
4377 + $special = static::get_special_page_id();
4378 + if ($special) {
4379 + $special_page = get_post($special);
4380 + if ($special_page && 'trash' !== $special_page->post_status) {
4381 + // Ensure this page has the necessary shortcode. LP 2026-09-01
4382 + if (!has_shortcode($special_page->post_content, 'vipps_special_page')) {
4383 + $new_content = $special_page->post_content . "\n\n<!-- wp:shortcode -->[vipps_special_page]<!-- /wp:shortcode -->";
4384 + wp_update_post([
4385 + 'ID' => $special,
4386 + 'post_content' => $new_content,
4387 + ]);
4388 + }
4389 + } else {
4390 + delete_option('woocommerce_vipps_special_page_page_id');
4391 + }
4392 + }
4393 +
4394 + }
4395 +
4269 4396 // We have added some hooks to wp-cron; remove these. IOK 2020-04-01
4270 4397 public static function deactivate() {
4271 4398 $timestamp = wp_next_scheduled('vipps_cron_cleanup_hook');
4272 4399 wp_unschedule_event($timestamp, 'vipps_cron_cleanup_hook');
@@ -4319,9 +4446,10 @@
4319 4446 // If setting is true, use Vipps as default payment. Called by the woocommrece_cart_updated hook. IOK 2018-06-06
4320 4447 private function maybe_set_vipps_as_default() {
4321 4448 if (WC()->session->get('chosen_payment_method')) return; // User has already chosen payment method, so we're done.
4322 4449 $gw = $this->gateway();
4323 - if ($gw->get_option('vippsdefault')=='yes') {
4450 + // Do *not* default to vipps if Kustom Checkout is installed IOK 2026-09-11
4451 + if ($gw->get_option('vippsdefault')=='yes' && !class_exists('KCO')) {
4324 4452 WC()->session->set('chosen_payment_method', $gw->id);
4325 4453 }
4326 4454 }
4327 4455
@@ -4569,9 +4697,10 @@
4569 4697 }
4570 4698 if (!$o) return;
4571 4699 if (!$o->get_meta('_vipps_single_product_express')) return;
4572 4700 if ($failed && !apply_filters('woo_vipps_restore_cart_on_express_checkout_failure', true, $o)) return;
4573 - if ($failed) WC()->cart->empty_cart();
4701 + // Restoring cart! But clear it first so we dont add this single product to the restored cart. LP 2026-09-22
4702 + WC()->cart->empty_cart();
4574 4703 $this->restore_cart($o);
4575 4704 }
4576 4705
4577 4706
@@ -4927,46 +5056,37 @@
4927 5056 wp_send_json(array('status'=>'error', 'msg'=> __('Unknown payment status','woo-vipps') . ' ' . $payment));
4928 5057 return false;
4929 5058 }
4930 5059
4931 - // The various return URLs for special pages of the Vipps stuff depend on settings and pretty-URLs so we supply them from here
4932 - // These are for the "fallback URL" mostly. IOK 2018-05-18
4933 - private function make_vipps_url($what) {
4934 - if ( !get_option('permalink_structure')) {
4935 - return add_query_arg('VippsSpecialPage', $what, home_url("/", 'https'));
4936 - }
4937 - return trailingslashit(home_url($what, 'https'));
5060 + // The various return URLs for special pages of the Vipps stuff. Previously used a fake page and had to check permalink_structure. LP 2026-08-26
5061 + private function make_special_page_url($action) {
5062 + return add_query_arg('action', $action, $this->get_special_page_url());
4938 5063 }
5064 +
4939 5065 public function payment_return_url() {
4940 - return apply_filters('woo_vipps_payment_return_url', $this->make_vipps_url('vipps-betaling'));
5066 + return apply_filters('woo_vipps_payment_return_url', $this->make_special_page_url('wait_for_payment'));
4941 5067 }
4942 5068 public function express_checkout_url() {
4943 - return $this->make_vipps_url('vipps-express-checkout');
5069 + return $this->make_special_page_url('do_express_checkout');
4944 5070 }
4945 5071 public function buy_product_url() {
4946 - return $this->make_vipps_url('vipps-buy-product');
5072 + return $this->make_special_page_url('buy_product');
4947 5073 }
4948 5074
4949 - // Return the method in the Vipps
4950 - public function is_special_page() {
4951 - $specials = array('vipps-betaling' => 'vipps_wait_for_payment', 'vipps-express-checkout'=>'vipps_express_checkout', 'vipps-buy-product'=>'vipps_buy_product');
4952 - $method = null;
4953 - if ( get_option('permalink_structure')) {
4954 - foreach($specials as $special=>$specialmethod) {
4955 - // IOK 2018-06-07 Change to add any prefix from home-url for better matching IOK 2018-06-07
4956 - $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
4957 - if ($path && preg_match("!/$special/?$!", $path, $matches)) {
4958 - $method = $specialmethod; break;
4959 - }
4960 - }
4961 - } else {
4962 - if (isset($_GET['VippsSpecialPage'])) {
4963 - $method = @$specials[$_GET['VippsSpecialPage']];
4964 - }
4965 - }
4966 - return $method;
5075 + public static function is_special_page() {
5076 + $id = static::get_special_page_id();
5077 + return $id && is_page($id);
4967 5078 }
4968 5079
5080 + public static function get_special_page_id() {
5081 + $id = wc_get_page_id('vipps_special_page'); // -1 if not found
5082 + return $id > 0 ? $id : null;
5083 + }
5084 +
5085 + public static function get_special_page_url() {
5086 + return get_permalink(static::get_special_page_id());
5087 + }
5088 +
4969 5089 // Just create a spinner and a overlay.
4970 5090 public function spinner () {
4971 5091 $flavour = sanitize_title($this->get_payment_method_name());
4972 5092 ob_start();
@@ -5148,41 +5268,88 @@
5148 5268
5149 5269
5150 5270 // Checkout replaces the default checkout page, and currently uses its own page for this which needs to exist
5151 5271 // IOK 2026-04-30 remove this when checkout is end-of-life'd
5272 + // We now also use this for the vipps special page, previously a fakepage. LP 2026-08-18
5152 5273 public function woocommerce_create_pages ($data) {
5274 + // Vipps Checkout page
5153 5275 $vipps_checkout_activated = get_option('woo_vipps_checkout_activated', false);
5154 - if (!$vipps_checkout_activated) return $data;
5276 + if ($vipps_checkout_activated) {
5277 + $data['vipps_checkout'] = array(
5278 + 'name' => _x( 'vipps_checkout', 'Page slug', 'woo-vipps' ),
5279 + 'title' => _x( 'Vipps MobilePay Checkout', 'Page title', 'woo-vipps' ),
5280 + 'content' => '<!-- wp:shortcode -->[' . 'vipps_checkout' . ']<!-- /wp:shortcode -->',
5281 + );
5282 + }
5155 5283
5156 - $data['vipps_checkout'] = array(
5157 - 'name' => _x( 'vipps_checkout', 'Page slug', 'woo-vipps' ),
5158 - 'title' => _x( 'Vipps MobilePay Checkout', 'Page title', 'woo-vipps' ),
5159 - 'content' => '<!-- wp:shortcode -->[' . 'vipps_checkout' . ']<!-- /wp:shortcode -->',
5160 - );
5161 -
5284 + // Vipps special page for certain payment flow actions. Previously a fake page. LP 2026-08-18
5285 + $data['vipps_special_page'] = [
5286 + 'name' => 'vipps-payment', // slug
5287 + /* translators: company name */
5288 + 'title' => sprintf(__('%s special page', 'woo-vipps'), static::CompanyName()), // we hide the title frontend in template_redirect. LP 2026-08-27
5289 + 'content' => '<!-- wp:shortcode -->[vipps_special_page]<!-- /wp:shortcode -->',
5290 + ];
5162 5291 return $data;
5163 5292 }
5164 5293
5165 - // Creates any necessary Vipps pages. Will be called e.g. when activating Checkout or turning it on.
5294 + // Creates any necessary Vipps pages. E.g vipps checkout page or vipps special page. LP 2026-09-01
5295 + // If a page slug already exists, then it won't overwrite or duplicate it!. LP 2026-09-02
5166 5296 public function maybe_create_vipps_pages () {
5297 + $make_pages = false;
5298 +
5299 + // Vipps Checkout page. LP 2026-08-18
5167 5300 $checkoutid = wc_get_page_id('vipps_checkout');
5168 - $makeit = !$checkoutid || ! get_post_status($checkoutid);
5169 - if ($makeit) {
5301 + if (!$checkoutid || ! get_post_status($checkoutid)) {
5170 5302 delete_option('woocommerce_vipps_checkout_page_id');
5303 + $make_pages = true;
5171 5304 }
5172 5305
5173 - if ($makeit) {
5174 - WC_Install::create_pages();
5306 + // vipps special page, previously a fake page. LP 2026-08-18
5307 + $builtin_special_page_id = static::get_special_page_id();
5308 + if (!$builtin_special_page_id || !get_post_status($builtin_special_page_id)) {
5309 + delete_option('woocommerce_vipps_special_page_page_id');
5310 + $make_pages = true;
5175 5311 }
5312 +
5313 + if ($make_pages) {
5314 + WC_Install::create_pages();
5315 + }
5176 5316 }
5177 5317
5318 + public function vipps_special_page_shortcode($atts, $content) {
5319 + // No point in expanding this unless we are actually doing the special actions. LP 2026-08-25
5320 + if (is_admin()) return;
5321 + if (wp_doing_ajax()) return;
5322 + if (defined('REST_REQUEST') && REST_REQUEST) return;
5323 + if (did_filter('woo_vipps_special_page_html')) return; // User has somehow added two shortcodes. IOK 2026-09-18
5178 5324
5325 + $action = $_GET['action'] ?? '';
5326 + $html = "";
5327 + switch ($action) {
5328 + case 'wait_for_payment':
5329 + $html = $this->vipps_wait_for_payment();
5330 + break;
5331 + case 'do_express_checkout':
5332 + $html = $this->vipps_express_checkout();
5333 + break;
5334 + case 'buy_product':
5335 + $html = $this->vipps_buy_product();
5336 + break;
5337 + default:
5338 + $html = '';
5339 + }
5340 + // This is mostly to avoid this shortcode evaluating twice IOK 2026-09-18
5341 + $html = apply_filters('woo_vipps_special_page_html', $html, $action);
5342 +
5343 + // Remember, this is a shortcode, so the html must be returned, not echoed IOK 2026-09-11
5344 + return $html;
5345 + }
5346 +
5347 +
5179 5348 // This URL will when accessed add a product to the cart and go directly to the express checkout page.
5180 5349 // The argument passed must be a shareable link created for a given product - so this in effect acts as a landing page for
5181 5350 // the buying thru Vipps Express Checkout of a single product linked to in for instance banners. IOK 2018-09-24
5182 5351 public function vipps_buy_product() {
5183 - status_header(200,'OK');
5184 - Vipps::nocache();
5185 5352
5186 5353 add_filter('body_class', function ($classes) {
5187 5354 $classes[] = 'vipps-express-checkout';
5188 5355 $classes[] = 'woocommerce-checkout'; // Required by Pixel Your Site IOK 2022-11-24
@@ -5218,9 +5385,9 @@
5218 5385
5219 5386 if (!$productinfo) {
5220 5387 $title = __("Product is no longer available",'woo-vipps');
5221 5388 $content = __("The link you have followed is for a product that is no longer available at this location. Please return to the store and try again",'woo-vipps');
5222 - return $this->fakepage($title,$content);
5389 + return $this->special_page_html($title,$content);
5223 5390 }
5224 5391
5225 5392 // Pass the productinfo to the express checkout form
5226 5393 $args = array();
@@ -5237,20 +5404,16 @@
5237 5404 }
5238 5405 $args[sanitize_title(wp_unslash($key))] = sanitize_text_field(wp_unslash($value));
5239 5406 }
5240 5407
5241 - $this->print_express_checkout_page(true,'do_single_product_express_checkout',$args);
5408 + return $this->express_checkout_page_html(true,'do_single_product_express_checkout',$args);
5242 5409 }
5243 5410
5244 - // This is a landing page for the express checkout of then normal cart - it is done like this because this could take time on slower hosts.
5245 - public function vipps_express_checkout() {
5246 - status_header(200,'OK');
5247 - Vipps::nocache();
5411 + public function vipps_express_checkout_consistency_check() {
5248 5412 // We need a nonce to get here, but we should only get here when we have a cart, so this will not be cached.
5249 5413 // IOK 2018-05-28
5250 5414 $ok = isset($_REQUEST['sec']) && wp_verify_nonce($_REQUEST['sec'],'express');
5251 5415
5252 -
5253 5416 $backurl = wp_validate_redirect(@$_SERVER['HTTP_REFERER']);
5254 5417 if (!$backurl) $backurl = home_url();
5255 5418
5256 5419 if (!$ok) {
@@ -5264,8 +5427,19 @@
5264 5427 wp_redirect($backurl);
5265 5428 exit();
5266 5429 }
5267 5430
5431 + add_filter('woo_vipps_express_checkout_consistent', '__return_true');
5432 + }
5433 +
5434 + // This is a landing page for the express checkout of then normal cart - it is done like this because this could take time on slower hosts.
5435 + public function vipps_express_checkout() {
5436 + // Some checks are made in template_redirect, we check here if they are ok IOK 2026-09-21
5437 + if (!apply_filters('woo_vipps_express_checkout_consistent', false)) {
5438 + $content = __('Link expired, please try again', 'woo-vipps');
5439 + return $content;
5440 + }
5441 +
5268 5442 add_filter('body_class', function ($classes) {
5269 5443 $classes[] = 'vipps-express-checkout';
5270 5444 $classes[] = 'woocommerce-checkout'; // Required by Pixel Your Site IOK 2022-11-24
5271 5445 return apply_filters('woo_vipps_express_checkout_body_class', $classes);
@@ -5272,9 +5446,9 @@
5272 5446 });
5273 5447
5274 5448 do_action('woo_vipps_express_checkout_page');
5275 5449
5276 - $this->print_express_checkout_page(true, 'do_express_checkout');
5450 + return $this->express_checkout_page_html(true, 'do_express_checkout');
5277 5451 }
5278 5452
5279 5453 // This method tries to ensure that a customer does not 'lose' the return page and
5280 5454 // starts ordering the same products twice. IOK 2020-01-22
@@ -5369,9 +5543,10 @@
5369 5543 return $orderspec;
5370 5544 }
5371 5545
5372 5546 // Used as a landing page for launching express checkout - borh for the cart and for single products. IOK 2018-09-28
5373 - protected function print_express_checkout_page($execute,$action,$productinfo=null) {
5547 + // Returns the html. LP 2026-08-27
5548 + protected function express_checkout_page_html($execute,$action,$productinfo=null) {
5374 5549 $gw = $this->gateway();
5375 5550
5376 5551 $expressCheckoutMessages = array();
5377 5552 $expressCheckoutMessages['termsAndConditionsError'] = __( 'Please read and accept the terms and conditions to proceed with your order.', 'woocommerce' );
@@ -5454,10 +5629,9 @@
5454 5629
5455 5630 if ($execute) {
5456 5631 $content .= "<p id=waiting>" . __("Please wait while we are preparing your order", 'woo-vipps') . "</p>";
5457 5632 $content .= "<div id='vipps-status-message'></div>";
5458 - $this->fakepage(__('Order in progress','woo-vipps'), $content);
5459 - return;
5633 + return $this->special_page_html('', $content);
5460 5634 } else {
5461 5635 $content .= $askForConfirmationHTML;
5462 5636 $content .= $extraHTML;
5463 5637 $content .= $termsHTML;
@@ -5464,21 +5638,16 @@
5464 5638 $content .= apply_filters('woo_vipps_express_checkout_validation_elements', '');
5465 5639 $title = sprintf(__('Buy now with %1$s!', 'woo-vipps'), $this->get_payment_method_name());
5466 5640 $content .= "<div class='vipps_buy_now_wrapper noloop'><a href='#' id='do-express-checkout' class='vipps-express-checkout' title='$title'>$buttonhtml</a></div>";
5467 5641 $content .= "<div id='vipps-status-message'></div>";
5468 - $this->fakepage(sprintf(__('%1$s Express Checkout','woo-vipps'), $this->get_payment_method_name()), $content);
5469 - return;
5642 + return $this->special_page_html('', $content);
5470 5643 }
5471 5644 }
5472 5645
5473 5646
5474 -
5475 - public function vipps_wait_for_payment() {
5476 - status_header(200,'OK');
5477 - Vipps::nocache();
5478 -
5647 + // Called in template_redirect before we get to the wait-for-payment page IOK 2026-09-21
5648 + private function handle_payment_poll_and_redirect () {
5479 5649 $orderid = WC()->session->get('_vipps_pending_order');
5480 -
5481 5650 $order = null;
5482 5651 $gw = $this->gateway();
5483 5652
5484 5653 // Failsafe for when the session disappears IOK 2018-11-19
@@ -5490,9 +5659,9 @@
5490 5659 // If so, we will read the order id from the GET arguments and check if the auth token is correct,
5491 5660 // simulating the session with that.
5492 5661 // IOK 2019-11-19, changed to using GET 2023-01-23
5493 5662 if ($no_session && $limited_session) {
5494 - $orderid = intval(@$_GET['id']);
5663 + $orderid = intval($_GET['id'] ?? false);
5495 5664 }
5496 5665 if ($orderid) {
5497 5666 clean_post_cache($orderid);
5498 5667 $order = wc_get_order($orderid);
@@ -5511,11 +5680,8 @@
5511 5680 $session->set('_vipps_pending_order', $orderid);
5512 5681 }
5513 5682 }
5514 5683
5515 -
5516 - do_action('woo_vipps_wait_for_payment_page',$order);
5517 -
5518 5684 $deleted_order=0;
5519 5685 if ($orderid && !$order) {
5520 5686 // If this happens, we actually did have an order, but it has been deleted, which must mean that it was cancelled.
5521 5687 // Concievably a hook on the 'cancel'-transition or in the callback handlers could clean that up before we get here. IOK 2019-09-26
@@ -5540,9 +5706,9 @@
5540 5706 clean_post_cache($orderid);
5541 5707 $order = wc_get_order($orderid); // Reload order object
5542 5708 }
5543 5709 } else {
5544 - // No need to do anyting here. IOK 2020-01-26
5710 + // No need to do anyting here. IOK 2020-01-26
5545 5711 }
5546 5712
5547 5713 $payment = 'notchecked';
5548 5714 if ($do_poll) {
@@ -5558,9 +5724,8 @@
5558 5724 exit();
5559 5725 }
5560 5726
5561 5727 // We are done, but in failure. Don't poll.
5562 - $content = "";
5563 5728 $failure_redirect = apply_filters('woo_vipps_order_failed_redirect', '', $orderid);
5564 5729
5565 5730 // Status is failed; still send to return url (as of now /order-recieved), the text there will depend on the status.
5566 5731 // For failed it shows a "Retry payment" button that takes the customer to /pay-for-order where it will be retried. LP 2026-03-17
@@ -5568,8 +5733,9 @@
5568 5733 $failure_redirect = $failure_redirect ?: $gw->get_return_url($order);
5569 5734 wp_redirect($failure_redirect);
5570 5735 exit();
5571 5736 }
5737 +
5572 5738 if ($status == 'cancelled' || $payment == 'cancelled') {
5573 5739 $this->maybe_restore_cart($orderid,'failed');
5574 5740 if ($failure_redirect){
5575 5741 wp_redirect($failure_redirect);
@@ -5574,27 +5740,45 @@
5574 5740 if ($failure_redirect){
5575 5741 wp_redirect($failure_redirect);
5576 5742 exit();
5577 5743 }
5744 + } else {
5745 + // If not, enqueue the status checker IOK 2026-09-21
5746 + wp_enqueue_script('check-vipps',plugins_url('js/check-order-status.js',__FILE__),array('jquery','vipps-gw'),filemtime(dirname(__FILE__) . "/js/check-order-status.js"), 'true');
5747 + }
5748 +
5749 + // Communicate this to the shortcode IOK 2026-09-21
5750 + add_filter('woo_vipps_wait_for_payment_status', function () use($orderid, $status, $payment) {
5751 + return ['orderid'=>$orderid, 'status'=>$status, 'payment'=>$payment];
5752 + });
5753 +
5754 + }
5755 +
5756 + public function vipps_wait_for_payment() {
5757 +
5758 + // This will have been computed in template_redirect, but the status will be either still pending or failed. IOK 2026-09-21
5759 + $data = apply_filters('woo_vipps_wait_for_payment_status', []);
5760 +
5761 + $orderid = $data['orderid'] ?? 0;
5762 + $status = $data['status'] ?? "";
5763 + $payment = $data['payment'] ?? "";
5764 +
5765 + $order = wc_get_order($orderid);
5766 + if (!$order) wp_die(__('Unknown order', 'woo-vipps'));
5767 +
5768 + do_action('woo_vipps_wait_for_payment_page',$order);
5769 + $gw = $this->gateway();
5770 +
5771 + $content = "";
5772 + if ($status == 'cancelled' || $payment == 'cancelled') {
5578 5773 $content .= "<div id=failure><p>". __('Order cancelled','woo-vipps') . '</p>';
5579 5774 $content .= "<p><a href='" . home_url() . "' class='btn button'>" . __('Continue shopping','woo-vipps') . '</a></p>';
5580 5775 $content .= "</div>";
5581 - $this->fakepage(__('Order cancelled','woo-vipps'), $content);
5582 -
5583 - return;
5776 + return $this->special_page_html('', $content);
5584 5777 }
5585 5778
5586 5779 // Still pending and order is supposed to exist, so wait for Vipps. This happens all the time, so logging is removed. IOK 2018-09-27
5587 -
5588 5780 // Otherwise, go to a page waiting/polling for the callback. IOK 2018-05-16
5589 - wp_enqueue_script('check-vipps',plugins_url('js/check-order-status.js',__FILE__),array('jquery','vipps-gw'),filemtime(dirname(__FILE__) . "/js/check-order-status.js"), 'true');
5590 -
5591 - // Check that order exists and belongs to our session. Can use WC()->session->get() I guess - set the orderid or a hash value in the session
5592 - // and check that the order matches (and is 'pending') (and exists)
5593 - $vippsstamp = $order->get_meta('_vipps_init_timestamp');
5594 - $vippsstatus = $order->get_meta('_vipps_status');
5595 - $message = __($order->get_meta('_vipps_confirm_message'),'woo-vipps');
5596 -
5597 5781 $signal = $this->callbackSignal($order);
5598 5782 $content = "";
5599 5783 $content .= "<div id='waiting'><p>" . sprintf(__('Waiting for confirmation of purchase from %1$s','woo-vipps'), $this->get_payment_method_name());
5600 5784
@@ -5602,15 +5786,16 @@
5602 5786 $signalurl = $this->callbackSignalURL($signal);
5603 5787
5604 5788 $content .= "</p></div>";
5605 5789
5606 - // We impersonate the woocommerce-checkout form here mainly to work with the Pixel Your Site plugin IOK 2022-11-24
5607 - $classlist = apply_filters("woo_vipps_express_checkout_form_classes", "woocommerce-checkout");
5608 - $content .= "<form id='vippsdata' class='" . esc_attr($classlist) . "'>";
5790 + $failure_redirect = apply_filters('woo_vipps_order_failed_redirect', '', $orderid);
5791 +
5792 + // Carry the order status to the checking script IOK 2026-09-21
5793 + $content .= "<form id='vippsdata'>";
5609 5794 $content .= "<input type='hidden' id='fkey' name='fkey' value='".htmlspecialchars($signalurl)."'>";
5610 5795 $content .= "<input type='hidden' name='key' value='".htmlspecialchars($order->get_order_key())."'>";
5611 5796 $content .= "<input type='hidden' name='action' value='check_order_status'>";
5612 - $content .= wp_nonce_field('vippsstatus','sec',1,false);
5797 + $content .= wp_nonce_field('vippsstatus','sec',1,false);
5613 5798 $content .= "</form>";
5614 5799
5615 5800
5616 5801 $content .= "<div id='error' style='display:none'><p>".__('Error during order confirmation','woo-vipps'). '</p>';
@@ -5627,93 +5812,21 @@
5627 5812 $content .= "<a id='continueToOrderFailed' style='display:none' href='" . $failure_redirect . "'></a>";
5628 5813 $content .= "<a id='continueToOrderFailedFallback' style='display:none' href='" . $gw->get_return_url($order) . "'></a>";
5629 5814 $content .= "</div>";
5630 5815
5816 + return $this->special_page_html('', $content);
5817 + }
5631 5818
5632 - $this->fakepage(__('Waiting for your order confirmation','woo-vipps'), $content);
5819 + // Returns formatted html for the vipps special page. LP 2026-08-27
5820 + public function special_page_html($header, $content) {
5821 + $header_html = $header ? "<h2 class='vipps-special-page-title page-title'>$header</h2>" : '';
5822 + $html = <<<EOF
5823 + $header_html
5824 + <div class="vipps-special-page-content">$content</div>
5825 + EOF;
5826 + return apply_filters('woo_vipps_special_page_html', $html, $header, $content);
5633 5827 }
5634 5828
5635 -
5636 -
5637 - public function fakepage($title,$content) {
5638 - global $wp, $wp_query;
5639 - // We don't want this here.
5640 - remove_filter ('the_content', 'wpautop');
5641 -
5642 - $specialid = $this->gateway()->get_option('vippsspecialpageid');
5643 - $wp_post = null;
5644 - if ($specialid) {
5645 - $wp_post = get_post($specialid);
5646 - if ($wp_post) {
5647 - $wp_post->post_title = $title;
5648 - $wp_post->post_content = $content;
5649 - // Normalize a bit
5650 - $wp_post->filter = 'raw'; // important
5651 - $wp_post->post_status = 'publish';
5652 - $wp_post->comment_status= 'closed';
5653 - $wp_post->ping_status= 'closed';
5654 - } else {
5655 - $this->log(sprintf(__("Could not use special page with id %s - it seems not to exist.", 'woo-vipps'), $specialid), 'error');
5656 - }
5657 - }
5658 - if (!$wp_post || is_wp_error($wp_post)) {
5659 - $post = new stdClass();
5660 - $post->ID = -99;
5661 - $post->post_author = 1;
5662 - $post->post_date = current_time( 'mysql' );
5663 - $post->post_date_gmt = current_time( 'mysql', 1 );
5664 - $post->post_title = $title;
5665 - $post->post_content = $content;
5666 - $post->post_status = 'publish';
5667 - $post->comment_status = 'closed';
5668 - $post->ping_status = 'closed';
5669 - $post->post_name = 'vippsconfirm-fake-page-name';
5670 - $post->post_type = 'page';
5671 - $post->filter = 'raw'; // important
5672 - $wp_post = new WP_Post($post);
5673 - wp_cache_add( -99, $wp_post, 'posts' );
5674 - }
5675 -
5676 - // Update the main query
5677 - $wp_query->post = $wp_post;
5678 - $wp_query->posts = array( $wp_post );
5679 - $wp_query->queried_object = $wp_post;
5680 - $wp_query->queried_object_id = $wp_post->ID;
5681 - $wp_query->found_posts = 1;
5682 - $wp_query->post_count = 1;
5683 - $wp_query->max_num_pages = 1;
5684 - $wp_query->is_page = true;
5685 - $wp_query->is_singular = true;
5686 - $wp_query->is_single = false;
5687 - $wp_query->is_attachment = false;
5688 - $wp_query->is_archive = false;
5689 - $wp_query->is_category = false;
5690 - $wp_query->is_tag = false;
5691 - $wp_query->is_tax = false;
5692 - $wp_query->is_author = false;
5693 - $wp_query->is_date = false;
5694 - $wp_query->is_year = false;
5695 - $wp_query->is_month = false;
5696 - $wp_query->is_day = false;
5697 - $wp_query->is_time = false;
5698 - $wp_query->is_search = false;
5699 - $wp_query->is_feed = false;
5700 - $wp_query->is_comment_feed = false;
5701 - $wp_query->is_trackback = false;
5702 - $wp_query->is_home = false;
5703 - $wp_query->is_embed = false;
5704 - $wp_query->is_404 = false;
5705 - $wp_query->is_paged = false;
5706 - $wp_query->is_admin = false;
5707 - $wp_query->is_preview = false;
5708 - $wp_query->is_robots = false;
5709 - $wp_query->is_posts_page = false;
5710 - $wp_query->is_post_type_archive = false;
5711 - // Update globals
5712 - $GLOBALS['wp_query'] = $wp_query;
5713 - $wp->register_globals();
5714 - return $wp_post;
5715 - }
5716 5829
5717 5830 // Support the interactivity API with data about our cart IOK 2026-02-23
5718 5831 public function woo_vipps_store_api_cart_data() {
5719 5832 // Reverting the condition with the directive data-wp-bind--hidden does not work, so we need the flipped bool here (hide instead of show). LP 2026-02-10