bsandall

Member
  • Content count

    144
  • Joined

  • Last visited

  • Days Won

    5

bsandall last won the day on April 19

bsandall had the most liked content!

Community Reputation

10 Good

About bsandall

  1. Do any of your product options have price adjustments? Are any set to absolute price? The admin JavaScript does not handle absolute option prices well, but if you don't have any of those, it should have worked fine. If you could post a screenshot of your product's options tab, that would be helpful.
  2. At least you're getting the challenge - for me, I don't even get a chance to prove I'm human, it just fails automatically.
  3. Same here. I deal with manually deleting the obvious bot/would-be-hacker customer registrations so that paying customers don't have to be inconvenienced so much that they'll probably decide it's not worth placing an order.
  4. Heh, yeah my JS isn't too hot either - lots of trial and error. Just to note that my store I have added length, width and height to the products and product options. I also dynamically modify the product specification data displayed on the product page so that the product code and dimensions update based on the selected options. In other words, some portions of the above code may be completely irrelevant to your store, but it will at least hopefully get you started.
  5. I checked my (unedited) PayPal gateway class and it already had the bare ampersand - using PayPal Pro v1.1.7.
  6. You speak English well enough, mejor que hablo EspaƱol CubeCart makes an AJAX call via JavaScript (in `\skins\foundation\js\2.cubecart.js`) to format the price on the product page when options are selected. I modified that to instead query the database for the product data, including modifications from the options matrix. There were quite a few changes involved, including to the database, but here is my code for sending and handling the AJAX call. You will of course need to modify it to match your database and code needs. // in /skins/foundation/js/2.cubecart.js // change any calls to the `price_inc_options` function to use this function instead function specification_inc_options() { var options = []; $("[name^=productOptions]").each(function (index, element) { if (!$(this).val() || ($(this).is('input:radio') && $("input[name='" + element.name + "']:checked").length < 1)) { } else if ($(this).is('input:radio')) { // Prevent empty radio selections from adding multiple entries if (!$(this).is('input:radio') || $.inArray(element.name + '=0', options) === -1) { options.push(element.name + '=0'); } if ($(this).is(':checked')) { options.push(element.name + '=' + $(this).val()); } } else if ($(this).is('select')) { options.push(element.name + '=' + ($(this).find("option:selected").val())); } else if (($(this).is('textarea') || $(this).is('input:text')) && $(this).val() !== '') { // TODO options.push(element.name + '=' + $(this).val()); } else { // include other product options, e.g. those with only 1 option options.push(element.name + '=' + $(this).val()); } }); if (options.length > 0) { var product_id = document.getElementById('product_id'); if (product_id && product_id.tagName === 'INPUT') { options.push('product_id=' + product_id.value); } var action = $('form.add_to_basket').attr('action'); var parts = action.split("?"); action += (parts.length > 1 ? '&' : '?') + '_g=ajax_update_product_data&'; options = options.join('&'); $.ajax({ url: action + options, cache: true, complete: function(returned) { var data = $.parseJSON(returned.responseText); for (var key in data) { switch (key) { case 'price': $('#fbp').html(data[key]); break; case 'sale_price': $('#ptp').html(data[key]); break; case 'use_stock_level': var rows = $('table#product_spec_table tr'); if (data[key] == 1) { rows.filter('#stock_level_row').show(); rows.filter('.hidden_row').remove(); } else { rows.filter('#stock_level_row').hide(); if (rows.filter('.hidden_row').length == 0) { rows.filter('#stock_level_row').after('<tr class="hide hidden_row"><td></td><td></td></tr>'); } } break; case 'CTRL_SETTINGS': if (data[key]['CTRL_ALLOW_PURCHASE'] && !data[key]['CATALOGUE_MODE']) { if (data['set_enabled'] == 1) { $('#allow_purchase').show(); $('#lead_time').show(); } else { $('#allow_purchase').hide(); $('#lead_time').hide(); } $('#login_to_view').hide(); } else { $('#allow_purchase').hide(); $('#lead_time').hide(); if (data['set_enabled'] == 1 && data[key]['CTRL_HIDE_PRICES']) { $('#login_to_view').show(); } else { $('#login_to_view').hide(); } } break; default: // update product specifications var id = '#spec_' + key; if (data.hasOwnProperty(key) && $(id).length) { $(id).html(data[key]); } } } if (data['set_enabled'] == 1 && !data['CTRL_SETTINGS']['CTRL_HIDE_PRICES'] && data['CTRL_SETTINGS']['CTRL_OUT_OF_STOCK']) { $('#out_of_stock').show(); } else { $('#out_of_stock').hide(); } // Handle after loop so elements are properly displayed / hidden if (data['set_enabled'] == 1) { $('#ptp').show(); if (data['ctrl_sale']) { if ($('#fbp').length > 0) { $('#fbp').show(); $('#ptp').addClass('sale_price'); } } else { $('#fbp').hide(); $('#ptp').removeClass('sale_price'); } $('#combination_unavailable').hide(); } else { $('#fbp').hide(); $('#ptp').hide(); $('#combination_unavailable').show(); } } }); } } And then the processing of that AJAX request: // in `cubecart.class.php` after `case 'ajax_price_format':` in the `loadPage` function case 'ajax_update_product_data': $GLOBALS['debug']->supress(); $product_id = filter_var($_GET['product_id'], FILTER_VALIDATE_INT); if (!is_int($product_id)) { die(json_encode(false)); } $options = (isset($_GET['productOptions']) && is_array($_GET['productOptions']) ? $_GET['productOptions'] : false); $product = $GLOBALS['catalogue']->getProductData($product_id, 1, false, 10, 1, false, null); if ($product && $options) { // running totals of price modifiers for dealing with multiple absolute pricing options $product['price_total_modifier'] = 0.00; $product['option_price_ignoring_tax_modifier'] = 0.00; $product['price_optional_modifier'] = 0.00; // total price modifier of all non-matrix options // Modify product specifications based on each option $product['set_enabled'] = true; // default product, i.e. no options selected, should not show 'unavailable' message foreach ($options as $option_id => $option_data) { if (is_array($option_data)) { // Text option foreach ($option_data as $trash => $option_value) { if (($assign_id = $GLOBALS['db']->select('CubeCart_option_assign', false, array('product' => $product_id, 'option_id' => $option_id))) !== false) { $assign_id = $assign_id[0]['assign_id']; } else { $assign_id = 0; } $value = $GLOBALS['catalogue']->getOptionData((int)$option_id, $assign_id); if ($value) { Cart::updateProductDataWithOption($product, $value); } } } elseif (is_numeric($option_data)) { if (($value = $GLOBALS['catalogue']->getOptionData((int)$option_id, (int)$option_data)) !== false) { Cart::updateProductDataWithOption($product, $value); } } } // Apply option matrix modifiers, if any $options_identifier_string = $GLOBALS['catalogue']->defineOptionsIdentifier($options); $result = $GLOBALS['db']->select('CubeCart_option_matrix', 'product_id, set_enabled, price, sale_price, use_stock as use_stock_level, stock_level, product_code, upc, ean, jan, isbn', array('product_id' => $product_id, 'status' => 1, 'options_identifier' => $options_identifier_string)); if ($result) { Cart::applyProductMatrix($product, $result[0]); } } // Finally, format product values for display if (is_array($product)) { if ($product['sale_price'] == 0 || $product['price'] < $product['sale_price']) { $product['sale_price'] = $product['price']; } $product['ctrl_sale'] = ($product['sale_price'] > 0 && $product['sale_price'] < $product['price'] ? true : false); $product['price'] = $GLOBALS['tax']->priceFormat($product['price']); $product['sale_price'] = $GLOBALS['tax']->priceFormat($product['sale_price']); // Format the following entries to 3-decimal precision $thousands = array('product_weight','product_length','product_height','product_width'); foreach ($thousands as $key) { $product[$key] = sprintf('%.3F', $product[$key]); } // Add settings to determine which GUI elements to display / hide (replicates variables / logic in Catalogue#displayProduct) $product['CTRL_SETTINGS'] = array( 'CATALOGUE_MODE' => ($GLOBALS['config']->get('config', 'catalogue_mode') ? true : false), 'CTRL_ALLOW_PURCHASE' => true, 'CTRL_OUT_OF_STOCK' => false, 'CTRL_HIDE_PRICES' => false ); if ((bool)$product['use_stock_level']) { if ((int)$product['stock_level'] < 1) { $product['CTRL_SETTINGS']['CTRL_ALLOW_PURCHASE'] = (bool)$GLOBALS['config']->get('config', 'basket_out_of_stock_purchase'); $product['CTRL_SETTINGS']['CTRL_OUT_OF_STOCK'] = true; } } if ($GLOBALS['session']->get('hide_prices')) { $product['CTRL_SETTINGS']['CTRL_ALLOW_PURCHASE'] = false; $product['CTRL_SETTINGS']['CTRL_HIDE_PRICES'] = true; } } die(json_encode($product)); break;
  7. @havenswift-hosting Thanks for that info - had the same issue with some customers' orders getting stuck in pending and it turns out PayPal had turned off our IPN as well. :\
  8. Tried deleting the session cookie as well, FF still won't even show the reCAPTCHA sidebar tab with the terms and privacy policy links. Basically, I am unable to do anything on the store front as a customer would when using FF with invisible reCAPTCHA enabled. In Chrome, the invisible reCAPTCHA works for everything but checking out as a guest, as described in the original post. I'm using the latest versions of both FF and Chrome. Not sure if this is a bug in the browsers, with Google's invisible reCAPTCHA, with CubeCart, some combination of those, or if it really is just a caching issue. If it is a caching issue, it's a pretty serious one that I imagine will also affect many of our customers. @Dirty Butter I'm curious to hear the results of your further testing. You said that it was working in FF, but now it isn't... that's exactly what I experienced. Would you be willing to also try using Chrome? That makes sense, but I'm not getting challenged at all during the checkout process. Instead, when I click continue, I simply get the 'The verification code was incorrect' error message indicating that reCAPTCHA couldn't verify I was human, and after that for some reason no matter what email address I enter in the form, after clicking continue again it tells me the email address is invalid. I realize that reCAPTCHA does not validate email addresses - I'm just describing the symptoms that I am experiencing, both in Chrome and FF. Note that the process works fine, at least in Chrome, so long as I choose to create an account during the checkout process.
  9. The problem with that is there is no guarantee that the store admins will set a default for all required options on every single product that has options. The ability to even set a default was only introduced in 6.1.6 and there are thousands of stores out there with tens or hundreds of thousands of products - I highly doubt everyone has had time to go through and set default options, and many stores might not even bother as it may not be something that is required for their business model. That said, I do see what you are saying. Yes, the product price fields are redundant for the type of use case you have. CubeCart is not set up to efficiently query a price from a set of options, however, especially considering that option prices can be either absolute or cumulative. It would be a mess trying to determine prices for all of the products displayed on the home page or in a category, so CubeCart takes the route of having an easily retrievable price at the product level. This seems to me to be a good compromise for the sake of site speed and ease of use. However, the potential for data inconsistency could be addressed by providing some method of auto-setting the product price based on the default options, e.g. when saving the product. Normal price would be easy, but how would you propose determining sale price? How about cost? For my own store, I solved that issue by modifying the code to have a 'Price' and 'Sale Price' field for each entry in the options matrix. Non-required options can still modify those prices, but any required options I don't even bother setting price adjustments at the option level - just in the options matrix.
  10. Interestingly, the reCAPTCHA sidebar won't even display anymore in Firefox (it did once before I tried registering an account), even in a private window after clearing the cache, which means I can't do anything that requires the verification code. No challenge is given and I cannot submit the contact or registration forms. It still shows up in Chrome and those forms work fine, just not checking out as a guest. I'll try restarting my browsers tomorrow and see if that gets me anywhere.
  11. reCAPTCHA stores your browser fingerprint along with other data such as your computer's hardware configuration; once you have proven that combination to belong to a human, it is very unlikely to challenge you again unless you start using a different browser, hardware, or both. Do you get challenged if you try again now with a bogus email address?
  12. To clarify, the reCAPTCHA is working fine when registering as a customer - I've had challenges pop up for me and succeeding at them allowed me to continue registration. The only case I've found where it failed (and no challenge popped up) was checking out as a guest. Also, I don't think the reCAPTCHA necessarily catches bad email addresses, at least not as the only indicator. For example, I was only challenged by reCAPTCHA to prove I am human the first time I tried to create an account even though I used my full name and a real email address; later in a private browser session it let me pass despite me typing my name as 'B S' and email as 'b@s.ru'.... -.-
  13. Store is on 6.1.7 and has SSL enabled. Enabled Invisible reCAPTCHA. I am able to register new accounts, log in, and checkout as a logged in customer. I am also able to create an account during checkout and proceed as normal. However, trying to checkout as a guest, i.e. not creating a registered account, does not work. Upon entering the customer data and clicking either `Update Basket` or `Secure Checkout`, the error message `The verification code was incorrect. Please try again` appears, indicating that reCAPTCHA failed to verify that I am human. No reCAPTCHA dialogue box popped up to select images or anything. Once that fails, the email address I had entered has been cleared and any further attempt to proceed after re-entering an email address is met with the `Please enter a valid email address` error. For now, I've simply disabled reCAPTCHA so as not to interfere with my customers' experience. Has anyone else experienced this issue? Anyone know of a fix? Cheers.
  14. Unfortunately there isn't yet a way for CubeCart to automatically determine the correct price, and it would probably be computationally somewhat expensive to do so (i.e. the site would be slower to load). You can avoid such a discrepancy, however, by setting the product's price to whatever the price is for the product with the default options selected. So in the case of the screenshot above, you should set the price for 'Test Product' to 150 Euros and remove the sale price. The customer will then see the price as 150 Euros wherever the product may be displayed, and that is the price for the default version of the product.
  15. It should look like the attached photo when you are creating or editing a product's options.