Sending JSON data to remote server

August 25, 2013  |  2 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  |  5 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: [code language="bash"]shopt -s extglob[/code]

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.

Backup Magento project files / db using bash script

July 1, 2013  |  8 Comments  |  by Raj (MagePsycho)  |  Linux, Magento

I have googled for the bash script to backup Magento sites/db but none of them worked for me the way I wanted.
So I decided to create a custom bash script which is simple and does the job perfectly.

I have developed the script for my own need. But I thought it would be helpful if shared with you guys as well.
Here goes the overall backup script:

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

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

dbXmlPath="app/etc/local.xml"
{
host="$(echo "cat /config/global/resources/default_setup/connection/host/text()" | xmllint --nocdata --shell $dbXmlPath | sed '1d;$d')"
username="$(echo "cat /config/global/resources/default_setup/connection/username/text()" | xmllint --nocdata --shell $dbXmlPath | sed '1d;$d')"
password="$(echo "cat /config/global/resources/default_setup/connection/password/text()" | xmllint --nocdata --shell $dbXmlPath | sed '1d;$d')"
dbName="$(echo "cat /config/global/resources/default_setup/connection/dbname/text()" | xmllint --nocdata --shell $dbXmlPath | sed '1d;$d')"
}

fileName=$projectName-$(date +"%Y-%m-%d")
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 > $fileName.sql
	echo "Done!"
fi

if [[ $backupType = @(f|b) ]]; then
	echo "----------------------------------------------------"
	echo "Archiving Files..."
	printf "Skip /media folder?\ny: Yes\nn: No\n"
	read skipMedia
	if [ $skipMedia == y ]; then
		tar -zcf $fileName.tar.gz --exclude=var --exclude=includes --exclude=media * .htaccess
	else
		tar -zcf $fileName.tar.gz --exclude=var --exclude=includes * .htaccess
	fi
	echo "Done!"
	echo "----------------------------------------------------"
	echo "Cleaning..."
	rm -f $fileName.sql
	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 $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]
Notes: If you get the following error:

syntax error in conditional expression: unexpected token `(‘
line 24: syntax error near `@(d’
line 24: `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:[code language="bash"] shopt -s extglob [/code]

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 XML configuration.
3. Makes a copy of project files and compresses it in .tar.gz format.
While copying it also gives options whether to exclude media folder or not.
Note that by default ‘var’ & ‘includes’ folder are excluded by the script.
4. Deletes the dumped SQL file as it’s already copied in the 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 _magebackup.sh to configure variables ‘projectName’ & ‘backupDir’
2. Upload the edited _magebackup.sh to the root of your Magento installation
3. Run following series of commands in terminal:

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

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

Snapshots for different backup types

DB backup only


Files backup only


Files backup with DB


Let’s comment if there’s any room for improvement in this script.
Thanks for reading & sharing.

Configuring city as dropdown option in checkout billing & shipping address

June 15, 2013  |  19 Comments  |  by Raj (MagePsycho)  |  Latest, Magento

Introduction

Magento provides country and region* as dropdown option in checkout addresses unlike city which is an input text field. This on one side provides flexibility but on other side increases chances of typo in city names.
If you want your store to have an extra operations like giving free shipping to certain cities, giving COD payment option to certain cities etc., it’s better to configure the input city field as dropdown.
Here we will be discussing on listing United Arab Emirates’ cities as dropdown option.

Steps

Assume MagePsycho_Citydropdown skeleton module has already been created.
1. Adding functions for populating cities.
File: app/code/local/MagePsycho/Citydropdown/Helper/Data.php
Code:

<?php
/**
 * @category   MagePsycho
 * @package    MagePsycho_Citydropdown
 * @author     magepsycho@gmail.com
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
class MagePsycho_Citydropdown_Helper_Data extends Mage_Core_Helper_Abstract
{
	public function getUaeCities()
	{
		$helper = Mage::helper('directory');
		$cities = array(
			$helper->__('Abu Dhabi'),
			$helper->__('Ajman'),
			$helper->__('Al Ain'),
			$helper->__('Dubai'),
			$helper->__('Fujairah'),
			$helper->__('Ras al Khaimah'),
			$helper->__('Sharjah'),
			$helper->__('Umm al Quwain'),
		);
		return $cities;
	}

	public function getUaeCitiesAsDropdown($selectedCity = '')
	{
		$cities = $this->getUaeCities();
		$options = '';
		foreach($cities as $city){
			$isSelected = $selectedCity == $city ? ' selected="selected"' : null;
			$options .= '<option value="' . $city . '"' . $isSelected . '>' . $city . '</option>';
		}
		return $options;
	}
}

Notes: You can also populate the cities in db tables to make it more dynamic. For example, you can create following tables similar to regions:
+ directory_country_city (city_id, country_id, code, default_name)
+ directory_country_city_name (locale, city_id, name)

2. Replacing input text city field to dropdown using javascript
2.1
File: app/design/frontend/[package]/[theme]/template/checkout/onepage/billing.phtml
Code: Add the following code to the last of above template

<script type="text/javascript">
	<?php
	$helper			 = Mage::helper('citydropdown');
	$address		 = Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress();
	$defaultCity	 = $address->getCity();
	$citiesOptions	 = addslashes($helper->getUaeCitiesAsDropdown($defaultCity));
	?>

	var billingCity = '<?php echo $defaultCity ; ?>';
	function billingSwitchCityField(){
		var selectVal = jQuery('#billing\\:country_id option:selected').val();
		if(selectVal == "AE"){
			jQuery("#billing\\:city")
			.replaceWith('<select id="billing:city" name="billing[city]" class="required-entry">' +
				  '<option value=""></option>' +
				  '<?php echo $citiesOptions; ?>' +
				'</select>');
		}else{
			jQuery("#billing\\:city")
			.replaceWith('<input type="text" class=" input-text required-entry absolute-advice " title="City" value="' + billingCity + '" id="billing:city" name="billing[city]" autocomplete="off">');
		}

	}
   jQuery(document).ready(function(){
		billingSwitchCityField();
		jQuery('#billing\\:country_id').change(function() {
			billingSwitchCityField();
		});
   })
</script>

2.2
File: app/design/frontend/[package]/[theme]/template/checkout/onepage/shipping.phtml
Code: Add the following code to the last of above template

<script type="text/javascript">
	<?php
	$helper			 = Mage::helper('citydropdown');
	$address		 = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress();
	$defaultCity	 = $address->getCity();
	$citiesOptions	 = addslashes($helper->getUaeCitiesAsDropdown($defaultCity));
	?>




	var shippingCity = '<?php echo $defaultCity ; ?>';
	function shippingSwitchCityField(){
		var selectVal = jQuery('#shipping\\:country_id option:selected').val();
		if(selectVal == "AE"){
			jQuery("#shipping\\:city")
			.replaceWith('<select id="shipping:city" name="shipping[city]" class="required-entry">' +
				  '<option value=""></option>' +
				  '<?php echo $citiesOptions; ?>' +
				'</select>');
		}else{
			jQuery("#shipping\\:city")
			.replaceWith('<input type="text" class=" input-text required-entry absolute-advice " title="City" value="' + shippingCity + '" id="shipping:city" name="shipping[city]" autocomplete="off">');
		}




	}
   jQuery(document).ready(function(){
		shippingSwitchCityField();
		jQuery('#shipping\\:country_id').change(function() {
			shippingSwitchCityField();
		});
   })
</script>

3. Reload the checkout page, you can see the city options for United Arab Emirates as:

City as dropdown field


In the similar manner you can configure the city options for other countries as well and for other sections like My Account > Address Book etc.

Thanks for reading & sharing.