So với phương thức GetTripOptions, phương thức GetBulkTripOptions
có những ưu điểm sau:
- Cho phép điền sẵn bộ nhớ đệm của Google một cách hiệu quả hơn bằng cách sử dụng ít yêu cầu hơn và bằng cách điều chỉnh tốt hơn với các API thượng nguồn của nhà khai thác mà các đối tác có thể sử dụng để tự thu thập dữ liệu.
- Giúp các đối tác có một nhóm chuyến đi được xác định trước dễ dàng cung cấp dữ liệu mà không cần kiểm tra hành trình chi tiết.
- Đối với những đối tác phức tạp hơn, vẫn cung cấp cho họ danh sách các hành trình đã biết để tối đa hoá việc so khớp quỹ phòng và hành trình của đối tác do công cụ định tuyến của Google tạo ra, nhờ đó cho thấy giá của đối tác trên nhiều hành trình nhất có thể.
- Cho phép tiếp nhận những hành trình mà Google chưa cung cấp, để có thể điều chỉnh công cụ định tuyến của Google cho phù hợp hơn với khoảng không quảng cáo của đối tác trong tương lai.
GetBulkTripOptionsRequest
Định nghĩa Proto
// Request sent to partners. message GetBulkTripOptionsRequest { // The MarketDates for which to return results. // Initially, only a single value will be supplied, representing one-way // trips. repeated MarketDate market_dates = 1; // List of itineraries matching market_dates that Google knows about and will // serve to end users. Partners should try to return results matching these // itineraries, as other itineraries will not be immediately useful other than // for analysis purposes. repeated ItineraryKey known_itineraries = 2; // If true, only the explicitly specified known_itineraries should be // returned. Not in use yet (always set to false). bool only_known_itineraries = 3; } message MarketDate { // ID of the stop where the traveler starts their journey. string origin_ticketing_stop_id = 1; // Stop ID of the ultimate journey destination of the traveler. string destination_ticketing_stop_id = 2; // Date of departure at the origin, in the timezone at the origin. .google.type.Date departure_date = 3; } // A full end-to-end journey for a traveler, including all vehicles used. message ItineraryKey { // All segments together should form a single trip for which a ticket can be // booked. repeated ext.travel.transport.partner.SegmentKey segment_keys = 1; }
Mẫu JSON
{ "market_dates": [ { "origin_ticketing_stop_id": "ZRH-1234", "destination_ticketing_stop_id": "WOL-2455", "departure_date": { "year": 2023, "month": 5, "day": 15 } } ], "known_itineraries": [ { "segment_keys": [ { "ticketing_trip_id": "123456", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "LUZ-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "988833", "from_ticketing_stop_time_id": "LUZ-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] }, { "segment_keys": [ { "ticketing_trip_id": "98765", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "ZUG-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "43210", "from_ticketing_stop_time_id": "ZUG-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] } ], "only_known_itineraries": false }
GetBulkTripOptionsResponse
Định nghĩa Proto
// Response received from partners. message GetBulkTripOptionsResponse { oneof response { BulkTripOptionsResult bulk_trip_options_result = 1; BulkTripOptionsError bulk_trip_options_error = 2; } } // A message representing a successful response. message BulkTripOptionsResult { // One response per entry in known_itineraries in the request, plus any // additional ones partners choose to return if only_known_itineraries is // false. repeated ItineraryResponse itinerary_responses = 1; } // A message for errors affecting the whole request. message BulkTripOptionsError { enum BulkTripOptionsErrorType { // An unexpected error happened during retrieval of this trip. // This indicates a bug that needs to be fixed by the partner. // This error is retriable. // Always returns HTTP 500 status code in response. INTERNAL_ERROR = 1; } BulkTripOptionsErrorType error_type = 1; // This is not user-visible and is for logging and debugging purposes only. string error_message = 2; } // A message container for an itinerary with a set of prices for that itinerary. message ItineraryResponse { // A single itinerary that this response relates to. ItineraryKey itinerary = 1; oneof response { // A set of prices for this itinerary. TripOptionSet trip_option_set = 2; // Error information about the retrieval of this itinerary. TripOptionsError trip_options_error = 3; } } // A container for multiple trip options. message TripOptionSet { // To reduce the amount of data transferred, segments.segment_key can be empty // inside these trip_options, since the segment_key is already present in // ItineraryResponse.itinerary.segment_keys. This requires the number of // segments in to each TripOption to match exactly the number of segments // inside ItineraryResponse.itinerary. We then assume that the n-th // trip_options.segments.segment_key matches the n-th itinerary.segment_key. repeated TripOption trip_options = 1; } // A travel option for users covering the whole end-to-end journey with the // partner. message TripOption { // A series of Segments that cover the whole trip option, one for each // SegmentKey in the request. repeated Segment segments = 1; // This is the lowest standard fare of all seats with the specified segments. // This field is optional if the series of segments is unavailable. // This "standard fare" should be the lowest seat price where no age or other // booking restrictions apply. The currency should be the local currency of // the origin of the first segment. Fare lowest_standard_fare = 2; // The availability status for bookings of this trip option at the // lowest_standard_fare. Availability availability = 3; // This is used to receive optional extra data via the Travel Transport API // and pass it into the ticketing deep link. // Booking links should still work without the booking token, but the token // can be used to ensure price consistency between Google Search results and // the partner booking page. string booking_token = 4 [features.field_presence = EXPLICIT]; } // A segment traveled on a single vehicle in a given Service Class. message Segment { SegmentKey segment_key = 1; // The service class used on this segment. ServiceClass service_class = 2; }
Mẫu JSON
{ "bulk_trip_options_result": { "itinerary_responses": [ { "itinerary": { "segment_keys": [ { "ticketing_trip_id": "123456", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "LUZ-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "988833", "from_ticketing_stop_time_id": "LUZ-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] }, "trip_option_set": { "trip_options": [ { "segments": [ { "service_class": { "type": "SECOND_CLASS" } }, { "service_class": { "type": "SECOND_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 10, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 9, "nanos": 750000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 0, "nanos": 250000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 44, "total_seat_count": 200 } } }, { "segments": [ { "service_class": { "type": "FIRST_CLASS" } }, { "service_class": { "type": "FIRST_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 15, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 13, "nanos": 950000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 1, "nanos": 50000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 10, "total_seat_count": 100 } } } ] } }, { "itinerary": { "segment_keys": [ { "ticketing_trip_id": "98765", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "ZUG-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "43210", "from_ticketing_stop_time_id": "ZUG-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] }, "trip_option_set": { "trip_options": [ { "segments": [ { "service_class": { "type": "SECOND_CLASS" } }, { "service_class": { "type": "SECOND_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 9, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 8, "nanos": 750000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 0, "nanos": 250000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 30, "total_seat_count": 150 } } }, { "segments": [ { "service_class": { "type": "FIRST_CLASS" } }, { "service_class": { "type": "FIRST_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 14, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 12, "nanos": 950000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 1, "nanos": 50000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 15, "total_seat_count": 60 } } } ] } } ] } }
Mẫu lỗi JSON
{ "bulk_trip_options_error": { "error_type": "INTERNAL_ERROR", "error_message": "Unexpected RoutingException during trip lookup." } }
Lỗi một phần JSON
{ "bulk_trip_options_result": { "itinerary_responses": [ { "itinerary": { "segment_keys": [ { "ticketing_trip_id": "123456", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "LUZ-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 25, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "988833", "from_ticketing_stop_time_id": "LUZ-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] }, "trip_option_set": { "trip_options": [ { "segments": [ { "service_class": { "type": "SECOND_CLASS" } }, { "service_class": { "type": "SECOND_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 10, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 9, "nanos": 750000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 0, "nanos": 250000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 44, "total_seat_count": 200 } } }, { "segments": [ { "service_class": { "type": "FIRST_CLASS" } }, { "service_class": { "type": "FIRST_CLASS" } } ], "lowest_standard_fare": { "total_amount": { "units": 15, "nanos": 0, "currency_code": "CHF" }, "line_items": [ { "line_item_type": "BASE_FARE", "amount": { "units": 13, "nanos": 950000000, "currency_code": "CHF" } }, { "line_item_type": "SERVICE_CHARGE", "amount": { "units": 1, "nanos": 50000000, "currency_code": "CHF" } } ] }, "availability": { "available": { "available_seat_count": 10, "total_seat_count": 100 } } } ] } }, { "itinerary": { "segment_keys": [ { "ticketing_trip_id": "98765", "from_ticketing_stop_time_id": "ZRH-1234", "to_ticketing_stop_time_id": "ZUG-1235", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 14, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 16, "minutes": 30, "seconds": 0, "nanos": 0, "utc_offset": "0s" } }, { "ticketing_trip_id": "43210", "from_ticketing_stop_time_id": "ZUG-1235", "to_ticketing_stop_time_id": "WOL-2455", "service_date": { "year": 2023, "month": 5, "day": 15 }, "boarding_time": { "year": 2023, "month": 5, "day": 15, "hours": 18, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" }, "arrival_time": { "year": 2023, "month": 5, "day": 15, "hours": 20, "minutes": 13, "seconds": 0, "nanos": 0, "utc_offset": "0s" } } ] }, "trip_options_error": { "error_type": "SEGMENT_KEY_NOT_FOUND", "error_message": "No matching segments found, no departures at 14:30" } } ] } }
Các trường hợp điển hình
Chúng tôi hình dung ra các trường hợp sau đây với các hình dạng yêu cầu cụ thể cho API:
Đối với những đối tác ít am hiểu về kỹ thuật, bạn chỉ cần cung cấp một
market_date
. Các đối tác này có thể sử dụng truy vấn dựa trênmarket_date
cho dữ liệu nguồn của họ và trả về tất cả kết quả được liên kết với định dạng dữ liệu của chúng tôi. Google có thể lọc kết quả để chỉ hiển thị những hành trình dự kiến.Đối với những đối tác có trình độ kỹ thuật cao hơn, hãy cung cấp cả
market_date
vàknown_itineraries
. Đối tác có thể tra cứu chi tiết trong cơ sở dữ liệu nội bộ để có thể định giá chính xác các hành trình dự kiến. Tất cảknown_itineraries
được yêu cầu sẽ xuất hiện với người dùng, vì vậy, đối tác có thể tối đa hoá số lượng hành trình hiển thị giá và đường liên kết đặt phòng. Các đối tác vẫn có thể trả về các hành trình bổ sung để giúp Google so khớp tốt hơn khoảng không quảng cáo của riêng họ (được quảng bá).
Error reporting
Bạn nên báo cáo lỗi cho từng chuyến đi riêng lẻ. Do đó, phản hồi ưu tiên là BulkTripOptionsResult
(HTTP 200), cho biết lỗi theo chuyến đi trong bulk_trip_options_result.itinerary_responses[i].trip_options_error
. Nếu toàn bộ yêu cầu không thành công một cách bất ngờ, hãy sử dụng bulk_trip_options_error
với BulkTripOptionsErrorType.INTERNAL_ERROR
(HTTP 500).
Để biết thêm thông tin, hãy xem TripOptionsErrorType
Để biết thông tin về mã trạng thái được trả về trong phản hồi HTTP, hãy tham khảo phần Mã trạng thái và xử lý lỗi.
Nhận xét
MarketDate.departure_date
chỉ định một ngày trên lịch. Để so khớp tốt hơn các API của nhà mạng, thao tác này sẽ sử dụng múi giờ tại nơi xuất phát. Tuy nhiên, SegmentKey sẽ tiếp tục chỉ định thời gian lên máy bay và thời gian đến bằng giờ UTC để nhất quán với GetTripOptions
.