I’ve been on contract for the past couple of months at a lovely company up in Newmarket, called Solutions360. I’m part of a team working on a system for the travel industry. So we’re deep into API’s for hotels, flights, cruises and such. Listing, booking, cancelling have been our constant concerns for weeks now.
My bailiwick is a module called a Service Manager, which translates requests from our system to an outside web service. Then captures the responses and again translates them into a standard format for the system to display.
The first Service Manager I wrote used the cURL
library to communicate with the external service. So when it came time to interface with the Sabre services I tried using the same mechanism; but for some reason it was a non-starter. I tweaked it as much as I could; as much as it made sense to. But the only response I got was an error that the service “couldn’t internalize the request.” *sigh*
And while Sabre’s support team has proven to be enormously helpful and responsive, on the phone and via email, if it isn’t Java or .Net, you’re pretty much on your own.
Then I turned to the Interwebs for help, and that’s where I found Moazzam Khan’s blog post PHP and Sabre. In it Moazzam gives us a class which eschews cURL
in favour of a low-level approach using fsockopen()
, and the ssl://
scheme. Brilliant. And more importantly, it works.
I’ve tweaked the routine a bit, and present it here complete with an invocation for SessionCreateRQ. All you need to add are your credentials.
<?php $serverProperties = array ( 'SERVER' => 'sws-crt.cert.sabre.com' ,'USERNAME' => '*USERNAME*' ,'PASSWORD' => '*PASSWORD*' ,'PCC' => '*PCC*' ); // == Process Request $oDate = new DateTime(); $timestamp = $oDate->format('Y-m-d\Th:i:sP'); $timetolive = $oDate->add(new DateInterval('PT1H'))->format('Y-m-d\Th:i:sP'); $xml = <<<SESSIONCREATEXML <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"> <soapenv:Header> <MessageHeader xmlns="https://www.ebxml.org/namespaces/messageHeader"> <From> <PartyId type="urn:x12.org:IO5:01">Sabre WS Example</PartyId> </From> <To> <PartyId type="urn:x12.org:IO5:01">Sabre</PartyId> </To> <CPAId>{$serverProperties['PCC']}</CPAId> <ConversationId>MyConversationID</ConversationId> <Service type="string">Cruise</Service> <Action>SessionCreateRQ</Action> <MessageData> <MessageId>1000</MessageId> <Timestamp>{$timestamp}</Timestamp> <TimeToLive>{$timetolive}</TimeToLive> </MessageData> </MessageHeader> <Security xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext"> <UsernameToken> <Username>{$serverProperties['USERNAME']}</Username> <Password>{$serverProperties['PASSWORD']}</Password> <Organization>{$serverProperties['PCC']}</Organization> <Domain>DEFAULT</Domain> </UsernameToken> </Security> </soapenv:Header> <soapenv:Body> <SessionCreateRQ xmlns="https://www.opentravel.org/OTA/2002/11"> <POS> <Source PseudoCityCode="{$serverProperties['PCC']}" /> </POS> </SessionCreateRQ> </soapenv:Body> </soapenv:Envelope> SESSIONCREATEXML; // == Submit Request $xmlResponse = callSabre($xml); echo '<pre>'; echo $xmlResponse; echo '</pre>'; function callSabre($xml) { $oSabre = new Sabre(); $oSabre->host = $serverProperties['SERVER']; $content = $oSabre->makeRequest($xml); return $content; } /** * Sabre class (for connecting to Sabre web services) * @author Moazzam Khan <moazzam at moazzam-khan dot com> * @version $Id$ * @source https://moazzam-khan.com/blog/?p=495 */ class Sabre { public $host; public $port = 443; public $timeout = 30; public function makeRequest($body) { $header = "POST /websvc HTTP/1.1 Host: {$this->host}:{$this->port} Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Content-Type: text/xml Content-Length: ".strlen($body)." Pragma: no-cache Cache-Control: no-cache"; $fp = fsockopen("ssl://".$this->host, $this->port, $errno, $errstr, $this->timeout); if(!$fp){ throw new Exception("SOCKET ERROR ({$errno}): {$errstr}\n"); } else { //send the request $req = $header."\r\n\r\n".$body; fputs($fp, $req, strlen($req)); stream_set_timeout($fp, $this->timeout); stream_set_blocking($fp, 1); while (!feof($fp)) { $line = fread($fp, 2048); // if (trim(strlen($line)) < 10) continue; $output .= $line; } fclose($fp); } // remove the HTTP response header $ret = explode("\r\n\r\n", $output); $ret = $ret[1]; // format XML so we can read it. $dom = new DOMDocument; $dom->preserveWhiteSpace = FALSE; $dom->loadXML($ret); $dom->formatOutput = TRUE; $ret = $dom->saveXml(); return $ret; } }
I hope you find this helpful.
Hi Alfred,
This looks nice. I am glad my blog post was helpful. What I also did (but did not publish) is create a session manager along with “Sabre” class. Session manager, checks for the right parameters, etc and instantiates a connection object (an instance of Sabre class).
I have fallen in love with dependency injection so I have been refactoring everything to use that. You should check it out too!
Yes, I’ve looked at Dependency Injection, but I haven’t yet seen the light on that one. From a testing perspective I see it makes it easier. When I jump into testing with both feet I expect it’ll make more sense to me.
Thanks for taking the time to look at my post.
Hi Alfred,
is it still working?
I’ve copied the same code and I’ve changed my credentials. And get some error.
As well:
unable to connect to ssl://:443 (No connection could be made because the target machine actively refused it. )
On the call Sabre->makeRequest( )
Can you help me?
I haven’t touched this API in many moons. From what you’ve posted however, it looks like ssl://:443 is amiss. Should be https://example.com. Just an avenue to investigate, perhaps.
Good luck.
Your problems with Sabre might be related to its convoluted development history:
https://en.wikipedia.org/wiki/Sabre_%28computer_system%29#History
https://en.wikipedia.org/wiki/SabreTalk
Ideally they would scrap Sabre and start again from scratch.
Peter, I disagree.
Just because a system has a convoluted history does not mean that it should be scrapped. Using that logic, banks would be redoing their Point of Sale and ATM systems every couple of years. There is no way any non IT company can afford to replace a systenm simply because it is old….
Good afternoon, thank you for your example, everything turned out. Many examples of how to find flights, book, etc. Ready to take part in the development examples, only direct.
is this for sabre web services 2.0
Sorry, Scott, it’s been so long, I don’t rightly remember. I’ve moved on since then.
Hi Moazzam Khan,
please help me,
i have create the PNR, nt now i want to issue the ticket on sabre webconnect, i try a lot but i still unsuccessfully, please mention me which payload send to sabre server, i using these webservice for issue ticket
DesignatePrinterLLS
PhaseIVAddInfoLLS for PQ
TravelItineraryReadLLS
AirTicketLLS
without payment
please help me some body.
Sorry KabirSafi, it’s been almost 2 years since I’ve played with this API. I don’t even think I have credentials to access it anymore. But perhaps someone else, more current with it, can. Also, have you looked at Sabre’s own site for developers? What about StackOverflow?
Best of luck.
Alfred Ayache,
please help me, i didn,t get any response from StackOverflow.
stay blessed
Ask to the developers mail of Sabre. They are also very help full.
@Alfred
I’m just started using sabre api. As a reference I’m using this codes of Alfred. Though sabre api is totally different now.
Thanks Alfred for this helpfull post.
Thanks for your note Nadim. I’m happy the post helped you. Good luck with your project.
are you create the session or not, if you not create the session then you first create the session, when create the session the close the session.
when you close the session then you get the security token which is most important in sabre api. then call RQ payload, through security token it’s get response to you.
1: createSession payload.
2: closeSession payload
3: you target payload (RQ)
xpert of sabre web service
kabir safi
Kabir , i think first we need to create session then in response it returns token and we have to store that token because for another request you need that token , at the end you close session.
can anybody tell me how can i create session and check flights availability using sabre web-service in java, please help me, i need urgent help related to use sabre web-services consumption and usage in java
Sana,
Did you get the solution…?
Now I need something similar that. Can I ask you the solution, please?
I am facing error for this code.
Hi guys
anybody can tell me how can i create my site in Python , Some Changes i required who can fix problem on my site. #Paid_Task
Hola no me funciono en php no se que puede estar saliendo mal.
Good afternoon,
Thanks for sharing this helpful information but i am facing error for this code.
Sorry, but I haven’t touched Sabre since I wrote this post. Best of luck with their API.