Here is my code, and I can't figure out why it's not working.
$soapUrl = "http://airarabia.isaaviations.com/webservices/services/AAResWebServices?wsdl";
$xml_post_string = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Header><wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-17855236" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>xxx</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">xxx</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body xmlns:ns2="http://www.opentravel.org/OTA/2003/05"><ns2:OTA_AirAvailRQ EchoToken="11868765275150-1300257933" PrimaryLangID="en-us" SequenceNmbr="1" Target="LIVE" TimeStamp="2018-10-08T11:39:35" Version="20061.00"><ns2:POS><ns2:Source TerminalID="Farhath/Farhath"><ns2:RequestorID ID="WSBENZTRAVELS" Type="4" /><ns2:BookingChannel Type="12" /></ns2:Source></ns2:POS><ns2:OriginDestinationInformation><ns2:DepartureDateTime>2018-10-30T00:00:00</ns2:DepartureDateTime><ns2:OriginLocation LocationCode="CMB" /><ns2:DestinationLocation LocationCode="RUH" /></ns2:OriginDestinationInformation><ns2:OriginDestinationInformation><ns2:DepartureDateTime>2018-11-30T00:00:00</ns2:DepartureDateTime><ns2:OriginLocation LocationCode="RUH" /><ns2:DestinationLocation LocationCode="CMB" /></ns2:OriginDestinationInformation><ns2:TravelerInfoSummary><ns2:AirTravelerAvail><ns2:PassengerTypeQuantity Code="ADT" Quantity="1" /></ns2:AirTravelerAvail></ns2:TravelerInfoSummary></ns2:OTA_AirAvailRQ></soap:Body></soap:Envelope>';
$headers = array(
"Host: airarabia.isaaviations.com",
"Content-Type: application/soap+xml; charset=utf-8",
"Content-Length: ".strlen($xml_post_string)
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
$parser = simplexml_load_string($response);
print_r($parser);
I am able to connect to the API, but couldn't get a result.
Do you have any idea, any solution ?
I wrote a class that helps to simplify generating SOAP XML for a Laravel package. Here is the class:
<?php
namespace Mtownsend\CollectionXml\Soap;
use SoapClient;
/**
* Use the SoapFactory class to build a valid SOAP request
* but prevent it from making an actual request
* and capture the data it builds for use.
*/
class SoapFactory extends SoapClient
{
public $soapRequest;
public $soapLocation;
public $soapAction;
public $soapVersion;
public function __construct($wsdl, $options)
{
parent::__construct($wsdl, $options);
}
/**
* Build the SOAP xml string
* #param array $soapRootAndXml [$soapRoot => $xml]
* #return Mtownsend\CollectionXml\Soap\SoapFactory
*/
public function build(array $soapRootAndXml)
{
$this->ProcessXMLRequest($soapRootAndXml);
return $this;
}
/**
* Override the SoapClient __doRequest method.
*/
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$this->soapRequest = $request;
$this->soapLocation = $location;
$this->soapAction = $action;
$this->soapVersion = $version;
return ''; // Return a string value or the SoapClient throws an exception
}
/**
* A proxy for the getSoapRequest method.
* #return string
*/
public function getSoapXml()
{
return $this->getSoapRequest();
}
/**
* Return the SOAP request XML.
* #return string
*/
public function getSoapRequest()
{
return $this->soapRequest;
}
/**
* Return the SOAP request location url.
* #return string
*/
public function getSoapLocation()
{
return $this->soapLocation;
}
/**
* Return the SOAP request action.
* #return string
*/
public function getSoapAction()
{
return $this->soapAction;
}
/**
* Return the SOAP request version number.
* #return string
*/
public function getSoapVersion()
{
return $this->soapVersion;
}
}
If you would like to use it, save the contents to SoapFactory.php and include it in your script.
Next, get your raw xml ready. Don't try to SOAPify it or anything. Store it in a variable $xml_post_string.
You may need to change your soap root if it doesn't work. I've connected to soap endpoints in the past that use 'xmlBody'.
$soapRoot = 'xmlBody';
$soapFactory = new SoapFactory($soapUrl, ['trace' => 1]));
$soapXml = $soapFactory->build([$soapRoot => $xml_post_string])->getSoapXml();
Now you can try a curl call.
$headers = array(
"Host: airarabia.isaaviations.com",
"Content-Type: application/soap+xml; charset=utf-8",
"Content-Length: ".strlen($soapXml)
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapXml);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$parser = simplexml_load_string($response);
print_r($parser);
There's no guarantee with SOAP, but try that and see if it gets you anywhere.
Related
I would like to get multiple poosible translations for a given word using the /getTranslations method from the Microsoft Translator API according to the API reference. Unfortunately, the provided example on github is outdated: Outdated Example. I did manage to update the getTokens function and references to it, and I did get a translation back, but I need multiple.
Does anyone have a working example/know a fix to my code?
Here is my code:
<?php
class AccessTokenAuthentication {
/*
* Get the access token.
*
* #param string $grantType Grant type.
* #param string $scopeUrl Application Scope URL.
* #param string $clientID Application client ID.
* #param string $clientSecret Application client ID.
* #param string $authUrl Oauth Url.
*
* #return string.
*/
function getToken($azure_key)
{
$url = 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken';
$ch = curl_init();
$data_string = json_encode('{body}');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
'Ocp-Apim-Subscription-Key: ' . $azure_key
)
);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$strResponse = curl_exec($ch);
curl_close($ch);
return $strResponse;
}
}
/*
* Class:HTTPTranslator
*
* Processing the translator request.
*/
Class HTTPTranslator {
/*
* Create and execute the HTTP CURL request.
*
* #param string $url HTTP Url.
* #param string $authHeader Authorization Header string.
*
* #return string.
*
*/
function curlRequest($url, $authHeader) {
//Initialize the Curl Session.
$ch = curl_init();
//Set the Curl url.
curl_setopt ($ch, CURLOPT_URL, $url);
//Set the HTTP HEADER Fields.
curl_setopt ($ch, CURLOPT_HTTPHEADER, array($authHeader,"Content-Type: text/xml", 'Content-Length: 0'));
//CURLOPT_RETURNTRANSFER- TRUE to return the transfer as a string of the return value of curl_exec().
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
//CURLOPT_SSL_VERIFYPEER- Set FALSE to stop cURL from verifying the peer's certificate.
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, False);
//Set HTTP POST Request.
curl_setopt($ch, CURLOPT_POST, TRUE);
//Execute the cURL session.
$curlResponse = curl_exec($ch);
//Get the Error Code returned by Curl.
$curlErrno = curl_errno($ch);
if ($curlErrno) {
$curlError = curl_error($ch);
throw new Exception($curlError);
}
//Close a cURL session.
curl_close($ch);
return $curlResponse;
}
}
try {
//Azure Key
$azure_key = "<my key>";
//Client ID of the application.
//$clientID = "clientId";
//Client Secret key of the application.
//$clientSecret = "ClientSecret";
//OAuth Url.
$authUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/";
//Application Scope Url
//$scopeUrl = "http://api.microsofttranslator.com";
//Application grant type
//$grantType = "client_credentials";
//Create the AccessTokenAuthentication object.
$authObj = new AccessTokenAuthentication();
//Get the Access token.
$accessToken = $authObj->getToken($azure_key);
//Create the authorization Header string.
$authHeader = "Authorization: Bearer ". $accessToken;
//Set the Params.
$inputStr = "get";
$fromLanguage = "en";
$toLanguage = "de";
//$user = 'TestUser';
$category = "general";
//$uri = null;
$contentType = "text/plain";
$maxTranslation = 5;
//Create the string for passing the values through GET method.
$params = "from=$fromLanguage".
"&to=$toLanguage".
"&maxTranslations=$maxTranslation".
"&text=".urlencode($inputStr).
//"&user=$user".
//"&uri=$uri".
"&contentType=$contentType";
//HTTP getTranslationsMethod URL.
$getTranslationUrl = "http://api.microsofttranslator.com/V2/Http.svc/GetTranslations?$params";
//Create the Translator Object.
$translatorObj = new HTTPTranslator();
//Call the curlRequest.
$curlResponse = $translatorObj->curlRequest($getTranslationUrl, $authHeader);
//Interprets a string of XML into an object.
$xmlObj = simplexml_load_string($curlResponse);
$translationObj = $xmlObj->Translations;
$translationMatchArr = $translationObj->TranslationMatch;
print_r($translationMatchArr);
echo "Get Translation For <b>$inputStr</b>";
echo "<table border ='2px'>";
echo "<tr><td><b>Count</b></td><td><b>MatchDegree</b></td>
<td><b>Rating</b></td><td><b>TranslatedText</b></td></tr>";
foreach($translationMatchArr as $translationMatch) {
echo "<tr><td>$translationMatch->Count</td><td>$translationMatch->MatchDegree</td><td>$translationMatch->Rating</td>
<td>$translationMatch->TranslatedText</td></tr>";
}
echo "</table></br>";
} catch (Exception $e) {
echo "Exception: " . $e->getMessage() . PHP_EOL;
}
I solved the problem this way:
(IncludeMultipleMTAlternatives mast be first in options section)
<GetTranslationsArrayRequest>
<AppId></AppId>
<From>en</From>
<Options>
<IncludeMultipleMTAlternatives xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">true</IncludeMultipleMTAlternatives>
<State xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">777</State>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">world</string>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">sun</string>
</Texts>
<To>ru</To>
<MaxTranslations>10</MaxTranslations>
</GetTranslationsArrayRequest>
The GetTranslations() and GetTranslationsArray() methods in the V2 API of Microsoft Translator include an optional Boolean flag "IncludeMultipleMTAlternatives".
The method will return up to maxTranslations alternatives, even if there are not as many CTF entries available, where the delta is supplied from the n-best list of the translator engine. The machine-generated alternatives are returned with a rating of 0. The human-curated alternatives will have a rating of 1 or higher.
When I call route in Slim php from the browser it works perfectly, however when I call it via Ajax I recieve a 404 error. The function in question makes a Curl request. I suspect this may have something to do with the headers I'm sending with curl:
$data = $this->curl->call($url, $urlParams, $postParams, $method, $this->getDefaultHeaders());
protected function getDefaultHeaders() {
return array(
'Authorization' => 'Bearer ' . $this->access_token,
'Accept' => self::HTTP_HEADER_ACCEPT,
);
}
class Curl {
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
const METHOD_PUT = 'PUT';
const METHOD_DELETE = 'DELETE';
const CURL_TIMEOUT_IN_SECS = 15;
public static $successFullHttpCodes = array(200, 201, 204);
public function call($url, $urlParams = array(), $postParams = null, $method = self::METHOD_GET, $headers = array()) {
$finalUrl = $url . $this->getUrlParameterString($urlParams);
$data = $this->makeCurlCall($finalUrl, $postParams, $method, $headers);
return $data;
}
/**
* Creates a curl call for the given url, automatically validates the return value for errors.
* If an error has been found a new Exception will be thrown.
*
* #param string $url
* #param array $postParams Parameters for Post and Put-Requests
* #param string $method HTTP-Method (GET, PUT, POST, DELETE)
* #param string $headers HTTP-Headers
* #throws Exception
*/
private function makeCurlCall($url, $postParams = array(), $method = self::METHOD_GET, $headers = array()) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_VERBOSE, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, self::CURL_TIMEOUT_IN_SECS);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
if ($headers) {
$usableHeaders = array();
foreach ($headers as $name => $value) {
$usableHeaders[] = sprintf('%s: %s', $name, $value);
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $usableHeaders);
}
if ($postParams) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $postParams);
}
$data = curl_exec($curl);
$this->checkForError($curl, $data);
return $data;
}
/**
* Checks for any errors in the api response.
* If an error has been found a new Exception will be thrown.
*
* #param string $data the resulting data
* #throws Exception
*/
private function checkForError($curl, $data) {
$curlInfo = curl_getinfo($curl);
if (isset($curlInfo['http_code']) && !in_array($curlInfo['http_code'], self::$successFullHttpCodes)) {
throw new Exception($curlInfo['http_code'] ? $data : 'could not get a response from the service...'.$curl." data: ".$data, $curlInfo['http_code'] ? $curlInfo['http_code'] : 500);
}
}
/**
* Builds a valid http query
*
* #param array $urlParams
* #return string
*/
private function getUrlParameterString(array $urlParams) {
if (!$urlParams) {
return "";
}
return "?" . http_build_query($urlParams);
}
}
It turns out my error was with storing the api token in a session variable when there are two different sessions evoked.
I am trying to use the ChannelAdvisor REST API in PHP to load a list of stock levels that changed since the last sync. This process is documented here: http://developers.channeladvisor.com/rest/#946
Based on the documentation, I have ran a test in Post Man (chrome rest client) to make sure It's working as intended & it does:
Since the test was successfully, I started to work on the PHP script to interact with the REST API in the same manner and it's not quite working correctly. I am getting the following output:
Bad Request - HTTP Error 400. The request is badly formed.
This is my script so far (I am working with Laravel 4, but it's unrelated to that). The issue is with the curlGET method:
<?php namespace Latheesan\ThirdParty\ChannelAdvisorREST;
class ChannelAdvisorREST {
/**
* ChannelAdvisor base uri
*/
const BASE_URL = 'https://api.channeladvisor.com';
/**
* ChannelAdvisor config data
*/
private $config;
/**
* Class constructor
*/
public function __construct()
{
$this->config = \Config::get('channeladvisor');
}
/**
* Method to load stock updates since last sync.
*
* #param $accountId
* #param $lastSync
* #return array
*/
public function getStockUpdates($accountId, $lastSync)
{
// Anticipate errors
try
{
// Init
$stockUpdates = [];
// Query channel advisor
$stockUpdateResults = self::curlGET($accountId, '/v1/Products?$filter=QuantityUpdateDateUtc gt '. $lastSync);
// TODO: parse $stockUpdateResults into $stockUpdates
// Success
return $this->successResponse($stockUpdateResults);
}
catch (\Exception $ex)
{
// Error response
return $this->errorResponse('Failed to load stock updates - '. $ex->getMessage());
}
}
/**
* Generic method to output error responses.
*
* #param string $message
* #return array
*/
private function errorResponse($message = '')
{
// Error
return [
'IsError' => true,
'ErrorMsg' => $message,
'Data' => ''
];
}
/**
* Generic method to output success responses.
*
* #param $data
* #return array
*/
private function successResponse($data)
{
// Success
return [
'IsError' => false,
'ErrorMsg' => '',
'Data' => $data
];
}
/**
* Method to get access token from rest server.
*
* #param $accountId
* #return string
* #throws \Exception
*/
private function getAccessToken($accountId)
{
// Define cache key
$cache_key = 'CA_REST_ACCESS_TOKEN.'. $accountId;
// Check if there is a cached version of access token
if (\Cache::has($cache_key))
return \Cache::get($cache_key);
// Anticipate errors
try
{
// Call rest api server
$response = self::curlPOST('/oauth2/token', [
'client_id' => $this->config['api_app_id'],
'grant_type' => 'soap',
'scope' => 'inventory',
'developer_key' => $this->config['api_developer_key'],
'password' => $this->config['api_password'],
'account_id' => $accountId
]);
// Check if there was an error
if (isset($response->Message))
throw new \Exception($response->Message);
if (isset($response->error))
throw new \Exception($response->error);
// Check if there was an invalid response
if (!isset($response->access_token) || !isset($response->expires_in))
throw new \Exception('Invalid response - '. json_encode($response));
// Cache server response
\Cache::add($cache_key, $response->access_token, floor($response->expires_in / 60));
// Success
return $response->access_token;
}
catch (\Exception $ex)
{
// Rethrow error
throw new \Exception('Failed to load rest api access token - '. $ex->getMessage());
}
}
/**
* Method to generate a HTTP POST request
*
* #param $endpoint
* #param array $fields
* #return string
* #throws \Exception
*/
private function curlPOST($endpoint, $fields = array())
{
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_USERPWD, $this->config['api_app_id'] .':'. $this->config['api_shared_secret']);
curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $endpoint);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded'
));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Execute post request
$result = curl_exec($ch);
// Debug error
if ($result === FALSE) {
$curlError = 'Error #'. curl_errno($ch) .':'. htmlspecialchars(curl_error($ch));
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
$curlError .= "\r\nDebug Info: ". htmlspecialchars($verboseLog);
curl_close($ch);
throw new \Exception($curlError);
}
#fclose($verbose);
// Close connection
curl_close($ch);
// Finished
return json_decode($result);
}
/**
* Method to generate HTTP GET request
*
* #param $accountId
* #param $queryString
* #return string
* #throws \Exception
*/
private function curlGET($accountId, $queryString)
{
// Open connection
$ch = curl_init();
// Set the url, query string & access token
curl_setopt($ch, CURLOPT_URL, self::BASE_URL . $queryString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '. self::getAccessToken($accountId)
));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Execute post request
$result = curl_exec($ch);
// TESTING
var_dump($result); exit;
// TESTING
// Debug error
if ($result === FALSE) {
$curlError = 'Error #'. curl_errno($ch) .':'. htmlspecialchars(curl_error($ch));
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
$curlError .= "\r\nDebug Info: ". htmlspecialchars($verboseLog);
curl_close($ch);
throw new \Exception($curlError);
}
#fclose($verbose);
// Close connection
curl_close($ch);
// Finished
return json_decode($result);
}
}
The above is a façade class, so I use it like this:
echo '<pre>';
print_r(ChannelAdvisorREST::getStockUpdates
(
'xxx-xxx-xxx', // accountId
'2016-01-18T11:50:03.000Z' // lastSync utc date & time
));
echo '</pre>';
Any idea why it works in Postman REST Client, but fails in my PHP? I thought I am doing the exact same steps. I tried urlencode the query string also; but that did not work either.
I have solved it (for now) like this and it's working correctly for me. Let me know if there's a better/proper way to do this.
/**
* Method to generate HTTP GET request
*
* #param $accountId
* #param $queryString
* #return string
* #throws \Exception
*/
private function curlGET($accountId, $queryString)
{
// Open connection
$ch = curl_init();
// Set the url, query string & access token
curl_setopt($ch, CURLOPT_URL, self::BASE_URL . self::formatUri($queryString));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '. self::getAccessToken($accountId)
));
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
// Execute post request
$result = curl_exec($ch);
// Debug error
if ($result === FALSE) {
$curlError = 'Error #'. curl_errno($ch) .':'. htmlspecialchars(curl_error($ch));
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
$curlError .= "\r\nDebug Info: ". htmlspecialchars($verboseLog);
curl_close($ch);
throw new \Exception($curlError);
}
#fclose($verbose);
// Close connection
curl_close($ch);
// Finished
return json_decode($result);
}
/**
* Method to format query string
*
* #param $queryString
* #return string
*/
private function formatUri($queryString)
{
return str_replace(
['$', ' '],
['%24', '%20'],
$queryString
);
}
I'm trying create a PHP class to send Push Notification. When I try send push doesn't works an throws an exception of syntax error and I can't find this error. I'm using PHP 5.3.28.
How could I solve it ?
Pusher
<?php
class Pusher{
const GOOGLE_GCM_URL = 'https://android.googleapis.com/gcm/send';
private $apiKey;
private $proxy;
private $output;
public function __construct($apiKey, $proxy = null)
{
$this->apiKey = $apiKey;
$this->proxy = $proxy;
}
/**
* #param string|array $regIds
* #param string $data
* #throws \Exception
*/
public function notify($regIds, $data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, self::GOOGLE_GCM_URL);
if (!is_null($this->proxy)) {
curl_setopt($ch, CURLOPT_PROXY, $this->proxy);
}
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getHeaders());
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->getPostFields($regIds, $data));
$result = curl_exec($ch);
if ($result === false) {
throw new \Exception(curl_error($ch));
}
curl_close($ch);
$this->output = $result;
}
/**
* #return array
*/
public function getOutputAsArray()
{
return json_decode($this->output, true);
}
/**
* #return object
*/
public function getOutputAsObject()
{
return json_decode($this->output);
}
private function getHeaders(){
return [
'Authorization: key=' . $this->apiKey,
'Content-Type: application/json'
];
}
private function getPostFields($regIds, $data){
$fields = [
'registration_ids' => is_string($regIds) ? [$regIds] : $regIds,
'data' => is_string($data) ? ['message' => $data] : $data,
];
return json_encode($fields, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
}
}
Exception
Fatal Error
Error: syntax error, unexpected '['
File: /app/Plugin/Push/Pusher.php
Line: 60
At line 60 have
private function getHeaders(){
return [
'Authorization: key=' . $this->apiKey,
'Content-Type: application/json'
];
}
I wrote a really basic wrapper class for Highrise's API. It works perfectly for Reads (GET), and I'm just starting to test it for Creates (POST). As far as I can tell, these two requests (one on the command line, one via PHP's cURL library) are identical. Same XML, same options set....just one works, and the other doesn't.
Any help is appreciated. I posted this question to 37signals developer mailing list also, but stackoverflow is generally faster at spotting my dumb mistakes...
This is the error I get with PHP's cURL (makes me think Highrise is having a problem parsing the XML string):
<?xml version="1.0" encoding="UTF-8"?> <errors> <error>First name can't be blank</error> </errors>
This is what works on the command line:
curl -u 'my_api_key:X'
-H 'Content-type: application/xml'
-d '<?xml version="1.0" encoding="UTF-8"?> <person><first-name>Savos</first-name><last-name>Aren</last-name><title>Archmage</title><company-name>Winterhold College</company-name><contact-data><email-addresses/><phone-numbers><phone-number><number>555-555-5555</number><location>Home</location></phone-number><phone-number><number>555-555-5555</number><location>Work</location></phone-number><phone-number><number>555-555-5555</number><location>Mobile</location></phone-number></phone-numbers><addresses><address><city>Winterhold</city><country>Tamriel</country><state>Skyrim</state><street>Hall of the Elements, College of Winterhold</street><zip>99999</zip><location>Work</location></address></addresses></contact-data></person>'
https://myuserid.highrisehq.com/people.xml
Here's my wrapper class:
class HighriseAPICall {
protected $_timeout = 120;
protected $_url_prefix = 'https://';
protected $_url_suffix = '.highrisehq.com';
protected $_password = 'X';
protected $_userpwd;
protected $_url;
public function __construct($api_key, $username) {
$this->_userpwd= $api_key . ':' . $this->_password;
$this->_url = $this->_url_prefix . $username . $this->_url_suffix;
}
/**
* Make the specified API call.
* #param string $action one of the four HTTP verbs supported by Highrise
* #param string $resource_name the Highrise resource to be accessed
* #param string $xml a well-formed XML string for a Highrise create, update, or delete request
*
* $xml parameter should include any query parameters as suggested by Highrise API documentation
* eg, if you want to GET all People, pass in "/people.xml"
* and if you want to get People by search term where field=value,
* then pass in "/people/search.xml?criteria[field]=value"
*/
public function makeAPICall($action,$resource_name,$xml=null) {
/* initialize curl session and set defaults for new API call */
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->_url . $resource_name);
curl_setopt($curl, CURLOPT_USERPWD, $this->_userpwd);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->_timeout);
/* if xml was passed in, set header and postfields */
if (isset($xml)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: application/xml');
curl_setopt($curl, CURLOPT_POSTFIELDS, "$xml");
}
/* set action as custom request */
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $action);
/* get the string response from executing the curl session */
$result = curl_exec($curl);
curl_close($curl);
// return the response as a simpleXMLElement
try {
$result_simplexml = new SimpleXMLElement($result);
}
catch (Exception $e) {
throw new Exception("Highrise API Call Error: " . $e->getMessage() . ", Response: " . $result);
}
if (!is_object($result_simplexml)) {
throw new Exception("Highrise API Call Error: Could not parse XML, Response: " . $result);
}
return $result_simplexml;
}
}
?>
And the simple testpage I'm using:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<?php
require_once('HighriseAPICall.class.php');
$highrise_api_key = 'OBSCURED';
$highrise_username = 'OBSCURED';
$highrise_api = new HighriseAPICall($highrise_api_key, $highrise_username);
$person_xml ='<?xml version="1.0" encoding="UTF-8"?> <person><first-name>Savos</first-name><last-name>Aren</last-name><title>Archmage</title><company-name>Winterhold College</company-name><contact-data><email-addresses/><phone-numbers><phone-number><number>555-555-5555</number><location>Home</location></phone-number><phone-number><number>555-555-5555</number><location>Work</location></phone-number><phone-number><number>555-555-5555</number><location>Mobile</location></phone-number></phone-numbers><addresses><address><city>Winterhold</city><country>Tamriel</country><state>Skyrim</state><street>Hall of the Elements, College of Winterhold</street><zip>99999</zip><location>Work</location></address></addresses></contact-data></person>';
$response = $highrise_api->makeAPICall('POST', '/people.xml', $person_xml);
echo htmlentities($response->asXML());
?>
</body>
</html>
try this lines instead of what you have in your script
if (isset($xml)) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/xml'));
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST ,false);
}
In my wrapper class, the line:
curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: application/xml');
should have been:
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/xml'));