payment_gateways(); return WC_Gateway_Vipps::instance(); } else { $Vipps->log(__("Error: Cannot instantiate payment gateway, because WooCommerce is not loaded! This can happen when WooCommerce updates itself; but if it didn't, please activate WooCommerce again", 'woo-vipps'), 'error'); return null; } } // Handle the submission of the admin settings page public function ajax_vipps_update_admin_settings() { $ok = wp_verify_nonce($_REQUEST['vippsadmin_nonce'], 'vippsadmin_nonce'); if (!$ok) { echo json_encode(array('ok' => 0, 'options' => [], 'msg' => __('You don\'t have sufficient rights to edit these settings', 'woo-vipps'))); exit(); } if (!current_user_can('manage_woocommerce')) { echo json_encode(array('ok' => 0, 'options' => [], 'msg' => __('You don\'t have sufficient rights to edit these settings', 'woo-vipps'))); exit(); } // Decode the settings from the values sents, then save them to "woocommerce_vipps_settings" and "woocommerce_vipps_card_settings" $new_settings = $_POST['values']; // IOK TODO This will ensure sanitization etc works as it is supposed to using the // admin settings api of WooCommerce. We will however want to run this code independently, so we'll handle this // by ourselves at a later point, ending it like so: // update_option('woocommerce_vipps_settings', $new_settings); // After sanitation etc // update_option('woocommerce_vipps_card_settings', $card_settings); // Separated out $admin_options = []; $card_admin_options= []; foreach ($new_settings as $key => $value) { // Checkbox settings (yes/no) can't be passed directly to set_post_data, because *any* value will be interpreted as "yes" // because of this, checkbox settings with the value "no" will be completely ignored if($value !== 'no') { // Because settings are processed manually, their keys need to prefixed with "woocommerce__" // options with prefix cc_ are for the credit card gateway. if (preg_match("!^cc_!", $key)) { $key = preg_replace("!^cc_!", "", $key); $card_admin_options['woocommerce_vipps_card_' . $key] = $value; } else { $admin_options['woocommerce_vipps_' . $key] = $value; } } } // Save options for the main gateway first // We need to initialize these again so "conditional" options are available // IOK 2024-06-05 $this->gateway()->init_form_fields(); $this->gateway()->set_post_data($admin_options); $this->gateway()->process_admin_options(); // $this->gateway()->add_error("Jaboloko!"); // Also add_warning, add_notice plz $form_errors = $this->gateway()->get_errors(); // Then the card gateway $cards= WC_Gateway_VippsCard::instance(); $cards->init_form_fields(); $cards->set_post_data($card_admin_options); $cards->process_admin_options(); $form_errors = array_merge($form_errors, $cards->get_errors()); $form_ok = empty($form_errors); // end use of process_admin_options IOK 2024-01-03 $connection_msg = ""; // Verify the connection to Vipps list($connection_ok, $error_message) = $this->gateway()->check_connection(); if ($connection_ok) { $connection_msg .= sprintf(__("Connection to %1\$s is OK", 'woo-vipps'), Vipps::CompanyName()); } else { $connection_msg .= sprintf(__("Could not connect to %1\$s", 'woo-vipps'), Vipps::CompanyName()) . ": $error_message"; } // Get the current options $options = get_option('woocommerce_vipps_settings'); // Augment with card gateway, with prefix $card_options = get_option('woocommerce_vipps_card_settings'); foreach($card_options as $key => $data) { $options["cc_$key"] = $data; } // Add receipt image URL if receipt image exists if (!empty($new_settings['receiptimage'])) { $options['receiptimage_url'] = wp_get_attachment_url($new_settings['receiptimage']); } // Return the result, sending the new options, the connection status/message and the form status/errors echo json_encode( array( 'connection_ok' => $connection_ok, // Whether the connection to the Vipps servers is OK. 'connection_msg' => $connection_msg, // The connection message, whether the connection is OK or not. 'form_ok' => $form_ok, // Whether the form fields are OK. 'form_errors' => $form_errors, // The form field errors, if any. 'options' => $options // The new options ) ); exit(); } // Initializes the admin settings UI for VippsMobilePay function init_admin_settings_page_react_ui() { global $Vipps; echo "
"; // Add nonce first. wp_nonce_field('vippsadmin_nonce', 'vippsadmin_nonce'); // We must first generate the root element for the React UI before we load the React app itself, otherwise React will fail to load. ?>
gateway(); $card_gw = WC_Gateway_VippsCard::instance(); // Loads the React UI $reactpath = "dist"; wp_enqueue_script('vipps-mobilepay-react-ui', plugins_url($reactpath . '/plugin.js', __FILE__), array('wp-element'), filemtime(__DIR__ . "/$reactpath/plugin.js"), true); // wp_enqueue_style('vipps-mobilepay-react-ui', plugins_url($reactpath . '/plugin.css', __FILE__), array(), filemtime(__DIR__ . "/$reactpath/plugin.css")); $metadata = array( 'admin_url' => admin_url('admin-ajax.php'), 'page' => 'admin_settings_page', 'currency' => get_woocommerce_currency(), // for debugging/testing: show wizard screen always IOK 2025-01-20 '__dev_force_wizard_screen' => defined('WOO_VIPPS_FORCE_WIZARD') && WOO_VIPPS_FORCE_WIZARD, // Only show checkout options if checkout has actually been activated. 'vipps_checkout_activated' => intval(get_option('woo_vipps_checkout_activated')) ); // Add some extra common translations only used by the React UI $commonTranslations = array( 'save_changes' => __('Save changes', 'woo-vipps'), 'initial_settings' => __('Initial settings', 'woo-vipps'), 'upload_image' => __('Upload image', 'woo-vipps'), 'remove_image' => __('Remove image', 'woo-vipps'), 'next_step' => __('Next step', 'woo-vipps'), 'previous_step' => __('Previous step', 'woo-vipps'), 'receipt_image_size_requirement' => __('The image must be at least 167 pixels in height', 'woo-vipps'), 'receipt_image_error' => __('The uploaded image is too small. It must be at least 167 pixels in height.', 'woo-vipps'), 'settings_saved' => __('Settings saved', 'woo-vipps'), 'kustom_sale_1' => __('Checkout - Important Update', 'woo-vipps'), 'kustom_sale_2' => __('Vipps MobilePay has entered into an agreement to sell the Checkout solution to Kustom', 'woo-vipps'), 'kustom_sale_3' => __('As part of this transition, Vipps MobilePay Checkout will become Kustom Checkout. This means the Checkout product you ordered will be delivered and developed by Kustom going forward.', 'woo-vipps'), 'kustom_sale_4' => __('If your account is newer than March 27. 2026, it will not support Vipps MobilePay Checkout in this plugin.', 'woo-vipps'), 'kustom_sale_5' => __('If you have questions, you can check our FAQ.', 'woo-vipps'), ); /* We need to postprocess the settings for.. various reasons IOK 2024-06-04 */ /* Also we need to run init_form_fields here, because for whatever reason the * first time it is called, it does wrong things in this context. IOK 2024-06-04 */ $gw->init_form_fields(); $settings = $gw->settings; $wizardTranslations = [ 'wizard_header' => [ 'title' => __('Initial settings', 'woo-vipps'), 'description' => sprintf(__('Welcome! You are almost ready to accept payments with %1$s', 'woo-vipps'), Vipps::CompanyName()), ], 'checkout_options_wizard' => array( 'title' => sprintf(__('Get started with %1$s', 'woo-vipps'), Vipps::CheckoutName()), 'description' => sprintf(__('%1$s is a service from %2$s, which allows you to replace the usual WooCommerce checkout page with a super simple checkout screen, where your customers can pay with Vipps, Visa, and MasterCard!', 'woo-vipps'), Vipps::CheckoutName(), Vipps::CompanyName()), ), 'enablestaticshipping_checkout_wizard' => array( 'title' => __('Are you going to base shipping price on the customers address?', 'woo-vipps'), 'label' => __('Yes, I want dynamic shipping calculation', 'woo-vipps'), 'description' => __('If your shipping prices are the same no matter where the customer lives, you don\'t need dynamic shipping calculation.'), ), 'checkoutcreateuser_wizard' => array( 'title' => sprintf(__('Do you want to create new customers on %1$s?', 'woo-vipps'), Vipps::CheckoutName()), 'label' => sprintf(__('Yes, create new customers on %1$s', 'woo-vipps'), Vipps::CheckoutName()), 'description' => sprintf(__('By creating new customers, you avoid orders showing up as guest orders. We recommend combining this with Log in with %1$s for a full overview of your customers.', 'woo-vipps'), Vipps::CompanyName()), ), 'noAddressFields_wizard' => array( 'title' => __('Do you want the customer to enter their address?', 'woo-vipps'), 'label' => __('Yes, all customers must enter their address', 'woo-vipps'), 'description' => __('If you only sell products that are not to be shipped, you don\'t need the customer to enter their address.', 'woo-vipps'), ), 'checkout_shipping_wizard' => array( 'title' => sprintf(__('Shipping alternatives available with %1$s', 'woo-vipps'), Vipps::CheckoutName()), 'description' => sprintf(__('When you use %1$s, you have a variety of shipping options to choose from, giving you even more choices from certain shipping providers.'), Vipps::CheckoutName()) ), 'vcs_posten_wizard' => array( 'title' => __('Posten Norge', 'woo-vipps'), 'custom_attributes' => array('data-vcs-show' => '.vcs_depend.vcs_posten'), 'label' => __('Offer Posten Norge as a shipping method', 'woo-vipps'), 'description' => __('Select this to offer this shipping method.', 'woo-vipps'), ), 'vcs_helthjem_wizard' => array( 'title' => __('Helthjem', 'woo-vipps'), 'label' => __('Offer Helthjem as a shipping method', 'woo-vipps'), 'description' => __('Select this to offer this shipping method.', 'woo-vipps'), ), 'vcs_posti_wizard' => array( 'title' => __('Posti', 'woo-vipps'), 'label' => __('Offer Posti as a shipping method', 'woo-vipps'), 'description' => __('Select this to offer this shipping method.', 'woo-vipps'), ), 'vcs_postnord_wizard' => array( 'title' => __('PostNord', 'woo-vipps'), 'label' => __('Offer PostNord as a shipping method', 'woo-vipps'), 'description' => __('Select this to offer this shipping method.', 'woo-vipps'), ), 'vcs_porterbuddy_wizard' => array( 'title' => __('Porterbuddy', 'woo-vipps'), 'label' => __('Offer Porterbuddy as a shipping method', 'woo-vipps'), 'description' => __('Select this to offer this shipping method.', 'woo-vipps'), ), 'help_box' => [ 'get_started' => __('Get started', 'woo_vipps'), 'documentation' => __('Documentation', 'woo-vipps'), 'portal' => sprintf(__('%1$s Portal', 'woo-vipps'), Vipps::CompanyName()), 'support' => [ 'title' => __('Support', 'woo-vipps'), 'description' => __('If you have any questions related to this plugin, you are welcome to check out the support forum.', 'woo-vipps'), ], ], 'checkout_confirm' => [ 'title' => sprintf(__('Upgrade your customer experience with %1$s', 'woo-vipps'), Vipps::CheckoutName()), 'img' => [ 'vipps' => [ 'src' => plugins_url('img/no_vippsmobilepay_checkout_app-teaser_2400x1600.webp', WC_VIPPS_PAYMENT_MAIN_FILE), 'alt' => __('Sketch of', 'woo-vipps') . ' Vipps Checkout', // dont translate checkout name ], 'mobilepay' => [ 'src' => plugins_url('img/dk_vm_checkout_app-teaser_2400x1600.webp', WC_VIPPS_PAYMENT_MAIN_FILE), 'alt' => __('Sketch of', 'woo-vipps') . ' MobilePay Checkout', ], ], 'paragraph1' => [ 'header' => sprintf(__('Why %1$s?', 'woo-vipps'), Vipps::CheckoutName()), 'first' => __('Effortless Payments: Accept payments smoothly with Vipps/MobilePay, Visa, and Mastercard.', 'woo-vipps'), 'second' => __('Streamlined Shopping Process: Simplify your customers\' journey from cart to confirmation', 'woo-vipps'), 'third' => __('All-in-One Solution: No fixed monthly fees-just pure convenience.', 'woo-vipps'), ], 'paragraph2' => [ 'header' => __('Perfect for you if:', 'woo-vipps'), 'first' => __('You want simple, varied payment options', 'woo-vipps'), 'second' => __('You need easy shipping solutions with diverse choices.', 'woo-vipps'), ], 'accept' => sprintf(__('Start using %1$s', 'woo-vipps'), Vipps::CheckoutName()), 'skip' => __('Skip & save', 'woo-vipps'), ], 'express_options_wizard' => array( 'title' => sprintf(__('Get started with %1$s', 'woo-vipps'), Vipps::ExpressCheckoutName()), 'description' => sprintf(__("%1\$s allows you to buy products by a single click from the cart, checkout, or directly from product or catalog pages. Product will get a 'buy now' button which will start the purchase process immediately.", 'woo-vipps'), Vipps::ExpressCheckoutName()), 'readmore' => __('Read more', 'woo-vipps'), ), 'singleproductexpressarchives_wizard' => [ 'title' => sprintf(__('%s on product catalog pages', 'woo-vipps'), Vipps::ExpressCheckoutName()), 'label' => sprintf(__('Enable a %s button for relevant products on catalog pages', 'woo-vipps'), Vipps::ExpressCheckoutName()), ], ]; if (!empty($settings['receiptimage'])) { $settings['receiptimage_url'] = wp_get_attachment_url($settings['receiptimage']); } if (!$gw->allow_external_payments_in_checkout()) { unset($settings['checkout_external_payments_klarna']); } else { // nop right now } /* Add the options from the credit card gateway too, with a cc_prefix which we strip on process_payments. IOK 2026-05-27*/ $card_gw->init_form_fields(); $cc_translations = []; foreach($card_gw->settings as $key => $data) { $settings["cc_$key"] = $data; } foreach($card_gw->form_fields as $key => $data) { $cc_translations["cc_$key"] = $data; } $cc_translations['cc_options'] = [ 'title' => __('Card payments', 'woo-vipps'), 'description' => __("Provide a card payment method for customers that haven't got the app (yet!)", 'woo-vipps'), 'test_mode_warning' => sprintf(__('Warning: card payments may not yet be available in the test environment, please check the %1$s knowledge base for updated status about the test environment.'), Vipps::CompanyName()), ]; wp_localize_script('vipps-mobilepay-react-ui', 'VippsMobilePayReactTranslations', array_merge($gw->form_fields, $cc_translations, $commonTranslations, $wizardTranslations)); wp_localize_script('vipps-mobilepay-react-ui', 'VippsMobilePayReactOptions', $settings); wp_localize_script('vipps-mobilepay-react-ui', 'VippsMobilePayReactMetadata', $metadata); echo "
"; } } ?>