Showing posts with label opencart. Show all posts
Showing posts with label opencart. Show all posts

May 25, 2021

quickpay opencart 3d secure

  • Go to Settings → Acquirers → Swedbank (or any other acquirer) → View Advanced Settings → Enable SecurePay
  • Create a Fraud Filter having:
    • Metric=Transaction Type, Operator=in, Transaction Type=Card,Payment
    • Do=Enforce 3-D Secure
  • In the Opencart admin go to Extensions → Payment → QuickPay Creditcard → Cardtypelock 3d-creditcard
  • Alternatively, go to Settings → Integration → Default payment settings → Default payment methods → set 3d-creditcard

May 6, 2021

Google Search Console showing "Sitemap could not be read" and "Couldn't fetch"

The issue

  1. We run an Opencart website which has a built-in, default sitemap available at http://example.com/index.php?route=extension/feed/google_sitemap
  2. This sitemap has been submitted to Google Search Console → Sitemaps for years
  3. Google has stopped fetching it about a year ago, and any attempts to re-submit it under the same URL (or it's http/https and www/non-www variations) resulted in Couldn't fetch displayed in the list, as well as Sitemap could not be read on the drill-down page.

The confusion

  1. This support thread Sitemap could not be read in new GSC says it's a known bug:
    That the new console says 'couldnt fetch' is a bug in the console. Pending is the real status! Alas there is no real way (that I know of!) to tell between them. But can try using the URL Inspection on the sitemap url. it SHOULD say not indexed (it's a sitemap not a page, so shouldn't be indexed!), but can use the Live Test, to check if Googlebot CAN fetch it! Again as its a sitemap, NOT a page, DON'T use the 'Request Indexing' button! If Google can fetch it, it's most likely just Pending, which case just wait.
  2. The above has kept me from experimenting with our sitemap, but after keeping an eye on this for a few months, the status hasn't changed, so I decided to revisit

The solution

  1. Make your sitemap avalilable under /sitemap.xml. I have used the following Nginx rule: rewrite ^/sitemap.xml$ /index.php?route=extension/feed/google_sitemap break;
  2. Explicitly link to it using the robots.txt directive: Sitemap: https://www.example.com/sitemap.xml
  3. If you have a multistore (several domain names served by the same Opencart copy), you may have to have a dynamic robots.txt that replies with e.g. Sitemap: http<?=isset($_SERVER['HTTPS'])?'s':''?>://<?=$_SERVER['HTTP_HOST']?>/sitemap.xml. Make sure it's accessible under the default robots.txt name: rewrite ^/robots.txt$ /robots.php break;.
  4. The newly submitted Sitemap (essentially the same built-in Opencart sitemap submitted under a different URL) got fetched and showed Status=Success in just a few minutes, so there was no need to actually wait.

February 23, 2021

MySQL: SELECT an order having 2 or more identical products

SELECT 
    op.order_id, op.product_id, COUNT(op.product_id)
FROM
    order_product op
GROUP BY op.order_id, op.product_id
HAVING COUNT(op.product_id) >= 2
with a join to the actual orders table
SELECT 
    o.order_id, op.product_id, COUNT(op.product_id)
FROM
    `order` o
        INNER JOIN
    order_product op ON (o.order_id = op.order_id)
WHERE
    o.store_id = 18
        AND o.date_added > '2020-01-01 00:00:00'
        AND o.date_added < '2020-12-29 12:08:00'
GROUP BY o.order_id , op.product_id
HAVING COUNT(op.product_id) >= 2
ORDER BY o.date_added DESC

May 29, 2018

What do I think is wrong with Opencart

This is supposed to be a cumulative post expressing what I feel after years of closely working with Opencart.


  • Lack of attention to detail in everything, from texts (An email with a reset link has been sent your email address) to making things future-proof. 
  • No product id available on the cart page
  • Don't use the amp sign then
  • No currency cookie check
  • https://forum.opencart.com/viewtopic.php?f=10&t=12043&start=20#p151005 - this was back in 2010 and apparently admins/significant contributors are not very proficient with web security, which takes knowing how vulnerabilities are tested - see qphoria being surprised that simply removing the form from the template won't be enough, since vulnerability scanners generate their own forms (which to me is pretty much obvious). seeing most of the opencart code was contributed/made around that time and was mostly reused without refactoring, that may be an issue.
  • 20200619: admin/extension: every type of extension (shipping, theme) has its own listing script, i.e. shipping.php, theme.php - each doing pretty much the same thing, thus duplicating themselves
  • https://stackoverflow.com/questions/41746041/check-current-language-of-opencart-on-footer you can get the current language code but not the id
  • 20200708 if a multistore has different currencies, when calculating totals it still sums them up as if they're the same currency
  • 2021-04-30 Convoluted URL rewrite logic "that really sucks"
  • /r/webdev/comments/5hezip/is_opencart_as_bad_as_it_seems/
  • Still no proper PDO implementation, more importantly, utilising placeholders aka parameters
  • Admin Token. Admin auth is maintained via a Token added to every URL query string, instead of being stored in cookies or seesion. This extra, unnecessary URL component clutters the browser history (and you can't use top hits or url autocomplete), as well as the server logs. You can't bookmark some admin page, or hotlink to it from an external site. Your code is cluttered with $this->url->link('…', 'token=' . $this->session->data['token']). And more inportantly, this creates frustration when you submit a large form, but since the token has expired, it redirects you to log in (and loses all data), and after logging in you can't go back to re-submit, because your previous submission still has the old token in the URL (while if it was in the cookies, your browser would use whatever the current token is in the cookies, and the server would accept it).
  • poor admin UX design
    • No quick item management tools. If you need to disable a product, category, etc., you have to go to that item edit page, click the Data tab, scroll to the bottom, click to open the Status select box options (of course it's a select box), click the desired option, scroll to the top, click Save. Compare that to just clicking an iOS-like switch in the product list page (and having it save immediately).
    • Regarding the UX, the owners say you can buy an extension, and true enough, there are lots of extensions like Quantity Discount Price Bands Manager - OC - 2.X , which themselves say:
      So in order to add these quantity discounts you have manually to go to every single product you are selling and once you edit product, go to DISCOUNT tab and add one by one add discount:) It is a pain and a time killer process to manually add the very same discount tables to every product. Not to mention what if you made a mistake, or your price for X quantity has changed ? After a month? Yes:) once again The PAIN:) and once again manually re-edit every single product and edit the discounts one by one. … So No more Manual edit products, no more wasted time checking and changing each product discount table one by one entry. … So If you value your time, and want to focus on money making instead of wasting the time by doing Quantity discounts tables manually in each product, this extension is a must to have for you.
      So the extension's sole purpose is to fix the core software imperfection. So while Opencart itself is free, the cost of just the above is $20.
    • Editing something that has translations requires you to fill in translations for each language. Say, you have 10 languages in a store and you need to create a draft of an information page in English only. You will have to fill in the title, content, meta title, meta description etc. 10 times (when you need just 1) before it lets you save and leave. Some paid extension are proud to have the "save and leave" feature, which confirms people want it
  • 2021-04-30 A declining trend (and rightfully so) and shrinking first-world presence https://trends.google.com/trends/explore?date=all&q=opencart,prestashop
  • 2021-05-06 They seem to have no idea about return early e.g. in catalog/controller/extension/feed/google_sitemap.php or catalog/model/checkout/order.php.
  • 2021-05-17 make sure SEO URL is globally unique -- isn't it your job as a CMS though? Especially since for a CMS it's a matter of 1 (one) AJAX query vs. me as an admin I'm not even sure how can I check manually, are users expected to know MySQL, or are they expected to remember all the SEO urls they had used over time? Check every product, category or information page manually? Ridiculous
  • 2021-05-18 Have I mentioned vQmod?
    Notice: Undefined offset: 15 in /var/www/opencart/vqmod/vqcache/vq2-admin_view_template_catalog_information_form.tpl on line 95
    You can tell the error is somewhere in admin/view/template/catalog/information_form.tpl, but the line will be different in the real file from what the one it refers to in the modded file
  • 2021-05-25 not a true MVC: checkout order validation is done in a controller; if I add custom validation there, the admin edit order won't pick it up, so I now have to duplicate my code; no ability to reuse admin models in catalog and vice versa, leading to even more code duplication or hacky solutions. just copy the functions you need into the right file is not a viable solution at all.
  • 2021-08-19 no roadmap, no vision, no mission one man operation https://forum.opencart.com/viewtopic.php?t=222624
  • 2021-08-19 related options require a separate paid extension from a guy with heavy russian accent https://www.youtube.com/watch?v=qDZv081O9RM, while prestashop has it out of the box (called combinations)
  • 2021-09-29 checkout javascript code is very coupled. Say you need to reuse the form, you won't be able to reuse the validation javascript
  • 2021-09-29 controller/api/order::edit is fat, has too much logic, can't be reused granularly
  • 2021-10-01 same with https://github.com/opencart/opencart/blob/master/upload/catalog/model/checkout/order.php#L48, which even though it had been brought to look "modern" with namespaces and all, is still the old code, where I can't edit the order address without editing the whole order, even though it's a model and it's supposed to be fat and granular
  • 2021-10-04 no reusable order validation in order model - I have to implement all the validations all over the place
  • 2021-10-04 no vendor architecture on old versions
  • 2021-10-08 duplicated associations: order linked to country using country_id, but the country name is stored separately; when you update the country id you also have to update the name stored next to it, instead of having it retrieved via a join
  • 2021-10-26 https://github.com/opencart/opencart/search?q=error_firstname duplicated and hardcoded instead of sprintf
  • 2021-11-30 affiliate links e.g. https://github.com/opencart/opencart/blob/2.3.0.2/upload/admin/language/en-gb/extension/payment/pp_express.php#L9
  • 2021-12-01 The payment gateway integration architecture. You can't invoke a payment gateway giving it a total and some order info. Instead, you put that into $this->data->session, and all the payment gateways expect to read the data from there. This makes it impossible to pay for an existing order without clearing the cart contents.
  • 2021-12-29 Loading a language file inside a reusable controller element (a separate function, basically) loads the language for the whole thing, and it may overwrite the page title for example. I needed a phrase "Order Details" which exists in the account/order language file, and loading it for a reusable banner on the checkout, changed the checkout page title to "Order History". So basically I now have to come up with my own custom translation, in other words, the Opencart architecture keeps encouraging code duplication
  • 2022-02-16 The API is poorly documented, with typos and omissions: https://docs.opencart.com/en-gb/system/users/api/. Making a simple API request to have order status updated seems impossible and overcomplicated: you'd have to use your API key to request a token first, and then make requests with that token. However, due to a bug or who knows what, that token doesn't get linked properly (despite Daniel saying it got fixed) to something inside $this->data->session, so the requests result in a permission error. The advice that's closest to a real fix is to manually copy the session handlers from the latest version.
  • 2022-02-16 Daniel is an absolute insecure jerk. When someone came up with a bunch of improvement suggestions, the response was:
    i think its a case of "i want to add my own little piece of code because i'm going to use it in my projects from now on. so ill make an issue up and hope hes to stupid to check!" wasting my time!
    followed by:
    no not post issues here again! there are no performance issues! your just dumb!

    How about duplicate queries resulting in performance issues?

    there are no performance issues! your just dumb!
    Defensive. Denial. Daniel.
  • 2022-12-08 UX not a priority. A reasonable suggestion on a quick but significant improvement met with "ffs": https://github.com/opencart/opencart/issues/12001
  • 2023-03-06 calling `$this->cart->getTotal()` does not account for coupons; doesn't seem to be a built-in way to just see the actual cart total

