Tag Archives: web service

CodeIgniter and XMLRPC

What are we going to do?

We’ll mimic what we already achieved in CodeIgniter and NuSOAP post using XMLRPC method.

So, we’ll create two endpoints, one is for getting a CD info (function name : getCdInfo) and the other is for getting all of CDs listed (function name : getCds).

We’ll still implement all of our function inside Welcome controller. The difference is that the registration process is placed inside index() function while the implementation is outside index() function but still within Welcome class.

The Server

Here’s the configuration and registration process inside index() function:

        public function index()
    {
    $this->load->library('xmlrpc');
        $this->load->library('xmlrpcs');
        
        //REGISTRATION AND CONFIGURATION
        $config['functions']['getCdInfo'] = array('function' => 'Welcome.getCdInfo');
        $config['functions']['getCds'] = array('function' => 'Welcome.getCds');
        $config['object'] = $this;

        $this->xmlrpcs->initialize($config);
        $this->xmlrpcs->serve();
    }

Notice how I defined the endpoint name and register it. So, getCdInfo endpoint will be implemented in Welcome controller and getCdInfo function, while getCds endpoint will be implemented in Welcome controller as getCds function.
Now, here’s the implementation:

        //IMPLEMENTATION
    public function getCdInfo($request)
    {
    $this->load->library('xmlrpc');

        $parameters = $request->output_parameters();

        $id = $parameters[0];  // first parameter
        $this->db->where('id', $id);
        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()==1) {
            $ret = $qcd->row_array();
        } else {
            return $this->xmlrpc->send_error_message('404', 'Invalid results');
        }

        $response = array(
            array(
                'titel'  => array($ret['titel'], 'string'),
                'interpret'    => array($ret['interpret'], 'string'),
                'jahr'       => array($ret['jahr'], 'int'),
                'id'     => array($ret['id'], 'int')
            ),
             'struct'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function getCds()
    {
    $this->load->library('xmlrpc');

        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()>0) {
            $ret = array();
            $i = 0;
            foreach ($qcd->result_array() as $row) {
                $ret[$i] = array(array(
                        'titel'  => array($row['titel'], 'string'),
                        'interpret'    => array($row['interpret'], 'string'),
                        'jahr'       => array($row['jahr'], 'int'),
                        'id'     => array($row['id'], 'int')
                ), 'struct');
                $i++;
            }
        } else {
            return $this->xmlrpc->send_error_message('404', 'Empty results');
        }

        $response = array(
                $ret,
                 'array'
        );

        return $this->xmlrpc->send_response($response);
    }

getCdInfo takes one parameter, so, we need to pass $request as getCdInfo function parameter while getCds function doesn’t take any parameter, so we omit it.
Pay attention on getCds function, you’ll learn how I implement an XMLRPC endpoint that return an array of array (a data table).

The Client

Same as CodeIgniter and NuSOAP, for simplicity, we’ll implement the client as part of Welcome controller. Here’s the client code:

        public function testClient()
    {
    $server_url = site_url('welcome');

        $this->load->library('xmlrpc');

        //Call getCdInfo
        $this->xmlrpc->server($server_url, 80);
        $this->xmlrpc->method('getCdInfo');

        $request = array(array(1, 'int'));
        $this->xmlrpc->request($request);

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }

        //Call getCDs
        $this->xmlrpc->method('getCds');

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }
    }

getCdInfo call will output something like this:

array(4) {
  ["titel"]=>
  string(6) "Beauty"
  ["interpret"]=>
  string(16) "Ryuichi Sakamoto"
  ["jahr"]=>
  string(4) "1990"
  ["id"]=>
  string(1) "1"
}

While getCds will return something like this:

array(3) {
  [0]=>
  array(4) {
    ["titel"]=>
    string(6) "Beauty"
    ["interpret"]=>
    string(16) "Ryuichi Sakamoto"
    ["jahr"]=>
    string(4) "1990"
    ["id"]=>
    string(1) "1"
  }
  [1]=>
  array(4) {
    ["titel"]=>
    string(33) "Goodbye Country (Hello Nightclub)"
    ["interpret"]=>
    string(13) "Groove Armada"
    ["jahr"]=>
    string(4) "2001"
    ["id"]=>
    string(1) "4"
  }
  [2]=>
  array(4) {
    ["titel"]=>
    string(4) "Glee"
    ["interpret"]=>
    string(13) "Bran Van 3000"
    ["jahr"]=>
    string(4) "1997"
    ["id"]=>
    string(1) "5"
  }
}

