Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Convert fopen() to curl ? 1

Status
Not open for further replies.

youradds

Programmer
Jun 27, 2001
817
GB
Hi,

I'm not a PHP expert, buit I've got a script which needs changing from fopen() to curl()

The code in question is as follows:

Code:
function req_post($url, $data, $optional_headers = null) {
    $params = array('http' => array(
                'method' => 'POST',
                'content' => $data
                ));
    if ($optional_headers !== null) {
        $params['http']['header'] = $optional_headers;
    }
    $ctx = stream_context_create($params);
    $fp = fopen($url, 'rb', false, $ctx);
    if (!$fp) {
        throw new Exception("Problem with $url");
    }
    $response = @stream_get_contents($fp);
    if ($response === false) {
        throw new Exception("Problem reading data from $url");
    }
    return $response;
}

Is anyone able to help me? :)

TIA

Andy
 
Code:
<?php

function req_post($url, $data, $optional_headers = null) {
    $params = array('http' => array(
					                'method' => 'POST',
					                'content' => $data
					                ));
    
	
	/* establish CURL options */
	$options = array(
					CURLOPT_FOLLOWLOCATION=>true,
					CURLOPT_MAXREDIRS=>5,
					CURLOPT_FRESH_CONNECT=>true,
					CURLOPT_FORBID_REUSE=>true,
					CURLOPT_POST=>$params['method'],
					CURLOPT_RETURNTRANSFER=>true,
					CURLOPT_SSL_VERIFYPEER=>false,
					CURLOPT_SSL_VERIFYHOST=>false,
					CURLOPT_TIMEOUT=>10);
	
	/* in case GET method is used, transform data array into query string */
	switch (strtolower($params['method'])):
		case 'get':
			if(is_array($data)):
				$string = array();
				foreach ($params['content'] as $key=>$value):
					$string[] = urlencode($key) .'='.urlencode($value);
				endforeach;
				$params['content'] = implode ('&amp;', $string);
			endif;
				$url .= '?'.$params['content'];
			break;
		case 'post':
			$options[CURLOPT_POSTFIELDS]= $params['content'];
			break;
	endswitch;

	/* initiate curl handle */
	$cH = curl_init($url);
	
	/* set up curl options */
	curl_setopt_array($cH, $options);
	
	/* test for additional option */
	/* note these must now be in the form of CURL options */ 
	if ($optional_headers !== null && is_array($optional_headers)):
        foreach ($optional_headers as $key=>$value):
        	$r = @curl_setopt($cH, $key, $value);
			if($r === false):
				throw new Exception ('Error setting option '.$key .' to value ' . $value .'. Error reported: ' . curl_error());
			endif;
        endforeach;
    endif;
	
	/* execute request */
	$response = curl_exec($cH);
	if ($response === false){
		throw new Exception("Problem reading data from $url. \nError was " . curl_error($cH));
	} else {
    	return $response;
	}
}
?>
 
Thanks a million - just gonna have a play with this and see if it all works ok :)

Cheers

Andy
 
Hi,

Thanks - almost works :)

Code:
[URL unfurl="true"]http://www.telecomnational.com/custadd.php?name=andy%20newby&website=http://www.domain.com&address=19%20slcose&city=rudgwick&state=surry&zip=rh12%203fe&salutation=mr&firstname=andrew&lastname=newby&title=bnla&email=andy@gmail.com&phone=13234535345[/URL]