What can be improved

  • 2021-09-30 09:32 if deleting an order status that has already been used, instead of an error message "Warning: This order status cannot be deleted as it is currently assigned to 1 orders!" let reassign those orders quickly
  • 2023-07-28 Refunds and returns. No way to refund the postage/shipping fee out of the box and have it recorded for accounting. No credit notes. Only one product per return.
To post: https://forum.opencart.com/viewtopic.php?f=202&t=216883

August 4, 2017

opencart attach all categories and products to a new store

Added a new store to opencart and now realised that none of the existing products and categories are linked to it. Will have to either manually edit 700 items, or come up with a MySQL query to bulk add multiple products and categories to that store for me.

Products

Store ID=123. Deleting all existing links to this store (if any) to avoid duplicate index error. Then attaching all products to it.
DELETE FROM feetunique.product_to_store where store_id=123;
INSERT INTO product_to_store (product_id, store_id) SELECT product_id, '123' from `product`;

Categories

Again, first deleting all existing links then adding new ones.
DELETE FROM feetunique.category_to_store where store_id=123;
INSERT INTO category_to_store (category_id, store_id) SELECT category_id, '123' from `category`;

You can add conditions to retrieve only active products (status=1), or any other filters if you want.

July 19, 2017

debug opencart 2.3 events triggers not working