As you can see, the output of XMLRPC method is the same as NuSOAP method. No fixing needed!
Here’s the complete source code of our controller:

defined('BASEPATH') or exit('No direct script access allowed');

class Welcome extends CI_Controller 
{
    public function index()
    {
    $this->load->library('xmlrpc');
        $this->load->library('xmlrpcs');

        //REGISTRATION AND CONFIGURATION
        $config['functions']['getCdInfo'] = array('function' => 'Welcome.getCdInfo');
        $config['functions']['getCds'] = array('function' => 'Welcome.getCds');
        $config['object'] = $this;

        $this->xmlrpcs->initialize($config);
        $this->xmlrpcs->serve();
    }


    //IMPLEMENTATION
    public function getCdInfo($request)
    {
    $this->load->library('xmlrpc');

        $parameters = $request->output_parameters();

        $id = $parameters[0];  // first parameter
        $this->db->where('id', $id);
        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()==1) {
            $ret = $qcd->row_array();
        } else {
            return $this->xmlrpc->send_error_message('404', 'Invalid results');
        }

        $response = array(
            array(
                'titel'  => array($ret['titel'], 'string'),
                'interpret'    => array($ret['interpret'], 'string'),
                'jahr'       => array($ret['jahr'], 'int'),
                'id'     => array($ret['id'], 'int')
            ),
             'struct'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function getCds()
    {
    $this->load->library('xmlrpc');

        $qcd = $this->db->get('cds');

        if ($qcd->num_rows()>0) {
            $ret = array();
            $i = 0;
            foreach ($qcd->result_array() as $row) {
                $ret[$i] = array(array(
                        'titel'  => array($row['titel'], 'string'),
                        'interpret'    => array($row['interpret'], 'string'),
                        'jahr'       => array($row['jahr'], 'int'),
                        'id'     => array($row['id'], 'int')
                ), 'struct');
                $i++;
            }
        } else {
            return $this->xmlrpc->send_error_message('404', 'Empty results');
        }

        $response = array(
                $ret,
                 'array'
        );

        return $this->xmlrpc->send_response($response);
    }

    public function testClient()
    {
    $server_url = site_url('welcome');

        $this->load->library('xmlrpc');

        //Call getCdInfo
        $this->xmlrpc->server($server_url, 80);
        $this->xmlrpc->method('getCdInfo');

        $request = array(array(1, 'int'));
        $this->xmlrpc->request($request);

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }

        //Call getCDs
        $this->xmlrpc->method('getCds');

        if ( ! $this->xmlrpc->send_request())
        {
            echo $this->xmlrpc->display_error();
        }
        else
        {
            var_dump($this->xmlrpc->display_response());
        }
    }
}

CodeIgniter and NuSOAP

What are we going to do?

We’ll use NuSOAP to create a webservice using CodeIgniter and consume it using CI also.

In this tutorial, we’ll use “cds” table from “cdcol” database bundled from XAMPP. “cds” table content looks like this:

cds table content

cds table content

Download NuSOAP here : https://sourceforge.net/projects/nusoap/
Extract “lib” folder from nusoap-0.9.5.zip into your CI “application/libraries/”. We’ll create simple library warper for NuSoap.
Now, enter your CI “application/libraries/” folder and create a new file named “Nusoap_library.php”. Here’s the content:


We'll use default controller from CI, i.e. Welcome.php. We'll create two webservice endpoints: one for getting info about a CD based in it's "id" and one for getting all of CDs.
All of webservice data types definition, registration and implmentation will be placed inside Wellcome controller's "__construct()" function. Here's the complete code for "__construct()" function:

    function __construct() 
    {
        parent::__construct();

        $this->load->library("Nusoap_library"); //load the library here
        $this->nusoap_server = new soap_server();
        $this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
        $this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

        //DATA TYPES
        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

        //REGISTRATION
        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

        //IMPLEMENTATION
        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                //echo "masuk hasil";
                foreach ($qcd->result_array() as $row) {
                    //var_dump($row);
                    $ret_val[$i]=$row;
                    $i++;
                }
                //var_dump($ret_val);
                return $ret_val;
            } else {
                return false;
            }
            
        }
    }

The first step is loading the library and configuring your webservice:

$this->load->library("Nusoap_library"); //load the library here
$this->nusoap_server = new soap_server();
$this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
$this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

We'll define a new data type for our CD info based on "cds" table structure:

        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

Now, our complex type that will hold list of CDs (array of CDs).

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

After finished defining all needed data types, we'll register all needed webservice endpoint.
First endpoint is "getCdInfo" to get info about a CD based on it's "id". It takes one parameter ("id") and return a "Cd" type.

        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