(sorry isn't a proper link - the forum did weird stuff with it when I tried that :()

If it helps, here is the whole script:

Code:
<?php

/*
 * Uses PHP 5 but not JSON 
 */

$GLOBALS['api_url'] = "[URL unfurl="true"]https://demo.rpmsoftware.com/rpm/Api.svc/";[/URL]
$GLOBALS['api_key'] = "7403bd28-f709-424f-b14d-0a62f82622fc";

/*
 * An array with the customer data to add
 * 
 */
$customer = array(
	'name' => $_GET['name'],
	'website' => $_GET['website'],
	'address' => $_GET['address'],
	'city' => $_GET['city'],
	'stateprovince' => $_GET['state'],
	'zippostalcode' => $_GET['zip'],
	'salutation' => $_GET['salutation'],
	'first name' => $_GET['firstname'],
	'last name' => $_GET['lastname'],
	'title' => $_GET['title'],
	'email' => $_GET['email'],
	'phone' => $_GET['phone'],

	// To use custom fields make 'fields' an array like this:
	'fields' => array(
	     'comments' => $_GET['comments']
	 )

);

/*
 * A generic POST function
 *
 * This isn't specific to RPM, it's just a simple POST wrapper to
 * fopen. Any post function will do and something using CURL is
 * probably better: [URL unfurl="true"]http://curl.haxx.se/libcurl/php/[/URL]
 *
 */

/*
function req_post($url, $data, $optional_headers = null) {
	$params = array('http' => array(
				'method' => 'POST',
				'content' => $data
				));
	if ($optional_headers !== null) {
		$params['http']['header'] = $optional_headers;
	}
	$ctx = stream_context_create($params);
	$fp = fopen($url, 'rb', false, $ctx);
	if (!$fp) {
		throw new Exception("Problem with $url");
	}
	$response = @stream_get_contents($fp);
	if ($response === false) {
		throw new Exception("Problem reading data from $url");
	}
	return $response;
}
*/


function req_post($url, $data, $optional_headers = null) {
    $params = array('http' => array(
                                    'method' => 'POST',
                                    'content' => $data
                                    ));
    
    
    /* establish CURL options */
    $options = array(
                    CURLOPT_FOLLOWLOCATION=>true,
                    CURLOPT_MAXREDIRS=>5,
                    CURLOPT_FRESH_CONNECT=>true,
                    CURLOPT_FORBID_REUSE=>true,
                    CURLOPT_POST=>$params['method'],
                    CURLOPT_RETURNTRANSFER=>true,
                    CURLOPT_SSL_VERIFYPEER=>false,
                    CURLOPT_SSL_VERIFYHOST=>false,
                    CURLOPT_TIMEOUT=>10);
    
    /* in case GET method is used, transform data array into query string */
    switch (strtolower($params['method'])):
        case 'get':
            if(is_array($data)):
                $string = array();
                foreach ($params['content'] as $key=>$value):
                    $string[] = urlencode($key) .'='.urlencode($value);
                endforeach;
                $params['content'] = implode ('&amp;', $string);
            endif;
                $url .= '?'.$params['content'];
            break;
        case 'post':
            $options[CURLOPT_POSTFIELDS]= $params['content'];
            break;
    endswitch;

    /* initiate curl handle */
    $cH = curl_init($url);
    
    /* set up curl options */
    curl_setopt_array($cH, $options);
    
    /* test for additional option */
    /* note these must now be in the form of CURL options */
    if ($optional_headers !== null && is_array($optional_headers)):
        foreach ($optional_headers as $key=>$value):
            $r = @curl_setopt($cH, $key, $value);
            if($r === false):
                throw new Exception ('Error setting option '.$key .' to value ' . $value .'. Error reported: ' . curl_error());
            endif;
        endforeach;
    endif;
    
    /* execute request */
    $response = curl_exec($cH);

echo "FOO: $response ";

    if ($response === false){
        throw new Exception("Problem reading data from $url. \nError was " . curl_error($cH));
    } else {
        return $response;
    }
}



/*
 * API call without JSON functions
 *
 */
function rpm_req($call, $data_string = "") {
	if ("" != $data_string) $data_string = ", ".$data_string;

	// Build the request
	$data = '{"Key":"'.$GLOBALS['api_key'].'" '.$data_string.' }';
	
	// Make the request
	$result = req_post($GLOBALS['api_url'].$call, $data, 'Content-Type: application/json; charset=utf-8');
	
	// Analyse the results
	$response_pattern = '/\{\"[A-Za-z]+\":\"(.+)\"\}/';
	$error_pattern = '/\{\\\"Error\\\":\\\"([A-za-z0-9 ]+)\\\"\}/';
	if (preg_match($response_pattern, $result, $matches)) {
		$return = $matches[1];
		if (preg_match($error_pattern, $return, $matches)) {
			throw new Exception("API returned error: $matches[1]");
		}
		return $return;
	} else {
		throw new Exception("Problem with return from $url");
	}
}

?>

[CODE]<html>
<head>
<title>Add customer API example</title>
<style>
	body { background: #eee; font-family: Arial, sans-serif; font-size: small; }
</style>
</head>
<body>

<?php

if (is_array($customer['fields'])) {
	$customer_fields = ', "Fields": [';
	foreach ($customer['fields'] as $field_name => $field_value) {
		$customer_fields .= '{"Field":"'.$field_name.'","Value":"'.$field_value.'"},';
	}
	$customer_fields = substr($customer_fields, 0, strlen($customer_fields) - 1); // chop off the last ,
	$customer_fields .= ']';
} else $customer_fields = "";

try {
	$result = rpm_req('CustomerAdd','
		"Customer": {
			"Name": "'.$customer['name'].'",
			"Website": "'.$customer['website'].'",
			"Address": "'.$customer['address'].'",
			"City": "'.$customer['city'].'",
			"StateProvince": "'.$customer['stateprovince'].'",
			"Country": "United States",
			"ZipPostalCode": "'.$customer['zippostalcode'].'",
			"PrimaryContact": {
				"Salutation": "'.$customer['salutation'].'",
				"FirstName": "'.$customer['first name'].'",
				"LastName": "'.$customer['last name'].'",
				"Title": "'.$customer['title'].'",
				"Email": "'.$customer['email'].'",
				"PhoneBusiness": { "Number":"'.$customer['phone'].'"}
			}
			'.$customer_fields.'
		}
	');
	echo 'Customer added';
} catch (Exception $e) {
	echo $e->getMessage();
}



?>

</body>
</html>


TIA :)

Andy
 
Andy
i suggest you ask the moderators to delete your API key from this thread.

I think that this fix should work. If not, it would help to see the API specification for the webservice. Json does not feel like a great format for data transfer.

Code:
<?php

function req_post($url, $data, $optional_headers = null) {
    $params = array('http' => array(
					                'method' => 'POST',
					                'content' => $data
					                ));
    
	
	/* establish CURL options */
	$options = array(
					CURLOPT_FOLLOWLOCATION=>true,
					CURLOPT_MAXREDIRS=>5,
					CURLOPT_FRESH_CONNECT=>true,
					CURLOPT_FORBID_REUSE=>true,
					CURLOPT_POST=>$params['method'],
					CURLOPT_RETURNTRANSFER=>true,
					CURLOPT_SSL_VERIFYPEER=>false,
					CURLOPT_SSL_VERIFYHOST=>false,
					CURLOPT_TIMEOUT=>10);
	
	/* in case GET method is used, transform data array into query string */
	switch (strtolower($params['http']['method'])):
		case 'get':
			if(is_array($params['http']['content'])):
				$string = array();
				foreach ($params['http']['content'] as $key=>$value):
					$string[] = urlencode($key) .'='.urlencode($value);
				endforeach;
				$params['http']['content'] = implode ('&amp;', $string);
			endif;
				$url .= '?'.$params['http']['content'];
			break;
		case 'post':
			$options[CURLOPT_POSTFIELDS]= $params['http']['content'];
			break;
	endswitch;

	/* initiate curl handle */
	$cH = curl_init($url);
	
	/* set up curl options */
	curl_setopt_array($cH, $options);
	
	/* test for additional option */
	/* note these must now be in the form of CURL options */ 
	if ($optional_headers !== null):
		if (!is_array($optional_headers)):
			$headers[] = $optional_headers;
		else:
			$headers =& $optional_headers;
		endif;
        $r = @curl_setopt($cH, CURLOPT_HTTPHEADER, $headers);
    endif;
	
	/* execute request */
	$response = curl_exec($cH);
	if ($response === false){
		throw new Exception("Problem reading data from $url. \nError was " . curl_error($cH));
	} else {
    	return $response;
	}
}

/*
 * API call without JSON functions
 *
 */
function rpm_req($call, $data_string = "") {
	if ("" != $data_string) $data_string = ", ".$data_string;
	
	// Build the request
	$data = '{"Key":"'.$GLOBALS['api_key'].'" '.$data_string.' }';
	
	// Make the request
	$result = req_post($GLOBALS['api_url'].$call, $data, 'Content-Type: application/json; charset=utf-8');
	
	// Analyse the results
	$response_pattern = '/\{\"[A-Za-z]+\":\"(.+)\"\}/';
	$error_pattern = '/\{\\\"Error\\\":\\\"([A-za-z0-9 ]+)\\\"\}/';
	if (preg_match($response_pattern, $result, $matches)) {
	    $return = $matches[1];
	    if (preg_match($error_pattern, $return, $matches)) {
	        throw new Exception("API returned error: $matches[1]");
	    }
	    return $return;
	} else {
	    throw new Exception("Problem with return from $url");
	}
}
/**
 * function to provide against early versions of php
 * 
 * @param object $key
 * @param object $data
 * @return 
 */
function _json_encode($key,$data){
	$array = array($key=>$data);
	if (function_exists('json_encode')):
		return json_encode($array);
	else:
		$string = ', "'.$key.'" [';
		foreach ($data as $field_name => $field_value):
        	$bits[] = '{"Field":"'.$field_name.'","Value":"'.$field_value.'"}';
		endforeach;
		$bits = implode (',', $bits);
		return $string . $bits .']';
	endif;
}

$customer_fields = (is_array($customer['fields'])) ? _json_encode('Fields', $customer['fields']) :'';

try {
    $result = rpm_req('CustomerAdd','
        "Customer": {
            "Name": "'.$customer['name'].'",
            "Website": "'.$customer['website'].'",
            "Address": "'.$customer['address'].'",
            "City": "'.$customer['city'].'",
            "StateProvince": "'.$customer['stateprovince'].'",
            "Country": "United States",
            "ZipPostalCode": "'.$customer['zippostalcode'].'",
            "PrimaryContact": {
                "Salutation": "'.$customer['salutation'].'",
                "FirstName": "'.$customer['first name'].'",
                "LastName": "'.$customer['last name'].'",
                "Title": "'.$customer['title'].'",
                "Email": "'.$customer['email'].'",
                "PhoneBusiness": { "Number":"'.$customer['phone'].'"}
            }
            '.$customer_fields.'
        }
    ');
    echo 'Customer added';
} catch (Exception $e) {
    echo $e->getMessage();
}
 
Hi,

Thanks - getting there - but keeps telling me I need to pass in a unique contact name (even though I'm changing it)

It seems to add the record to the system, but I still get an error:

Customer added API returned error: A unique customer name is required

..not quite sure why though :/

TIA

Andy

 
as said, I need the API reference to assist further.

 
ok. I have written a partial gateway API for you.
here are the classes you need

Code:
class customerAdd extends gateway{
	
	public function __construct($data, $customerFields=array()){
		parent::__construct();
		if (is_array($customerFields) && count($customerFields)>0){
			foreach ($customerFields as $field=>$value):
				$data['Fields'][]=array('Field'=>$field, "Value"=>$value);
			endforeach;
		}
		$result = $this->doRequest('CustomerAdd', array('Customer'=>$data));
		$this->result = $this->_json_decode($this->_json_decode($result)->CustomerAddResult);
	}
}

class customer extends gateway{
	
	public function __construct($customerID=NULL, $customerName=NULL){
		parent::__construct();
		if (!is_null($customerName)):
			$result = $this->doRequest('Customer', array('Customer'=>$customerName));
		elseif(!is_null($customerID)):
			$result = $this->doRequest('CustomerID', array('Customer'=>$customerID));
		endif;
		$result = $this->_json_decode($result);
		
		$this->result = $this->_json_decode($result->CustomerResult);
	}
}

class customerList extends gateway{
	public function __construct(){
		parent::__construct();
		$result = $this->doRequest('Customers');
		$this->parseResult($result);
	}
	
	public function parseResult($result){
		$result = $this->_json_decode($result);
		$customers = $this->_json_decode($result->CustomersResult);
		$this->result = $customers;
	}
}

class gateway{
	
	public $url = "[URL unfurl="true"]https://demo.rpmsoftware.com/rpm/Api.svc/";[/URL]
	public $key = "7403bd28-f709-424f-b14d-0a62f82622fc";
	
	public function __construct(){
		
	}
	public function isError(){
		return (isset($this->result->Error)); 
	}
	
	public function getError(){
		return $this->result->Error;
	}
	public function getResults(){
		return $this->result;
	}
	public function doRequest($type, $data=null){
		$options = array(
					CURLOPT_FOLLOWLOCATION=>true,
					CURLOPT_MAXREDIRS=>5,
					CURLOPT_POST=>true,
					CURLOPT_RETURNTRANSFER=>true,
					CURLOPT_SSL_VERIFYPEER=>false,
					CURLOPT_SSL_VERIFYHOST=>false,
					CURLOPT_TIMEOUT=>10,
					CURLOPT_POSTFIELDS => $this->assembleData($data),
					CURLOPT_HTTPHEADER=>array('Content-Type: application/json; charset=utf-8'));
		//establish connection
		$cH = curl_init($this->url . $type);
		curl_setopt_array($cH, $options);
		//set options
		$return = curl_exec($cH);
		return $return;
	}
	
	public function assembleData($data){
		if (is_array($data)):
			$data = array_merge(array('Key'=>$this->key), $data);
		else:
			$data = array('Key'=>$this->key);
		endif;
		return $this->_json_encode($data);
	}
	
	public function _json_decode($json) {  
		if (function_exists('json_decode')):
			return json_decode($json);
		endif;
		// Author: walidator.info 2009 
		$out = '$x='; 
		
		for ($i=0; $i<strlen($json); $i++): 
			if ($json[$i] == '{'):
				$out .= ' array('; 
			elseif ($json[$i] == '}'):    
				$out .= ')'; 
			elseif ($json[$i] == ':'):
				$out .= '=>'; 
			else:
				$out .= $json[$i];
			endif;            
		endfor;
		eval($out . ';'); 
		return $x;
	}
	
	public function _json_encode($data){
		if (function_exists('json_encode')):
			return json_encode($data);			
		endif;
	}
}

the classes handle listing customers, finding a customer by ID or name and adding a customer

example for adding a customer
Code:
/* PROFILE FIELDS FOR USE */
$fields = array('Name', 'Website','Address','City', 'StateProvince', 'Country', 'ZipPostalCode');
$primaryContactFields = array('Salutation','FirstName', 'LastName', 'Title', 'Email');
$data = array();


/* handle basic customer data */
foreach($fields as $field){
	$_field = strtolower($field);
	if(!empty($_REQUEST[$_field])):
		$data[$field] =  trim ($_REQUEST[$_field]);
	endif;
}

/* handle contact data */
foreach($primaryContactFields as $field):
	$_field = strtolower($field);
	if(!empty($_REQUEST[$_field])):
		$data['PrimaryContact'][$field] =  trim ($_REQUEST[$_field]);
	endif;
endforeach;

/* handle phone numbers */
if (!empty($_REQUEST['phone'])):
	$data['PrimaryContact']['PhoneBusiness']['Number'] = trim ($_REQUEST['phone']);
endif;

$data['Name'] = empty($data['Name']) ? 'James Earl Jones ' . uniqid('') : $data['Name'];
$obj = new customerAdd($data, $customer_fields);
if ($obj->isError()):
	echo 'Error: ' . $obj->getError();
else:
	echo 'Customer Add succesful<br/>';
	//couble check by searching for the customer
	$obj=new Customer(NULL, $data['Name']);
	print_r($obj->getResults());
endif;

example for finding a customer
Code:
$obj=new Customer(NULL, 'Johnny');
if ($obj->isError()):
	$e = $obj->getError();
	if ($e === 'Customer not found'):
		echo 'Sorry '. $e;
	else:
		echo 'Error: ' . $e;
	endif;
else:
	echo 'Customer Found <br/>';
	print_r($obj->getResults());
endif;

and to retrieve a customer list
Code:
$obj=new CustomerList();
if ($obj->isError()):
	echo 'Error: ' . $e->getError;
else:
	echo "<table>";
	foreach ($obj->getResults()->Customers as $customer):
		echo <<<HTML
<tr><td>{$customer->CustomerID}</td><td>{$customer->Customer}</td></tr>
HTML;
	endforeach;
	echo "</table>";
endif;
 
Hi,

Thanks - your a star - will have a play around with this later :)

Cheers

Andy
 
oops.

watch out for this line
Code:
$data['Name'] = empty($data['Name']) ? 'James Earl Jones ' . uniqid('') : $data['Name'];

it is there to create a dummy dataset rather than build a whole form or data stub.

note I have not tested the API with a full data load yet.

post back if there are problems
 
Cool , thanks for the heads up. Will let you know how it goes :)

Thanks again

Andy
 
and one more heads up ...

you need to have php >= 5.2 for this to work. otherwise I will need to write a routing to encode json. no big deal.
 
Hi,

Thanks - we are using 5.2.3, so should be all good :)

Cheers

Andy
 
good..

you will see rather a lot of test customers that i had to create on your account.

an additional class for editing customer information
Code:
class customerEdit extends gateway{
	public function __construct($data, $customerFields=array()){
		parent::__construct();
		if (is_array($customerFields) && count($customerFields)>0){
			foreach ($customerFields as $field=>$value):
				$data['Fields'][]=array('Field'=>$field, "Value"=>$value);
			endforeach;
		}
		$result = $this->doRequest('CustomerEdit', array('Customer'=>$data));
		$this->result = $this->_json_decode($this->_json_decode($result)->CustomerAddResult);
	}
}

usage is as per the add customer class save that the error trapping is as follows

Code:
if ($obj->isError()):
  echo 'Sorry: no customer was found with that ID or name';
endif;
 
Hi,

Its working like a chamr - I can't thank you enough! :)

One little question - which I expect is pretty simple. With the old code, I did:

// To use custom fields make 'fields' an array like this:
'fields' => array(
'comments' => $_GET['comments']
)

I tried editing your code, by adding "comments" (the name of the extra field I added in their system), but it never gets populated:

$fields = array('Name', 'Website','Address','City', 'StateProvince', 'Country', 'ZipPostalCode','comments');

Any ideas on this one?

BTW, "star" coming your way <G>

Cheers

Andy
 
the comment field is not supported in the core dataset by the webservice.

however the service does allow user defined key pairs in the Fields field.

I have implemented this in the $customer_fields argument that you can pass to the customerAdd constructor.

so if you have a field called 'comments' you would add it to the $customer_fields variable before calling customerAdd

Code:
$customer_fields['comments']=>$_GET['comments'];
 $obj = new customerAdd($data, $customer_fields);
...etc
 
As always, perfect - works a charm. Thanks again :) (just gave you a star btw)

Cheers

Andy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top