Perl Sample Step 2:
Booking an Air Reservation

This sample uses response data from the air availability request in Sample 1 to book an air reservation. Booking calls can be made through either the Reservation Builder eBL or a combination of transactions in the XML Select Web Service. In this example, the booking call is made through a call to the Reservation Builder eBL, using the  minimum data required to book an air reservation.

  1. Create a proxy of the XML Select Web Service, using a WSDL for your region or service level. For example:
    https://americas.copy-webservices.travelport.com/B2BGateway/service/ReservationBuilder?WSDL
    .

  1. Create ReservationBuilder controller, which formats an XML template, retrieves the required data from the AirAvailability_6_5 response, and sets the parameters for the request, including a Booking Profile. The following code also contains proxy server credentials that are included with the request to bypass the firewall.

Notes:

Declares the BWSController class, which manages the Reservation Builder eBL request.

package Controllers::ReservationBuilder;

   

   

   

use SOAP::Lite +trace => 'debug';

   

use XML::Simple;

   

   

Creates and sets up the credentials for Reservation Builder eBL. The user name and password are assigned by Galileo.

Note
: Credentials are only required for one file in a module.  However, the credentials are included in each sample Controller so that they can function as stand-alone samples.

our $USER_NAME = "UserName";

our $PASSWORD  = "Password";

   

   

Creates and sets up the credentials for the Reservation Builder eBL. User name and password are assigned by Galileo.

sub SOAP::Transport::HTTP::Client::get_basic_credentials {

   

return $USER_NAME => $PASSWORD;

   

}

   

 

The constructor for Reservation Builder eBL.

sub new {

   

my $type = shift;

   

my $self = {};

Defines the Host Access Profile, which is required to access Galileo Web Services.

$self->{HAP} = "HostAccessProfile";

Declares and initializes variables for the required namespaces and Web Service URLs.

Note: The trailing slash (/) is required. The on_action handler should join the method name to the namespace without adding another slash.

$self->{NAMESPACE} = 'http://webservices.galileo.com/ReservationBuilder/';

$self->{ENDPOINT} = 'https://americas.copy-webservices.travelport.com/Booking/Booking.asmx';

   

return bless $self, $type;

   

}

   

   

Builds an XML Document using booking information from a valid Air Availability response.

sub BuildRequest

{

my $self = shift;

my $xmlAirAvail = shift;

 

 

Parses the Air Availability response and retrieves the first flight segment from a valid air availability response.

my $xs = new XML::Simple();

my $availRef = $xs->XMLin($xmlAirAvail);

my $allSegments = $availRef->{'soap:Body'}->{SubmitXmlResponse}->{SubmitXmlResult}->{AirAvailability_6_2}->{AirAvail}->{AvailFlt};

my $firstSegment = $allSegments->[0];

 

 

Gets the departure and arrival dates and times.

my @departDate;

$departDate[0] = substr($firstSegment->{StartDt}, 0 ,4);

$departDate[1] = substr($firstSegment->{StartDt}, 4, 2);

$departDate[2] = substr($firstSegment->{StartDt}, 6, 2);

$departDate[3] = substr($firstSegment->{StartTm}, 0, 2);

$departDate[4] = substr($firstSegment->{StartTm}, 2, 2);

my @arriveDate;

$arriveDate[0] = substr($firstSegment->{StartDt}, 0 ,4);

$arriveDate[1] = substr($firstSegment->{StartDt}, 4, 2);

$arriveDate[2] = 0 + substr($firstSegment->
{StartDt}, 6, 2) + $firstSegment->{DayChg};

$arriveDate[3] = substr($firstSegment->{EndTm}, 0, 2);

$arriveDate[4] = substr($firstSegment->{EndTm}, 2, 2);

 

 

Gets the flight number.

my $flightNum =  $firstSegment->{FltNum};

Gets the departure airport.

my $departAirport = $firstSegment->{StartAirp};

Gets the destination airport.

my $arriveAirport = $firstSegment->{EndAirp};

Gets the airline vendor.

my $airline = $firstSegment->{AirV};

 

 

Gets tomorrow's date, then sets the Arrange Ticketing Date to the next day (TAU). The TAU typically defaults to Queue 10.

my $today = {day => (localtime)[3], month => ('JAN','FEB','MAR','APR','MAY','JUN','JUL',
'AUG','SEP','OCT','NOV','DEC')[(localtime)[4]]};

my $ticketString = "TAU/" . sprintf("%02d%s", $today->{day}, $today->{month});

 

 

Makes a Minimal Trip request to the Reservation Builder eBL. See the Minimal Trip Sample for detailed parameters.

my $req = "";

$req .= '<GWS_Trip';

The namespace of the schemas. ota: fields are defined by the Open Travel Alliance. The namespace is defined in the WSDL, whether ns.galileo.com or webservices.galileo.com

$req .= "    xmlns='http://ns.galileo.com' xmlns:ota='http://www.opentravel.org/OTA'";

If PaymentAuthorize is FALSE, credit card authorization is not required.

$req .= "    ReceivedFrom='GWSSample' Ticketing='" . $ticketString . "' PaymentAuthorize='false'>\r\n";

Begins the travel request.

$req .= "    <InventoryItems>\r\n";

Begins the flight request.

$req .= "        <Flight>\r\n";

Begins the flight segment request.

$req .= "            <FlightSegment ";

The departure date.

$req .= "DepartureDateTime='" . sprintf("%4d-%02d-%02dT%02d:%02d:%02d-00:00",@departDate)."' ";

The arrival date.

$req .= "ArrivalDateTime='" . sprintf("%4d-%02d-%02dT%02d:%02d:%02d-00:00",@arriveDate)."' ";

The flight number.

$req .= "FlightNumber='" . $flightNum . "' ";

 

$req .= ">\r\n";

The departure city.

$req .= "                <ota:DepartureAirport LocationCode='" . $departAirport . "' />\r\n";

The arrival city.

$req .= "                <ota:ArrivalAirport
LocationCode='" . $arriveAirport . "' />\r\n";

The vendor code for the airline.

$req .= "                <ota:MarketingAirline Code='" . $airline . "' />\r\n";

The booking class.
If the booking class is Requested, the Status element is required.

$req .= "                <BookingClass>\r\n";

$req .= "                    <Requested Status=
'NN-Need Need' ResBookDesigCode='Y' />\r\n";

$req .= "                </BookingClass>\r\n";

Ends the flight segment request.

$req .= "            </FlightSegment>\r\n";

Ends the flight request.

$req .= "        </Flight>\r\n";

Ends the Reservation Builder eBL request.

$req .= "    </InventoryItems>\r\n";

 

$req .= "</GWS_Trip>\r\n";

 

return $req;

 

}

 

 

