tripit / api

TripIt's API Documentation and Support Forum
http://www.tripit.com/developer
Other
47 stars 16 forks source link

LodgingObject Is Rejecting ReservationObject attributes #233

Open tomjohn1028 opened 5 years ago

tomjohn1028 commented 5 years ago

I'm trying to create the following LodgingObject

<Request>
  <LodgingObject>
    <StartDateTime>
      <date>2019-12-15</date>
    </StartDateTime>
    <EndDateTime>
      <date>2019-12-17</date>
    </EndDateTime>
    <booking_date>2019-05-30</booking_date>
    <booking_rate>150</booking_rate>
    <total_cost>900</total_cost>
    <supplier_name>Hilton</supplier_name>
    <supplier_phone>(310) 410-4000</supplier_phone>
    <supplier_conf_num>123456789</supplier_conf_num>
    <is_purchased>true</is_purchased>
    <Address>
      <address>5711 W Century Blvd, Los Angeles, CA 90045</address>
    </Address>
    <Guest>
      <first_name>First</first_name>
      <middle_name>Middle</middle_name>
      <last_name>Last</last_name>
    </Guest>
    <number_guests>1</number_guests>
    <number_rooms>1</number_rooms>
    <room_type>Standard King</room_type>
  </LodgingObject>
</Request>

But I keep getting rejections from attributes in the ReservationObject type.

XML did not validate with the xsd: Element 'booking_date': This element is not expected. Expected is one of ( Address, Guest, number_guests, number_rooms, room_type, bic_code ).

It returns the same response for any attribute inherited from the ReservationObject. I'm referring to the following schema.

Any help or response is greatly appreciated!

lundbrianh commented 5 years ago

Hi, @tomjohn1028 Sorry you're having trouble with the API, but thanks for reaching out. This looks likes an ordering issue to me.

Because the schema defines these in a sequence, you must retain the ordering defined in the schema. The LodgingObject type extends the ReservationObject type, so all ReservationObject properties come first, followed by the LodgingObject properties.

For this request, try:

<Request>
    <LodgingObject>
        <booking_date>2019-05-30</booking_date>
        <booking_rate>150</booking_rate>
        <supplier_conf_num>123456789</supplier_conf_num>
        <supplier_name>Hilton</supplier_name>
        <supplier_phone>(310) 410-4000</supplier_phone>
        <is_purchased>true</is_purchased>
        <total_cost>900</total_cost>
        <StartDateTime>
            <date>2019-12-15</date>
        </StartDateTime>
        <EndDateTime>
            <date>2019-12-17</date>
        </EndDateTime>
        <Address>
            <address>5711 W Century Blvd, Los Angeles, CA 90045</address>
        </Address>
        <Guest>
            <first_name>First</first_name>
            <middle_name>Middle</middle_name>
            <last_name>Last</last_name>
        </Guest>
        <number_guests>1</number_guests>
        <number_rooms>1</number_rooms>
        <room_type>Standard King</room_type>
    </LodgingObject>
</Request>
tomjohn1028 commented 5 years ago

@lundbrianh that was it, works beautifully now, thank you!

One more question if you don't mind (now that I know the API works for my proof of concept):

I'd ideally like to the use a JSON format. Is the url https://api.tripit.com/v1/create/format/json or do you pass in a single POST body argument json that contains stringified json data? The documentation is little unclear on consuming the JSON API.

lundbrianh commented 5 years ago

It sounds like you understood the API correctly, but I'll try to clarify things.

Our API looks at a format request parameter to find/parse input and format output. This can be supplied either via the path, /v1/create/format/json, or in the query string, /v1/create?format=json. That parameter defaults to xml.

The value of format dictates in which parameter we look for the request content. If you change the format to json, then you also want to change the POST body from xml=[xml document] to json=[json document].

To merge the example from the docs with yours, a curl command might look like:

curl -k -D /dev/tty --data-urlencode json@lodging_object.json --user <username>:<password> https://api.tripit.com/v1/create?format=json

Where loging_object.json would look like:

{
    "LodgingObject": {
        "booking_date": "2019-05-30",
        "booking_rate": 150,
        "supplier_conf_num": 123456789,
        "supplier_name": "Hilton",
        "supplier_phone": "(310) 410-4000",
        "is_purchased": true,
        "total_cost": 900,
        "StartDateTime": {
            "date": "2019-12-15"
        },
        "EndDateTime": {
            "date": "2019-12-17"
        },
        "Address": {
            "address": "5711 W Century Blvd, Los Angeles, CA 90045"
        },
        "Guest": {
            "first_name": "First",
            "middle_name": "Middle",
            "last_name": "Last"
        },
        "number_guests": 1,
        "number_rooms": 1,
        "room_type": "Standard King"
    }
}
tomjohn1028 commented 5 years ago

@lundbrianh I'm working on the JSON implementation in Ruby but I keep getting the following error responses. It's either that and occasionally an "invalid signature".

<Response>
    <Error>
        <code>400</code>
        <description>Input cannot be null or an empty string.</description>
    </Error>
</Response>

I have tried sending the request in various formats as you can see from a couple snapshots of the traffic below. Sometimes if I change the request to use the parameters format=json I get an "Invalid Signature" (you can see the failed signatures on the left side of these screenshots).

I could be off base posting this here. My first thought was somehow the signing process was incorrect or the data was getting corrupted somewhere along the way. So I tried taking the OAuthCredential implementation from the TripIt ruby lib had the same issues. Then I rewrote my library using the OAuth gem and had the same issues.

Has your team noticed any issues like this? Or anything stand out that might indicate what I'm doing wrong?

Screen Shot 2019-06-14 at 5 58 10 PM

Screen Shot 2019-06-14 at 6 03 08 PM

lundbrianh commented 5 years ago

@tomjohn1028 I'm not familiar with this tool, so I think I need a little bit more context. I suspect that the invalid signature errors are closer to correct than the input cannot be null ones. The latter suggest that we cannot find the json request parameter at all. Whereas the former suggests that we found something, but it didn't match our expectations.

Can you ensure that the json document is getting properly encoded?

Notice in the curl example above, we're using the --data-urlencode. Perhaps the curl documentation on this might give some indication on how that translates to your tool:

   --data-urlencode <data>
          (HTTP) This posts data, similar to the other -d, --data options with the exception that this performs URL-encoding.

          To be CGI-compliant, the <data> part should begin with a name followed by a separator and a content specification. The <data> part can be passed to curl using one of the following syntaxes:

           ... omitted for brevity ...

          name@filename
                 This will make curl load data from the given file (including any newlines), URL-encode that data and pass it on in the POST. The name part  gets  an  equal  sign  appended,  resulting  in
                 name=urlencoded-file-content. Note that the name is expected to be URL-encoded already.