PluginProbe
Pay with Vipps and MobilePay for WooCommerce / 5.4.2
Pay with Vipps and MobilePay for WooCommerce v5.4.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 5.4.0 5.3.4 trunk All 183 releases
woo-vipps / payment / js / vipps.js

vipps.js in Pay with Vipps and MobilePay for WooCommerce 5.4.2, at payment/js/vipps.js

296 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2
3 This file is part of the plugin Pay with Vipps and MobilePay for WooCommerce
4 Copyright (c) 2019 WP-Hosting AS
5
6 MIT License
7
8 Copyright (c) 2019 WP-Hosting AS
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27
28 */
29
30 // Hook vippsInit to woocommerce/product-collection render event. LP 29.11.2024
31 // IOK 2026-01-14 available from woo 9.4 - so the buy now block will not be available until that version
32 document.body.addEventListener('wc-blocks_product_list_rendered',
33 function (event) {
34 document.body.dispatchEvent(new Event('vippsInit'));
35 }
36 );
37
38
39 jQuery( document ).ready( function() {
40
41 // This is for WooCommerce Product Bundles, which potentially have *several* variant-products or configurable products, so
42 // the standard Woo hooks don't apply. Luckily, we have other, simpler events to use.
43 // For this to work, we also have to force the compat-mode thing on. IOK 2020-04-21
44 jQuery('.cart.bundle_data').on('woocommerce-product-bundle-hide', function (e, variant) {
45 jQuery('form .button.single-product.vipps-buy-now').removeClass('variation-found');
46 jQuery('form .button.single-product.vipps-buy-now').attr('disabled','disabled');
47 jQuery('form .button.single-product.vipps-buy-now').addClass('disabled');
48 // We don't know why the button is hidden, so ensure we use compatibility-mode IOK 2020-04-21
49 jQuery('.button.single-product.vipps-buy-now').addClass('compat-mode');
50 removeErrorMessages();
51 });
52 jQuery('.cart.bundle_data').on('woocommerce-product-bundle-show', function (e, variant) {
53 jQuery('form .button.single-product.vipps-buy-now').addClass('variation-found');
54 jQuery('form .button.single-product.vipps-buy-now').removeAttr('disabled');
55 jQuery('form .button.single-product.vipps-buy-now').removeClass('disabled');
56 removeErrorMessages();
57 });
58
59 // Hooks for the 'buy now with vipps' button on product pages etc
60 jQuery('body').on('found_variation', function (e,variation) {
61 const form = jQuery(e.target);
62 const target = form.find(".button.single-product.vipps-buy-now.variable-product");
63
64 var purchasable=true;
65 if ( ! variation.is_purchasable || ! variation.is_in_stock || ! variation.variation_is_visible ) {
66 purchasable = false;
67 }
68 target.addClass('variation-found');
69 if (purchasable) {
70 target.removeAttr('disabled');
71 target.removeClass('disabled');
72 removeErrorMessages();
73 } else {
74 target.attr('disabled','disabled');
75 target.addClass('disabled');
76 removeErrorMessages();
77 }
78 });
79 jQuery('body').on('reset_data', function (e) {
80 const form = jQuery(e.target)
81 const target = form.find(".button.single-product.vipps-buy-now.variable-product");
82 target.removeClass('variation-found');
83 target.attr('disabled','disabled');
84 target.addClass('disabled');
85 removeErrorMessages();
86 });
87 // If this is triggered, somebody just loaded a variation form, so we need to redo the button init scripts
88 jQuery('body').on('wc_variation_form', function () {
89 vippsInit();
90 });
91 // Allow other guys to do this too
92 jQuery('body').on('vippsInit', function () {
93 vippsInit();
94 });
95
96
97 // Using ajax, get a session and a key and redirect to the "buy single product using express checkout" page.
98 function buySingleProduct (event) {
99 event.preventDefault();
100
101 var element = jQuery(this);
102 if (jQuery('body').hasClass('processing')) return; // Trying to stop doublecclickers. IOK 2018-09-27
103
104 if (jQuery(element).hasClass('disabled')) {
105 if (typeof wc_add_to_cart_variation_params != 'undefined') {
106 if (jQuery(element).hasClass('variation-found')) {
107 window.alert(wc_add_to_cart_variation_params.i18n_unavailable_text);
108 } else {
109 window.alert(wc_add_to_cart_variation_params.i18n_make_a_selection_text);
110 }
111 } else {
112 console.log("Missing the wc_add_to_cart_variation_params");
113 }
114 return false;
115 }
116
117 jQuery('body').addClass('processing');
118 removeErrorMessages();
119 jQuery(element).attr('disabled','disabled');
120 jQuery(element).attr('inactive','inactive');
121 jQuery(element).addClass('disabled');
122 jQuery(element).addClass('loading');
123
124 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
125 wp.hooks.doAction('vippsBuySingleProduct', element, event);
126 }
127
128 var compatMode = jQuery(element).hasClass('compat-mode');
129 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
130 compatMode = wp.hooks.applyFilters('vippsBuySingleProductCompatMode', compatMode, element, event);
131 }
132
133 // In compatibility mode, we delegate to the existing buy now button instead of doing the logic
134 // ourselves. This allows more filters and actions in existing plugins to run. IOK 2019-02-26
135 if (compatMode) {
136 var form = jQuery(element).closest('form');
137 var otherbutton = form.find('.single_add_to_cart_button').first();
138 var compatAction = function () {
139 form.prepend('<input type=hidden id="vipps_compat_mode" name="vipps_compat_mode" value="1">');
140 if (otherbutton.length>0) otherbutton.click();
141 }
142 // If your theme or product is weird enough, you may need this
143 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
144 compatAction = wp.hooks.applyFilters('vippsBuySingleProductCompatModeAction', compatAction, element, event);
145 }
146 compatAction();
147 return false;
148 }
149
150 var data = {};
151 if (element.data('product_id') || element.data('product_sku')) {
152 data = element.data();
153 } else {
154 var form = element.closest('form.cart');
155 if (!form) {
156 jQuery(element).removeClass('disabled');
157 jQuery(element).removeClass('loading');
158 jQuery(element).removeAttr('disabled');
159 jQuery(element).removeAttr('inactive');
160 jQuery('body').removeClass('processing');
161 addErrorMessage('Cannot add product - unknown error');
162 return false;
163 }
164 // Initialize with the entire content of the form if we have it.
165 var serialized = form.serializeArray();
166 for (var i=0;i<serialized.length;i++) {
167 if (serialized[i]['name'] != 'add-to-cart') {
168 data[serialized[i]['name']] = serialized[i]['value'];
169 }
170 }
171 var prodid = jQuery(form).find('input[name="product_id"]');
172 var varid = jQuery(form).find('input[name="variation_id"]');
173 var quantity = jQuery(form).find('input[name="quantity"]');
174 data['quantity'] = (quantity.length>0) ? quantity.val() : 1;
175 data['product_id'] = (prodid.length>0) ? prodid.val() : 0;
176 data['variation_id'] = (varid.length>0) ? varid.val() : 0;
177 // Earlier versions, no variation:
178 if (prodid.length == 0) {
179 prodid = jQuery(form).find('button[name="add-to-cart"]');
180 if (prodid.length > 0) {
181 data['product_id'] = prodid.val();
182 } else {
183 // Some weird themes are even more incompatible
184 prodid = jQuery(form).find('button[data-product_id]');
185 data['product_id'] = prodid.length > 0 ? prodid.data('product_id') : 0;
186 }
187 }
188 }
189 // Finally, create a hook for even weirder themes.
190 data = wp.hooks.applyFilters('vippsBuySingleProductData', data, element, event);
191 data['action'] = 'vipps_buy_single_product';
192
193 jQuery.ajax(VippsConfig['vippsajaxurl'], {
194 "method": "POST",
195 "data":data,
196 "cache":false,
197 "headers": {"Accept-Language": `${VippsConfig['vippslocale']}, *`},
198 "dataType": "json",
199 "error": function (xhr, statustext, error) {
200 console.log("Error creating express checkout:" + statustext + " " + error);
201 addErrorMessage(error, element);
202 jQuery(element).prop('disabled',true);
203 jQuery(element).prop('inactive',true);
204 jQuery('body').removeClass('processing');
205 },
206 "success": function (result, statustext, xhr) {
207 if (result["ok"]) {
208 console.log("We created the order!");
209 /* In case user presses the back button */
210 setTimeout(function () {
211 jQuery(element).removeClass('disabled');
212 jQuery(element).removeClass('loading');
213 jQuery(element).removeAttr('disabled');
214 jQuery(element).removeAttr('inactive');
215 jQuery('body').removeClass('processing');
216 }
217 , 1500);
218 window.location.assign(result["url"]);
219 } else {
220 console.log("Failure!");
221 jQuery(element).removeClass('disabled');
222 jQuery(element).removeClass('loading');
223 jQuery(element).removeAttr('disabled');
224 jQuery(element).removeAttr('inactive');
225 addErrorMessage(result['msg'],element);
226 jQuery('body').removeClass('processing');
227 }
228 },
229 "timeout": 0
230 });
231
232 }
233
234
235
236 // Remove old error messages
237 function removeErrorMessages () {
238 jQuery('.woocommerce-error.vipps-error').fadeOut(300, function () { jQuery(this).remove(); });
239 jQuery(document).trigger('woo-vipps-remove-errors');
240 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
241 wp.hooks.doAction('vippsRemoveErrorMessages');
242 }
243 }
244
245 // And add new ones
246 function addErrorMessage(msg,element) {
247 // Allow developers to customize error message by hiding vipps-default-error-message and hooking woo-vipps-error-message <messsage>,<element>
248 var msg = "<p><ul class='woocommerce-error vipps-error vipps-default-error-message vipps-buy-now-error'><li>"+msg+"!</li></ul></p>";
249 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
250 msg = wp.hooks.applyFilters('vippsErrorMessage',msg, element);
251 }
252 jQuery(document).trigger('woo-vipps-error-message',[msg, element]);
253 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
254 wp.hooks.doAction('vippsAddErrorMessage', msg, element);
255 }
256
257 jQuery(msg).hide().insertAfter(element).fadeIn(300);
258 jQuery('.woocommerce-error.vipps-error').click(removeErrorMessages);
259 }
260
261 // Hooks for the button itself
262 function vippsInit() {
263 jQuery('.button.single-product.vipps-buy-now:not(.initialized)').click(buySingleProduct);
264 jQuery('.button.single-product.vipps-buy-now').addClass('initialized');
265 if (typeof wp !== 'undefined' && typeof wp.hooks !== 'undefined') {
266 wp.hooks.doAction('vippsInit');
267 }
268 }
269
270 // For modern wp/woo we want to subscribe to events for the cart especially. IOK 2026-02-24
271 if( window.wp?.data) {
272 // The interactivity based minicart is only loaded once; so if the cart changes wrt supporting Vipps Checkout we must handle that
273 // by subscribing to the cart data. IOK 2026-02-23
274 let prevCheckoutUrl = "";
275 function handleCartChanges () {
276 const minicartbutton = document.querySelector('a.wp-block-woocommerce-mini-cart-checkout-button-block');
277 if (!minicartbutton) return;
278
279 const cart = wp.data.select("wc/store/cart")?.getCartData?.();
280 if (!cart) return;
281 const vippsdata = cart?.extensions?.['woo-vipps'];
282 if (!vippsdata) return;
283 if (vippsdata['checkout_url'] && prevCheckoutUrl != vippsdata['checkout_url']) {
284 prevCheckoutUrl = vippsdata['checkout_url'];
285 minicartbutton.href = vippsdata['checkout_url'];
286 }
287 }
288 wp.data.subscribe(handleCartChanges);
289 }
290
291
292
293 vippsInit();
294 });
295
296