Creates a Booking Profile, which is required to book a segment. See the Profiles without TravelScreen sample.

sub BuildProfile

{

 

my $self = shift;

 

 

 

my $profile = "";

The namespace of the schemas.

$profile .= "<GWS_BookingProfile xmlns='http://ns.galileo.com' xmlns:ota='http://www.opentravel.org/OTA' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://ns.galileo.com' >\r\n";

Personal information of the primary traveler.

$profile .= "    <Primary Gender='Female'
BirthDate='1970-10-14' CurrencyCode='USD' PassengerIdentificationCode=''
TicketingIdentificationCode=''
xmlns='http://ns.galileo.com' xmlns:ota='http://www.opentravel.org/OTA' xmlns:xsi='http://www.w3.org/2001/
XMLSchema-instance'>\r\n";

Primary traveler's name.

$profile .= "        <PersonName ShareSynchInd='Yes' ShareMarketInd='Yes' NameType='Former'>\r\n";

$profile .= "            <ota:NamePrefix>MS</ota:NamePrefix>\r\n";

$profile .= "            <ota:GivenName>PAM</ota:GivenName>\r\n";

$profile .= "            <ota:Surname>TEST</ota:Surname>\r\n";

$profile .= "        </PersonName>\r\n";

Primary traveler's contact information.

The CityAbbr field is a reference-only field for travel agents that is required by the CRS.

$profile .= "        <Telephone ShareSynchInd='Yes' ShareMarketInd='Yes' PhoneLocationType='Home' PhoneTechType='VOICE' CountryAccessCode='000' AreaCityCode='303' PhoneNumber='1234561' Extension='0' PIN='String' FormattedInd='false' CityAbbr='DEN'/>\r\n";

Primary traveler's address. Both the <Address> and <DeliveryAddress> elements are required, even if they are the same address.

Unneeded fields (e.g., ShareSynchInd, ShareMarketInd, FormattedInd) may be omitted.

$profile .= "        <Address FormattedInd='false' ShareSynchInd='Yes' ShareMarketInd='Yes' Type='Home' DefaultInd='false' UseType='Delivery'>\r\n";

$profile .= "            <ota:StreetNmbr PO_Box='String'>123</ota:StreetNmbr>\r\n";

$profile .= "            <ota:AddressLine>YELLOW BRICK ROAD</ota:AddressLine>\r\n";

$profile .= "            <ota:CityName>EMERALD CITY</ota:CityName>\r\n";

$profile .= "            <ota:PostalCode>80111</ota:PostalCode>\r\n";

$profile .= "            <ota:County>DOUGLAS</ota:County>\r\n";

$profile .= "            <ota:StateProv StateCode='CO'>COLORADO</ota:StateProv>\r\n";

$profile .= "            <ota:CountryName
Code='US'>UNITED STATES OF AMERICA
</ota:CountryName>\r\n";

$profile .= "        </Address>\r\n";

Credit card information that can be used to pay for travel.  

If the itinerary has at least one segment (air, car, or hotel), then your profile must have at least one form of payment.

For more information, see Form of Payment.

$profile .= "        <FormOfPayment RPH='01'>\r\n";

$profile .= "            <ota:PaymentCard
ShareSynchInd='Yes' ShareMarketInd='Yes'
CardType='Credit' CardCode='AX' CardNumber='300000000000000' SeriesCode='0' EffectiveDate='0101'
ExpireDate='1005'>\r\n";

$profile .= "                <ota:CardHolderName>PAM TEST</ota:CardHolderName>\r\n";

$profile .= "                <ota:CardIssuerName BankId='String'/>\r\n";

$profile .= "                <ota:Address FormattedInd='false' ShareSynchInd='Yes'
ShareMarketInd='Yes' Type='Home'>\r\n";

$profile .= "                    <ota:StreetNmbr PO_Box='String'>123</ota:StreetNmbr>\r\n";

$profile .= "                    <ota:AddressLine>
YELLOW BRICK ROAD</ota:AddressLine>\r\n";

$profile .= "                    <ota:CityName>
EMERALD CITY</ota:CityName>\r\n";

$profile .= "                    <ota:PostalCode>80111</ota:PostalCode>\r\n";

$profile .= "                    <ota:County>DOUGLAS</ota:County>\r\n";

$profile .= "                    <ota:StateProv StateCode='CO'>COLORADO</ota:StateProv>\r\n";

$profile .= "                    <ota:CountryName Code='US'>UNITED STATES OF AMERICA
</ota:CountryName>\r\n";

$profile .= "                </ota:Address>\r\n";

$profile .= "            </ota:PaymentCard>\r\n";

$profile .= "        </FormOfPayment>\r\n";

Ends the primary traveler information.

$profile .= "    </Primary>\r\n";

Ends the profile.

$profile .= "</GWS_BookingProfile>\r\n";

 

return $profile;

 

}

 

 

