amabnl / amadeus-ws-client

PHP Amadeus SOAP Web Service client library
Apache License 2.0
183 stars 191 forks source link

How to get TST Number on ticketCreateTSTFromPricing? #196

Closed mhrahul closed 5 years ago

mhrahul commented 6 years ago

Dear @DerMika, I can retrieve PNR and successfully get controlNumber. But a bit confused about the TST_number, where to get it? Without it, I cant use the function ticketCreateTSTFromPricing to create tickets. Please need urgent help!

DerMika commented 6 years ago

You need a pricing to create a TST from. To create a pricing, call Fare_PricePNRwithBookingClass or an associated message (such as Fare_PricePNRwithLowestFare).

This message will return one or more possible pricings, which you then have to turn into a TST with Ticket_CreateTSTFromPricing.

You should probably read the "Amadeus WBS Implementation Guide - Internet Booking Engine with Master Pricer", which can be downloaded on the Amadeus Extranet. It shows you the entire flow needed to create an online booking engine.

mhrahul commented 6 years ago

@DerMika I have tried with Fare_PricePNRwithBookingClass where I passed the farebasis after createPNR. But it shows the below error! ` [status] => ERR [messages] => Array ( [0] => Amadeus\Client\Result\NotOk Object ( [code] => 1383 [text] => PNR NOT PRESENT [level] => )

    )`

Please need help!

DerMika commented 6 years ago

Either you're not using a Stateful session, or you're re-instantiating the client object between different messages.

For the first, see here

For the second: you can get the currently active session and restore that session when re-instantiating the client as explained here

mhrahul commented 6 years ago

ow my Stateful session was false. 'stateful' => false, //Enable stateful messages by default - can be changed at will to switch between stateless & stateful. 'logger' => null

Trying with enabling it.

mhrahul commented 6 years ago