Second endpoint is "getCds" to get all stored CD in the "cds" table. It takes no parameter and return an array of CDs.

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

Registration is finished, now onto the implementation. Here's the code:

        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                foreach ($qcd->result_array() as $row) {
                    $ret_val[$i]=$row;
                    $i++;
                }
                return $ret_val;
            } else {
                return false;
            }
            
        }

Pay attention, that I'm using "get_instance()" in order to query the database because we can't call "$this" inside these endpoint functions.
Next, we'll edit the default "index()" function, replace it with these:

        public function index()
    {
        $this->nusoap_server->service(file_get_contents("php://input")); //shows the standard info about service
    }

You may try accessing your webservice from your browser and see how it looks

WSDL schema

WSDL schema

webservice description

webservice description

Now, some fixing!

Before accessing our webservice via a SOAP client, we need to fix NuSoap library. Open "application/libraries/lib/nusoap.php", go to line 6132 and comment that line so it would look like this:

//$this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");

If you didn't do this fixing step, you'll get a blank result when calling an endpoint that return an array of data. Further testing using SoapUI will reveal some error like this:

A PHP Error was encountered

Severity: Notice Message: Array to string conversion Filename: lib/nusoap.php Line Number: 6132

Fixing is done, now we'll test it.
For simplicity reason, we'll put our client inside our Welcome controller. Here's the code:

    public function testClient()
    {
        $wsdl = 'http://localhost/ci_soap/?wsdl';
        $this->load->library("Nusoap_library"); //load the library here

        $client = new nusoap_client($wsdl, 'wsdl');

        $res1 = $client->call('getCdInfo', array('id'=>1));
        var_dump($res1);

        $res2 = $client->call('getCds');
        var_dump($res2);
    }

As you can see, the code is quite simple, $res1 will contain output from "getCdInfo" endpoint

array(4) {
  ["id"]=>
  int(1)
  ["jahr"]=>
  int(1990)
  ["interpret"]=>
  string(16) "Ryuichi Sakamoto"
  ["titel"]=>
  string(6) "Beauty"
}

and $res2 will contain an array of CDs as a result from calling "getCds".

array(3) {
  [0]=>
  array(4) {
    ["id"]=>
    int(1)
    ["jahr"]=>
    int(1990)
    ["interpret"]=>
    string(16) "Ryuichi Sakamoto"
    ["titel"]=>
    string(6) "Beauty"
  }
  [1]=>
  array(4) {
    ["id"]=>
    int(4)
    ["jahr"]=>
    int(2001)
    ["interpret"]=>
    string(13) "Groove Armada"
    ["titel"]=>
    string(33) "Goodbye Country (Hello Nightclub)"
  }
  [2]=>
  array(4) {
    ["id"]=>
    int(5)
    ["jahr"]=>
    int(1997)
    ["interpret"]=>
    string(13) "Bran Van 3000"
    ["titel"]=>
    string(4) "Glee"
  }
}

Here's the complete source code of our controller, in case you missed something:

defined('BASEPATH') or exit('No direct script access allowed');

class Welcome extends CI_Controller
{

    function __construct() 
    {
        parent::__construct();
        //$this->load->model(''); //load your models here

        $this->load->library("Nusoap_library"); //load the library here
        $this->nusoap_server = new soap_server();
        $this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer");
        $this->nusoap_server->wsdl->schemaTargetNamespace = 'urn:MySoapServer';

        //DATA TYPES
        $this->nusoap_server->wsdl->addComplexType(
            'Cd',
            'complexType',
            'struct',
            'all',
            '',
            array(
                'id' => array('name' => 'id', 'type' => 'xsd:integer'),
                'jahr' => array('name' => 'jahr', 'type' => 'xsd:integer'),
                'interpret' => array('name' => 'interpret', 'type' => 'xsd:string'),
                'titel' => array('name' => 'titel', 'type' => 'xsd:string')
            )
        );

        $this->nusoap_server->wsdl->addComplexType(
            "CdArray",
            "complexType",
            "array",
            "",
            "SOAP-ENC:Array",
            array(),
            array(
                array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:Cd[]")
            ),
            "tns:Cd"
        );

        //REGISTRATION
        $this->nusoap_server->register(
            'getCdInfo',
            array('id' => 'xsd:integer'),  //parameters
            array('return' => 'tns:Cd'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCdInfo',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get CD Info by ID' //description
        );

        $this->nusoap_server->register(
            'getCds',
            array(),  //parameters
            array('return' => 'tns:CdArray'),  //output
            'urn:MySoapServer',   //namespace
            'urn:MySoapServer#getCds',  //soapaction
            'rpc', // style
            'encoded', // use
            'Get all CDs' //description
        );

        
        //IMPLEMENTATION
        function getCdInfo($id)
        {
            $ci =& get_instance();
            $ci->db->where('id', $id);
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                return $qcd->row_array();
            } else {
                return false;
            }
            
        }

        function getCds()
        {
            $ci =& get_instance();
            $qcd = $ci->db->get('cds');
            if ($qcd->num_rows()>0) {
                $ret_val=array();
                $i=0;
                foreach ($qcd->result_array() as $row) {
                    $ret_val[$i]=$row;
                    $i++;
                }
                return $ret_val;
            } else {
                return false;
            }
            
        }
    }
    
