国际酒店标准接口开发文档-V2.1.0
本文档说明主要涵盖如下几点
- 在线预订流程
- HTTP接口说明
- 重点注意事项
- FAQ
1 开始
1.1 开发步骤
- 代理商联系Qunar销售或者运营,说明接入意向,获取open开发平台的用户名和密码。
- 参考平台上标准开发文档,进行开发,可以使用此开发平台的自测工具进行测试。
- 请按照文档下方case进行测试,保证测试case正常运行。
- case测试通过后,使用待上线正式数据在open平台进行最后一次测试,准备上线。
- 联系Qunar销售客服,上线一个酒店,Qunar协助代理商在线上测试完整业务流程;并安排培训上线后续事宜。
1.2 重要说明
- 所有的API接口,
Content-Type
只能为文本类型,如Content-Type="text/xml"
。请解压缩gzip
文件。 - 所有的API接口,
charset
只能为UTF-8
。 - 所有的API接口,请不要忘记xml声明
<?xml version="1.0" encoding="utf-8"?>
。 - 所有的API接口,在传输特殊字符(如:
&、<、>、‘、“
)时,请对特殊字符进行转义。
1.3 预订过程
接入去哪儿的代理商需先了解去哪儿网搜索预订逻辑,以便更好的理解接口文档,建议下载"去哪儿旅行"APP,以更好的了解预订过程及方便后续的线上验证。
因设备及版本不同,以下示例图片仅供参考。
预订过程
酒店搜索页–>酒店列表页–>酒店详情页–>酒店订单页->支付以及订单确认等操作
Hotel Search –> Hotel List –> Hotel Detail –>Hotel Booking->Pay/Order Confirm ..
1) 酒店搜索页(Search页)
打开“去哪儿旅行”APP,点击海外酒店频道,进入【酒店搜索页】;
指定入参:目的地、入离日期、成人/儿童数、关键字。点击 开始搜索,进入【酒店列表页】。
2) 酒店列表页(List页)
指定入参:入离日期、成人/儿童数、关键字,点击【确定】,可以刷新酒店报价列表。
数据来源:Qunar本地缓存或实时抓取;代理商可以在Quanr配置缓存时间,若不配置,系统默认时间为6小时;当刷新报价时,若代理商报价未过期则使用缓存报价,若报价过期则实时抓取指定入离日期、成人/儿童数的报价;代理商可通过缩短缓存时间或配置实时抓取来降低变价率,具体配置方式,请与Quanr销售或运营沟通;
选中酒店,进入【酒店详情页】。
3) 酒店详情页(Detail页)
酒店信息:展示Qunar维护的酒店图片、房型图片、酒店亮点、介绍、设施、酒店政策、交通和周边、点评信息等信息。
Qunar房型-代理商房型:一个Qunar房型对应多个代理商房型报价。
点击预订按钮,可进入【订单填写页】。
指定入参:入住日期、离店日期、成人/儿童数。变更参数,点击 确定,可以刷新酒店报价数据。
数据来源:Qunar本地缓存或实时抓取;代理商可以在Quanr配置缓存时间,若不配置,系统默认时间为6小时;当刷新报价时,若代理商报价未过期则使用缓存报价,若报价过期则实时抓取指定入离日期、成人/儿童数的报价;代理商可通过缩短缓存时间或配置实时抓取来降低变价率,具体配置方式,请与Quanr销售或运营沟通;
4) 订单填写页(Booking页)
指定入参:酒店、房型、入离日期、成人/儿童数、房间数。
消费者在此页面可变更间数,不可变更酒店、房型、入离日期、成人/儿童数。
数据来源:此页面报价均为实时获取,Detail页→Booking页的过程称为进订,若出现变价或超时可能导致进订失败;
点击提交订单按钮,进入支付页面;
特别说明:
响应时间超长(10s超时),则会预订失败,这将严重影响用户体验。
5) 订单操作(Pay/Order Confirm)
在消费者支付之后,Qunar会向代理商一侧发起下单请求。
消费者取消订单时,Qunar会向代理商一侧发起取消请求。
2 数据接口
国际酒店标准接口基础数据主要包含两部分:酒店基础数据(代理商提供)和报价接口数据(代理商提供)。
2.1 酒店基础数据(代理商提供)
Qunar通过调用此接口,获得代理商的酒店列表。
数据用途:用于代理商和Qunar的酒店信息映射,实现代理商酒店和Qunar酒店的聚合。
更新方式:全量,不支持增量,不支持分页。
更新时间:每天凌晨自动更新。亦可以通过人工处理。
更新限制:酒店一次性减少3/4,或者减少超过1000家,只能通过人工处理。
如果不能完成酒店聚合,请参照www.qunar.com上对应的酒店名称、酒店地址,并更正【酒店基础数据】接口提供的酒店名称、酒店地址,以实现聚合。
2.1.1 request
HTTP URL:https://base_url
HTTP Param:无要求
HTTP Method:GET
URL由代理商提供,在Qunar端进行配置。
base_url由代理商提供,代理商可以附加参数,用于识别请求来源。
示例
https://test.hotel.com?source=Qunar
https://test.hotel.com
两者都可以。
以下接口中涉及的base_url,均可参照此解释。
2.1.2 response
<?xml version="1.0" encoding="utf-8"?> <list>
<hotel id="58283" tel="82-2-771-0500" address="87, Sogong-dong, Jung-gu, Seoul, Korea (100-070) (106, Sogong-ro, Jung-gu, Seoul)" name="The Westin Chosun Seoul" nameCN="首尔威斯汀朝鲜酒店" city="seoul" coordinateProvider="1" longitude="139.44468" latitude="35.54667" hotelRelationships="ctrip:123, expedia:8888, booking:3333"></hotel>
<hotel id="58284" tel="82-2-7711000" address="30, Eulji-ro, Jung-gu, Seoul(EX.1, Sogong-dong, Jung-gu, Seoul, Korea)" name="LOTTE HOTEL SEOUL" nameCN="首尔乐天饭店" city="seoul" coordinateProvider="1" longitude="139.44468" latitude="35.54667" hotelRelationships="ctrip:123, expedia:8888, booking:3333"></hotel>
<hotel id="58285" tel="02-771-2200" address="119, Sogong-ro, Jung-gu, Seoul" name="THE PLAZA HOTEL" nameCN="首尔广场傲途格精选酒店" city="seoul" coordinateProvider="1" longitude="139.44468" latitude="35.54667" hotelRelationships="ctrip:123, expedia:8888, booking:3333"></hotel>
<hotel id="58286" tel="82-2-2233-3131" address="249, Dongho-ro, Jung-gu, Seoul" name="THE SHILLA SEOUL" nameCN="首尔新罗酒店" city="seoul" coordinateProvider="1" longitude="139.44468" latitude="35.54667" hotelRelationships="ctrip:123, expedia:8888, booking:3333"></hotel>
<hotel id="58287" tel="82-2-3216-5656" address="353, Yeonhui-ro, Seodaemun-gu, Seoul" name="GRAND HILTON SEOUL HOTEL" nameCN="首尔希尔顿大酒店" city="seoul" coordinateProvider="1" longitude="139.44468" latitude="35.54667" hotelRelationships="ctrip:123, expedia:8888, booking:3333"></hotel> ... </list>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
hotel@id | 酒店ID | String | 必选 | 否 | 代理商酒店的唯一标识。 字符长度[1,16]。 对同一个酒店而言,酒店ID不能动态变化。 |
hotel@name | 酒店名称(英文) | String | 必选 | 否 | 字符长度[1,100]。 请使用英文名称。 国际酒店此项为必填项,且仅能输入英文; |
hotel@nameCN | 酒店名称(中文) | String | 可选 | 是 | 字符长度[1,100]。 请使用中文名称。 输入此项可提高聚合准确率,请尽量填写; 此项为选填项,港澳台酒店若无英文名称可输入中文名称; |
hotel@address | 酒店地址 | String | 必选 | 否 | 字符长度[1,150]。 请使用英文或中文。 |
hotel@coordinateProvider | 坐标提供者 | Integer | 必选 | 否 | 1-Google,2-Baidu |
hotel@longitude | 经度 | String | 必选 | 否 | 酒店经度 |
hotel@latitude | 纬度 | String | 必选 | 否 | 酒店纬度 |
hotel@tel | 联系电话 | String | 必选 | 是 | 最大50字符。 输入此项可提高聚合准确率,请尽量填写; |
hotel@hotelRelationships | 关联供应商酒店Id | String | 可选 | 是 | 输入此项可提高聚合准确率,请尽量填写; 供应商key:ctrip, agoda, booking, expedia, hotelbeds, elong ctrip:xxxx, expedia:xxxx, booking:xxx |
2.2 报价接口数据-单酒店
Qunar通过调用此接口,获得指定酒店的报价信息,报价信息包括房型基本属性、房价、房态、房量等。
发生时间:
Search页→List页、List页→Detail页、Detail页→Booking页、Booking页→Pay/Order Confirm
请求区别:
1)无roomId参数:Search页→List页、List页→Detail页;
2)有roomId参数:Detail页→Booking页、Booking页→Pay/Order Confirm;
3)成人/儿童参数:若报价请求无成人/儿童参数(默认配置),请返回所有人数的可用报价;如无法返回全量报价,请通过您的商务经理联系Qunar端进行配置,改为按用户真实人数请求配置,此策略会按照用户真实请求抓取报价
2.2.1 request
HTTP URL:https://base_url?xml=xxx
HTTP Param:xml
HTTP Method:GET
说明: base_url由代理商提供,Qunar端进行配置。代理商可以附加参数,用于识别请求来源。
base_url示例:
https://test.hotel.com?source=Qunar
https://test.hotel.com
完整示例:
https://test.hotel.com?source=Qunar&xml=xxx
https://test.hotel.com?xml=xxx
参数xml示例:
<?xml version="1.0" encoding="utf-8"?> <priceRequest> <hotelId>16166</hotelId> <checkin>2019-09-13</checkin> <checkout>2019-09-14</checkout> <roomId>199</roomId><!-- only appears at order filling page --> <numberOfRooms>2</numberOfRooms> <customerInfos> <customerInfo seq="0" numberOfAdults="2" numberOfChildren="2" childrenAges="8|12" > </customerInfo> <customerInfo seq="1" numberOfAdults="2" numberOfChildren="0" childrenAges="" > </customerInfo> </customerInfos> </priceRequest> urlDecode编码之后的参数示例(参数已编码,请先解码再解析) "https://hotel-s.oneworldtrip.cn/qunar/shkqrj03p3/api/hotel/search?xml=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22+standalone%3D%22yes%22%3F%3E%0A%3CpriceRequest%3E%0A++++%3ChotelId%3E10P410000206%3C%2FhotelId%3E%0A++++%3Ccheckin%3E2022-03-18%3C%2Fcheckin%3E%0A++++%3Ccheckout%3E2022-03-19%3C%2Fcheckout%3E%0A++++%3CnumberOfRooms%3E1%3C%2FnumberOfRooms%3E%0A++++%3CcrawlSource%3Eremote%3C%2FcrawlSource%3E%0A%3C%2FpriceRequest%3E%0A"
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
hotelId | 酒店ID | String | 必选 | 否 | 代理商酒店的唯一标识,来源于【酒店基础数据(代理商提供)】 |
checkin | 入住日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 例如: 2019-09-13 |
checkout | 离店日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 例如: 2019-09-13 |
roomId | 房型id | String | 可选 | 否 | 来源于酒店报价room节点。 |
numberOfRooms | 房间数 | Integer | 可选 | 否 | 等于customerInfos的子节点数目 (特别说明:初次进入订单填写页的请求,默认1,无customerInfos节点)。 |
customerInfo@ seq |
序列号 | Integer | 可选 | 否 | customerInfo的id,从0开始。 若无成人儿童数请返回所有可用报价; |
customerInfo@ numberOfAdults |
成人数 | Integer | 可选 | 否 | 此值上限为代理商返回的最大入住人数。 |
customerInfo@ numberOfChildren |
儿童数 | Integer | 可选 | 否 | 此值上限为代理商返回的最大入住人数。 |
customerInfo@ childrenAges |
儿童年龄 | Integer | 可选 | 否 | 以|分隔的数字组合。 例如4|7意味着两个儿童的年龄分别为4岁和7岁。 |
extras | 其他 | String | 可选 | 否 | 如进订check环节需要传入报价请求参数,请于wrapper报价返回Extra节点数据,我司通过check请求该字段传入 |
2.2.2 response
<?xml version="1.0" encoding="utf-8"?> <priceResponse hotelId="9987" hotelName="Toyoko Inn Tokyo Machida-eki Odakyu-sen Higashi-guchi" hotelNameCN="东京东横町田站东口小田急森酒店" hotelAddress="1-3-3, Naka-machi, Machida-city, Tokyo" hotelPhone="0081-42-7281045" coordinateProvider="1" longitude="139.44468" latitude="35.54667" checkin="2019-09-13" checkout="2019-09-14" currencyCode="USD" > <rooms> <!-- one or more <room> --> <room id="P_1" physicRoomId=7572685 name="Double(breakfast)" nameCN="标准房(含早)"payType="PREPAY" prices="200|200" status="ACTIVE|DISABLED" counts="5|5" roomRate="180|180" taxAndFee="20|20" broadband="FREE" maxOccupancy="2" occupancyNumber="2" freeChildrenNumber="1" freeChildrenAgeLimit="8" instantConfirmRoomCount="3|3" wifi="FREE" window="1" checkinTime="12:00" checkoutTime="12:30" area="" guestType="ALL_GUEST" > <!-- constraint: for each day prices = roomRate + taxAndFee --> <bookingRule userProperty="101,102,103,111"ipLimitType="1" locationType="1" weeklyIndex="0000011" start="10"end="23"visible="true"ip="1" > <bookingTime maxAdvanceDays="8" minAdvanceDays="2" minAdvanceHours="6" last="2" maxLast="3" /> </bookingRule> <customerLimit regionLimit="1" regions="CHN,TWN"/> <bedType> <beds code="DOUBLE" desc="大床" count="1" size="1.8m*2m" > </beds> </bedType> <meal> <breakfast count="2|2" desc="日式早餐" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal> <refund returnable="true" timeZone="GMT+9" > <!-- timeZone --> <refundRules> <refundRule before="29" type="DEDUCT_BY_AMOUNT" value="50" /> <refundRule before="25" type="DEDUCT_BY_PERCENT" value="70" /> </refundRules> </refund> <remarks><!-- optional --> <remark seq="1" value="the weather will be rainy in July, please prepare rain gears by yourself"/> <remark seq="2" value="no pets allowed please"/> <remark seq="3" value="free parking, but cannot make sure available parking lots any time"/> </remarks> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> <taxes><!-- optional --> <tax id="51" type="IncludedInTotalPrice" amount="100|100" currency="CNY" /> </taxes> </room> </rooms> </priceResponse>
如果没有相应报价数据,请返回空节点<priceResponse/>
priceResponse
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
hotelId | 酒店ID | String | 必选 | 否 | 代理商酒店的唯一标识,不能重复,来源于酒店列表。请与priceRequest中的hotelId保持一致 |
hotelName | 酒店名称(英文) | String | 必选 | 否 | 请与【酒店基础数据(代理商提供)】的酒店名称(英文)保持一致 |
hotelNameCN | 酒店名称(中文) | String | 必选 | 否 | 请与【酒店基础数据(代理商提供)】的酒店名称(中文)保持一致 |
hotelAddress | 酒店地址 | String | 必选 | 否 | 请与【酒店基础数据(代理商提供)】的酒店地址保持一致 |
coordinateProvider | 坐标提供者 | Integer | 必选 | 否 | 1-Google,2-Baidu |
longitude | 经度 | String | 必选 | 否 | 酒店经度 |
latitude | 纬度 | String | 必选 | 否 | 酒店纬度 |
checkin | 入住日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 必须与请求一致 |
checkout | 离店日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 必须与请求一致 |
currencyCode | 币别 | String | 必选 | 否 | 房型报价的币别代码,当前支持的币别如下USD("美元"), EUR("欧元"), JPY("日元"), CNY("人民币"), HKD("港币"), MOP("澳门币"),TWD("台币"), KER("韩元"), SGD("新元"), THB("泰珠"), GBP("英镑"), AUD("澳大利亚元"), CAD("加元"),RUB("卢布"),并且必须与在Qunar后台配置的结算币别保持一致。 |
room
节点属性
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
id | 房型ID | String | 必选 | 否 | 1)当前酒店下的产品房型ID。 2)订单填写页的报价请求中的roomId来源于此。 3)最大长度为255个字符。 4)房型id唯一不能重复。 |
physicRoomId | 物理房型ID | Long | 可选 | 是 | 1)该字段需要传输代理商自己的物理房型id。 2)字段用于辅助房型聚合。 |
name | 房型名称(英文) | String | 必选 | 否 | 最大字符长度均为255,取值尽量与官网保持一致。 对于海外酒店,name为必选,不可为空,全为英文(含数字及英文符号)。 对于中国港澳台酒店,name或nameCN至少传一个,且不为空。 |
nameCN | 房型名称(中文) | String | 必选 | 否 | |
payType | 支付方式 | Enum | 必选 | 否 | PREPAY -预付 |
prices | 房型总价 | String | 必选 | 否 | 1)表示房型总价(单间夜)的总价,prices=roomRate+taxAndFee,由“|”分割数字。例如: checkin=2019-09-03, checkout = 2019-09-05 prices=“100|108” 表示: 2019-09-03至2019-09-04,单间夜价格为100 2019-09-04至2019-09-05单间夜价格为108 代理商需要返回的是每日每间(单间夜)的价格,如果请求多间而每间价格不一样,代理商需要计算平均值并将其返回给Qunar。 2)每天的报价可为0,但不能为空。100||110 是非法的,100 3)计算订单总价时,Qunar会将单间夜报价乘以间数。 |
status | 房型状态 | Enum | 必选 | 否 | 表示房型单天的可订状态,"ACTIVE"表示当前可订,"DISABLED"表示当前不可定,由“|”分隔; 例如:ACTIVE|DISABLED 表示第一天可住,第二天不可住 |
counts | 房间数 | String | 必选 | 否 | 表示剩余可住房型数量,由“|”分隔; 例如:3|5 表示第一天有3间房可住,第二天有5间房可住。 |
roomRate | 房型报价 | String | 必选 | 否 | 表示单间夜房间价格,格式参照prices; prices=roomRate+taxAndFee |
taxAndFee | 税费或服务费 | String | 必选 | 否 | 表示包含在总价中的单间夜税费或服务费,格式参照prices; prices=roomRate+taxAndFee |
broadband | 宽带 | Enum | 必选 | 否 | 参照枚举FeeMode,不确定填UNKNOWN |
wifi | 无线 | Enum | 必选 | 否 | 同broadband |
window | 窗 | Integer | 必选 | 否 | 1有窗 2无窗 3部分无窗 99未知 |
maxOccupancy | 最大可住人数 | Integer | 必选 | 否 | 表示物理房型最大可住人数。 |
occupancyNumber | 此报价可住人数 | Integer | 必选 | 否 | 1)表示此报价的可住人数,即同一个房间,1成人报价和2成人报价不同,需要在priceResponse节点maxOccupancy后添加occupancyNumber,字段值为该报价对应的人数; 示例:如该房间最大可入住2人,所给的报价是1人报价; maxOccupancy=“2”,occupancyNumber=“1” 订单填写页的上显示的报价可住人数则为可住1人。 2)订单填写页【成人数】的默认值显示规则: A、occupancyNumber 不为空,则显示occupancyNumber的取值 B、occupancyNumber为空:如果 maxOccupancy = 1 则 显示 1;否则,一律显示2。 3)若同一间房不同成人儿童数报价相同,请按请求的成人儿童总数赋值occupancyNumber; 4)occupancyNumber <= maxOccupancy; |
instantConfirmRoomCount | 即时确认 房间数 |
String | 必选 | 否 | 1)表示代理商可以立即确认的房间数,由“|”分隔; 示例: 若代理商回传counts=10|10,instantConfirmRoomCount= 5|5; 表示代理商每天都有10间的房间库存,其中每天可以立即确认的房间数量为5间; 此时Qunar通过【订单预订接口(代理商提供)】向代理商下单,只要代理商返回Success,则订单自动确认成功,代理商无需通过【订单操作接口(Qunar提供)】进行确认; 此case下,如果消费者预订6间房,则不属于即时确认的情形 2)请代理商自行维护即时确认房间数,Quanr不会维护此库存,用户进订时将调用实时报价获取最新库存; 3)非即时确认房,则 instantConfirmRoomCount = 0|0|...|0,代理商需通过【订单操作接口(Qunar提供)】进行确认。 |
checkinTime | 入住时间 | String | 可选 | 是 | 酒店的入住时间,在订单填写页显示,例如12:00 |
checkoutTime | 离店时间 | String | 可选 | 是 | 酒店的离店时间,在订单填写页显示,例如14:00 |
area | 房型面积 | String | 可选 | 是 | 房型面积,例如12,则为12平方米 有请尽量填写,否则用户有此类投诉时,有承担赔偿的风险 |
guestType | 宾客类型 | Enum | 必选 | 否 | 参照枚举GuestType |
taxes | 税费信息 | String | 可选 | 是 | 单条税费详细信息,包含税费id、类型、单间夜税费、币种 |
以下节点为room子节点,如<bookingRule>、<bedType>、<meal>、<refund>、<remarks>、<guaranteeRules>、<customerLimit>
。
bookingRule节点属性*(bookingRule
是room的可选节点)
限制报价展示条件。
<bookingRule userProperty="101,102,103" ip="1" > <bookingTime maxAdvanceDays="8" minAdvanceDays="2" minAdvanceHours="6" last="2" maxLast="3" /> </bookingRule>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
bookingRule@userProperty | 限制的用户身份 | String | 可选 | 否 | 多选,若不传则对所有用户可见,会员身份和交叉身份为且的关系 会员身份 101:普通会员(新用户) 189:白银会员 102:黄金会员 103:铂金会员 104:钻石会员 交叉身份 111:机票用户 107:火车票用户 109:汽车票用户 112:网约车用户 108:门票用户 120:度假用户 eg.若传189,102,111,107则代表对白银、黄金会员等级且是机票、火车票的用户可见 |
bookingRule@ipLimitType | IP与时间限制类型 | Enum | 可选 | 否 | 单选 0:不限制 1:本异地限制 与bookingRule@locationType、bookingRule@weeklyIndex、bookingRule@start、bookingRule@end、bookingRule@visible控制与酒店所在地本地/异地的用户IP在工作日/非工作日(几点到几点)是否可见 2:区域限制 与bookingRule@countryList、bookingRule@cityList、bookingRule@weeklyIndex、bookingRule@start、bookingRule@end、bookingRule@visible控制该酒店对指定的国家/城市在工作日/非工作日(几点到几点)是否可见 |
bookingRule@locationType | IP本异地限制维度 | Enum | 可选 | 否 | ipLimitType=1情况下必选 1:用户IP与酒店所在地同国家 2:用户IP与酒店所在地同城市 |
bookingRule@countryList | 用户所在的国家区域限制 | String | 可选 | 是 | ipLimitType=2情况下生效国家 eg.countryList="中国,日本" |
bookingRule@cityList | 用户所在的城市区域限制 | String | 可选 | 是 | ipLimitType=2情况下生效城市,如果countryList不为空且cityList不为空,以cityList为准 eg.cityList="i-macau,i-hong_kong" |
bookingRule@weeklyIndex | 生效日期 | String | 可选 | 否 | 工作日:"1111100",非工作日:"0000011" 说明:工作日为周一至周五,非工作日为周六、周日 |
bookingRule@start | 生效开始时间 | String | 可选 | 否 | 仅支持数字0~24 weeklyIndex = "1111100",start = "12",end = "14";代表工作日(周一至周五)12点至14点 weeklyIndex ="000011",start = "22",end = "23" 代表非工作日(星期六至星期天)22点至23点 weeklyIndex = "1111100,000011",start = "12,22",end = "14,23" 代表工作日(星期一至星期五)12点至14点,非工作日(星期六至星期天)22点至23点 |
bookingRule@end | 生效结束时间 | String | 可选 | 否 | 与bookingRule@start配合使用,仅支持数字0~24 |
bookingRule@visible | 是否可见 | Boolean | 必选 | 否 | true:可见;false:不可见 ps:仅针对ipLimitType生效 |
bookingRule@ip | 用户所在的区域限制 | Enum | 可选 | 否 | 单选,若获取不到用户当前所在区域,则该用户不可见 1:仅大陆ip可见 2:仅大陆+港澳台ip可见 3:仅酒店当地ip不可见 (若为海外酒店,为国家维度;若为港澳台酒店,为省份维度。 eg.东京某酒店设为当地不可见,则为日本ip不可见;香港某酒店设为当地不可见,则为香港ip不可见) |
bookingTime@maxAdvanceDays | 最大提前预订天数 | Integer | 可选 | 否 |
若无限制,不要传该字段, 若有限制,该字段需>=0, 若checkin_date=2019-10-10, maxAdvanceDays=8, 则报价最多提前192(8x24)小时可订,从2019-10-11 00:00开始计算, 即为报价2019-10-03 00:00之后可订(当地时间) |
bookingTime@minAdvanceDays | 最小提前预订天数 | Integer | 可选 | 否 |
若无限制,不要传该字段, 若有限制,该字段需>=0, 若checkin_date=2019-10-10, minAdvanceDays=2, minAdvanceHours=6, 则报价需提前48+6=54小时可订,从2019-10-11 00:00开始计算, 即为报价2019-10-08 18:00之前可订(当地时间) |
bookingTime@minAdvanceHours | 最小提前预订小时数 | Integer | 可选 | 否 | 若无限制,不要传该字段, 若有限制,该字段需>=0,<=23, 若checkin_date=2019-10-10, minAdvanceDays=2, minAdvanceHours=6, 则报价需提前48+6=54小时可订,从2019-10-11 00:00开始计算, 即为报价2019-10-08 18:00之前可订(当地时间) |
bookingTime@last | 最小连住天数 | Integer | 可选 | 否 | 若无限制,不要传该字段, 若有限制,该字段需>=1,超过90默认取90, 若checkin_date=2019-10-10, checkout_date=2019-10-11, last=2, 则该条报价不可见 若checkin_date=2019-10-10, checkout_date=2019-10-12, last=2, 则该条报价可见 |
bookingTime@maxLast | 最大连住天数 | Integer | 可选 | 否 | 若无限制,不要传该字段, 若有限制,该字段需>=1, 若checkin_date=2019-10-10, checkout_date=2019-10-12, maxLast=1, 则该条报价不可见 若checkin_date=2019-10-10, checkout_date=2019-10-12, maxLast=2, 则该条报价可见 |
bedType节点属性*(bedType是room的必选节点)
有时一个酒店对同一个房型可以提供不同的床型。例如下面的例子提供了两种床型。
否则只需要一个
<beds>
节点即可.
<bedType relation="OR" > <beds seq="1" code="SINGLE" desc="单人床" count="2" size="1.2m*2m" > </beds> <beds seq="2" code="DOUBLE" desc="大床" count="1" size="1.8m*2m" > </beds> </bedType>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
relation | 关系 | String | 必选 | 是 | AND, OR |
beds@seq | 床型id | String | 必选 | 否 | 床型ID。在提供多种床型的情形下,Reservation API中的bedChoice节点会用到此值。 |
beds@code | 床型 | Enum | 必选 | 否 | 参照枚举BedTypeCode,不确定填OTHERS |
beds@count | 床型数量 | Integer | 必选 | 否 | 床型数量。若无法确定床型数量,请默认填"1" |
beds@size | 床型面积 | String | 必选 | 是 | 例1.8m*2m 有请尽量填写,否则用户有此类投诉时,有承担赔偿的风险 |
meal节点属性*(meal
是room的必选节点)
请提供
breakfast
。
<meal> <breakfast count="2|2" desc="self-service breakfast" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
breakfast@count | 早餐数量 | String | 必选 | 否 | “|“分隔的数字,必须大于等于零。示例:count=2|1,第一天2人份,第二天1人份 |
breakfast@desc | 早餐描述 | String | 必选 | 是 | 可以为空。 |
refund节点属性*(refund
是room的可选节点)
如果无此节点则意味着消费者在Qunar不可退订。
<refund returnable="true" timeZone="GMT+9" > <!-- 增加timeZone --> <refundRules> <refundRule before="130" type="NO_DEDUCTION" value="0" /> <refundRule before="36" type="DEDUCT_BY_AMOUNT" value="20" /> <refundRule before="25" type="DEDUCT_BY_PERCENT" value="30" /> </refundRules> </refund>
以上可按照解析规则翻译为(假设checkIn = 2019-09-25 checkOut = 2019-10-02)
before | type | value | 含义 |
---|---|---|---|
130 | NO_DEDUCTION | 0 | 2019-09-20 14:00:00之前不扣款 |
36 | DEDUCT_BY_AMOUNT | 20 | 2019-09-20 14:00:00~2019-09-24 12:00:00 按指定金额20扣除 |
25 | DEDUCT_BY_PERCENT | 30 | 2019-09-24 12:00:00~2019-09-24 23:00:00 按百分比30%扣除 |
2019-09-24 23:00:00 以后不能取消订单 |
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
refund@returnable | 是否可退订 | Boolean | 必选 | 否 | true意味着,可以根据退款规则可以取消订单 |
refund@timeZone | 时区 | String | 必选 | 否 | 酒店时区,Qunar将根据此值,转换得到北京时间, 例如:GMT+9 /GMT+09为 东京的一家酒店 GMT+09:00这种格式不可以 |
refundRule@before | 规则有效期 | Integer | 必选 | 是 | 表示用户距离入住日当天24:00前多少小时可以取消订单,数值表示小时数且必须大于24; Quanr在计算可取消时间时会增加2小时,以避免因时差、系统或其他因素导致的Q侧可取消代理商侧不可取消; |
refundRule@type | 退款类型 | Enum | 必选 | 是 | 参照枚举RefundType |
refundRule@value | 取值 | Number | 必选 | 是 | 当退款类型为扣除固定金额、扣除房费的百分比时,必填。 |
特别说明:现在生产环境逻辑,退款规则只保留三段:免费取消、部分退款(解析为一段)、全额扣款。
部分退款(解析为一段)的示例:
代理商一侧提供的退款规则: <refundRule before="36" type="DEDUCT_BY_AMOUNT" value="20" /> <refundRule before="25" type="DEDUCT_BY_PERCENT" value="30" /> Qunar现有逻辑合并为 : <refundRule before="36" type="DEDUCT_BY_PERCENT" value="30" />
remarks节点属性*(remarks
是room的可选节点)
预订提示信息。
<remarks><!-- optional --> <remark seq="1" value="the weather will be rainy in July, please prepare rain gears by yourself"/> <remark seq="2" value="no pets allowed please"/> <remark seq="3" value="free parking, but cannot make sure available parking lots any time"/> </remarks>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
remark@value | 字段内容 | String | 必选 | 否 | 字段最大长度为100个字符。 此项将展示在Booking页面的预订说明项下,供用户查看,若有需要用户特别注意的信息请通过此值传至Quanr,以防止用户投诉,如:用户到店办理入住必须准备哪些证件、是否允许儿童入住、哪些费用需要用户到店支付等等;不可填写电话、邮箱、网址等信息 |
customerLimit节点属性*(customerLimit
是room的可选节点)
宾客国籍限制
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
customerLimit@regionLimit | 限制类型 | Integer | 必选 | 否 | 1.黑名单 2.白名单 3.无限制 |
customerLimit@regions | 国籍列表 | String | 必选 | 否 | ISO 3166-2标准3位国家代码,存在多个国籍时以逗号隔开,最大允许5个国籍限制 |
extras节点属性*(extras
是room的可选节点)
<extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> <property key="EAN" value="XXXYYY" /> <property key="BK" value="XXXYYY" /> <property key="AGODA" value="XXXYYY" /> <property key="ELONG" value="XXXYYY" /> <property key="GCTRIP" value="XXXYYY" /> </extras>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
property@key | 字段枚举Key值 | String | 必选 | 否 | 字段最大长度为100个字符。 关联供应商相关枚举key值,依据实际情况选择枚举值填写 EAN:供应商expedia对应物理房型Id, BK:供应商booking对应物理房型Id, AGODA:供应商agoda对应物理房型Id, ELONG:供应商艺龙对应物理房型Id, GCTRIP:供应商携程对应物理房型Id |
property@value | 字段内容,以key值对应枚举含义为准 | String | 必选 | 否 | 字段最大长度为100个字符。 |
有时代理商需要在
<room>
节点附加额外的信息,在预订(<bookingRequest>中
)时可回传此信息。
taxes节点属性*(taxes
是room的可选节点)
<taxes><!-- optional --> <tax id="51" type="IncludedInTotalPrice" amount="100|100" currency="CNY" /> </taxes>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
tax@id | 税费id | String | 必选 | 否 | 税费id,id与名称映射关系如下: 51: 香港房租税 |
tax@type | 税费类型 | Enum | 必选 | 否 |
IncludedInTotalPrice: 预付税 ExcludedFromTotalPrice: 到店税 “预付税”:税费金额包含在房型总价中,即【房型总价】 room.prices 、【税费或服务费】room.taxAndFee 均包含该税费“到店税”:税费金额不包含在房型总价中,即【房型总价】 room.prices 、【税费或服务费】room.taxAndFee 不包含该税费
|
tax@amount | 税费金额 | String | 可选 | 是 | 表示单间夜税费金额,格式参照price、taxAndFee。 |
tax@currency | 税费币种 | String | 可选 | 是 | 税费币种,值同currencyCode |
2.3 报价接口数据-多酒店(废弃)
Qunar通过调用此接口,获得多个酒店的报价信息。(此接口目前Q已不接入,无需开发)
2.3.1 request
HTTP URL:https://base_url?xml=xxx
HTTP Param:xml
HTTP Method:GET
响应时间:不超过30s
URL由代理商提供,在Qunar端进行配置。 HTTP必要参数只有一个即xml
。例如
<?xml version="1.0" encoding="utf-8"?> <priceRequest> <hotelIds>9987,9988</hotelIds> <hotelCity>tokyo</hotelCity> <checkin>2019-09-13</checkin> <checkout>2019-09-14</checkout> <numberOfRooms>2</numberOfRooms> <customerInfos> <customerInfo seq="0" numberOfAdults="2" numberOfChildren="2" childrenAges="8|12" > </customerInfo> <customerInfo seq="1" numberOfAdults="2" numberOfChildren="0" childrenAges="" > </customerInfo> </customerInfos> </priceRequest>
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
hotelIds | 酒店ID | String | 必选 | 否 | 代理商酒店的唯一标识,由逗号分隔,最多为100个。 |
hotelCity | 城市code | String | 必选 | ·否 | Qunar提供的城市code,与hotelIds二选一作为条件 |
checkin | 入住日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 例如. 2015-12-21 |
checkout | 离店日期 | String | 必选 | 否 | 格式为YYYY-MM-DD, 例如. 2015-12-21 |
numberOfRooms | 房间数 | Integer | 可选 | 否 | |
customerInfo@seq | 序列号 | Integer | 可选 | 否 | customerInfo的id,从0开始。customerInfo存在时,customerInfo的数目等于numberOfRooms |
customerInfo@numberOfAdults | 成人数 | Integer | 可选 | 否 | |
customerInfo@numberOfChildren | 儿童数 | Integer | 可选 | 否 | |
customerInfo@childrenAges | 儿童年龄 | Integer | 可选 | 否 | 以|分隔的数字组合。 例如4|7意味着一个4岁的儿童和一个7岁的儿童。 |
2.3.2 response
如果没有相应报价数据,请返回空节点
<list/>
。字段含义与【报价接口数据-单酒店】保持一致。
<?xml version="1.0" encoding="utf-8"?> <list> <priceResponse hotelId="9987" hotelCity="tokyo" hotelName="Toyoko Inn Tokyo Machida-eki Odakyu-sen Higashi-guchi" hotelNameCN="东京东横町田站东口小田急森酒店" hotelAddress="1-3-3, Naka-machi, Machida-city, Tokyo" hotelPhone="0081-42-7281045" coordinateProvider="1" longitude="139.44468" latitude="35.54667" checkin="2015-02-20" checkout="2015-02-22" currencyCode="USD" > <rooms> <!-- one or more <room> --> <room id="P_1" name="Double(breakfast)" nameCN="标准房(含早)" payType="PREPAY" prices="200|200" status="ACTIVE|DISABLED" counts="5|5" roomRate="180|180" taxAndFee="20|20" broadband="FREE" maxOccupancy="2" occupancyNumber="2" freeChildrenNumber="1" freeChildrenAgeLimit="8" instantConfirmRoomCount="3|3" wifi="FREE" window="1" checkinTime="12:00" checkoutTime="12:30" area="" guestType="ALL_GUEST" > <!-- constraint: for each day prices = roomRate + taxAndFee --> <bookingRule userProperty="101,102,103" ip="1" > <bookingTime maxAdvanceDays="8" minAdvanceDays="2" minAdvanceHours="6" /> </bookingRule> <bedType> <beds seq="1" code="DOUBLE" desc="大床" count="1" size="1.8m*2m" > </beds> </bedType> <meal> <breakfast count="2|2" desc="日式早餐" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal> <refund returnable="true" timeZone="GMT+9" > <!-- timeZone --> <refundRules> <refundRule before="29" type="DEDUCT_BY_AMOUNT" value="50" /> <refundRule before="25" type="DEDUCT_BY_PERCENT" value="70" /> </refundRules> </refund> <remarks><!-- optional --> <remark seq="1" value="the weather will be rainy in July, please prepare rain gears by yourself"/> <remark seq="2" value="no pets allowed please"/> <remark seq="3" value="free parking, but cannot make sure available parking lots any time"/> </remarks> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> </room> </rooms> </priceResponse> <priceResponse hotelId="9988" hotelName="Toyoko Inn Tokyo Machida-eki Odakyu-sen Higashi-guchi" hotelNameCN="东京东横町田站东口小田急森酒店" hotelAddress="1-3-3, Naka-machi, Machida-city, Tokyo" hotelPhone="0081-42-7281045" coordinateProvider="1" longitude="139.44468" latitude="35.54667" checkin="2019-09-13" checkout="2019-09-14" currencyCode="USD" > <rooms> <!-- one or more <room> --> <room id="P_2" name="Double(breakfast)" nameCN="标准房(含早)" payType="PREPAY" prices="200|200" status="ACTIVE|DISABLED" counts="5|5" roomRate="180|180" taxAndFee="20|20" broadband="FREE" maxOccupancy="2" occupancyNumber="2" freeChildrenNumber="1" freeChildrenAgeLimit="8" instantConfirmRoomCount="3|3" wifi="FREE" window="1" checkinTime="12:00" checkoutTime="12:30" area="" guestType="ALL_GUEST" > <!-- constraint: for each day prices = roomRate + taxAndFee --> <bookingRule userProperty="101,102,103" ip="1" > <bookingTime maxAdvanceDays="8" minAdvanceDays="2" minAdvanceHours="6" /> </bookingRule> <bedType> <beds seq="1" code="DOUBLE" desc="大床" count="1" size="1.8m*2m" > </beds> </bedType> <meal> <breakfast count="2|2" desc="日式早餐" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal> <refund returnable="true" timeZone="GMT+9" > <!-- timeZone --> <refundRules> <refundRule before="29" type="DEDUCT_BY_AMOUNT" value="50" /> <refundRule before="25" type="DEDUCT_BY_PERCENT" value="70" /> </refundRules> </refund> <remarks><!-- optional --> <remark seq="1" value="the weather will be rainy in July, please prepare rain gears by yourself"/> <remark seq="2" value="no pets allowed please"/> <remark seq="3" value="free parking, but cannot make sure available parking lots any time"/> </remarks> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> </room> </rooms> </priceResponse> </list>
3 订单接口
3.1 订单预订接口(代理商提供)
在消费者支付完成后,Qunar会向代理商一侧发起预订请求。 每次预订只能指定一个房型。
3.1.1 request
HTTP URL:https://base_url
HTTP Param:xml
HTTP Method:POST
Connection Timeout:响应时间不超过10s
HTTP ContentType:x-www-form-urlencode
URL由代理商提供,在Qunar端进行配置。
<?xml version="1.0" encoding="utf-8"?> <bookingRequest> <hotelId>16166</hotelId> <checkin>2019-09-13</checkin> <checkout>2019-09-14</checkout> <totalPrice>800</totalPrice><!-- totalPrices = sum(prices) * numberOfRooms --> <currencyCode>USD</currencyCode> <rmbPrice>5504</rmbPrice> <totalPriceAfterPromotion>5500</totalPriceAfterPromotion> <promotionPrice>4</promotionPrice> <customerArriveTime>16:00-18:00</customerArriveTime> <specialRemarks>PREFER_NON_SMOKING,PREFER_HIGH_FLOOR</specialRemarks> <!-- preference from consumer --> <numberOfRooms>2</numberOfRooms> <bedChoice>1</bedChoice> <instantConfirm>false</instantConfirm> <requiredAction>CONFIRM_ROOM_SUCCESS/CONFIRM_ROOM_FAILURE</requiredAction> <specialRemarks>Room 1:Guest 1 - YANG/CHENG,Guest 2 - XU/CHUBO;Room 2:Guest 1 - ZHANG/LUPING,Guest 2 - WANG/XIAOLAN;need smoking room,need adjoining rooms,need quiet room,need high floor room尽量安排吸烟房,尽量安排相近房间,尽量安排安静房间,尽量高层</specialRemarks> <room id="9986" name="特色房" broadband="FREE" payType="PREPAY" prices="200|200" status="ACTIVE|ACTIVE" counts="5|5" roomRate="180|180" taxAndFee="20|20" maxOccupancy="2" occupancyNumber="2" freeChildrenNumber="1" freeChildrenAgeLimit="8" instantConfirmRoomCount="3|3" wifi="FREE" checkinTime="" checkoutTime="" area="" guestType="ALL_GUEST" > <bedType> <beds seq="1" code="SINGLE" desc="单人床" count="2" size="1.2m*2m" > </beds> </bedType> <meal> <breakfast count="2|2" desc="self-service breakfast" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal> <promotionRules> <promotionRule code="FREE_UPGRADE" desc="免费升级" value="0"></promotionRule> </promotionRules> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> </room> <customerInfos> <customerInfo seq="0" numberOfAdults="2" numberOfChildren="2" childrenAges="8|12" > <customer firstName="Ziqiang" lastName="Deng" nationality="CN" gender="male" /> </customerInfo> <customerInfo seq="1" numberOfAdults="2" numberOfChildren="0" childrenAges="" > <customer firstName="XoXo" lastName="Li" nationality="CN" gender="male" /> </customerInfo> </customerInfos> <qunarOrderInfo> <orderNum>j3gm141219163017759</orderNum><!-- unique order id at Qunar --> <hotelSeq>osaka_2202</hotelSeq><!-- unique id for a hotel at Qunar --> <hotelName>阪急阪神大阪国际酒店(Hotel Hankyu International)</hotelName> <hotelAddress>19-19, Chayamachi, Kita-ku, Osaka 530-0013, Japan</hotelAddress> <cityName>大阪</cityName> <hotelPhone>0081-6-63772100</hotelPhone> <orderDate>2014-12-19 16:30:17</orderDate> <contactName>张三</contactName> <contactPhone>1381****818</contactPhone> <contactEmail>miao.****@Qunar.com</contactEmail> <payType>PREPAY</payType> <customerIp>103.24.27.9</customerIp> <!-- N=no require Y=paper invoice E=electronic receipt --> </qunarOrderInfo> </bookingRequest>
<room>
节点相关信息来自代理商提供的报价信息。
<customerInfos>
为顾客信息。
<qunarOrderInfo>
包含了本次预订的部分订单信息。
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
totalPrice | 总报价 | Number | 必选 | 否 | 总报价 |
rmbPrice | 人民币报价 | number | 必选 | 否 | 消费者支付的人民币价格。 |
promotionPrice | 促销价格 | number | 必选 | 否 | 如果房型报价含有商家优惠(在Q平台配置的),则该值为商家优惠的原始币种金额. |
totalPriceAfterPromotion | 促后底价 | number | 必选 | 否 | 原始币种促后底价,如果房型报价含有商家优惠(在Q平台配置的),则促后底价为减去优惠金额的值. |
specialRemarks | 特殊说明 | String | 必选 | 否 | 用于标注每间房的用户姓名及客人的特殊说明; 示例: <specialRemarks> Room 1:Guest 1 - YANG/CHENG,Guest 2 - XU/CHUBO;Room 2:Guest 1 - ZHANG/LUPING,Guest 2 - WANG/XIAOLAN;need smoking room,need adjoining rooms,need quiet room,need high floor room尽量安排吸烟房 ,尽量安排相近房间,尽量安排安静房间,尽量高层</specialRemarks>\n。 |
bedChoice | 选择的床型 | String | 可选 | 是 | 来源于多床型的选择,beds@seq |
orderNum | 订单号 | String | 必选 | 否 | Qunar唯一订单号,代理商可以用此进行订单的查询 |
qunarOrderInfo@ contactName |
用户姓名 | String | 必选 | 否 | 订单填写页的用户姓名 |
qunarOrderInfo@ contactPhone |
用户联系电话 | String | 必选 | 否 | 在预订时打马赛克,代理商必须确认订单后才能通过【订单查询接口(Qunar提供)】看到完整内容。 |
qunarOrderInfo@ contactEmail |
用户Email | String | 必选 | 否 | 在预订时打马赛克,代理商必须确认订单后才能通过【订单查询接口(Qunar提供)】看到完整内容。 |
instantConfirm | 即时确认标识 | Boolean | 必选 | 否 | true即时确认房,false表示代理商需要通过【订单操作接口(Qunar提供)】 确认有房或者确认无房。 |
requiredAction | 可执行操作 | Enum | 可选 | 是 | instantConfirm=false则requiredAction= CONFIRM_ROOM_SUCCESS/CONFIRM_ROOM_FAILURE |
3.1.2 response
<?xml version="1.0" encoding="utf-8"?> <bookingResponse> <qunarOrderNum>j3gm141219163017759</qunarOrderNum> <orderId>9987654</orderId> <result>SUCCESS</result> <msg></msg> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> </bookingResponse>
字段说明:
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
qunarOrderNum | Quanr订单号 | String | 必选 | 否 | Qunar唯一订单号 |
orderId | 代理商订单ID | String | 必选 | 否 | 代理商一方的订单ID |
result | 返回值状态 | enum | 必选 | 否 | SUCCESS或FAILURE |
msg | 返回信息 | String | 必选 | 否 | result="FAILURE",需要代理商返回备注信息,以便于对拒单进行统计,请代理商尽量按如下格式返回msg: 01 - rooms_unavailable;房量不足 02 - price_mismatch;价格不匹配 03 - invalid_input;无效请求 04 - service_unavailable;服务不可用 05 - unknown_error;未知错误 |
3.2 订单操作接口(Qunar提供)
有时代理商未提供即时确认房,代理商需要调用此接口以确认此预订是否成功。
使用订单操作接口的代理商需通知Qunar运营配置代理商的IP白名单。
3.2.1 request
HTTP URL:https://sub_domain/api/ota/otaOpt?orderNum=xxx&hmac=xxx&opt
HTTP Param:orderNum、hmac、opt
HTTP Method:POST
sub_domain、signKey由Qunar指定,供代理商使用。代理商访问此地址时有IP和signKey限制。
Beta环境(open平台)测试时,测试方式请参照open平台操作手册。
字段 | 含义 | 类型 | 可选\必选 | 可为空 | 说明 |
---|---|---|---|---|---|
orderNum | 订单号 | String | 必选 | 否 | Qunar订单号 |
opt | 操作类型 | String | 必选 | 否 | 参考 OptCode |
hmac | hmac | String | 必选 | 否 | 1) hmac=md5(signKeyorderNumopt),32 位小写; 示例: signKey=asdf; orderNums=80291; opt=CONFIRM_ROOM_SUCCESS; hmac=md5(asdf80291CONFIRM_ROOM_SUCCESS); hmac=383266846e0d0dc4d17fa9906b28ae5d; |
confirmationNumber | 确认号,客人在办理入住时提供给酒店的编号 | String | 可选 | 否 | 客人在办理入住时提供给酒店的编号,若有此信息请回传至Quanr;若回传了这个参数,则生成hmac的时候需要加上confirmationNumber,即hmac=md5(signKeyorderNumoptconfirmationNumber) |
hmac 示例
package com.qunar.test; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; public class MyHmacUtil { public static byte[] hashMD5(String str) { return (str == null) ? null : hashMD5(str.getBytes()); } public static byte[] hashMD5(byte[] bytes) { try { return hash("MD5", bytes); } catch (NoSuchAlgorithmException e) { return null; // can't happen } } public static byte[] hash(String algorithm, byte[] bytes) throws NoSuchAlgorithmException { if (algorithm == null || bytes == null) { return null; } MessageDigest md = MessageDigest.getInstance(algorithm.toUpperCase()); return md.digest(bytes); } public static String toHexString(byte[] byteArray, String delim) { if (delim == null) { delim = ""; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < byteArray.length; i++) { if (i > 0) { sb.append(delim); } String hex = Integer.toHexString(byteArray[i] & 0x00ff).toLowerCase(); if (hex.length() < 2) { sb.append("0"); } sb.append(hex); } return sb.toString(); } public static String toHexString(byte[] byteArray) { return toHexString(byteArray, null); } public static String getHmac(List<String> params) { StringBuffer buf = new StringBuffer(""); for (String param : params) { buf.append(param); } return toHexString(hashMD5(buf.toString())); } }
3.2.2 response
{ "statusCode": 6, "ret": true, "statusDesc": "订单取消" }
{ "statusCode": 6, "ret": false, "errorMsg": ["订单当前状态不满足对应操作"], "statusDesc": "订单取消" }
字段说明:
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
ret | 返回值 | string | 必选 | 否 | true = SUCCESS , false = FAILURE ,请以此值作为判断操作是否成功的依据。 |
errorMsg | 错误信息 | String | 可选 | 否 | 错误信息 |
statusCode | 状态码 | number | 必选 | 否 | |
statusDesc | 状态描述 | string | 必选 | 否 |
3.2.3 重要说明-opt
opt | 用途 | 需要附加的参数 | 备注 |
---|---|---|---|
CONFIRM_ROOM_SUCCESS | 确认可住 | 无 | 非即时确认房,需要代理商进行此操作。 |
CONFIRM_ROOM_FAILURE | 确认不可住 | 无 | 非即时确认房,需要代理商进行此操作。 |
ORDER_CHANGE | 订单信息变更 | confirmationNumber 目前仅支持 确认号变更 |
3.3 订单取消接口(代理商提供)
消费者取消预订时,需要调用订单取消接口。
关于已确认订单的取消逻辑:
消费者在订单详情页取消订单时,Qunar保证退款符合代理商房型报价的退款规则。
有时退款规则不允许取消预订,则可以通过Qunar后台进行强制取消,并通知代理商。。
关于订单取消:
现阶段,Qunar不支持订单修改,消费者必须先取消先前订单,然后再重新做一次预订。
另外, 一个
<cancelRequest>
请求意味着取消的是整个订单,Qunar不支持取消订单的部分间夜。
3.3.1 request
HTTP URL:https://base_url
HTTP Param:xml
HTTP Method:POST
Connection Timeout:3s, Request Timeout: 100s
base_url由代理商提供,在Qunar端配置。
<?xml version="1.0" encoding="utf-8"?> <cancelRequest> <qunarOrderNum>j3gm141219163019999</qunarOrderNum> <orderId>9987654</orderId> <requiredAction>AGREE_UNSUBSCRIBE/REFUSE_UNSUBSCRIBE</requiredAction> <reason></reason> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="OTHER_KEY" value="XXXYYY" /> </extras> </cancelRequest>
字段 | 含义 | 类型 | 可选\必选 | 否可为空 | 备注 |
---|---|---|---|---|---|
qunarOrderNum | Qunar订单号 | String | 必选 | 否 | |
orderId | 代理商订单ID | String | 必选 | 否 | |
requiredAction | Enum | 必选 | 是 | 从Qunar后台强制取消(条件:不符合退款规则,消费者希望取消订单,经协商,代理商同意取消)时,requiredAction=AGREE_UNSUBSCRIBE/REFUSE_UNSUBSCRIBE |
|
reason | 取消原因 | String | 必选 | 是 |
3.3.2 response
<?xml version="1.0" encoding="utf-8"?> <cancelResponse> <qunarOrderNum>j3gm141219163017759</qunarOrderNum> <orderId>9987654</orderId> <result>SUCCESS</result> <msg></msg> </cancelResponse>
字段说明:
字段 | 含义 | 类型 | 可选/必选 | 可为空 | 说明 |
---|---|---|---|---|---|
result | 返回值 | enum | 必选 | 否 | SUCCESS , FAILURE |
3.4 订单查询接口(代理商提供)
在Qunar调用代理商预订接口时如果发生异常,Qunar需要在重试前,携带去哪儿订单号访问此接口以确认代理商是否生单成功。
3.4.1 request
HTTP URL:https://base_url
HTTP Param:xml
HTTP Method:GET
Connection Timeout:3s, Request Timeout: 10s
base_url由代理商提供,在Qunar端配置。
<?xml version="1.0" encoding="utf-8"?> <wrapperOrderQueryRequest> <qunarOrderNum>j3gm141219163017759</qunarOrderNum><!-- require --> <orderId>12345678</orderId><!-- orderId optional --> <extras><!-- optional --> <property key="TOKEN" value="ASDFJJJJ9999XXXXYYY" /> <property key="EAN" value="XXXYYY" /> <property key="BK" value="XXXYYY" /> <property key="AGODA" value="XXXYYY" /> <property key="ELONG" value="XXXYYY" /> <property key="HB" value="XXXYYY" /> <property key="GCTRIP" value="XXXYYY" /> </extras> </wrapperOrderQueryRequest>
字段 | 含义 | 类型 | 可为空 | 说明 |
---|---|---|---|---|
qunarOrderNum | 订单号 | String | 否 | Qunar订单号 |
orderId | 代理商订单号 | String | 是 |
3.4.2 response
代理商需要返回所有bookingRequest中含有的所有节点信息。
如果没有相应订单数据,请返回空节点
<wrapperOrderQueryResponse/>
。
<?xml version="1.0" encoding="utf-8"?> <wrapperOrderQueryResponse> <orderInfo> <orderNum>j3gm141219163017759</orderNum><!-- unique order id at Qunar --> <orderId>9987654</orderId><!-- unique order id at wrapper --> <payType>PREPAY</payType> <status>CONFIRMED_SUCCESS</status> <hotelSeq>osaka_2202</hotelSeq><!-- unique id for a hotel at Qunar --> <hotelName>阪急阪神大阪国际酒店(Hotel Hankyu International)</hotelName> <hotelAddress>19-19, Chayamachi, Kita-ku, Osaka 530-0013, Japan</hotelAddress> <cityName>大阪</cityName> <hotelPhone>0081-6-63772100</hotelPhone> <orderDate>2014-12-19 16:30:17</orderDate> <contactName>张三</contactName> <contactPhone>1381****818</contactPhone> <contactEmail>miao.****@Qunar.com</contactEmail> <customerIp>103.24.27.9</customerIp> <invoiceCode>E</invoiceCode><!-- N不需要 Y纸质收据 E电子收据 --> <invoice type="" title="somebody" content="" dispatch="" contactName="" contactPhone="" province="" city="" area="" detailAddress="" fee="" /> <hotelId>16166</hotelId> <checkin>2014-12-29</checkin> <checkout>2014-12-30</checkout> <totalPrice>380</totalPrice><!-- totalPrices = sum(prices) * numberOfRooms --> <currencyCode>USD</currencyCode> <totalPriceAfterPromotion>370</totalPriceAfterPromotion><!-- totalPrices = sum(prices) * numberOfRooms --> <promotionPrice>10</promotionPrice> <room id="9987" prices="200|200" roomRate="180|180" taxAndFee="20|20" > <bedType> <beds seq="1" code="5" desc="单人床" count="2" size="" /> <beds seq="2" code="0" desc="大床" count="1" size="" /> </bedType> <meal> <breakfast count="2|2" desc="self-service breakfast" /> <lunch count="0|0" desc="" /> <dinner count="0|0" desc="" /> </meal> <promotionRules> <promotionRule code="FREE_UPGRADE" desc="免费升级" value="0"></promotionRule> </promotionRules> </room> <customerArriveTime>16:00-18:00</customerArriveTime> <specialRemarks>PREFER_NON_SMOKING,PREFER_HIGH_FLOOR</specialRemarks> <customerInfos> <customerInfo seq="0" numberOfAdults="2" numberOfChildren="2" childrenAges="8|12" > <customer firstName="Ziqiang" lastName="Deng" nationality="CN" gender="male" /> </customerInfo> <customerInfo seq="1" numberOfAdults="2" numberOfChildren="0" childrenAges="" > <customer firstName="XoXo" lastName="Li" nationality="CN" gender="male" /> </customerInfo> </customerInfos> </orderInfo> </wrapperOrderQueryResponse>
3.4.3 重要说明-订单状态
enum value | description |
---|---|
NEW_ORDER | 初始状态,代理商接受预订的状态 |
CONFIRMED_SUCCESS | 确认有房,等待入住 |
CONFIRMED_FAILURE | 确认无房,预订失败 |
CANCELED | 订单取消 |
CHECKED_IN | 入住 |
CHECKED_OUT | 离店 |
NO_SHOW | 客人未入住 |
3.5 订单查询接口(Qunar提供)
特别说明:对于未确认可住的订单,消费者联系方式均打了马赛克。
3.5.1 request
HTTP URL:https://sub_domain/api/ota/qunarOrderQuery?orderNums=xxx&hmac=xxx
HTTP Param:orderNums、hmac
HTTP Method:GET
sub_domain由Qunar指定,代理商访问时有IP和signKey限制。
字段 | 含义 | 类型 | 可选\必选 | 可为空 | 说明 |
---|---|---|---|---|---|
orderNums | 订单号 | String | 必选 | 否 | 1个或者多个订单号,最多100个,例如 j3gm141219163017759,j3gm141219163017760 |
hmac | String | 必选 | 否 | 1) hmac=md5(signKeyorderNumopt),32 位小写; 示例: signKey=asdf; orderNums=80291; hmac=md5(asdf80291); hmac=ea680450140097772ae80d49f582be18; |
3.5.2 response
<?xml version="1.0" encoding="utf-8"?> <qunarOrderQueryResponse> <orderInfo> <orderNum>j3gm141219163017759</orderNum><!-- unique order id at Qunar --> <orderId>9987654</orderId><!-- unique order id at wrapper --> <payType>PREPAY</payType> <qunarStatus>CONFIRMED_SUCCESS</qunarStatus> <roomNum>2</roomNum> <cityName>大阪</cityName> <hotelSeq>osaka_2202</hotelSeq> <hotelName>阪急阪神大阪国际酒店(Hotel Hankyu International)</hotelName> <hotelAddress>19-19, Chayamachi, Kita-ku, Osaka 530-0013, Japan</hotelAddress> <hotelPhone>0081-6-63772100</hotelPhone> <orderDate>2014-12-19 16:30:17</orderDate> <contactName>张三</contactName> <contactPhone>1381****818</contactPhone> <contactEmail>miao.miao@Qunar.com</contactEmail> <customerIp>103.24.27.9</customerIp> <invoiceCode>E</invoiceCode><!-- N不需要 Y纸质收据 E电子收据 --> <hotelId>16166</hotelId> <checkin>2014-12-29</checkin> <checkout>2014-12-30</checkout> <roomId>1010162|327223</roomId> <currencyCode>USD</currencyCode> <totalPriceAfterPromotion>5500</totalPriceAfterPromotion> <promotionPrice>4</promotionPrice> <customerArriveTime>16:00-18:00</customerArriveTime> <specialRemarks>PREFER_NON_SMOKING,PREFER_HIGH_FLOOR</specialRemarks> <customerInfos> <customerInfo seq="0" numberOfAdults="2" numberOfChildren="2" childrenAges="8|12" > <customer firstName="Ziqiang" lastName="Deng" nationality="CN" gender="male" /> </customerInfo> <customerInfo seq="1" numberOfAdults="2" numberOfChildren="0" childrenAges="" > <customer firstName="XoXo" lastName="Li" nationality="CN" gender="male" /> </customerInfo> </customerInfos> </orderInfo> <orderInfo> ... </orderInfo> </qunarOrderQueryResponse>
4. 枚举类型
4.1 BedType
字段 | 说明 |
---|---|
SINGLE | 单人床 |
DOUBLE | 大床 |
BUNK | 上下铺 |
DORM_BED | 通铺 |
TATAMI | 榻榻米 |
WATER_BED | 水床 |
ROUND_BED | 圆床 |
FOLDING_BED | 折叠床 |
BABY_COT | 婴儿床 |
CONNECTED_BED | 拼床 |
OTHERS | 其它 |
4.2 FeeMode
字段 | 说明 |
---|---|
FREE | 免费 |
CHARGE | 收费 |
NONE | 无 |
UNKNOWN | 未知 |
PART_CHARGE | 部分收费 |
PART_SUPPORT_AND_FREE | 部分支持且免费 |
PART_SUPPORT_AND_CHARGE | 部分支持且收费 |
PART_SUPPORT_AND_PART_CHARGE | 部分支持且部分收费 |
4.3 RefundType
字段 | 说明 |
---|---|
NO_DEDUCTION | 不扣房费 |
DEDUCT_BY_PERCENT | 扣除房费的百分比 |
DEDUCT_BY_AMOUNT | 扣除固定金额 |
DEDUCT_FIRST_NIGHT | 扣除首晚房费 |
4.4 UnitOfCharge
字段 | 说明 |
---|---|
PER_TIME | 每次 |
PER_DAY | 每天 |
PER_ITEM | 每份 |
PER_PERSON_TIME | 每人次 |
PER_HOUR | 每小时 |
4.5 OptCode
字段 | 说明 |
---|---|
CONFIRM_ROOM_SUCCESS | 确认有房 |
CONFIRM_ROOM_FAILURE | 确认无房 |
ORDER_CHANGE | 变更订单信息 |
4.6 GuestType
字段 | 说明 |
---|---|
ALL_GUEST | 所有宾客 |
DOMESTIC_GUEST | 内宾 |
CHINESE_GUEST | 中宾 |
FOREIGN_GUEST | 外宾 |
5 系统超时拒单逻辑说明
订单类型 | 担保完成时间 | 确认时间段 | 后台按钮操作 | Hota&QTA订单日志 |
---|---|---|---|---|
昨日房 | 00:00-06:00 | 60分钟内 | 代理商后台可以确认房间或拒单 | |
昨日房 | 00:00-06:00 | 超出60分钟 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
当日房 | 9:00---24:00 | 60分钟内 | 代理商后台可以确认房间或拒单 | |
当日房 | 9:00---24:00 | 超出60分钟 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
当日房 | 00:00---9:00 | 11点内 | 在代理商后台确认房间或拒单 | |
当日房 | 00:00---9:00 | 超出11:00 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
非当日房 | 9:00---17:00 | 23点前 | 代理商后台可以确认房间或拒单 | |
非当日房 | 9:00---17:00 | 超出23点 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
非当日房 | 17:00---24:00 | 次日12点前 | 代理商后台可以确认房间或拒单 | |
非当日房 | 17:00---24:00 | 超出12点 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
非当日房 | 00:00-9:00 | 当日12点前 | 代理商后台可以确认房间或拒单 | |
非当日房 | 00:00-9:00 | 超出12点 | 订单自动确认超时拒单。代理商后台无“确认房间”和“拒单”按钮。订单状态转为"拒单"。 | 已拒单,变更原因为:超时未确认订单自动拒单 |
6 如何测试
请使用供应商开发平台,平台账号请通过对应Qunar产品人员或运营人员索取。-
7 FAQ
问题1:酒店列表的更新频率?
通常每天更新一次,也可以手工触发,如果你需要更新大量酒店信息,请联系相关人员。
问题2:酒店聚合问题?
去哪儿同步代理商的酒店后,会将其聚合到去哪儿的基础酒店上。
部分酒店聚合不了通常原因是酒店名称,地址等超长或者不合法,
如果出现聚合问题,可以先在open平台,进行排查。
如仍有问题,请联系相关运营人员。
问题3:不展示报价?
代理商请先确认酒店是否已经聚合成功,然后在open测试平台测试报价是否符合要求,,如果都没有问题,请联系Qunar相关运营人员进行解决。
问题4: 进订率问题?
进订成功率是指: 用户点击预订进入订单填写页的成功次数/总进订次数,不包括进入订单填写页后改变入住时间,房间数目等报价请求。 如果代理商的进订成功率低于平均80%会进行下线处理,所以在此环节代理商需避免超时,无报价的情况发生。
问题5:产品已下线?
代理商订单页报价响应超时(超过10s)或代理商确实无房。
问题6:拒单?
通常是以下三种情况:
- 代理商确认无房。
- Qunar向代理商下单,调用代理商订单预订接口失败(网络异常等)。
- Qunar向代理商下单前,进行报价校验,查询报价失败。