The Reservation Builder eBL request.

sub doBooking

 

{

 

my $self = shift;

 

 

Wraps the input parameters with the appropriate parameter names. SOAP::Lite does support this function for complex types, such as XML.

my $trip = '<xmlTrip>'.(shift).'</xmlTrip>';

travelerProfile is the Booking Profile.

my $travelerProfile = '<xmlTravelerProfile>'.(shift).'</xmlTravelerProfile>';

 

 

Saves the filter and request to the object.

$self->{trip} = $trip;

 

$self->{travelerProfile} = $travelerProfile;

 

 

Instantiates the BWS Soap::Lite object.

my $webService = SOAP::Lite

Sets the URL of the Soap Proxy.

-> uri($self->{NAMESPACE})

By default, Soap::Lite uses the pound sign (#) to concatenate URLs. Replace the pound sign with a slash (/).

-> on_action(sub{sprintf '%s%s', @_ })

The default response is a hash value because the return type, xmlelement, is complex. Setting outputxml() to TRUE creates an XML response.

-> outputxml("1")

Sets the proxy endpoint to Reservation Builder eBL.

-> proxy($self->{ENDPOINT});

 

 

Assigns the return value of the Reservation Builder eBL object's call to the BookTrip method.

my $response = $webService

Sets the namespace for the BookTrip method parameters.

->call(SOAP::Data->name("BookTrip")->attr({xmlns =>
$self->{NAMESPACE}}),

A Host Access Profile is required to access Galileo Web Services.

SOAP::Data->name(AccessProfile => $self->{HAP})->type('string'),

Boolean value indicating whether or not to ignore warnings. If set to true, any items that are booked prior to the warning are saved. If set to false, any items that are booked prior to the warning are canceled.

Note: '0' or '1' should be used instead of 'TRUE' or 'FALSE', which will be processed as a literal text string.

SOAP::Data->name(ForcePNRBFWarnings => 0)->type('boolean'),

The Booking Profile for the traveler.

SOAP::Data->name(xmlTravelerProfile => $travelerProfile)->type('xml'),

 

SOAP::Data->name(xmlTrip => $trip)->type('xml'));

 

 

Saves the response to the object.

$self->{response} = $response;

 

return $response;

 

}

 

  1. The Apollo or Galileo CRS returns the following minimum data in a booking response.

Reservation Builder eBL response.

<Response Time="Wednesday, 25 September 2002 21:07:05" ServiceBuildVersion="1.0.39.0" xmlns="http://ns.galileo.com">

Information Context text fields are returned for each booked segment.

<Information Context="Selling Air">

Air segments include text responses with the departure and arrival times and locations, vendor messages, and agency-related prompts, such as offering additional travel services.

<Text>        CARRY ON CRITICAL FLIGHT *</Text>

<Text>                         ARRIVES ORD TERMINAL 1</Text>

<Text>DEN/0343CT/DPTS 1135A       OT       *</Text>

<Text>ORD/0343CT/ARVS  255P       OT       *</Text>

<Text>OFFER CAR/HOTEL    !CAL·     !CAQ·     !HOA·</Text>

 

</Information>

Information context for the stored fare quote includes rules for ticketing at the submitted fare.

<Information Context="Storing Farequote">

<Text>LAST DATE TO PURCHASE TICKET: 26SEP02</Text>

 

</Information>

The Success indicator contains the record locator for the PNR/BF.

<Success>LC97W0</Success>

 

</Response>

 

  1. In Sample 3, flight information is obtained from the air availability response in Sample 1.