    public function index()
    {
        $this->nusoap_server->service(file_get_contents("php://input")); //shows the standard info about service
    }

    public function testClient()
    {
        $wsdl = 'http://localhost/ci_soap/?wsdl';
        $this->load->library("Nusoap_library"); //load the library here

        $client = new nusoap_client($wsdl, 'wsdl');

        $res1 = $client->call('getCdInfo', array('id'=>1));
        var_dump($res1);

        $res2 = $client->call('getCds');
        var_dump($res2);
    }
}

Using linkbucks API / posting data using cURL in PHP

Background:

Solution:

  • Register to linkbucks if you don’t have any account there (it’s free and you probably should use email other than gmail and hotmail if you want quick confirmation from linkbucks)
  • Find your username and API password from your profile page: https://www.linkbucks.com/Profile/ . If your API password is empty, just click “Reset API Password” link to show it.

This is our little PHP function that help us to POST data to certain URL:

//function to POST data using cURL in PHP
function curl_post($url, $data, $ip="", $ref="", $ua="") {
    //initiate cURL
    $ch=curl_init($url);
    
    //set referer only if stated by user
    if ($ref!="") {
        curl_setopt($ch, CURLOPT_REFERER, $ref);
    }
    
    //set IP interface if needed (for multi-IP server)
    if ($ip!="") {
        curl_setopt($ch, CURLOPT_INTERFACE, $ip);
    }
    
    //set user agent if stated by user
    if ($ua!="") {
        curl_setopt($ch, CURLOPT_USERAGENT, $ua);
    }
    
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $response=curl_exec($ch);
    return $response;
}

How to use it to call linkbucks API:

$data_kirim=array(
    'user'=>'chmdznr',  //my username
    'apiPassword'=>'d55ae4eaf97b445f',  //my API password
    "originalLink"=>"http://google.com",  //the URL that need to be shorted
    "adType"=>2,  //paid links
    "contentType"=>1,   //not an adult content
    "domain"=>"yyv.co"  //target domain, a lot of possibility here, the default is: linkbucks.com 
);

//call linkbucks API
$url='https://www.linkbucks.com/api/createLink/single';

$returned_data=curl_post($url, json_encode($data_kirim));
$parsed_data=json_decode($returned_data);

//simple error checking
if (!empty($parsed_data->link)) {
    echo "This is your short URL : ".$parsed_data->link;
} else {
    echo "Something wrong! ".$parsed_data->errorDescription;
}

The curl_post function is quite generic, you can use it to send data to remote URL using POST method like this:

$login_data=array(
   'username'=>'admin',
   'password'=>'admin'
);

$target_url="http://the_login_website.com/";
$returned_data=curl_post($target_url, http_build_query($login_data));

You should notice that the data array need to be converted using http_build_query first (in linkbucks’ case, it doesn’t need to be converted first).
You can also add more advanced feature in the function such as handling the timeout and cookie.

Check your Windows Azure Datamarket remaining quota

In my previous post, I show you how to use Windows Azure Datamarket to create a Bing Search Engine Position checker. I told you that for free account, you only have 5000 requests per month. Paid subscription has higher limit.
This time I’ll show you how to check your remaining monthly quota for all of your Windows Azure Datamarket subscription without logging in to Azure Datamarket. This is the main function:

error_reporting(E_ALL^E_NOTICE);

function check_bing_quota($key) {
	$ret=array();
	
	$context = stream_context_create(array(
		'http' => array(
		    'request_fulluri' => true,
		    'header'  => "Authorization: Basic " . base64_encode($key . ":" . $key)
			)
		)
	);
	
	$end_point='https://api.datamarket.azure.com/Services/My/Datasets?$format=json';
	
	$response=file_get_contents($end_point, 0, $context);
		
	$json_data=json_decode($response);
	
	foreach ($json_data->d->results as $res) {
		$ret[]=array(
			'title'=>$res->Title,
			'provider'=>$res->ProviderName,
			'entry_point'=>$res->ServiceEntryPointUrl,
			'remaining'=>$res->ResourceBalance
		);
	}
	
	return $ret;
}

