Change shipping price & handling fee on the fly in Magento

October 10, 2013  |  No Comments  |  by Raj (MagePsycho)  |  Magento

Problem: How do I change shipping prices and handling fees on the fly?

You may want to have different shipping prices for different scenarios. Your scenario could be any of the following:

  1. 1. Different shipping price based on shipping address
  2. 2. Different shipping price based on weight
  3. 3. Different shipping price based on categories
  4. 4. Different shipping price based on no of items
  5. 5. Different shipping price based on your custom module
  6. 6. Different shipping price based on some conditions

There may be many solutions. A flexible solution which works for most cases is to develop a custom module which implements the event called ‘sales_quote_collect_totals_before’

Solution:

Assuming the skeleton module: MagePsycho_Shipmentfilter has already been created.
1. Register the event ‘sales_quote_collect_totals_before’:
Add the following xml code in app/code/local/MagePsycho/Shipmentfilter/etc/config.xml

...
<events>
    <sales_quote_collect_totals_before>
        <observers>
            <your_module>
                <type>singleton</type>
                <class>shipmentfilter/observer</class>
                <method>salesQuoteCollectTotalsBefore</method>
            </your_module>
        </observers>
    </sales_quote_collect_totals_before>
</events>
...

2. Implement the observer model:
Create the observer file: app/code/local/MagePsycho/Shipmentfilter/Model/Observer.php and add the following code:

class MagePsycho_Shipmentfilter_Model_Observer
{
    public function salesQuoteCollectTotalsBefore(Varien_Event_Observer $observer)
    {
        /** @var Mage_Sales_Model_Quote $quote */
        $quote = $observer->getQuote();
        $someConditions = true; //this can be any condition based on your requirements
        $newHandlingFee = 15;
        $store    = Mage::app()->getStore($quote->getStoreId());
        $carriers = Mage::getStoreConfig('carriers', $store);
        foreach ($carriers as $carrierCode => $carrierConfig) {
            if($carrierCode == 'fedex'){
                if($someConditions){
                    Mage::log('Handling Fee(Before):' . $store->getConfig("carriers/{$carrierCode}/handling_fee"), null, 'shipping-price.log');
                    $store->setConfig("carriers/{$carrierCode}/handling_type", 'F'); #F - Fixed, P - Percentage                  
                    $store->setConfig("carriers/{$carrierCode}/handling_fee", $newHandlingFee);
    
                    ###If you want to set the price instead of handling fee you can simply use as:
                    #$store->setConfig("carriers/{$carrierCode}/price", $newPrice);
    
                    Mage::log('Handling Fee(After):' . $store->getConfig("carriers/{$carrierCode}/handling_fee"), null, 'shipping-price.log');
                }
            }
        }
    }
}

Notes: Here we are adding handling fee of 15 for Fedex shipping carrier on some conditions.
If you want to set a new price instead of a handling fee then you can simply use:

$store->setConfig("carriers/{$carrierCode}/price", $newPrice);

in above code.
Similarly you can add any custom shipping price for any other shipping method.

3. Bingo!

Password protecting your development site using .htaccess / .htpasswd

September 21, 2013  |  1 Comments  |  by Raj (MagePsycho)  |  Apache

You may want to restrict the development site from search engine or from direct access. One of the popular way of doing so is to use Apache2 Basic Authentication.
Here we will be discussing on how to password protect your development site using Apache2 Basic Authentication which makes a use of .htaccess & .htpasswd files.

Steps:

1. Create & upload .htaccess file to the root of your dev site with the following content:

AuthName "Authorisation Required"
AuthUserFile "/path/to/.htpasswd"
AuthType Basic
require valid-user
ErrorDocument 401 "Authorisation Required"

Notes: If .htaccess file already exists then you can add the above code on the top.
Also note that omitting ‘ErrorDocument 401 “Authorisation Required”‘ line can lead to 404 error.
2. Create & upload the .htpasswd file to ‘AuthUserFile’ path with the following content:

foo:$apr1$yB1.9vIT$IVVBmq5vMauwsNR8CZdHQ.

Notes: Where ‘foo’ is the username and ‘$apr1$yB1.9vIT$IVVBmq5vMauwsNR8CZdHQ.’ is the MD5 encrypted password of ‘bar’.
That was just an example, in fact you can use any username/password combination.
In order to create encrypted password you can use some free online tool like:
http://www.htaccesstools.com/htpasswd-generator/

3. Now try to visit the dev site, you will get the screen similar as:

Apache2 Basic Authentication

Apache2 Basic Authentication


And you will only be able to browse the dev site once the correct username/password are entered.

Hope this helps you in password protecting your site.

Sending JSON data to remote server

August 25, 2013  |  1 Comments  |  by Raj (MagePsycho)  |  jQuery, Magento, PHP

JSON: JavaScript Object Notation.
JSON is syntax for storing and exchanging text information. Much like XML.
JSON is smaller than XML, and faster and easier to parse.

You may need to post JSON data to the server for different purposes. If you are wondering about ‘How to send JSON data to remote server?’ then this article is for you. Keep on reading.

In this article, we will share different techniques to send JSON data to the server.
For one of the payment module development in Magento we had to send the encrypted password(using plain password) to the gateway page. And we will use this scenario as an example.

Suppose we have the following data:

<?php
#web service to encrypt the password (which accepts the JSON data and returns the result in JSON format)
$url	= 'http://some-payment-gateway.com/WebService/EncryptPassword';
#password to be encrypted
$plainPass = 'some-plain-password';
$data = array(
	'password' => urlencode($plainPass)
);

