In this Opencart user manual, we are showing how you can install the store credit extension, add the transaction amount to the customer, and how the customer can use the amount while checkout.
Install the store credit extension
Go to admin >> Extensions >> Extensions >> Choose the Extensions Type >> Order totals >> Then, install the Store Credit.
Once you installed the Store Credit then you can edit it and enable it and enter the sort order as you want to show on the cart/checkout page.
Click Save and store credit order total extension is installed and configured.
Assign the amount to the customer through transactions
To add or assign an amount to the customer, go to admin >> Customers >> Customers list >> Edit the customer you want to add the amount >> then go to the Transactions tab >> Enter the description and amount you want to add for that customer and the amount is assigned to that customer.
How the customer will use the store credit assigned from the transactions?
Once the admin assigns or adds the amount from the transactions, then the customer can use that amount to their orders. Customers can view the Store credit amount from the transactions.
The customer can use these Store credits, which will be automatically decreased from their orders. You can see in the following how it decreased the amount in the shopping cart and confirm checkout page.
In this way, you can set up the Store Credit and customers can use it. As always please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our Twitter account @rupaknpl and subscribe to our youtube channel Opencart tutorials and click opencart user manual for more docs. Similarly, keep on visiting the blog where you will find lots of free modules.
In this free Opencart module, we can edit products directly from the product list in the opencart 3, it is using editable table widget javascript, with this you can easily edit the product name, module, price, quantity, and status.
First, download the Opencart 3 free module by clicking the button below:
Now login to your admin section >> go to Extensions >> Installer >> Upload the zip file and you will see the editfromproductslist.ocmod.zip in the install history.
Now, go to admin >> Extensions >> Modifications >> you will see the “Edit directly from Products list” in the list >> Then click the refresh button
Now go to the admin >> Catalog >> Products, now Product name, Model, Price, Quantity, and Status is editable directly from the product list.
Now edit any of the product names, then it will ask to choose the active language. If you want to update a different language then we need to enter the language id in the prompt box.
Once you click Ok or enter the language and click Ok, then, the product name is updated and it will show the alert box like below:
Similarly, you can edit the Model. But for the price you don’t need to enter the $ sign, you just add the number of the price that you want to update. If you enter something other than a number then it will alert is like below:
In the same way, for quantity also you just need to enter the number, if you don’t enter the number it will show an alert like above.
For the status, you need to enter 1 or 0 only. 1 is to enabled and 0 is to disabled. If you don’t enter then it will alert like:
Once you enter the 1 or 0 then it will show a success alert message like below:
In this way, you can easily edit the products’ name, model, price, quantity, and status directly from the product lists.
We are using the editable table Js and the following OCMOD modification:
<?xml version="1.0" encoding="utf-8"?>
<modification>
<name>Edit directly from Products list</name>
<version>3.0</version>
<author>Rupak Nepali</author>
<link>https://webocreation.com</link>
<code>webocreation_edit_products_in_admin</code>
<description>Edit products directly from the list in Opencart 3</description>
<file path="admin/controller/catalog/product.php">
<operation>
<search><![CDATA[public function autocomplete()]]></search>
<add position="before"><![CDATA[
public function editableTableUpdate()
{
$updated = "Please edit the right column";
$id = explode("___", $_POST['value']['id']);
$product_id = $id[1];
$columnToUpdate = $id[0];
if (in_array($columnToUpdate, array('name', 'model', 'price', 'quantity', 'status'))) {
$valueToUpdate = $_POST['value']['value'];
$lang = $_POST['value']['lang'];
$this->load->model('catalog/product');
$updated = $this->model_catalog_product->updateEditableTable($columnToUpdate, $product_id, $valueToUpdate, $lang);
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($updated));
}
]]>
</add>
</operation>
<operation>
<search><![CDATA[$data['products'] = array();]]></search>
<add position="before"><![CDATA[
$data['active_language'] = $this->config->get('config_language_id');
]]>
</add>
</operation>
</file>
<file path="admin/model/catalog/product.php">
<operation>
<search><![CDATA[public function getTotalProductsByLayoutId($layout_id)]]></search>
<add position="before"><![CDATA[
public function updateEditableTable($columnToUpdate, $product_id, $valueToUpdate, $lang)
{
try {
if ($columnToUpdate == "name") {
$this->db->query("UPDATE " . DB_PREFIX . "product_description SET " . $columnToUpdate . " = '" . $valueToUpdate . "' WHERE product_id = '" . (int) $product_id . "' and language_id = '" . $lang . "'");
} else {
$this->db->query("UPDATE " . DB_PREFIX . "product SET " . $columnToUpdate . " = '" . $valueToUpdate . "' WHERE product_id = '" . (int) $product_id . "'");
}
return "Product ID " . $product_id . "'s " . $columnToUpdate . " is updated with value " . $valueToUpdate;
} catch (ConnectionException $e) {
return $e->getMessage();
} catch (\RuntimeException $e) {
return $e->getMessage();
}
}
]]> </add>
</operation>
</file>
<file path="admin/view/template/catalog/product_list.twig">
<operation>
<search><![CDATA[{{ footer }} ]]></search>
<add position=" "><![CDATA[
<script type="text/javascript" src="view/javascript/jquery/mindmup-editabletable.js"></script>
<script>
$('#editable').editableTableWidget();
$('#editable td').on('change', function (evt, newValue) {
var targetid = evt.target.id;
if (['', 'name', 'status', 'quantity', 'price'].indexOf(targetid.split('___')[0])) {
}else{return false;}
if (targetid.split('___')[0] == 'name') {
var lang = prompt(
'The active language is' +
{{active_language}} +
'. If you want to update different language then please enter here',
{{active_language}}
);
}
if (targetid.split('___')[0] == 'status') {
var statusenter = 1;
if (newValue == 0 || newValue == 1) {
statusenter = 0;
}
if (statusenter) {
alert('The value need to be 0 or 1');
exit();
}
}
if (targetid.split('___')[0] == 'quantity') {
if (isNaN(newValue)) {
alert('Please enter the numeric value');
exit();
}
}
if (targetid.split('___')[0] == 'price') {
if (isNaN(newValue)) {
alert('Please enter the numeric value');
exit();
}
}
const postvalue = { id: targetid, value: newValue, lang: {{active_language}} };
$.post( 'index.php?route=catalog/product/editableTableUpdate&user_token={{ user_token }}',
{ value: postvalue }
).done(function (data) {
alert(data);
});
});
$('#editable td.uneditable').on('change', function (evt, newValue) {
return false;
});
</script>
]]> </add>
</operation>
<operation>
<search><![CDATA[<td class="text-left">{{ product.status }}]]></search>
<add position="replace"><![CDATA[<td class="text-left" id="status___{{product.product_id}}">{{ product.status }}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-right">{% if product.quantity <= 0 %}]]></search>
<add position="replace"><![CDATA[<td class="text-right" id="quantity___{{product.product_id}}">{% if product.quantity <= 0 %}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-right">{% if product.special %}]]></search>
<add position="replace"><![CDATA[<td class="text-right" id="price___{{product.product_id}}">{% if product.special %}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-left">{{ product.model }}]]></search>
<add position="replace"><![CDATA[<td class="text-left" id="model___{{product.product_id}}">{{ product.model }}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-left">{{ product.name }}]]></search>
<add position=" "><![CDATA[<td class="text-left" id="name___{{product.product_id}}">{{ product.name }}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-center">{% if product.image %}]]></search>
<add position=" "><![CDATA[<td class="text-center uneditable">{% if product.image %}]]></add>
</operation>
<operation>
<search><![CDATA[<td class="text-center">{% if product.product_id in selected %}]]></search>
<add position=" "><![CDATA[<td class="text-center uneditable">{% if product.product_id in selected %}]]></add>
</operation>
<operation>
<search><![CDATA[<table class="table table-bordered table-hover">]]></search>
<add position=" "><![CDATA[<table id="editable" class="table table-bordered table-hover">]]></add>
</operation>
</file>
</modification>
We write a simple Javascript custom email validation that allows only company emails and it was implemented on Unbounce landing pages. We use pattern, oninvalid and onchange attributes. We set regex (^[a-zA-Z0-9.%+-]+@(?!gmail.com)(?!yahoo.com)(?!hotmail.com)(?!yahoo.co.in)(?!aol.com)(?!live.com)(?!outlook.com)[a-zA-Z0-9-]+.[a-zA-Z0-9-.]{2,61}$) to validate the email pattern and set the custom validity message for oninvalid attribute with setCustomValidity() method of the HTMLObjectElement interface sets a custom validity message for the element, and finally onchange attribute we set the setCustomValidity() method to empty.
How to validate the email field to allow only company email?
With HTML5, we can do the email input field validation with pattern, setCustomValidity method easily. If you write the code like below, it will not allow the email that contains gmail.com, yahoo.com, hotmail.com, yahoo.co.in, aol.com, live.com and outlook.com
<input id="Email" name="Email" type="email" required pattern="^[a-zA-Z0-9._%+-]+@(?!gmail.com)(?!yahoo.com)(?!hotmail.com)(?!yahoo.co.in)(?!aol.com)(?!live.com)(?!outlook.com)[a-zA-Z0-9_-]+.[a-zA-Z0-9-.]{2,61}$" oninvalid="setCustomValidity('Please enter business email')" onchange="try{setCustomValidity('')}catch(e){}')">
Similarly, we can add custom Javascript into the Unbounce like below, which will allow only company emails. The Javascript code is like below:
<script>
/* Allow only company emails */
document
.getElementById("Email")
.setAttribute(
"pattern",
"^[a-zA-Z0-9._%+-]+@(?!gmail.com)(?!yahoo.com)(?!hotmail.com)(?!yahoo.co.in)(?!aol.com)(?!live.com)(?!outlook.com)[a-zA-Z0-9_-]+.[a-zA-Z0-9-.]{2,61}$"
).setAttribute(
"oninvalid",
"setCustomValidity('Please enter business email')"
).setAttribute("onchange", "try{setCustomValidity('')}catch(e){}')");
</script>
** If you email id is different then change the “Email” in the above code.
Log in to your Unbounce, click your page where you want to add the email validation.
Edit the variant of the page
Click the JavaScript at the bottom of the page editor
Then, you will see a popup where you can add the Javascript like below.
Click “Add Script to the Variant”
Then enter the “Script Name”
Add the above JS code
Click Done
After adding the above code in the Javascript manager of the Unbounce page and you tried to submit gmail email then it shows error like below:
In this way, you can add custom email validation in form field and similarly on the Unbounce page. Hope you liked this article, please subscribe to our YouTube Channel for Opencart video tutorials. You can also find us on Twitter and Facebook.
We were searching for the free API which gives the country code as per your IP addresses as per our requirement we were looking to show team members as per the Country, defaulting different currency as per the active country, defaulting different language as per the active country, etc. Our research found ip-api.com which is free for non-commercial use, no API key required, easy to integrate, and available in JSON, which fulfilled all our requirements, so we use ip-api.com. As they provide free for non-commercial use so we like to share with you as well.
We use a basic fetch request of Javascript. The following code is to get the country code as per your IP address
Have a look at their documentation of Geolocation API
We can get the following fields from the API: status, message, continent, continentCode, country, countryCode, region, regionName, city, district, zip, lat, on, timezone, offset, currency, isp, org, as, asname, reverse, mobile, proxy, hosting, query
Their endpoints are limited to 45 HTTP requests per minute from an IP address but they provide a Pro version with more benefits and unlimited HTTP requests.
So, hope this helps for your personal project to get the country code as per IP address and can use it as per your benefits. With this simple and easy API, we are able to show different team members as per country, and similarly, show different currencies and languages as per the country. Let us know if you find any other easy and better solutions.
We planned to show my top categories at the homepage as featured categories so we planned to make the OpenCart module for free to get this functionality. Let’s say it “Category Featured Show Module”. As we created an OpenCart module so we can enjoy an unlimited module instance system which means we can show the same module in different layouts on the same pages and also on different pages. Please take into consideration that we have created this module for OpenCart version 3.0, 2.0.3.1. and suppose that it will be compatible with above 2.0.2, we are lazy to test them. Please provide feedback if it is not compatible then we can go through the problem.
Let’s start to install Category Featured Show Module.
Then unzip it and upload the files and folders to their respective folders.
OpenCart core files are not changed.
Now login to Admin section and go to Extensions>> Module >> Category Featured
Install the Category Featured Show Module (If you don’t know how to install the OpenCart module then read here).
Click edit blue button
Then enter details
Enter Module Name which will show the module heading at front.
Then Start typing category name and click the category you want to show at the front (Uses AutoComplete functionality to show lists of a matched name of categories).
Enter limit to show categories at front
Enter the width of the image that you like to show at the front
Enter the height of the image that you like to show at the front
Choose the status, Enabled to show the module and Disabled to hide the module
Now Click Save button
Check our setting in the image below:
Now set layout and position for Category Featured Show Module. We are showing the Category Featured Show Module at homepage so follow the same steps as below if you like to show to different layout then choose the respective layout.
Go to Admin >> System >> Design >> Layouts.
Then click the blue plus button at the bottom which will add another row.
Then select “Category Featured > Top Category” at the Module column.
Select “Content Top” at Position Column.
Enter your desired Sort Order at Sort Order Column.
Then click the save button.
Our setting to show at home page is as shown in the image below:
Go to the home page and you will see the image below:
You can show as many module instances as you like and your heading title is shown as Module Name from admin so it is also customized as needed.
This module has been successfully tested for a standard OpenCart 2.0.3.1.
If you get any problem with the module then let me know by commenting or through the contact form.
Future upgrade: Options to hide and show of category description, name and upload the customized image for the category and different layouts. Likewise, make the module to show products as per the category. Keep on visiting for updates 🙂
Support:
Further help and customized versions: If you need a customized version of this module and any other Opencart help and support then let me know. You can email us at webocreation.com@gmail.com
We saw some posts in Stackoverflow and Opencart forum to make the slideshow module full-width, similarly, the HTML content module full-width and similar posts asking help. Thus, we are showing you a simple way to make full-width with CSS for Opencart.
Make Slideshow full-width
The CSS used is similar to below which calculates the left position and starts from it making it 100% vertical width.
Now let’s start with the slideshow module. As we need to add the above code, so the easy we add it is on the Google Analytics module section. For that, go to admin >> Extensions >> Extensions >> Choose the extension type >> Analytics >> Install the Google Analytics >> Edit it >> Paste the above code in the Google Analytics Code field >> Enabled it >> Then, click the save button.
With this simple CSS code, the slideshow of the Opencart core becomes full-width.
A simple way is to add the title, content, and CSS all in the HTML description like below:
<div class="htmlcontentfullwidth">
<h2>This is heading title of HTML module</h2>
<p>
HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description HTML Module description
</p>
</div>
<style>
.htmlcontentfullwidth{
left: calc(-1 * (100vw - 100%) / 2);
width: 100vw;
position: relative;
padding: 50px 20px;
}
</style>
An HTML content module doesn’t have any class or id by default so we implemented it like above. With that the HTML module becomes full width like below:
In this way, you can make a full-width module with a simple CSS in the Opencart version. Let us know if you have any other better ideas and need support to make any modules full-width. Please subscribe to our YouTube Channel for Opencart video tutorials and get lots of other Opencart free modules. You can also find us on Twitter and Facebook.
In this Opencart 3 module development tutorial, we are showing you how to create a multi-instance opencart 3 module frontend section and make an autoplay slider of testimonials. In our last two posts, we show how to perform Opencart CRUD functionalities of testimonials, create an admin custom listing page, form, validate it and save in the database, then create the admin section of the multi-instance opencart module now we will use those settings and show the testimonials at the frontend. The testimonial module at the frontend will look like in the image below. It will have a title, image, testimonial title, testimonial description, and sliders with autoplay and pagination.
We start by creating the language file go to catalog/language/en-gb/extension/module/ and create testimonial.php and paste the following code. We don’t have lots of text needed in the frontend so just adding heading_title.
After that, we create the controller file at catalog/controller/extension/module/ and name it testimonial.php, following is the code and the code is described in the comment. You can see one difference for multi-instance and single instance index method, in multi-instance we pass the $setting argument.
<?php
/*** As our file is testimonial.php so Class name is ControllerExtensionModuleTestimonial which extends the Controller base class ***/
class ControllerExtensionModuleTestimonial extends Controller
{
/*** Index method is called automatically or by default, if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4 .
$setting is the argument of index which contain all details of the module ***/
public function index($setting)
{
/*** Loads the language file catalog/language/en-gb/extension/module/testimonial.php by which the varaibles of the language file are accessible in twig file. ***/
$this->load->language('extension/module/testimonial');
/*** This is to load the model file catalog/model/extension/module/testimonial.php by which we can access all the method in ModelExtensionModuleTestimonial. ***/
$this->load->model('extension/module/testimonial');
/*** We can add custom CSS and JS as per needed for the controller. These two lines is to add the custom CSS that is needed only for this controller. Good for performance as it loads only when needed. We add these to show the slider effects for the testimonials ***/
$this->document->addStyle('catalog/view/javascript/jquery/swiper/css/swiper.min.css');
$this->document->addStyle('catalog/view/javascript/jquery/swiper/css/opencart.css');
/*** We add this to add custom JS for the slider effects of testimonials ***/
$this->document->addScript('catalog/view/javascript/jquery/swiper/js/swiper.jquery.js');
$data['testimonials'] = array();
/*** Setting array to pass for getTestimonials for filtering the testimonials
* $setting['limit'] is the value we get from the database which we added in the testimonial module setting section. Opencart find out for us to use the $setting. ***/
$filter_data = array(
'sort' => 'p.date_added',
'order' => 'DESC',
'start' => 0,
'limit' => $setting['limit']
);
/*** This is to call getTestimonials method of class ModelExtensionModuleTestimonial and retrieve the filtered out testimonials ***/
$results = $this->model_extension_module_testimonial->getTestimonials($filter_data);
if ($results) {
/*** This is to load the model file catalog/model/tool/image.php by which we can access all the method and especially we use resize method for resizing the image. ***/
$this->load->model('tool/image');
/*** We loop through the $results and sets testimonials array which is used in the twig or view file ***/
foreach ($results as $result) {
if ($result['image']) {
$image = $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height']);
} else {
$image = $this->model_tool_image->resize('placeholder.png', $setting['width'], $setting['height']);
}
$data['testimonials'][] = array(
'testimonial_id' => $result['testimonial_id'],
'thumb' => $image,
'name' => $result['name'],
'description' => html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')
);
}
/*** This is to load the view catalog/view/theme/default/template/extension/module/testimonial.twig. ***/
return $this->load->view('extension/module/testimonial', $data);
}
}
}
Model file code description
Testimonials are custom data, so we need to create a model file also to retrieve the testimonials from the database. So let go to catalog/model/extension/module/ and create a testimonial.php and paste the following code. The following code is SQL to retrieve the testimonials.
<?php
class ModelExtensionModuleTestimonial extends Model
{
/** getTestimonials method is to retrieve the testimonials which is called from controller like $results = $this->model_extension_module_testimonial->getTestimonials($filter_data);. $data is the filtering parameter. Multiple testimonials are returned ***/
public function getTestimonials($data = array())
{
$sql = "SELECT * FROM " . DB_PREFIX . "testimonial c1 LEFT JOIN " . DB_PREFIX . "testimonial_description cd2 ON (c1.testimonial_id = cd2.testimonial_id) WHERE cd2.language_id ='" . (int) $this->config->get('config_language_id') . "'";
$sort_data = array(
'name',
'sort_order'
);
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
$sql .= " ORDER BY " . $data['sort'];
} else {
$sql .= " ORDER BY sort_order";
}
if (isset($data['order']) && ($data['order'] == 'DESC')) {
$sql .= " DESC";
} else {
$sql .= " ASC";
}
if (isset($data['start']) || isset($data['limit'])) {
if ($data['start'] < 0) {
$data['start'] = 0;
}
if ($data['limit'] < 1) {
$data['limit'] = 20;
}
$sql .= " LIMIT " . (int) $data['start'] . "," . (int) $data['limit'];
}
$query = $this->db->query($sql);
return $query->rows;
}
}
View file or template file code description
At last, the view file or template file, which we create at catalog/view/theme/default/template/extension/module/, we named it testimonial.twig and paste the following code. We are showing the testimonial as a slider so we are using the Opencart default Swiper slider.
In this way, we create an Opencart 3 testimonial module’s frontend and show the setting that we entered in the multi-instance module admin section. Similarly, we make a slider of the testimonial module. Hope you liked this post, let us know if you have any questions or suggestions, please subscribe to our YouTube Channel for Opencart video tutorials. You can also find us on Twitter and Facebook. Enjoy!
In this Opencart tutorial, we go through how to create an off-site payment extension in Opencart 3.0.3.3, in our last tutorial, we show the eCommerce payment flow that happens in Opencart, here we will show how to create the PayPal Standard payment extension, as all 3rd party extensions are removed from the download files, saying it is taking too much time to maintain but these will be uploaded to opencart.com and will be provided in a JSON string to be downloaded on demand.
For OpenCart payment extension, here are the lists of files you need to create, the link is for GitHub page where you can get all the codes, below we are just describing what is important:
We see the form action URL is different so that field setting is needed in the admin, merchant email or business email is need where the payment is made, transaction method whether it is an Authorization or Sale transactions, Total field, Geo Zone field, Status, Sort Order field and order status fields are needed. You can know which fields are needed by going through the documentation of the Payment method.
So, for PayPal Standard here is the output for the admin section:
Let’s start with the admin controller file of Payment extension:
Open admin >> controller >> extension >> payment folder and create the paypal_standard.php, for yours you can name what your payment name is. In the file name _ is not needed, we add it just to differentiate it. Now open the paypal_standard.php and start creating the Controller Class.
As our file name is paypal_standard.php, the class name is ControllerExtensionPaymentPaypalStandard which extends the Controller base class. Although the filename includes _ (underscore), it is not needed for the Class name.
class ControllerExtensionPaymentPaypalStandard extends Controller {
Declaration of the private property ‘error’ so that we can get check if any error occurs in the whole class.
private $error = array();
Create an index method. The index method is called automatically if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4
public function index() {
Loads the language file by which the variables of language file are accessible in twig files
Loads the model admin/model/setting/setting.php so that we can use the methods defined there.
$this->load->model('setting/setting');
This is how we check if the form is submitted. When we submit the form then this block of code also runs. Then it also validates the modified permission and other validation.
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
Look at this line of codes, this is the code section which distinguishes from Single Instance to Multi-Instance. If it is a payment extension then it acts as a Single instance module, which will have editSetting function, see the first parameters “payment_paypal_standard”, which need to be unique and it should start with “payment_”, all $_POST values will be saved on the setting database table. Then, it sets the success message in session and then redirects to the payment listing page.
In the database setting table, the code is “payment_paypal_standard” and have the key which is the field name and value is the field value.
The editSetting saves the data to oc_setting database table, see payment_ is important else it will not be saved. The following code sets the success message in the session.
This is to check what we fill out in the form, whether the email is added. If it is the loading time then it gets the value from the database config value which was stored in the oc_setting database table.
Similarly, other fields are checked, like for fields payment_paypal_standard_test, payment_paypal_standard_transaction, payment_paypal_standard_debug, payment_paypal_standard_total, payment_paypal_standard_canceled_reversal_status_id, payment_paypal_standard_completed_status_id, payment_paypal_standard_denied_status_id, payment_paypal_standard_expired_status_id, payment_paypal_standard_failed_status_id, payment_paypal_standard_pending_status_id, payment_paypal_standard_processed_status_id, payment_paypal_standard_refunded_status_id, payment_paypal_standard_reversed_status_id, payment_paypal_standard_voided_status_id, payment_paypal_standard_status, and payment_paypal_standard_sort_order. You can check those all opencart codes here.
Mostly, we use geo zones for payment extensions so that we can control as per the country or zones. So to pull the geo zones in opencart we use the following code:
Now, we see the validate method, this is how validation is done, we check whether the user has permission to modify or not. If you want to validate the form data then you can check it here as well. If there is an error then $this->error[‘warning’] is set and a warning is shown. We check whether the Paypal email is added or not. Similarly, you can check other validation here.
private function validate()
{
if (!$this->user->hasPermission('modify', 'extension/payment/paypal_standard')) {
$this->error['warning'] = $this->language->get('error_permission');
}
if (!$this->request->post['payment_paypal_standard_email']) {
$this->error['email'] = $this->language->get('error_email');
}
return !$this->error;
}
In this way, we write the code in the controller for the payment extension module at admin section.
The button type is submitted, and form equals value needs to be the form id. The form id is form-payment that is why it is, form=”form-payment”, the form code is like below:
Likewise, look at Order status tab, the code is similar for all the statuses, the select field name starts with payment_ and it loops order_statuses and the selected order status is saved in the database setting table.
This way you can check other codes and let us know in a comment if you need any code explanation.
With above four files created, our admin side coding is completed.
Now, catalog language file of Payment extension:
Let’s start with the language file catalog/language/en-gb/extension/payment and create paypal_standard.php, let’s define some variables which are useful for module
<?php
// Text
$_['text_title'] = 'PayPal';
$_['text_testmode'] = 'Warning: The payment gateway is in \'Sandbox Mode\'. Your account will not be charged.';
$_['text_total'] = 'Shipping, Handling, Discounts & Taxes';
Now, catalog controller file of Payment extension:
The following code is of front end controller file, go to catalog/controller/extension/payment and create paypal_standard.php and paste following code, here there are two methods index method and callback method.
As our file is paypal_standard.php so Class name is ControllerExtensionPaymentPaypalStandard which extends the Controller base class
class ControllerExtensionPaymentPaypalStandard extends Controller{
Create index method. Index method is called automatically if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4. In payment extension you don’t need to pass any parameter in index() method.
public function index() {
Loads the language file by which the varaibles of language file are accessible in twig files
Now, let’s check the callback() method. Some Instant Update variables set up the Cart Upload to use your callback server. Include the following required variables in the Cart Upload command to have PayPal send Instant Update requests to your callback server. It means the Paypal will call this URL and update the order status in the database of the website.
public function callback() {
PayPal sends back the order id so that we know it it is the right order that we are processing back.
Once the Paypal sends us back data, we need to verify again with the returned data to finalized if the data are not tampered. The image shows the flow:
Once we call the CURL, it returns back the responses whether it is verified or not. Then, we can check and update our order status, for checking the code is like below:
In the switch statement, check Canceled_Reversal case, the code is
case 'Canceled_Reversal':
$order_status_id = $this->config->get('payment_paypal_standard_canceled_reversal_status_id');
break;
It sets the $order_status_id to Canceled Reversal value or as per the setting configuration we do in the Paypal standard extension. Other order statuses are similar except Completed. See the Completed switch case code:
case 'Completed':
$receiver_match = (strtolower($this->request->post['receiver_email']) == strtolower($this->config->get('payment_paypal_standard_email')));
$total_paid_match = ((float) $this->request->post['mc_gross'] == $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false));
if ($receiver_match && $total_paid_match) {
$order_status_id = $this->config->get('payment_paypal_standard_completed_status_id');
}
if (!$receiver_match) {
$this->log->write('paypal_standard :: RECEIVER EMAIL MISMATCH! ' . strtolower($this->request->post['receiver_email']));
}
if (!$total_paid_match) {
$this->log->write('paypal_standard :: TOTAL PAID MISMATCH! ' . $this->request->post['mc_gross']);
}
break;
For the completed status, we check whether the received amount and paid amount are matched or not. If it matched then only order status is set to completed. If the amount is not matched then a log is written on the log file.
Finally the order status is added on the history with the following lines of code:
In this way, we write the code at the catalog controller of Paypal Standard, similarly way we can write for other payment extensions.
Now, catalog model file of Payment extension
We need to create the model file, although we don’t call in the controller file. It is automatically called for payment methods. For that go to catalog/model/extension/payment and create paypal_standard.php and paste following code.
The payment class is created and we need the getMethod() method whose parameters are address and total. In getMethod() method we return the value when the currencies is supported, when geo zones are supported.
No header, no footer, no left or right column are needed on the template, with this, only the submit button is shown. Check the following code, this is to show the text saying it is only for test.
In this way, we write the code at the catalog template of PayPal Standard, similarly way we can write for other payment extensions. Please let us know in the comment if we need to define any of the code above.
Now once the Paypal Standard is activated then it will show like below:
In this way, you can create the form in the admin section, validate the form data, validate the permission, and save the data to the database in the setting database table for the Payment extension and show it in the front. Hope you liked this article, please subscribe to our YouTube Channel for Opencart video tutorials. You can also find us on Twitter and Facebook.
In this Opencart tutorial developer guide, we are showing how to create a custom payment module or extension in the Opencart version 3. Opencart by default supports more than 45 payment modules. Log in into admin, go to Extensions >> Extensions >> Choose the extension type “Payments”, you can see the lists of payments module in Opencart.
Here is the flow of the most eCommerce website.
Today we are showing you postmortem the payment gateway section.
Here are some of the normal steps that happen in the payment section:
When the customer is ready to pay for goods or services on your website, they select the payment method on your website.
There are two ways of payment gateway processing:
One is Off-site payment processing In the off-site payment, the website is redirected to the payment service website and payment is made on the payment service website. There will be no place to enter the credit card information or login to payment gateways. The payment gateway provides a Payment form in which we matched similar fields. Data are passed from Form. Need return URL or cancel URL so that when payment is a success it returns to that return URL and if the payment fails then it returns to the cancel URL. Skrill, Paypal Standard, Liqpay, etc. are the default payment modules for Off-site payment processing.
Another is on-site payment processing. In the on-site payment, the payment is made on the same site, the payment processing is done through APIs. The payment gateway provides a JSON request. There will be a form where they can enter the credit card details or bank information etc. Data are passed as JSON format. It will return success or failure messages through API in JSON format. Once you get the success or failure data then further processing can be done in the website server and the message can be shown or redirected to the success page. Authorize.net’s AIM, Paypal Pro, Square, etc. are the default payment modules for on-site payment processing.
When the payment method is Off-side payment processing then data are passed on hidden fields in the form. If we check the documentation of NoChex you can see the form code like below: https://ssl.nochex.com/downloads/Payment%20Guides/payment_page_integration_guide.pdf page no. 5
Mostly the payment gateway provides us with the form method type, action URL, and fields that we can pass to them for processing. Once you click the “Confirm Order” button, these hidden fields data are passed to the payment gateway and processing happens in their website.
When a payment gateway process the payment and is successful then the customer is directed to the success URL.
When the payment method is On-side payment processing then data are passed from website Server to payment gateway through API, as we are using Opencart which is builtin PHP so we use CURL to call the API.
The website server passes the data to the payment gateway through API, mostly CURL is used to communicate with the APIs, we pass JSON-formatted HTTP requests to the API endpoint in either the sandbox or production environment of the payment gateway.
Payment gateway requests authorization for the payment from the customer’s bank, third party provider, or card issuer.
The bank/provider/card issuer approves or rejects the transaction.
Payment gateway sends the success or failure response, containing the transaction result, and calls the Callback where the website server can process the data.
The website server processes data returned by the payment gateway and it redirects to the success page.
These are the steps that happen on Opencart for payments. So we need to take each step into consideration while developing the payment extensions.
Checklist for Developers while integrating the payment extension
Here is the checklist for the developer while integrating the payment extension on the Opencart or custom platform
Always make a google search if the Opencart payment extension is available, sometimes it is available for free.
If free is not available then start by creating/asking an account and visiting the documentation.
Mostly each payment gateway has a test environment so get test credentials. Create a playground account to get test credentials and get familiar with the test environment.
Follow the integration guide. Each of the product documentation provides an integration guide. Follow the instructions to make sure your payment process works as needed.
Be sure to check if what ISO country codes (3‐digit or 4-digit), what language support, and what currencies support are available for that payment gateway.
Check all your APIs in Postman to confirm everything, before development
Test the system. Make sure everything works. Remember you can place a test order using test credentials on Postman.
Be sure to read how error handling is done, how many rate limits, if any domains & IP address restrictions, policies, and compliance
After reading the documentation, now you can decide whether you need to make the Off-site payment extension or on-site payment extension.
How to use Opencart code snippets VSCode extensions?
Find “Opencart code snippets” extensions to install using the Extensions View.
Install an extension.
Once you installed the “Opencart Code snippets”, open ***.php or ***.twig or ***.xml
Then start typing oc… then you will see a list of Opencart related code snippets available.
For example, create a file called install.xml, then start typing oc, it will show ocmod and ocmodf, these are the Opencart code snippets available in the VScode extensions that you installed.
Once you finished the word like ocmod then it creates the codes automatically.
It highlights the word to be changed, enter the word that you need and click tab, then it will highlights the another words to be change
In this way, you can use the OpenCart Code snippets for rapid development.
Creating and publishing Visual Studio code extensions
This VSCode extension is for OpenCart developer which has a collection of OpenCart snippets. This is just starting, Please let us know if need to add more Contact Us
Documentation
All snippets start with oc. Some of the snippets are:
PHP page supported snippets:
occ: It creates a new Controller class
ocm: It creates a new Method or function
occm: It creates new starter Model class
ocl: It creates new variables for language files
ocprf: It creates print_r with pre
Twig page supported snippets:
oct: It creates starting template layouts in twig files
octfor: It creates for loop in twig files
octif: It creates if statement in twig files
ocbtn: It creates button markup
ocimg: It creates image markup
ocbc: It creates breadcrumbs loop in twig files
OCMOD XML page supported snippets:
ocmod: It creates OCMOD XML code boilerplate
ocmodf: It creates OCMOD XML code boilerplate for files only
Release Notes
Users appreciate release notes as you update your extension.
1.2.0 – OCMOD support added. – ocmod- for install.xml boilerplate creation – ocmodf- OCMOD XML file boilerplate – ocprf- print_r with pre
1.0.0
The initial release of Opencart Snippets for vscode
Please install the extension, try it out and share it with other Opencart developers which may help the development speed. It is free and open-source. Any suggestions, feedback, and other code snippets of Opencart are appreciated.
In this opencart tutorial, we are showing you, how to create an additional custom page in my OpenCart 3 website by coding. We are showing you by creating the categories listing custom page in Opencart 3.0.3.1.
“OpenCart theme and Module development” book says “OpenCart is an e-commerce shopping cart application built with its own in-house framework which uses MVCL (Model, view, controller, and language) pattern. Thus, each module in OpenCart also follows the MVCL pattern. The controller creates logic and gathers data from the model and it passes data to display in the view.” So to create a custom page, we will need a few files for it to work as a page.
Required files:
A controller file
A template file
Optional files:
Model file
Language file
Before you start reading below first, understand about the request and response in OpenCart, just understand the image and watch the following video which will clarify MVCL flow of Opencart.:
After watching the above video, you know about MVCL so it will be easy to understand below.
Controller File
Let’s start by creating a controller file in the controller folder. For this tutorial, we create a file named ‘categorieslist.php’ in the /catalog/controller/catalog/ folder. Since we named the file categorieslist.php and put it at the catalog/ folder, the controller class name will be ControllerCatalogCategorieslist which inherits the Controller like below, if you are thinking of any other custom pages then you also need to do same.
<?php
class ControllerProductCategorieslist extends Controller
{
public function index()
{
echo "This is category listing page";
}
}
The user requests to the controller through URL, so the URL here become YOURSITE.com/index.php?route=product/categorieslist. I was working in my localhost with “opencart.loc” domain so it shows like below:
If you get an error like below don’t panic just got to Admin >> Extensions >> Modifications and click the Refresh button.
Fatal error: Uncaught Error: Class ‘Controllerproductcategorieslist’ not found in …/modification/system/engine/action.php:71 Stack trace: #0 ../catalog/controller/startup/router.php(25): Action->execute(Object(Registry)) #1 …/modification/system/engine/action.php(79): ControllerStartupRouter->index() #2 /system/engine/router.php(67): Action->execute(Object(Registry)) #3 /system/engine/router.php(56): Router->execute(Object(Action)) #4 /system/framework.php(165): Router->dispatch(Object(Action), Object(Action)) #5 system/startup.php(104): require_once(‘/Applications/X…’) #6 /index.php(19): start(‘catalog’) #7 {main} thrown in modification/system/engine/action.php on line 71
These will help on easy debugging and no need to keep on clearing the cache again and again.
Now let’s add header, footer, column left, column right, content top and content-bottom like below and render the response output to categories list template.
As we write in our code $this->response->setOutput($this->load->view(‘product/categorieslist’, $data));, it means we are outputting code in categorieslist.twig file at catalog/theme/view/THEMENAME/template/product/categorieslist.twig. Let create the categorieslist.twig in that folder and put the following code:
{{ header }}
{{ column_left }}
{{ column_right }}
<div class="container">
<div class="col-sm-12">
This is categories list page
</div>
</div>
{{ content_top}}
{{ content_bottom }}
{{ footer }}
Then go to the URL YOURSITE.com/index.php?route=product/categorieslist and you will see like below with header and footer as we have not added any modules for this pages so there will be no module in this page for now:
If you don’t see the page, it means you have not cleared the theme cache and SCSS cache, which you can do from the admin dashboard:
Template File
Nothing fancy here, but whatever data you passed from the controller in $data[‘YOURVARIABLE’], you have access to the YOURVARIABLE in template twig file and just output as {{ YOURVARIABLE }}. Like this way you build logic in the controller, get the desired results and assign it in $data array and send it to the template.
Language File
OpenCart supports multi-language. So let’s create a language file and transfer data from language file to template twig file. For that let’s create a file named categorieslist.php in catalog/language/en-gb/product/categorieslist.php and paste the code below:
<?php
// Text
$_['meta_title'] = 'All Categories';
$_['meta_description'] = 'All Categories';
$_['meta_keyword'] = 'All Categories';
$_['categories_text'] = 'This is categories list page';
Whatever you define here, it will be access to template twig file when you load in a file in the controller. Now let’s change the /catalog/controller/catalog/categorieslist.php like below:
This is how we load the language files in the controller:
$this->load->language('product/categorieslist');
Then we can use the language file variable in controller and language file. In the controller, we use the language variable like:
$this->language->get('meta_title')
In the template twig file that is rendered by the controller, we can use directly with {{LANGUAGEVARIABLE}}, so our catalog/theme/view/THEMENAME/template/product/categorieslist.twig can directly access to categories_text variable of the language file.
Please be careful you can directly access to language variable into the twig file in Opencart 3, in OpenCart you cannot directly access without assigning to $data variable in the controller.
You can download all files from this tutorial in the file below:
We have successfully made our custom page. W can now access the page we created from YOURSITE.com/index.php?route=product/categorieslist .
In our next post, we will show all logics implemented to pull the categories from the database and work with the model class, databases, whole twig files by which we will make a whole module to show categories on a page.
Another free Opencart module for this Christmas and Happy New Year, we are providing Opencart module when activated we can add hovering image and in the frontend when we hover over to the image in products of category page it will swap with the hovering image.
How to install the swapping image Opencart module?
First, download the module by clicking the download button above and you will get hoveroverimage.ocmod.zip file. Then go to admin >> Extensions >> Installer >> then upload the hoveroverimage.ocmod.zip file.
Second go to admin >> Extensions >> Modifications >> then click the refresh button
Third, go to admin >> Extensions >> Extensions >> Choose module in extension type >> then find the “Hover Over Image” and click the install button for the Hover Over Image module. Once you install click edit and then choose enabled and click save.
Fourth, go to admin >> Catalog >> Products >> add or edit the product >> then enter the details of the product and click the Image tab, where you will see the “Upload Hover over Image” field, upload the image to show when it hovers over.
Finally, go to the frontend and visit the category where the product is assigned and then hover over the product image and see the swap of the image.
You installed the module, configured it and see the result like above. Let us know if you see any issues or want any improvement.
Once you upload the module then install the module, then it will create the oc_product_to_image_back database table. We need to create a new table because Opencart 3 doesn’t allow us to alter the core database tables.
public function installTableBackImage()
{
$this->db->query("CREATE TABLE `" . DB_PREFIX ."product_to_image_back` ( `id` INT NOT NULL AUTO_INCREMENT , `image_back` VARCHAR(255) NOT NULL , `product_id` INT NOT NULL , PRIMARY KEY (`id`))");
}
public function dropTableBackImage()
{
$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "product_to_image_back`");
}
When you upload the image in “Upload Hover over Image” field at product section then all data are stored in the DB_PREFIX.product_to_image_back database table.
The Ocmod install.xml contains the following code:
In this way, you can set up the swapping the image when hovering over in products on the category page. Let us know if need any support. Please subscribe to our YouTube Channel for Opencart video tutorials and get lots to other Opencart free modules. You can also find us on Twitter and Facebook. Merry Christmas and Happy New Year 2020.
We activate the free checkout payment module in Opencart 3.0.2.0, then we start ordering but all orders go to the Missing Orders in Sales, so debugging we found out that somehow the free checkout files were not updated properly in the Opencart version 3.0.2.0. Here are the changes that we did to make it work:
Open the file admin/controller/extension/payment/free_checkout.php and find the following lines of code:
See the “payment_”, as we mentioned in Single instance Opencart module development tutorial all single instance payment module fields should start with “payment_”, it was missing in the above code that is why it was not working.
Similarly, open admin/view/template/extension/payment/free_checkout.twig and find the following lines of code:
Download and upload the files to the respective folder which will override the files and you are good to go. With these changes, our orders are showing in Sales.
In this way, you can solve the issues of free checkout sales going to the missing order’s sales. Please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our twitter account @rupaknpl. Subscribe to our YouTube channel for Opencart tutorials, and click to see all Opencart free module.
In this post, we will show only admin code, in the next post we will show you the catalog or frontend code.
The code in admin/controller/extension/module/testimonial.php describes the controller code of the multi-instance opencart module. We describe the code in the comment:
<?php
/*** As our file is testimonial.php so Class name is ControllerExtensionModuleTestimonial which extends the Controller base class ***/
class ControllerExtensionModuleTestimonial extends Controller
{
/*** Declaration of the private property 'error' so that we can get check if any error occurs in the whole class**/
private $error = array();
/*** Index method is called automatically or by default, if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4 . ***/
public function index()
{
/*** Loads the language file admin/language/en-gb/extension/module/testimonial.php by which the varaibles of the language file are accessible in twig file. ***/
$this->load->language('extension/module/testimonial');
/*** Set the Document title ***/
$this->document->setTitle($this->language->get('heading_title'));
/*** Loads the model admin/model/setting/module.php so that we can use the methods defined there. The difference in single instance and multi-instance is here, in single instance we used to load $this->load->model('setting/setting'); but here we load setting/module ***/
$this->load->model('setting/module');
/*** This is how we check if it is form submitted or not. When we submit the form then this block of code also run. Then it also validate the modify permission and other validation. ***/
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
/*** Look at these lines of code, this code section which distinguishes from Single Instance to Multi-instance. If it is single instance then it will be like $this->model_setting_setting->editSetting('***', $this->request->post); This editSetting save the data to oc_setting database table. But in multi-instance the code is like below it checks if the module_id is set if it is set then it get edit module data by editModule method, but if someone click Add button then no module_id is set and it adds new module data to the module database table. ***/
if (!isset($this->request->get['module_id'])) {
$this->model_setting_module->addModule('testimonial', $this->request->post);
} else {
$this->model_setting_module->editModule($this->request->get['module_id'], $this->request->post);
}
/*** This is to delete the cache of the testimonial. ***/
$this->cache->delete('testimonial');
/*** This set the success message in the session. ***/
$this->session->data['success'] = $this->language->get('text_success');
/*** This is to redirect to the extensions page. ***/
$this->response->redirect($this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true));
}
/*** This is to check if there are any warnings ***/
if (isset($this->error['warning'])) {
$data['error_warning'] = $this->error['warning'];
} else {
$data['error_warning'] = '';
}
/*** As we are validating 'Module Name' in the validate method so if validate method returns name error then it is assigned here and the error is shown in the form field. ***/
if (isset($this->error['name'])) {
$data['error_name'] = $this->error['name'];
} else {
$data['error_name'] = '';
}
/*** This is also to set the error for the form field width ***/
if (isset($this->error['width'])) {
$data['error_width'] = $this->error['width'];
} else {
$data['error_width'] = '';
}
/*** This is also to set the error for the form field height ***/
if (isset($this->error['height'])) {
$data['error_height'] = $this->error['height'];
} else {
$data['error_height'] = '';
}
/*** Following are for breadcrumbs ***/
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'], true)
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_extension'),
'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true)
);
/*** Check this section of if else statement, we see the difference in single instance and multi-instance. Here it is checking if module_id is set then it has different href URl and if not set different URL. ***/
if (!isset($this->request->get['module_id'])) {
$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('extension/module/testimonial', 'user_token=' . $this->session->data['user_token'], true)
);
} else {
$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('extension/module/testimonial', 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $this->request->get['module_id'], true)
);
}
/*** Form action URL as per the module edited or for new module ***/
if (!isset($this->request->get['module_id'])) {
$data['action'] = $this->url->link('extension/module/testimonial', 'user_token=' . $this->session->data['user_token'], true);
} else {
$data['action'] = $this->url->link('extension/module/testimonial', 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $this->request->get['module_id'], true);
}
/*** Form cancel URL ***/
$data['cancel'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true);
/*** This is to get the module data, if module_id is set then it gets module data from database and set it to $module_info variable. ***/
if (isset($this->request->get['module_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
$module_info = $this->model_setting_module->getModule($this->request->get['module_id']);
}
/*** This will check if it form filled and clicked save button and occurs some errors then it will set the name with POST name value. If it is edit then it will set the name value with the module detail. If it is add then empty is set. ***/
if (isset($this->request->post['name'])) {
$data['name'] = $this->request->post['name'];
} elseif (!empty($module_info)) {
$data['name'] = $module_info['name'];
} else {
$data['name'] = '';
}
/*** Same as above this will check if it form filled and clicked save button and occurs some errors then it will set the limit with POST limit value. If it is edit then it will set the limit value with the module detail. If it is add then empty is set. ***/
if (isset($this->request->post['limit'])) {
$data['limit'] = $this->request->post['limit'];
} elseif (!empty($module_info)) {
$data['limit'] = $module_info['limit'];
} else {
$data['limit'] = 5;
}
/*** Same as above this will check if it form filled and clicked save button and occurs some errors then it will set the width with POST width value. If it is edit then it will set the width value with the module detail. If it is add then default value is set to 200. ***/
if (isset($this->request->post['width'])) {
$data['width'] = $this->request->post['width'];
} elseif (!empty($module_info)) {
$data['width'] = $module_info['width'];
} else {
$data['width'] = 200;
}
/*** Same as above this will check if it form filled and clicked save button and occurs some errors then it will set the height with POST height value. If it is edit then it will set the height value with the module detail. If it is add then default value is set to 200. ***/
if (isset($this->request->post['height'])) {
$data['height'] = $this->request->post['height'];
} elseif (!empty($module_info)) {
$data['height'] = $module_info['height'];
} else {
$data['height'] = 200;
}
/*** Same as above this will check if it form filled and clicked save button and occurs some errors then it will set the status with POST status value. If it is edit then it will set the status value with the module detail. If it is add then default value is set to empty. ***/
if (isset($this->request->post['status'])) {
$data['status'] = $this->request->post['status'];
} elseif (!empty($module_info)) {
$data['status'] = $module_info['status'];
} else {
$data['status'] = '';
}
/*** This is how we load the header, column left and footer ***/
$data['header'] = $this->load->controller('common/header');
$data['column_left'] = $this->load->controller('common/column_left');
$data['footer'] = $this->load->controller('common/footer');
/*** This is to set output data variables to the view or twig files and twig file is loaded and html rendering is done with it. ***/
$this->response->setOutput($this->load->view('extension/module/testimonial', $data));
}
/*** This is how validation is done, we check whether the user has permission to modify or not.***/
/*** Here we validate name, width and height ***/
/*** If there is error then $this->error['warning'] is set and warning are shown.***/
protected function validate()
{
if (!$this->user->hasPermission('modify', 'extension/module/testimonial')) {
$this->error['warning'] = $this->language->get('error_permission');
}
if ((utf8_strlen($this->request->post['name']) < 3) || (utf8_strlen($this->request->post['name']) > 64)) {
$this->error['name'] = $this->language->get('error_name');
}
if (!$this->request->post['width']) {
$this->error['width'] = $this->language->get('error_width');
}
if (!$this->request->post['height']) {
$this->error['height'] = $this->language->get('error_height');
}
return !$this->error;
}
}
For language we create testimonail.php file at admin/language/en-gb/extension/module/ and paste the following code. We defined required language variables and assign them the text of that language.
<?php
// Heading
$_['heading_title'] = 'Testimonial';
// Text
$_['text_extension'] = 'Extensions';
$_['text_success'] = 'Success: You have modified Testimonial module!';
$_['text_edit'] = 'Edit Testimonial Module';
// Entry
$_['entry_name'] = 'Module Name';
$_['entry_limit'] = 'Limit';
$_['entry_width'] = 'Width';
$_['entry_height'] = 'Height';
$_['entry_status'] = 'Status';
// Error
$_['error_permission'] = 'Warning: You do not have permission to modify Testimonial module!';
$_['error_name'] = 'Module Name must be between 3 and 64 characters!';
$_['error_width'] = 'Width required!';
$_['error_height'] = 'Height required!';
For the form page, we create testimonial.twig at admin/view/template/extension/module/ and add the following lines of code, they are self-explanatory, let us know in the comment is you didn’t understand anything.
In our next post, we will create the frontend section of the multi-instance testimonial module and show it in different layouts.
Like this way we create a testimonial module setting form in Opencart admin, validate the form, submit the form data to the database, list out the multiple instances of the module in the module listing page, edit each module and update it, and we can perform the delete from the module listing page, like this we create admin section of the multi-instance module in Opencart.
Upload the zip file from extension installer, refresh in modification and install it
Go to Admin >> Extensions >> Installer and upload the login-module.ocmod.zip. Then go to Admin >> Extensions >> Modifications and click Refresh button. Then go to Admin >> Extensions >> Extensions >> Choose Module >> find Login module then click the install blue button. Then click the edit button and select status to Enabled and click Save button.
Add to the layout to show in the frontend
Go to Admin >> Design >> Layouts >> edit one of the layouts, in our case let’s edit the Contact layout. Then add the login module in the left column. Then go to the contact us page and you can see like below:
Following are the frontend files for the login module:
<?php As our file is login.php so Class name is ControllerExtensionModuleLogin which extends the Controller base class class ControllerExtensionModuleLogin extends Controller {
Create the index method. The Index method is called automatically if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4. The difference between the single instance and multi-instance module is in the index method, multi-instance module’s index method is like “public function index($setting) {“ public function index() {
Loads the language file by which the variables of language file are accessible in twig files $this->load->language('extension/module/login');
This is to set the value if the customer is logged in or not if the customer is logged in then the value is 1 $data['logged'] = $this->customer->isLogged();
This is to set the form action URL, register link, and forgotten password URL $data['action'] = $this->url->link('account/login', '', true); $data['register'] = $this->url->link('account/register', '', true); $data['forgotten'] = $this->url->link('account/forgotten', '', true);
This is to set redirect so that when someone is logged in then they will get redirected to that page. if (isset($this->request->post['redirect']) && (strpos($this->request->post['redirect'], $this->config->get('config_url')) !== false || strpos($this->request->post['redirect'], $this->config->get('config_ssl')) !== false)) { $data['redirect'] = $this->request->post['redirect'];} elseif (isset($this->session->data['redirect'])) { $data['redirect'] = $this->session->data['redirect']; unset($this->session->data['redirect']);} else { $data['redirect'] = '';}
This is to set the success message if (isset($this->session->data['success'])) { $data['success'] = $this->session->data['success']; unset($this->session->data['success']);} else { $data['success'] = '';}
To check is there is post value of an email is set, if not then it is empty if (isset($this->request->post['email'])) { $data['email'] = $this->request->post['email'];} else { $data['email'] = '';}
To check is there is post value of an email is set, if not then it is empty if (isset($this->request->post['password'])) { $data['password'] = $this->request->post['password'];} else { $data['password'] = '';}
To load the login view return $this->load->view('extension/module/login', $data);} }
In our next post, we will start to create the admin section of the multi-instance module.
In this way, you can create a module in the frontend. Let us know if need any support. Hope you liked this post, please subscribe to our YouTube Channel for Opencart video tutorials. You can also find us on Twitter and Facebook.
This Opencart tutorial is to learn about the single instance and multi-instance module and create admin section for single instance by creating the form in the admin, validate the form data and submit, edit or add data to the database. In our last two posts, we show the hello world module workflow and the basic hello world module in OpenCart, now we are showing how to create the form, validate it and submit it to the database.
We show you the way to show the simple text in our previous hello world module in Opencart. Now, let’s start with the normal flow that happens from frontend to backend:
User logged into the Admin section
They go to Admin >> Extensions >> Extensions >> Choose Modules >> Then edit the module
After clicking the edit they will see a form
They enter the data and click save or cancel button.
If clicked cancel button then returns to the module listing page
If clicked save button then first it will validate the permission of the user if they can have modified permission
Then we check the data if it is POST or not and if it is POST then we save into database.
While saving the module data in the database, there are two ways as Opencart support two modules way:
One way is a single instance
Another way is multi-instance
Single instance module means it has one module only, install, edit and save the same module and use the same module in different layouts. It will not create another instance of modules. Example of core available only one instance Opencart module are: Account module, Category module, Information module, etc
Multi-instance module created multiple instances. Each is taken as a different module instance and can be used different in layouts. Example of core available multi-instance Opencart modules is: Banner module, Bestsellers module, Carousel module, Featured module, latest module, a slideshow module, special module, etc.
Once we save the data to the database and then add them to the layout and they are ready to show in the frontend.
In this blog post, we show you how to create a single instance Opencart module admin section and in the upcoming post, we will show you the frontend or catalog code of login module. Let’s create a module that shows the login form in the layout of the frontend.
<?php //As our file is login.php so Class name is ControllerExtensionModuleLogin which extends the Controller base class class ControllerExtensionModuleLogin extends Controller {
//Declaration of the private property ‘error’ so that we can get check if any error occurs in the whole class. private $error = array();
//Create an index method. The index method is called automatically if no parameters are passed, check this video tutorial for details https://www.youtube.com/watch?v=X6bsMmReT-4 public function index() {
//Loads the language file by which the variables of language file are accessible in twig files $this->load->language('extension/module/login');
//Set the Document title $this->document->setTitle($this->language->get('heading_title'));
//Loads the model admin/model/setting/setting.php so that we can use the methods defined there. $this->load->model('setting/setting');
//This is how we check if it is form submit. When we submit the form then this block of code also runs. Then it also validates the modify permission and other validation. if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
//Look at this line of code, this is the code section which distinguish from Single Instance to Multi Instance. If it is multi instance then it will look like below instead of editSetting it will be addModule and editModule and setting module model is called above. // if (!isset($this->request->get[‘module_id’])) { // $this->model_setting_module->addModule(‘bestseller’, $this->request->post); // } else { // $this->model_setting_module->editModule($this->request->get[‘module_id’], $this->request->post); // } //This editSetting save the data to oc_setting database table, see module_ is important else it will not be saved. If you are //creating shipping extension then it should be shipping_, for payment extension it should be payment_ $this->model_setting_setting->editSetting('module_login', $this->request->post); //This set the success message in the session. $this->session->data['success'] = $this->language->get('text_success'); //This is to redirect to the extensions page. $this->response->redirect($this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=module', true)); }
//This is to check if there are any warnings if (isset($this->error['warning'])) { $data['error_warning'] = $this->error['warning']; } else { $data['error_warning'] = ''; }
//This is to check what we fill out in the form, whether the status is Enabled or Disabled. If it is the loading time then it gets the //config value which we store in the oc_setting database table. if (isset($this->request->post['module_login_status'])) { $data['module_login_status'] = $this->request->post['module_login_status']; } else { $data['module_login_status'] = $this->config->get('module_login_status'); }
//This is how we load the header, column left and footer $data['header'] = $this->load->controller('common/header'); $data['column_left'] = $this->load->controller('common/column_left'); $data['footer'] = $this->load->controller('common/footer');
//This is to set output data variables to the view or twig files and twig file is loaded and HTML rendering is done with it. $this->response->setOutput($this->load->view('extension/module/login', $data)); }
//This is how validation is done, we check whether the user has permission to modify or not. //If you want to validate the form data then you can check it here as well. //If there is error then $this->error[‘warning’] is set and warning are shown. protected function validate() { if (!$this->user->hasPermission('modify', 'extension/module/login')) { $this->error['warning'] = $this->language->get('error_permission'); } return !$this->error; }
//Closing of the Class }
Like this way we write the code in the controller, so distinguishing difference for single instance and multi-instance is how it saves data in the database, for single instance it uses model setting setting and editSetting method and save data at oc_setting database table.
All others are similar, check <select name="module_login_status" the name you are using for the field should start with module_ for the single instance module.
Like this way, you can create the form in the admin section, validate the form data, validate the permission, and save the data to the database in the setting database table. Hope you liked this article, please subscribe to our YouTube Channel for Opencart video tutorials. You can also find us on Twitter and Facebook.
We are seeing issues in the Chrome browser for Opencart that it is adding duplicate products while adding the products, it looks like it is submitting the same form twice. We just commented on the form submission for the IE browser and it is not submitting duplicate products.
Go to admin/view/javascript/common.js and find the following lines of code:
After commenting on those lines of code it is not submitting the product twice, so there are no duplicate products inserted. We tested with test 3 products as in the above image.
Please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our twitter account @rupaknpl and subscribe to our YouTube channel for opencart tutorials.
In this tutorial, we set up Cloudflare CDN for eCommerce websites like Opencart, three steps are: first create a Cloudflare account, add a website domain in the Cloudflare dashboard, and change the DNS records of your domain. We show you how to fix the SSL issues that we face in Cloudflare, how to connect FTP after Cloudflare is set up, and finally how to log the real visitors’ IP than the Cloudflare IP.
Let’s take an example of https://dpsignadvertising.com where we install Opencart, register this domain at onlydomains.com, and delegate to name servers:
It is similar in your DNS settings also, mostly we point to servers ns1 and ns2.
If you were following the steps while registering an account then it will directly take you to add the site.
Log in to your Cloudflare account.
Click on Add Site from the top navigation bar.
Enter your website URL and then click “Add Site”.
Then you need to select the plan as per your need, we are using a free plan, select the free plan and click “Confirm plan”
Now Cloudflare attempts to automatically identify your DNS records and shows lists of DNS results, for dpsignadvertising.com it is showing as in the image: Be careful and check for missing DNS records, mostly MX records if you have setup. Then, click Continue.
Now you will see like NS records of Cloudflare:
Now login to the domain registrar, in our case is onlydomains.com and we change the NS1 and NS2, now it looks like in the image below:
Once you click “Delegate to your Name Servers”, sometimes it takes up to 24hrs to 48hrs, in our case, it was done within 10mins and we receive an email like below:
Once you got an email your Cloudflare is active and you can see the active status in the Cloudflare admin. Similarly, you can see the analytics that it is serving.
How to solve the SSL issue of Cloudflare?
Go to Cloudflare Dashboard >> Click SSL/TLS >> Edge Certificates >> Then toggle to ON for “Always Use HTTPS”
Then the SSL issues are resolved.
Cloudflare FTP issues?
The solution to FTP Cloudflare issues: With Cloudflare set up, you will not be able to connect to your FTP with the domain name so you need to use the IP of your server. You can find the Cloudflare Dashboard >> DNS >> Then find the FTP IP or your website URL IP.
Get the actual visitors’ IP address than the Cloudflare IP address in Opencart
If you are using Google Analytics then you may see the same Cloudflare IP address that the visitor’s IP address as all IPs are proxied by Cloudflare. Sometimes, the Payment gateway may block all the payments as well as it will see the same IP ordering the products which may create suspicious activities, so to fix that you need to add the following code at top of index.php
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
Cloudflare can be used on any website so it does not stick to Opencart, with the above you can enable Cloudflare on any website. It is the same case for the Opencart, we also installed Cloudflare in our webocreation.com blog and see a good improvement in site speed. You can hire us directly or can hire the top 3% of Freelance Cloudflare Experts.
We hope this helps someone to set up Cloudflare properly and easily in Opencart. Please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our Twitter account @rupaknpl and subscribe to our YouTube channel for opencart tutorials.
The easiest and fastest way to take the full webpage screenshot in chrome without the extension and just two commands is below:
Click “Option + Command + J”
Then click “Command + Shift + P”
Type “Capture full-size screenshot” and click it, your full screenshot will be captured and downloaded
Above is the Mac command, in Windows, it is similar just use Ctrl instead of Command and Alt instead of Option.
When you click the “Option + Command + J” it opens developer console:
Then click “Command + Shift + P” to open the input box and start to type full size to run command and you will see like below:
Click it and your fullscreen webpage is captured and downloaded.
We hope this help someone to take the full page screen capture in chrome easily. Please don’t forget to post your questions or comments so that we can add extra topics. You can follow us at our twitter account @rupaknpl and subscribe to our YouTube channel for opencart tutorials.
This WordPress plugin “Category Popular Posts” is to show category wise top popular posts in a widget. The widget has options to add a description, limit the number of posts, an option to show date or not, an option to show the author or not, and an option to show the featured image or not.
Download from the above link and got to WordPress admin >> Plugins >> Add Plugin and upload the downloaded zip file “category-popular-posts.zip“.
Then go to Appearance >> Widgets >> Add the “Category wise Popular posts” widgets to the widgets places like in the sidebar.
Settings:
Enter title, if needed description, number of posts to show here in our example it is 6, choose an option Yes or no to show date, author and featured image, click save and done.
Frontend view:
It displays popular posts of the category in the categories pages, and on the posts page, it displays the popular posts of the active post’s category posts.
CSS change:
You can make the CSS changes for the following CSS classes to match your theme design: