国际酒店标准接口开发文档-V2.1.0


本文档说明主要涵盖如下几点

  • 在线预订流程
  • HTTP接口说明
  • 重点注意事项
  • FAQ

1 开始

1.1 开发步骤

  1. 代理商联系Qunar销售或者运营,说明接入意向,获取open开发平台的用户名和密码。
  2. 参考平台上标准开发文档,进行开发,可以使用此开发平台的自测工具进行测试。
  3. 请按照文档下方case进行测试,保证测试case正常运行。
  4. case测试通过后,使用待上线正式数据在open平台进行最后一次测试,准备上线。
  5. 联系Qunar销售客服,上线一个酒店,Qunar协助代理商在线上测试完整业务流程;并安排培训上线后续事宜。

1.2 重要说明

1.3 预订过程

接入去哪儿的代理商需先了解去哪儿网搜索预订逻辑,以便更好的理解接口文档,建议下载"去哪儿旅行"APP,以更好的了解预订过程及方便后续的线上验证。

因设备及版本不同,以下示例图片仅供参考。

预订过程

酒店搜索页–>酒店列表页–>酒店详情页–>酒店订单页->支付以及订单确认等操作

Hotel Search –> Hotel List –> Hotel Detail –>Hotel Booking->Pay/Order Confirm ..

1) 酒店搜索页(Search页)

打开“去哪儿旅行”APP,点击海外酒店频道,进入【酒店搜索页】

tool-manager

指定入参:目的地、入离日期、成人/儿童数、关键字。点击 开始搜索,进入【酒店列表页】

tool-manager

tool-manager

2) 酒店列表页(List页)

指定入参:入离日期、成人/儿童数、关键字,点击【确定】,可以刷新酒店报价列表。

数据来源:Qunar本地缓存或实时抓取;代理商可以在Quanr配置缓存时间,若不配置,系统默认时间为6小时;当刷新报价时,若代理商报价未过期则使用缓存报价,若报价过期则实时抓取指定入离日期、成人/儿童数的报价;代理商可通过缩短缓存时间或配置实时抓取来降低变价率,具体配置方式,请与Quanr销售或运营沟通;

选中酒店,进入【酒店详情页】。

tool-manager

tool-manager

3) 酒店详情页(Detail页)

酒店信息:展示Qunar维护的酒店图片、房型图片、酒店亮点、介绍、设施、酒店政策、交通和周边、点评信息等信息。

Qunar房型-代理商房型:一个Qunar房型对应多个代理商房型报价。

tool-manager

tool-manager

点击预订按钮,可进入【订单填写页】

tool-manager

指定入参:入住日期、离店日期、成人/儿童数。变更参数,点击 确定,可以刷新酒店报价数据。

数据来源:Qunar本地缓存或实时抓取;代理商可以在Quanr配置缓存时间,若不配置,系统默认时间为6小时;当刷新报价时,若代理商报价未过期则使用缓存报价,若报价过期则实时抓取指定入离日期、成人/儿童数的报价;代理商可通过缩短缓存时间或配置实时抓取来降低变价率,具体配置方式,请与Quanr销售或运营沟通;

tool-manager

tool-manager

4) 订单填写页(Booking页)

指定入参:酒店、房型、入离日期、成人/儿童数、房间数。

消费者在此页面可变更间数,不可变更酒店、房型、入离日期、成人/儿童数。

数据来源:此页面报价均为实时获取,Detail页→Booking页的过程称为进订,若出现变价或超时可能导致进订失败;

点击提交订单按钮,进入支付页面;

特别说明:

响应时间超长(10s超时),则会预订失败,这将严重影响用户体验。

tool-manager

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:拒单?

通常是以下三种情况: