Deals

Thursday, August 27, 2015

Android Cordova 4.0.2 Webview Intercept Requests

Recently I was working on Android cordova app where I was using cordova 4.0.2 version. In this project I have to intercept urls loaded in webview and do some stuff.

In earlier cordova version we can do following.

myWebView.setWebViewClient(new WebViewClient() {
         public boolean shouldOverrideUrlLoading(WebView view, String url)  {
         }
});

But in newer version of cordova this will not work. So what to do? Here is this blog I am going to explain it.

First of all lets get webView


myWebView = (WebView) this.appView.getView();

Then add WebViewClient to webView.

myWebView.setWebViewClient(new SystemWebViewClient((SystemWebViewEngine) this.appView.getEngine()){
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
          }
          public void onPageFinished(WebView view, String url) {
                   super.onPageFinished(view, url);
          }
});

As you can see in cordova newer version they have added new class SystemWebViewClient in cordova lib that we have to use for accessing functions like shouldOverrideUrlLoading and onPageFinished.

Hope this helps you. 

Monday, August 24, 2015

PHP Parse SOAP XML Response

Recently in one of my project we were using SOAP service which was having XML response that we have to parse with PHP. For some reason PHP SOAP client was giving some because it XML response was using name namespaces and that was not parsed correctly with SOAP client. Here in this blog I am going to explain how to call XML web service without using SOAP client and parse response with PHP.

We will use PHP cURL. First lets create XML post data.

$postString = '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                 xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
<GetProducts xmlns="http://ws.sourcingcity.co.uk/">
  <query>pen</query>
  <username>username</username>
  <password>password</password>
  <pageindex>1</pageindex>
  <pagesize>20</pagesize>
</GetProducts>
  </soap:Body>
</soap:Envelope>';

So that's our post data. Now lets create cURL request.

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://ws.sourcingcity.co.uk/ws3dpromo.asmx?op=GetProducts');
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                                            'Content-Type: text/xml; charset=utf-8',
                                            'Connection: Keep-Alive',
                                            'SOAPAction: http://ws.sourcingcity.co.uk/GetProducts'
                                            ));    
$result = curl_exec($ch);
curl_close($ch);

Now you will get XML response in $result which is in string format. We will use SimpleXML class of PHP.

$soap = simplexml_load_string($result);

That will load SimpleXML object. Now we will register namespace.

$soap->registerXPathNamespace('ns1', 'http://ws.sourcingcity.co.uk/');

Now you can use XPATH to go to specific nodes.

$productsResult = $soap->xpath('//ns1:GetProductsResponse/ns1:GetProductsResult')[0]->Products;

for($i=0;$iProduct);$i++){
$product = $productsResult->Product[$i];
echo "Product ".$i;
echo "Name : ".$product->Name;
echo "SCRef : ".$product->SCRef;
echo "Description : ".$product->Description;
echo "PriceRange : ".$product->PriceRange;
echo "ProductType : ".$product->ProductType;
echo "ProductGroups : ".$product->ProductGroups;
echo "Colours : ".$product->Colours;
echo "ThumbImageURL : ".$product->ThumbImageURL;
echo "LargeImageURL : ".$product->LargeImageURL;
}

That's it. In the same way you can parse any other XML response.

Wednesday, July 15, 2015

MAMP - Install MSSQL Extension

Recently in one of my project I was trying to connect to MS SQL server from PHP and it was showing error  "Call to undefined function mssql_connect()". That means you are missing MSSQL extension and you have to install it. In this blog I am going to explain how to do this.

First of all you will need FreeTds. FreeTds is the library for linux and unix to communicate with MS SQL server. You can download latest stable release from this link

ftp://ftp.freetds.org/pub/freetds/stable/freetds-patched.tar.gz

After downloading it, extract it and go to that directory in terminal and run following command.

$ sudo ./configure --prefix=/private/etc/freetds --with-tdsver=8.0 --sysconfdir=/private/etc/freetds/conf
$ sudo make
$ sudo make install

This will install FreeTds on your system. Now we have to compile MSSQL extension for your PHP version. For that first check which PHP version are you using in MAMP. That you can check in Server -> PHP tab


Check your version and download source code of that PHP version.


Extract it and go to this directory in terminal.

Now run following commands in terminal

$ ./configure --with-php-config=/usr/bin/php-config
$ make

Now go to MSSQL extension directory in PHP source code.

$ cd ext/mssql/
$ /usr/bin/phpize
$ ./configure --with-php-config=/usr/bin/php-config --with-mssql=/private/etc/freetds
$ make

Above command will generate MSSQL module so now go to module directory.

$ cd modules/

Now we have to copy this generated module to MAMP's current PHP extension directory. For that open the ini file of your PHP version. In my case I was using PHP 5.5.3 so my ini file was located at.

/Applications/MAMP/bin/php/php5.5.3/conf/php.ini

Open this file and search for "extension_dir" and you will find following line.

extension_dir = "/Applications/MAMP/bin/php/php5.5.3/lib/php/extensions/no-debug-non-zts-20121212/"

so this is your extension directory. We have to copy module here. So now go to terminal and run following command.

$ cp mssql.so /Applications/MAMP/bin/php/php5.5.3/lib/php/extensions/no-debug-non-zts-20121212/

This will copy mssql.so in your extensions directory. Now we have to add this extension in php.ini file.

Now in php.ini file find for the word "; Extensions" below that there are list of extensions. Add following line to the end of the list.

extension=mssql.so

Save the file. Restart your MAMP and run the phpinfo(). You must see following section there.


But wait it won't be there. That means there is something wrong. After wasting almost an hour I figure out that MAMP is actually using different ini file.  So we have to update that. For that go to 

/Applications/

Right click on your MAMP or MAMP Pro icon (if you are using MAMP Pro) and select "Show Package Contents" Now go to Contents/Resources  and open ini file of your PHP version. Now in that file find for the word "; Extensions" below that there are list of extensions. Add following line to the end of the list.

extension=mssql.so

Save the file. Restart your MAMP and run the phpinfo(). You must see following section there.


That's it and now you can connect to MSSQL server with following code.

$con = mssql_connect('MYSQLSERVER', 'username', 'password')
or die('could not connect to server.");

I hope this helps you and saves your time.

Saturday, July 4, 2015

Android ClassNotFound Exception

Today when I was working on my Android project, I ran into strange issue. When I start my app, it crashes with ClassNotFound exception. It was unable to found Main activity class.

I tried so many things like clean - rebuild, removing all the references and add them again, changing target APIs. But it was not working. App never started.

After doing failed attempt for almost half an hour, it came to my attention that src folder in project was a simple folder. There was no package sign on it and when I explore it, all my packages where turned into folders and sub folders and that was the issue. My src folder was not a sources folder and because of that it was unable to found a class.

So to solve this issue.  Right click on src folder Select Java Build Path - > Use as a source folder.

And that's it all the folders and sub folders in the src folder turned into packages and application was working fine. Hope this helps you and save your time.

Saturday, June 20, 2015

Magento Get All Products With Special Prices

Hello,

Recently in one of my projects we were working with Magento APIs. Where we have to fetch a list of all products with special prices to display hot deals on site. There are no APIs for this in Magento so I decided to write custom logic for that.

Here is how you can fetch it.

First get product collections.

$productCollection = Mage::getModel('catalog/product')->getCollection();
$productCollection->addAttributeToSelect(array(
        'image',
        'name',
        'price',
        'short_description'
 ))
 ->addFieldToFilter('visibility', array(
        Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
        Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
 ));

Then apply filter on product collection to get products with only special prices.

$productCollection->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $todayDate))
                        ->addAttributeToFilter('special_to_date', array('or'=> array(
                        0 => array('date' => true, 'from' => $tomorrowDate),
                        1 => array('is' => new Zend_Db_Expr('null')))
                        ), 'left');

That's it and now it will give you collections of only those products for which there is a special price set.

Now just loop through it and add to array.

$hotDeals = array();
foreach ($productCollection as $product){
        $product = Mage::getModel('catalog/product')->load($product->getId());
$name = $product->getName();
$productPrice = number_format($product->getPrice(), 2, '.', ',');
$specialPrice = number_format($product->getSpecialPrice(), 2, '.', ',');

        $hotDeals[] = array(
"product_id" => $product->getId(),
"product_name" => $name,
"product_image" =>  ($product['image'] == 'no_selection') ? $skinUrl.'frontend/default/default/images/catalog/product/placeholder/thumbnail.jpg' : (string)Mage::helper('catalog/image')->init($product, 'image')->resize(60),
"product_price" => $productPrice,
"special_price" => $specialPrice
);
}

And return it as JSON array.

$resultArray['success'] = true;
$resultArray['hot_deals'] = $hotDeals;

echo json_encode($resultArray);

Hope this helps you.

Friday, June 19, 2015

Magento Load Quote Generated By API on Frontend

Hello,

Recently in one of my project we were using magento to implement checkout process for third party website. Basically we were using Magento APIs to create quote. Now for the paypal payment we were redirecting users to magento url and start checkout process by redirecting them to paypal and on successful payment redirect back to magento site, place and order and redirect them back to their site. Now the problem is when we redirect user to magento site to start checkout process there is no customer or checkout session hence checkout can not be started as shopping cart was empty. In this blog I am going to explain how to load quote generated by API on frontend and start checkout process.

First of all let me explain why we have to this changes. Magento has its own session management on front end. It will not load cart of there is no checkout session found on front end. So we have to store everything in frontend session so magento can remember it.

First of all you have to pass three params when user is redirecting to magento site. Following are three params required.

customer_id
quote_id
store_id

As on front end we have to set specific store and create customer session with customer_id and load shopping cart. I was using following URL for redirection.

http://yourmagento/paypal/express/start/button/1/?customer_id=1&store_id=3&quote_id=146

As you can see above we are directly starting checkout process and redirecting user to paypal. But before that we have to set store and generate customer session and load quote. So lets go step by step. First of all open following file.


app/code/core/Mage/Core/Controller/Varien/Front.php

and find following function.

/**
     * Init Front Controller
     *
     * @return Mage_Core_Controller_Varien_Front
     */
    public function init()
    {
    }

This function is called first for any magento URL request. So here are going to do some initialization steps.

First let's set up the store for which quote id was generated. Add following code to start of init function.

$storeId = '';
//////////////////////////////////////Setting up store id///////////////////////////
if(isset($_REQUEST['store_id'])){
        $storeId = $_REQUEST['store_id'];
    Mage::getSingleton('core/session')->setStoreId($_REQUEST['store_id']); 
}

if( Mage::getSingleton('core/session')->getStoreId()){
$storeId = Mage::getSingleton('core/session')->getStoreId();
}
switch($storeId){
case "1" : Mage::app()->setCurrentStore('store1');break;
case "2" : Mage::app()->setCurrentStore('store2');break;
default: Mage::app()->setCurrentStore('store1');break;
}
//////////////////////////////////////////////////////////////////////////////////////


First we are checking if there is store id in request then first we are storing it to magento core session. Later we are getting it from session and storing respective store. Please note this is required if you have multiple stores, else you can avoid this. In my case there were multiple stores. 

Now next step is to create customer session. Add following code after above code.

////////////////////////////////////////Setting up customer id////////////////////////
if(isset($_REQUEST['customer_id'])){
Mage::getSingleton('core/session')->setCustomerId($_REQUEST['customer_id']); 
}
        
if( Mage::getSingleton('core/session')->getCustomerId()){
Mage::getSingleton('customer/session')->loginById(Mage::getSingleton('core/session')->getCustomerId());
}
//////////////////////////////////////////////////////////////////////////////////////

Now next step is to store quote id in session so it can be used later.

/////////////////////////////////////////Saving Quote Id//////////////////////////////
if(isset($_REQUEST['quote_id'])){
Mage::getSingleton('core/session')->setQuoteId($_REQUEST['quote_id']); 
}
//////////////////////////////////////////////////////////////////////////////////////

Now open following file.

/app/code/core/Mage/Checkout/Model/Session.php

And check following function.

/**
     * Get checkout quote instance by current session
     *
     * @return Mage_Sales_Model_Quote
     */
    public function getQuote()
    {
    }

Add below code to the function after following line.

Mage::dispatchEvent('custom_quote_process', array('checkout_session' => $this));

//////////////////////////////////////////Returning quote stored in session////////////////////////
if(Mage::getSingleton('core/session')->getQuoteId()){
    $this->_quote = Mage::getModel('sales/quote')->setStore(Mage::app()->getStore())->load(Mage::getSingleton('core/session')->getQuoteId());
return $this->_quote;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

That's it and now you can start checkout process with this quote. Hope this helps you. 

Thursday, June 18, 2015

Magento Cart Payment List API, Paypal Not Available

Hello,

Recently we were working on Magento API. Where we were implementing checkout process for a website using Magento platforms. Since we were integrating in third party website which was built on ASP.NET, we were using Magento API. Here we have faced an issue on Select Payment Method step, that Paypal was not coming in list. In this blog I am going to explain how to solve this issue.

Magento API cart_payment.list is the API we were using for this and Paypal was enabled but still were not getting it. The reason was because we were using Paypal Standard Checkout where user is redirected to Paypal website for Payment. Since API is called on backend and there is no UI for that, so there is no point of redirecting to site. Hence this Payment method was ignored in API. Check the following function in app/code/core/Mage/Checkout/Model/Cart/Payment/Api.php file.

/**
     * @param  $method
     * @param  $quote
     * @return bool
     */
    protected function _canUsePaymentMethod($method, $quote)
    {
        if (!($method->isGateway() || $method->canUseInternal())) {
            return false;
        }

        if (!$method->canUseForCountry($quote->getBillingAddress()->getCountry())) {
            return false;
        }

        if (!$method->canUseForCurrency(Mage::app()->getStore($quote->getStoreId())->getBaseCurrencyCode())) {
            return false;
        }

        /**
         * Checking for min/max order total for assigned payment method
         */
        $total = $quote->getBaseGrandTotal();
        $minTotal = $method->getConfigData('min_order_total');
        $maxTotal = $method->getConfigData('max_order_total');

        if ((!empty($minTotal) && ($total < $minTotal)) || (!empty($maxTotal) && ($total > $maxTotal))) {
            return false;
        }

        return true;
    }


Here as you can see It's checking if Payment method is Gateway or can be used internally. Since Paypal standard checkout can not be used in internally as user is redirected to Paypal site. So to solve this issue just comment following code in _canUsePaymentMethod function.

/*if (!($method->isGateway() || $method->canUseInternal())) {
            return false;
}*/

That's it and now cart_payment.list will return you Paypal in list. Please note ideally you have to override this code and should not change in core code.