setConfig($config); if (!isset($config["baseUrl"]) || empty($config["baseUrl"])) { throw new Exception("The API URL is not specified"); } $this->httpClient = new Client(['base_uri' => $config["baseUrl"]]); } public function setConfig($config) { global $savvyext; $this->config = $config; $this->agentId = $config["agentId"] ; $this->agentPassword = $config["agentPassword"]; $this->currency = $config["currency"]; $this->templatesDir = $config["templatesDir"]; $this->loadTemplates($config); } public function loadTemplates($config) { if ( !array_key_exists('templatesDir', $config) || empty($config["templatesDir"])) { throw new Exception("The templates dir is not specified"); } $files = scandir($this->templatesDir); if ($files) { foreach ($files as $templateFile) { $template = file_get_contents($this->templatesDir."/".$templateFile); if ($template) { $this->templates[$templateFile] = $template; } } } if (count($this->templates) == 0) { throw new Exception("Any one template is not initialized"); } } public function getTemplate($name, $oldRootTag=NULL, $newRootTag=NULL) { if (!isset($this->templates[$name])) { return false; } $template = $this->templates[$name]; if (isset($oldRootTag) && isset($newRootTag)) { $template = str_replace($oldRootTag, $newRootTag, $template); } $xmlElement = new SimpleXMLElement($template); $xmlElement->Agent->attributes()->Id = $this->config["agentId"]; $xmlElement->Agent->Password = $this->config["agentPassword"]; return $xmlElement; } public function getHeaders($extraHeaders = []) { $headers = [ 'content-type' => 'text/xml', ]; return array_merge($headers,$extraHeaders); } public function getAvailability($source, $destination) { if (!isset($this->templates['autocab_agent_bid_request.xml'])) { throw new Exception("Bid request template is not initialized"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_bid_request.xml'); $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->BidParameters->Journey->From->Data = $source["address"]; $xmlElement->BidParameters->Journey->From->Coordinate->Latitude = $source["latitude"]; $xmlElement->BidParameters->Journey->From->Coordinate->Longitude = $source["longitude"]; $xmlElement->BidParameters->Journey->To->Data = $destination["address"]; $xmlElement->BidParameters->Journey->To->Coordinate->Latitude = $destination["latitude"]; $xmlElement->BidParameters->Journey->To->Coordinate->Longitude = $destination["longitude"]; $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error, "request"=>$xmlElement]; } $costs = []; foreach ($xmlResponse->Offers->Offer as $offer) { $item = self::processBidOffer($offer); array_push($costs, $item); } return array("error"=>0, "data"=>$costs, "raw_data"=>$xmlResponse, "request"=>$xmlElement); } public function getBookingAvailability($source, $destination, $vendor) { if (!isset($this->templates['autocab_agent_booking_availability_request.xml'])) { throw new Exception("Booking Availability request template is not initialized"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_booking_availability_request.xml'); $xmlElement->Vendor->attributes()->Id = $vendor; $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->BookingParameters->Journey->From->Data = $source["address"] ?? "No Address"; $xmlElement->BookingParameters->Journey->From->Coordinate->Latitude = $source["latitude"]; $xmlElement->BookingParameters->Journey->From->Coordinate->Longitude = $source["longitude"]; $xmlElement->BookingParameters->Journey->To->Data = $destination["address"] ?? "No Address"; $xmlElement->BookingParameters->Journey->To->Coordinate->Latitude = $destination["latitude"]; $xmlElement->BookingParameters->Journey->To->Coordinate->Longitude = $destination["longitude"]; $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error, "request"=>$xmlElement]; } $cost = null; if(isset($xmlResponse->Pricing)) { $cost = [ 'currency' => (string)$xmlResponse->Pricing->Currency, 'availability_ref' => (string)$xmlResponse->AvailabilityReference, 'display_name' => (string)$xmlResponse->VendorDetails->Name, 'high_estimate' => (int)$xmlResponse->Pricing->Price, 'low_estimate' => (int)$xmlResponse->Pricing->Price, 'distance_estimate' => (int) $xmlResponse->EstimatedJourney->Distance, 'duration_estimate' => (int) $xmlResponse->EstimatedJourney->Duration * 60, 'vendor_id' => (string) $xmlResponse->Vendor->attributes()->Id, ]; } return ["error"=>0, "data"=>$cost, "raw_data"=>$xmlResponse, "request"=>$xmlElement]; } public function cancelAvailability($availabilityRef, $vendor, $reason = self::REASON_NOT_REQUIRED) { if (!isset($this->templates['autocab_agent_booking_not_authorized_request.xml'])) { throw new Exception("BookingNotAuthorizedRequest template is not initialized"); } if (!isset($availabilityRef)) { throw new Exception("Invalid availability reference"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_booking_not_authorized_request.xml'); $xmlElement->Vendor->attributes()->Id = $vendor; $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->AvailabilityReference = $availabilityRef; $xmlElement->Reason = $reason; $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error, "request"=>$xmlElement]; } return ["error"=>0, "data"=>[], "raw_data"=>$xmlResponse, "request"=>$xmlElement]; } public function booking($availabilityRef, $passengers=[], $vendor) { if (!isset($this->templates['autocab_agent_booking_athorization_request.xml'])) { throw new Exception("BookingAuthorization template is not initialized"); } if (!isset($availabilityRef)) { throw new Exception("Invalid availability reference"); } if (!is_array($passengers) || count($passengers) < 1 || !array_key_exists("name", $passengers[0]) || empty($passengers[0]["name"]) ) { throw new Exception("Invalid passengers information"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_booking_athorization_request.xml'); $xmlElement->Vendor->attributes()->Id = $vendor; $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->AvailabilityReference = $availabilityRef; foreach ($passengers as $key => $passenger) { $xmlPassenger = $xmlElement->Passengers->addChild("PassengerDetails"); $isLead = ($key === array_keys($passengers)[0]) ? "true" : "false"; $xmlPassenger->addAttribute("IsLead", "$isLead"); $xmlPassenger->addChild("Name", $passenger["name"]); if (array_key_exists("phone", $passenger) && isset($passenger["phone"])) { $xmlPassenger->addChild( "TelephoneNumber", $passenger["phone"] ); } if (array_key_exists("email", $passenger) && isset($passenger["email"])) { $xmlPassenger->addChild("EmailAddress", $passenger["email"]); } } $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error]; } $resp = []; if(isset($xmlResponse->AuthorizationReference)) { $resp = [ 'authorization_ref' => (string)$xmlResponse->AuthorizationReference, 'booking_ref' => (string)$xmlResponse->BookingReference, ]; } return ["error"=>0, "data"=>$resp, "raw_data"=>$xmlResponse, "request"=>$xmlElement]; } public function bookingStatus($authorizationRef, $vendor) { if (!isset($this->templates['autocab_agent_booking_status_request.xml'])) { throw new Exception("BookingStatusRequest template is not initialized"); } if (!isset($authorizationRef)) { throw new Exception("Invalid authorization reference"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_booking_status_request.xml'); $xmlElement->Vendor->attributes()->Id = $vendor; $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->AuthorizationReference = $authorizationRef; $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error, "request"=>$xmlElement]; } $resp = [ 'booking_ref' => (string)$xmlResponse->BookingReference, 'status' => (string)$xmlResponse->Status, 'cancellation_reason' => (string)$xmlResponse->CancellationReason ]; return ["error"=>0, "data"=>$resp, "raw_data"=>$xmlResponse, "request"=>$xmlElement]; } public function bookingCancellation($authorizationRef, $vendor) { if (!isset($this->templates['autocab_agent_booking_cancellation_request.xml'])) { throw new Exception("BookingCancellationRequest template is not initialized"); } if (!isset($authorizationRef)) { throw new Exception("Invalid authorization reference"); } $uri = '/api/agent'; $xmlElement = $this->getTemplate('autocab_agent_booking_cancellation_request.xml'); $xmlElement->Vendor->attributes()->Id = $vendor; $xmlElement->Agent->Time = gmdate("Y-m-d\TH:i:s.v\Z"); $xmlElement->AuthorizationReference = $authorizationRef; $xml = $xmlElement->asXML(); $result = $this->genericPost($uri, $xml); if ($result["error"]) { return $result; } if ($result["code"] != 200) { var_dump($result["data"]); } $xmlResponse = new SimpleXMLElement($result["data"]); $error = self::processError($xmlResponse); if($error) { return ["error"=>1, "data" => $error, "code" => 500, "request"=>$xmlElement]; } $resp = []; return ["error"=>0, "data"=>$resp, "code" => 200, "raw_data"=>$xmlResponse, "request"=>$xmlElement]; } private function genericPost($uri, $xml, $extraHeaders=[]) { $code = 0; $data = []; $error = 0; try { $json = json_encode($data); $length = strlen($json); $response = $this->httpClient->request('POST', $uri, [ 'decode_content' => true, 'connect_timeout' => SELF::TIMEOUT, 'debug' => SELF::DEBUG, 'verify' => SELF::SSL_VERIFY, 'headers' => $this->getHeaders(), 'body' => $xml ]); $code = $response->getStatusCode(); $data = $response->getBody(); } catch (RequestException $e) { if (SELF::DEBUG) { echo Psr7\str($e->getRequest()); if ($e->hasResponse()) { echo Psr7\str($e->getResponse()); } } if ($e->hasResponse()) { $code = (int) $e->getResponse()->getStatusCode(); } $data = ["error" => "exception", "error_description" => $e->getMessage()]; $error = 1; } catch (ClientException $e) { if (SELF::DEBUG) { echo Psr7\str($e->getRequest()); echo Psr7\str($e->getResponse()); } $code = (int)$e->getResponse()->getStatusCode(); $data = ["error" => "exception", "error_description" => $e->getMessage()]; $error = 1; } catch (Exception $e) { if (SELF::DEBUG) { echo Psr7\str($e->getRequest()); echo Psr7\str($e->getResponse()); } $code = (int)$e->getResponse()->getStatusCode(); $data = ["error" => "exception", "error_description" => $e->getMessage()]; $error = 1; } return ["error" => $error, "data" => $data, "code" => $code]; } public static function processError($xmlResponse) { if ((string)$xmlResponse->Result->Success == "true") { return false; } return ["error"=>"API error", "error_description" => (string) $xmlResponse->Result->FailureReason, "error_code" => (string) $xmlResponse->Result->FailureCode]; } public static function processBidOffer($offer) { $item = [ 'currency' => (string)$offer->Pricing->Currency, 'transport_product' => (string)$offer['Reference'], 'display_name' => (string)$offer->VendorDetails->Name, 'high_estimate' => (int)$offer->Pricing->Price, 'low_estimate' => (int)$offer->Pricing->Price, 'distance_estimate' => (int) $offer->EstimatedJourney->Distance, 'duration_estimate' => (int) $offer->EstimatedJourney->Duration * 60, ]; return $item; } }