well I have enabled 'sessionHandlerParams' => [ 'soapHeaderVersion' => Client::HEADER_V4, //This is the default value, can be omitted. 'wsdl' => 'amadusWSDL/1ASIWGHUKKK_PDT_20180327_045112.wsdl', //Points to the location of the WSDL file for your WSAP. Make sure the associated XSD's are also available. 'stateful' => true, //Enable stateful messages by default - can be changed at will to switch between stateless & stateful. 'logger' => null ], Still successfully $pnrRet = $this->retrivePNR($replayData); but error with $pricingResponse = $this->client->farePricePnrWithBookingClass( new FarePricePnrWithBookingClassOptions([ 'pricingsFareBasis' => [ new FareBasis([ 'fareBasisCode' => $farebasis, 'references' => [ new PaxSegRef([ 'reference' => 1, 'type' => PaxSegRef::TYPE_SEGMENT ]) ] ]) ] ]) ); need help :(

DerMika commented 6 years ago

Which error?

mhrahul commented 6 years ago

`Amadeus\Client\Result Object ( [status] => ERR [messages] => Array ( [0] => Amadeus\Client\Result\NotOk Object ( [code] => 1383 [text] => PNR NOT PRESENT [level] => )

    )`

same error as before.

DerMika commented 6 years ago

What happens between PNR_Reply and your calling of Fare_PricePNRWithBookingClass?

Is there a user interface in between? If so: when the request comes back to the server, are you re-initializing the previous session? See the second item on my response here

mhrahul commented 6 years ago

well, I am using two functions for each. `private function createPnrAPI($firstName, $lastName, $phoneNo, $companyName, $flightNo, $departDate, $departCity, $arrivalCity, $bookingClass) {

    $createPnrOptions = new PnrCreatePnrOptions([
        'receivedFrom' => 'unittest',
        'travellers' => [
            new Traveller([
                'number' => 1,
                'lastName' => $lastName,
                'firstName' => $firstName
                    ])
        ],
        'actionCode' => PnrCreatePnrOptions::ACTION_END_TRANSACT_RETRIEVE,
        'itineraries' => [
            new Itinerary([
                'origin' => $departCity,
                'destination' => $arrivalCity,
                'segments' => [
                    new Air([
                        'date' => \DateTime::createFromFormat('Y-m-d His', $departDate, new \DateTimeZone('UTC')),
                        'origin' => $departCity,
                        'destination' => $arrivalCity,
                        'flightNumber' => $flightNo,
                        'bookingClass' => $bookingClass,
                        'company' => $companyName
                            ])
                ]
                    ])
        ],
        'elements' => [
            new Ticketing([
                'ticketMode' => Ticketing::TICKETMODE_OK
                    ]),
            new Contact([
                'type' => Contact::TYPE_PHONE_GENERAL,
                'value' => $phoneNo,
                'references' => [
                    new Reference([
                        'type' => Reference::TYPE_PASSENGER_REQUEST,
                        'id' => 1
                            ])
                ]
                    ])
        ]
    ]);

    $createdPnr = $this->client->pnrCreatePnr($createPnrOptions);

    $json = json_encode($createdPnr);
    $array = json_decode($json, TRUE);

    $flights = $array['response'];

    return $flights;
}

private function retrivePNR($recordLoc) {
    $pnrResult = $this->client->pnrRetrieve(
            new PnrRetrieveOptions(['recordLocator' => $recordLoc])
    );

    $json = json_encode($pnrResult);
    $array = json_decode($json, TRUE);

    $flights = $array['response'];

    return $flights;
}`

& `public function fareForPNR(Request $request) { $farebasis = $request->input('farebasis');

    $pricingResponse = $this->client->farePricePnrWithBookingClass(
            new FarePricePnrWithBookingClassOptions([
        'pricingsFareBasis' => [
            new FareBasis([
                'fareBasisCode' => $farebasis,
                'references' => [
                    new PaxSegRef([
                        'reference' => 1,
                        'type' => PaxSegRef::TYPE_SEGMENT
                            ])                        
                ]
                    ])
        ]
            ])
    );

    print_r($pricingResponse);
}`

the PNR retrival response: { "pnrHeader": { "reservationInfo": { "reservation": { "companyId": "1A", "controlNumber": "KR2SJP", "date": "220518", "time": 1853 } } }, "securityInformation": { "responsibilityInformation": { "typeOfPnrElement": "RP", "agentId": "AASU", "officeId": "DACVS32LN", "iataCode": "42305734" },

DerMika commented 6 years ago

Again, what happens beween our call to createAPI and fareForPNR? They seem to be in a controller of some kind?

If these are separate HTTP requests to your backend, your code will probably re-instantiate the Amadeus\Client object between the 2 calls. If that happens, you have to make sure to restore the previous session.

This means: before returning return response()->json($pnrRet); in your first action, make sure to store the Amadeus\Client session data in a session variable or something similar. ANd then when re-instantiating the client later on, check if a session variable is set with Amadeus\Client session data and if so, restore the session data to the client with that information.

Still the same issue I mentioned above.

mhrahul commented 6 years ago

Understood the problem. After retrieving same session it provides me the following output: { "applicationError": { "errorOrWarningCodeDetails": { "errorDetails": { "errorCode": "0", "errorCategory": "EC", "errorCodeOwner": "1A" } }, "errorWarningDescription": { "freeText": "NO FARES/RBD/CARRIER/PASSENGER TYPE" } }, "pnrLocatorData": { "reservationInformation": { "controlNumber": "KRBZKH" } }, "fareList": { "pricingInformation": { "tstInformation": { "tstIndicator": "O" }, "fcmi": "W" }, "fareReference": { "referenceType": "TST", "uniqueReference": 1 }, "lastTktDate": { "businessSemantic": "LT", "dateTime": { "year": 2018, "month": "6", "day": "6" } }, "validatingCarrier": { "carrierInformation": { "carrierCode": "AI" } }, "paxSegReference": { "refDetails": { "refQualifier": "PA", "refNumber": 2 } }, "fareDataInformation": { "fareDataMainInformation": { "fareDataQualifier": "F" }, "fareDataSupInformation": [ { "fareDataQualifier": "B", "fareAmount": "25.00", "fareCurrency": "USD" }, { "fareDataQualifier": "E", "fareAmount": "2069", "fareCurrency": "BDT" }, { "fareDataQualifier": "712", "fareAmount": "6827", "fareCurrency": "BDT" } ] }, "taxInformation": [ { "taxDetails": { "taxQualifier": "7", "taxIdentification": { "taxIdentifier": "X" }, "taxType": { "isoCountry": "BD" }, "taxNature": "AE" }, "amountDetails": { "fareDataMainInformation": { "fareDataQualifier": "TAX", "fareAmount": "500", "fareCurrency": "BDT" } } },, can't understand where to find TST number form here!

mhrahul commented 6 years ago

@DerMika I am getting the same issue now that #118 had. And I got below error after use docIssuanceIssueTicket. { "processingStatus": { "statusCode": "O" }, "errorGroup": { "errorOrWarningCodeDetails": { "errorDetails": { "errorCode": "OK" } }, "errorWarningDescription": { "freeTextDetails": { "textSubjectQualifier": "3", "source": "M", "encoding": "1" }, "freeText": "OK ETICKET NO PRINTERS DEFINED IN OFFICE PROFILE PLEASE CALL HELP DESK" } } } Please need help on it.

DerMika commented 6 years ago

That error is not an error in your flow, it's just that no e-ticket printers have been defined on your office. I mean, the error message is pretty clear. You need to contact Amadeus Support to setup your office for printing tickets.

About the error in #118, i can only give you the same advice I gave in that issue: Contact Amadeus Support and have them investigate what's going wrong.

mhrahul commented 6 years ago

Thanks a lot. I am contacting them now for it. Will let you know their answer. :)

mhrahul commented 6 years ago

Hi @DerMika, as the Amadeus said for my last thread it was a server end problem.

Now I think, I have done the full process but didn't find the e-ticket number. I asked their support and their replay was, "Ticket item can be obtained by reading FA item for PNR.". I didn't find any FA item. Where can I find it?

DerMika commented 6 years ago

If you retrieve the PNR again after ticket issuance, you should find an FA element under the dataElementsMaster node. If not, something probably went wrong during ticket issuance. Or perhaps the airline only writes the FA element to the PNR with a certain delay? This is something to ask Amadeus.

bimusiek commented 6 years ago

After you issue the ticket, close the session, wait 10s and with session-less request retrieve PNR again. FA element should be there.

mhrahul commented 6 years ago

@bimusiek i have tried as you mentioned but it give me output: "dataElementsMaster": { "marker2": [], "dataElementsIndiv": [ { "elementManagementData": { "reference": { "qualifier": "OT", "number": 1 }, "segmentName": "AP", "lineNumber": 3 }, "otherDataFreetext": { "freetextDetail": { "subjectQualifier": "3", "type": "5" }, "longFreetext": "8801922527441" } }, { "elementManagementData": { "reference": { "qualifier": "OT", "number": 3 }, "segmentName": "TK", "lineNumber": 4 }, "ticketElement": { "passengerType": "PAX", "ticket": { "indicator": "OK", "date": "260518", "officeId": "DACVS32LN" } } }, { "elementManagementData": { "reference": { "qualifier": "OT", "number": 9 }, "segmentName": "SSR", "lineNumber": 5 }, "serviceRequest": { "ssr": { "type": "OTHS", "status": " ", "companyId": "1A", "freeText": "AUTO XX IF SSR TKNA/E/M/C NOT RCVD BY BG BY 1242/26MAY/DAC LT" } } }, { "elementManagementData": { "reference": { "qualifier": "OT", "number": 4 }, "segmentName": "FE", "lineNumber": 6 }, "otherDataFreetext": { "freetextDetail": { "subjectQualifier": "3", "type": "10" }, "longFreetext": "PAX NONEND/NONREF- VALID ON BG ONLY" }, "referenceForDataElement": { "reference": [ { "qualifier": "ST", "number": "1" }, { "qualifier": "PT", "number": "2" } ] } }, { "elementManagementData": { "reference": { "qualifier": "OT", "number": 2 }, "segmentName": "FP", "lineNumber": 7 }, "otherDataFreetext": { "freetextDetail": { "subjectQualifier": "3", "type": "16" }, "longFreetext": "CASH" } }, { "elementManagementData": { "reference": { "qualifier": "OT", "number": 5 }, "segmentName": "FV", "lineNumber": 8 }, "otherDataFreetext": { "freetextDetail": { "subjectQualifier": "3", "type": "P18" }, "longFreetext": "PAX BG" }, "referenceForDataElement": { "reference": [ { "qualifier": "ST", "number": "1" }, { "qualifier": "PT", "number": "2" } ] } } ] }, is it for I am using a demo user? or am I missing something?

using $pnrResult = $this->client->pnrRetrieve( new PnrRetrieveOptions(['recordLocator' => $recordLoc]) ); for PNR retrive. Please guide.

bimusiek commented 6 years ago

If FA element is not there, that means you did not issue the ticket. Are you sure that ticket issuance was OK?

mhrahul commented 6 years ago

@bimusiek I have used below code for ticket booking. `$createTstResponse = $this->client->ticketCreateTSTFromPricing( new TicketCreateTstFromPricingOptions([ 'pricings' => [ new Pricing([ 'tstNumber' => 1, ])]])); $issueTicketResponse = $this->client->docIssuanceIssueTicket( new DocIssuanceIssueTicketOptions([ 'options' => [ DocIssuanceIssueTicketOptions::OPTION_ETICKET, DocIssuanceIssueTicketOptions::OPTION_RETRIEVE_PNR ]]));

    $pnrReply_end = $this->client->pnrAddMultiElements(
            new PnrAddMultiElementsOptions([
        'actionCode' => PnrAddMultiElementsOptions::ACTION_END_TRANSACT_RETRIEVE,
            ]));`

And the output for ticket_create is: { "processingStatus": { "statusCode": "W" }, "errorGroup": { "errorOrWarningCodeDetails": { "errorDetails": { "errorCode": "0" } }, "errorWarningDescription": { "freeTextDetails": { "textSubjectQualifier": "3", "source": "M", "encoding": "1" }, "freeText": "IT'S TIME TO BOOK TRAVEL INSURANCE" } } } What did I miss?

mhrahul commented 6 years ago

@DerMika after long struggle finally I have got some result. But sometimes it gives me "elementManagementData": { "reference": { "qualifier": "OT", "number": 10 }, "segmentName": "SSR", "lineNumber": 6 }, "serviceRequest": { "ssr": { "type": "OTHS", "status": " ", "companyId": "1A", "freeText": "AUTO XX IF SSR TKNA/E/M/C NOT RCVD BY BG BY 0517/29MAY/DAC LT" } } }, and sometimes { "elementManagementData": { "reference": { "qualifier": "OT", "number": 12 }, "segmentName": "FA", "lineNumber": 5 }, "otherDataFreetext": { "freetextDetail": { "subjectQualifier": "3", "type": "P06" }, "longFreetext": "PAX 098-5119491666/ETAI/BDT15433/28MAY18/DACVS32LN/42305734" }, "referenceForDataElement": { "reference": [ { "qualifier": "ST", "number": "1" }, { "qualifier": "PT", "number": "2" } ] } },

Please need help what is wrong here?

DerMika commented 6 years ago

The first seems to indicate the airline still requires extra information. You should contact Amadeus support to help you explain what is going on.

mhrahul commented 6 years ago

Thanks a lot. I already mailed to their support. One More thing to mention that I got the ticket I'd at local Host but when at live server it's missing. Using HostGator shared hosting.

DerMika commented 6 years ago

I cannot imagine 2 instances running the same code producing different results. Either you get an error from Amadeus or not. Of course each airline could have specific needs to issue tickets. Usually in a travel agency these messages are followed up by a travel agent with Amadeus knowledge...

mhrahul commented 6 years ago

Ya, I surprised too and it killed my day. But on local, it gave me FA item and in saver, FA was missing. Anyway, hope Amadeus has some good explanation on it.

mhrahul commented 6 years ago

sometime in the test environment problem occurred - it was the replay form Amadeus.

mhrahul commented 6 years ago

I have one last problem I think need help. My log serves: <ns1:PNR_AddMultiElements><ns1:pnrActions><ns1:optionCode>11</ns1:optionCode> But Amadeus recommend to save the changes with option code 10 rather than 11. How can I do it?

$pnrReply_end = $this->client->pnrAddMultiElements( new PnrAddMultiElementsOptions([ 'actionCode' => PnrAddMultiElementsOptions::ACTION_END_TRANSACT_RETRIEVE, ]) );

So far I am using it.

DerMika commented 6 years ago

Look in the source of the class PnrAddMultiElementsOptions, it contains the list of action code constants.

mhrahul commented 6 years ago

@DerMika Thanks a lot. Got it. :)

mhrahul commented 6 years ago

Hi @DerMika, I was using PnrAddMultiElementsOptions::ACTION_END_TRANSACT_RETRIEVE but as per Amadeus, they recommended using PnrAddMultiElementsOptions::ACTION_END_TRANSACT

(Amadeus recommend to save the changes with option code 10 rather than 11)

But with the returned controlNumber, I can't find any result. Its return blank on pnrRetrieve. How to fetch?

DerMika commented 6 years ago

I don't know why Amadeus recommends that, but an End Transact is a save without a re-retrieve. You'll get errors if the save went wrong, but you won't get the PNR contents back. For that you'd have to re-retrieve the PNR.

If you can't find the controlNumber you got back, something might have gone wrong during the save. Check with Amadeus.

mhrahul commented 6 years ago

Well, I have got the controllerNumber back. But with that number, I don't get anything on re-retrieve. I think I need to mail Amadeus on it.

mhrahul commented 6 years ago

Hello, @DerMika thanks for the continuous help. I am almost done with my integration as Amadeus has some wired issues to solve. Anyway, one last favor I need. I have got 2 SSR message.

  1. "ssr": { "type": "OTHS", "status": " ", "companyId": "1A", "freeText": "PLS ADD CUSTOMER CONTACT DETAILS" }
  2. "serviceRequest": { "ssr": { "type": "OTHS", "status": " ", "companyId": "1A", "freeText": "UPDATE DOCS DETAIL FOR ALL PAX WITH FULL NAME AS INPASSPORT" } } But I am providing all the customer details $servReq = new ServiceRequest(); $servReq->freeText[] = ['----' . $bd . '-' . $gen . '--' . $td['firstName'] . '-' . $td['lastName']]; $otp->travellers[] = new Traveller([ 'number' => 1, 'lastName' => $td['lastName'], 'firstName' => $td['firstName'], 'type' => Traveller::TRAV_TYPE_ADULT, 'dateOfBirth' => \DateTime::createFromFormat('Y-m-d', $td['dob']), ]);

SO do I missed anything?

DerMika commented 6 years ago

Sorry for the late answer, I've been busy.

Do you still need help with this?

It could be that the airline requires extra information, like a passport number, or a birth date in the SSR.

If it's an APIS format you are looking for, check the format mentioned here by @bimusiek

mhrahul commented 6 years ago

Thank @DerMika. Checking on it. But I stuck on very dump problem. I cant send multiple pricing for multiple passengers. It always sends 1 tst for tst pricing. If I going to send multiple like new TicketCreateTstFromPricingOptions([ 'pricings' => [ new Pricing([ 'tstNumber' => 1, ]), new Pricing([ 'tstNumber' => 2, ]) ]); it always send me one pricing for tickets. I also tried with new Pricing([ 'tstNumber' => [1,2], ]) for two adults but no luck!

DerMika commented 6 years ago

As far as I know, you can only create 1 TST at a time, since it depends on a pricing in context. But I may be wrong. To be sure... contact Amadeus ;)

DerMika commented 6 years ago

Hmm, seems like I'm wrong on that, the "Amadeus WBS Implementation Guide - Internet Booking Engine with Master Pricer" mentions multiple TST's:

<Ticket_CreateTSTFromPricing>
  <psaList>
    <itemReference>
      <referenceType>TST</referenceType>
      <uniqueReference>1</uniqueReference>
    </itemReference>
  </psaList>
  <psaList>
    <itemReference>
      <referenceType>TST</referenceType>
      <uniqueReference>2</uniqueReference>
    </itemReference>
  </psaList>
  <psaList>
    <itemReference>
      <referenceType>TST</referenceType>
      <uniqueReference>3</uniqueReference>
    </itemReference>
  </psaList>
</Ticket_CreateTSTFromPricing>

What XML structure does the library generate when you do new Pricing([ 'tstNumber' => [1,2], ])?

mhrahul commented 6 years ago

@DerMika so for 2 adults, 1 child and one infant what might be the structure? I have ued new Pricing([ 'tstNumber' => [1,2]]); new Pricing([ 'tstNumber' => [3]]); new Pricing([ 'tstNumber' => [4]]);

but it gives me an error in pricing. What will be the actual format in PHP?

DerMika commented 6 years ago

I just added a new testcase which should build the correct message, See the commit above. Can you try that?

mhrahul commented 6 years ago

using $createTstResponse = $this->client->ticketCreateTSTFromPricing( new TicketCreateTstFromPricingOptions([ 'pricings' => [ new Pricing([ 'tstNumber' => 1 ]) ] ]) );

if I use "$this->client->CreateTSTFromPricing" it shows error!

DerMika commented 6 years ago

You'll have to give me a bit more context. What error? Wat are you trying to achieve? What is the session context before the last call you made?

mhrahul commented 6 years ago

Actually, I am stuck on pricing problem. When I try to generate tickets for multiple passengers, it only sent the ticket price for one person. Review from Amadeus below.

  1. You are passing 2 ADT but we are getting only 1 ADT. Kindly check and fix. image
  2. TSTs have been not created image
DerMika commented 5 years ago

Closing issue because it's an old one without feedback. You can re-open if needed