Opencart's Event system is a better alternative to vQmod, although how to use it is not obvious, and the documentation is poorly written. As usual, working with Opencart is a major pain in the ass. I've spent quite a lot of hours trying to figure out how Events are supposed to work. I decided to write something down because surprisingly there doesn't seem to be a lot of information online. If you found this and still can't figure it out, please comment and I'll try to elaborate.

Here's how I was debugging them:

  • To debug what events are present on a given page, go to the Event::trigger() function and var_dump the $event variable. Those are the hooks you can listen on
  • Use either catalog or admin (depending on where's your callback) controller/startup/event.php file to check if your event was registered. This file's register function adds the events to the queue using the similarly named register() function from system/engine/event.php above. Once it's done, you can dump it's $this->data variable and check if a. your event is there and b. if it has a valid action. Here's what a valid action looks like:
  • If your action is null, the system may be looking for a wrong callback path. The action for your event is built upon the callback route you provide when you register an event. That route is then converted into a full path of a file the system tries to load and execute. 
  • If you're trying to hook before admin/controller/catalog/product::index(), your event trigger will be admin/controller/catalog/product/before, note that "index" gets omitted.
  • Another gotcha. When Opencart tries to execute an action, it checks if the number of parameter your callback action expects matches the number of arguments it's about to pass to it. If it doesn't match, the action will fail silently, with the Error: Could not call message only visible in the debug trace. The solution is to make your callback arguments optional.

April 17, 2017

opencart admin api & editing order permission denied

I wanted to update an order status but Opencart 2 showed me error_permission.

I spent some time debugging this pile of garbage and here's what I found.

The admin order editing function calls the internal API behind the scenes. The API requires the client to be logged in (hence the session check in the permission snipped I linked to above).

The log in is done per page, that is, you don't log in to the API once and then use that session. Each admin page seems to be logging in separately:



Here's the relevant portion where it tries to log in to the API from the order_info page.

I debugged the browser requests sent from that page and I could see the key variable was empty. I must've been passed empty like that from the sale/order.php controller. So I checked the relevant part in that controller too. Apparently, it checks the $api_info variable which, in it's turn, relies upon the config_api_id configuration. That value sits in your setting table and has to be set to 1:

UPDATE `setting` SET `value`='1' WHERE `key`='config_api_id'

Once that's done, make sure your store has an API user created and configured to be in use. Create under Settings - Users - API. Enable under Settings - Settings - [your primary store] - Option - API User.



December 21, 2016

Naming a new Opencart theme

Start by creating a controller, view and a language file for your theme in the admin

https://github.com/opencart/opencart/blob/master/upload/catalog/controller/event/theme.php#L13 not obvious as theu use "theme_default" everywhere and say that to create a theme you have to duplicate the default theme. so you start duplicating it as theme_example and in the end it turns out that they hardcoded a condition to rename "Theme_default" to default you should've called your theme just "Example"