How to call it:

$ret=check_bing_quota('put_your_real_account_key_here');

Example result:

array(2) {
  [0]=>
  array(4) {
    ["title"]=>
    string(36) "Bing Search API – Web Results Only"
    ["provider"]=>
    string(4) "Bing"
    ["entry_point"]=>
    string(57) "https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb"
    ["remaining"]=>
    int(4981)
  }
  [1]=>
  array(4) {
    ["title"]=>
    string(15) "Bing Search API"
    ["provider"]=>
    string(4) "Bing"
    ["entry_point"]=>
    string(54) "https://api.datamarket.azure.com/Data.ashx/Bing/Search"
    ["remaining"]=>
    int(4997)
  }
}

Fully working demo: http://demo.ahowto.net/bing_quota/

check remaining quota in Windows Azure Datamarket

example output formatted as table

Notes:

  1. The function will check ALL of your Windows Azure Datamarket subscription
  2. checking your quota does not subtract your quota
  3. your PHP version must be at least 5.2 and PHP-openssl module must be activated

[php] New Bing SERP checker using Windows Azure Datamarket

So, I got email from Bing Developer Team informing that Bing Search API 2.0 will be gone and moving to new platform: Windows Azure Datamarket. On my previous Bing SERP checker project, I’m using Bing Search API 2.0 which means that those codes will no longer working after 1st August.

Windows Azure Datamarket provide a trial package and a free package that has limit for 5000 requests per month. More than enough for us to toying for Bing SERP checker.

Go get your Account Key (was Application ID) : https://datamarket.azure.com/

This is the revised main function php codes so it will work on new Windows Azure Datamarket web service

error_reporting(E_ALL^E_NOTICE);
    
//this is the main function
function b_serp($keyword, $site, $market, $api_key)
{
	$found=FALSE;
	$theweb='';
	$pos=0;
	$ret=array();
	$limit=1;
	
	$site=str_replace(array('http://'), '', $site);
	
	$context = stream_context_create(array(
		'http' => array(
		    'request_fulluri' => true,
		    'header'  => "Authorization: Basic " . base64_encode($api_key . ":" . $api_key)
			)
		)
	);

	
	$pos=1;
	while ((!$found)&&($pos<=100)) {
		$skip=($limit-1)*50;
		
		//this is the end point of microsoft azure datamarket that we should call  -- only take data from web results
		$end_point='https://api.datamarket.azure.com/Data.ashx/Bing/SearchWeb/v1/Web?Query='.urlencode("'".$keyword."'").'&Market='.urlencode("'".$market."'").'&$format=JSON&$top=50&$skip='.$skip;
		
		//I'm using generic file_get_contents because cURL CURLOPT_USERPWD didn't work (no idea why)
		$response=file_get_contents($end_point, 0, $context);
		
		$json_data=json_decode($response);
		
		foreach ($json_data->d->results as $res) {
			$theweb=parse_url($res->Url);

			if (substr_count(strtolower($theweb['host']), $site))
		        {
				$found=TRUE;
				$ret['position']=$pos;
				$ret['title']=$res->Title;
				$ret['url']=$res->Url;
		                return $ret;
		        }

			$pos++;
		}
		
		$limit++;
	}
	
	if (!$found)
	{
		return NULL;
	}
}

How you call it:

$account_key='put your account key here';
$res=b_serp('how to upload mp3 to youtube', 'mp32u.net', 'en-US', $account_key);

Example output:

array(3) {
  ["position"]=>
  int(3)
  ["title"]=>
  string(70) "MP32U.NET - Helping independent artist getting acknowledged in the ..."
  ["url"]=>
  string(21) "http://www.mp32u.net/"
}

Fully working demo: http://demo.ahowto.net/new_bserp/

Actually, there are a lot of other “Search Market” that supported by Bing but I only listed some of them just for example. Download this document for complete list of Bing’s supported Search Market: http://www.bing.com/webmaster/content/developers/ADM_SCHEMA_GUIDE.docx

Notes:

  1. Your PHP version must be PHP 5.2 or higher (because of json_decode command)
  2. You must activate PHP OpenSSL module (php_openssl) because we are using file_get_contents and the webservice end point must be accessed via HTTPS

Update (2012-07-20) : the endpoint URL is changed