1. Using Ajax

var data = <?php echo json_encode($data) ?>;
var url  = '<?php echo $url ?>';
jQuery.ajax({
    type: "POST",
    url: url,
    data: JSON.stringify(data),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data){
		var jsonObj = jQuery.parseJSON(data);
		alert(jsonObj.encPassword);
	},
    failure: function(errorMsg) {
        alert(errorMsg);
    }
});

Note: This approach can’t be used in Payment Module as we have to pass the encrypted password in hidden form fields

2. Using Curl

<?php
$content = json_encode($data);

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER,
		array("Content-type: application/json"));
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $content);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //curl error SSL certificate problem, verify that the CA cert is OK

$result		= curl_exec($curl);
$response	= json_decode($result);
var_dump($response);
curl_close($curl);
?>

3. Using Streams

<?php
$options = array(
	'http' => array(
		'method'  => 'POST',
		'content' => json_encode( $data ),
		'header'=>  "Content-Type: application/json\r\n" .
					"Accept: application/json\r\n"
	  )
);

$context	 = stream_context_create($options);
$result		 = file_get_contents($url, false, $context);
$response	 = json_decode($result);
var_dump($response);

4. Raw HTTP Post

Using Zend Framework’s HTTP client: http://framework.zend.com/manual/en/zend.http.client.advanced.html#zend.http.client.raw_post_data

$json = json_encode($data);
$client = new Zend_Http_Client($url);
$client->setRawData($json, 'application/json')->request('POST');
var_dump($client->request()->getBody());

These were some basic examples. If you have any other idea regarding sending json data to the remote server, please share.

Backup WordPress project files / db using bash script

August 8, 2013  |  2 Comments  |  by Raj (MagePsycho)  |  Linux, Magento

WordPress is undoubtedly the most popular blogging platform on the Internet. And when it comes to the maintenance or regular backups, life is not easier unless you have some backup script which works great via SSH & cron daemons.

Here is the custom backup script used for taking backup of wordpress project files & db:
(If you want backup script for Magento then please go here)

#!/bin/bash
#@author		MagePsycho <magepsycho@gmail.com>
#@website		http://www.magepsycho.com
#@blog			http://www.blog.magepsycho.com
#@version		0.1.0

#/************************ EDIT VARIABLES ************************/
projectName=magepsycho_blog
backupDir=/home/magepsycho/_backups
#/************************ //EDIT VARIABLES **********************/

fileName=$projectName-$(date +"%Y-%m-%d")
host=$(grep DB_HOST "wp-config.php" |cut -d "'" -f 4)
username=$(grep DB_USER "wp-config.php" | cut -d "'" -f 4)
password=$(grep DB_PASSWORD "wp-config.php" | cut -d "'" -f 4)
dbName=$(grep DB_NAME "wp-config.php" |cut -d "'" -f 4)

printf "What kind of backup you would like?\n[ d ] DB backup only\n[ f ] Files backup only\n[ b ] Files backup with DB\n"
read backupType
if [[ $backupType = @(d|b) ]]; then
	echo "----------------------------------------------------"
	echo "Dumping MySQL..."
	mysqldump -h "$host" -u "$username" -p"$password" "$dbName" | gzip > $fileName.sql.gz
	echo "Done!"
fi

if [[ $backupType = @(f|b) ]]; then
	echo "----------------------------------------------------"
	echo "Archiving Files..."
	tar -zcf $fileName.tar.gz * .htaccess
	echo "Done!"
	echo "----------------------------------------------------"
	echo "Cleaning..."
	rm -f $fileName.sql.gz
	echo "Done!"
fi

if [[ $backupType = @(d|f|b) ]]; then
	echo "----------------------------------------------------"
	mkdir -p $backupDir;
	echo "Moving file to backup dir..."
	if [[ $backupType == d ]]; then
		mv $fileName.sql.gz $backupDir
	fi

	if [[ $backupType = @(f|b) ]]; then
		mv $fileName.tar.gz $backupDir
	fi
	echo "Done!"
else
	echo "Invalid selection!"
fi

Or you can download it from here: [WordPress Backup Script]
Notes: If you get the following error:

syntax error in conditional expression: unexpected token `(‘
line 20: syntax error near `@(d’
line 20: `if [[ $backupType = @(d|b) ]]; then’

then this means you are using older version of bash (< 4.0). And you need to patch the script by adding the following line after bash script declaration:

shopt -s extglob

What does this script do?

1. Gives options for backup type which are:
- DB backup only
- Files backup only
- Files backup with DB
2. Dumps the database by taking db info from wp-config.php
3. Makes a copy of project files and compresses it in .tar.gz format.
4. Deletes the dumped SQL file as it's already copied in compressed file.
5. Creates backup dir if not exists
6. Copies the compressed project file to the backup dir.

Besides, you can also setup cron job to run this backup script at regular intervals.

How to run backup script?

1. Edit _wpbackup.sh to configure variables 'projectName' & 'backupDir'
2. Upload the edited _wpbackup.sh to the root of your WordPress installation
3. Run following series of commands in terminal:

cd /path/to/wordpress/root
chmod +x _wpbackup.sh
ex -sc $'%s/\r$//e|x' _wpbackup.sh
sh _wpbackup.sh

4. You will get the compressed backup file at backup dir

Snapshots for different backup types

DB Backup Only

DB Backup Only


File Backup Only

File Backup Only

Files Backup with DB

Files Backup with DB

Thanks for reading & sharing.