尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

酒店系统对接携程接口全流程实战:订单、房态与房价同步

酒店系统对接携程接口全流程实战:订单、房态与房价同步 简介面向需要将机票、酒店、火车票等旅游预订能力集成到自身应用的开发者这是一套携程外部接口调用示例工程围绕API签名、请求构造、响应解析和错误处理等关键环节提供可直接阅读的C#实现适合.NET方向的中初级开发者。压缩包共67个文件以C#源码cs、Web服务描述文件wsdl/disco/svcinfo/svcmap、配置文件config为主并包含可运行的exe及依赖dll包体仅48KB便于快速下载与代码审查。已有1831人浏览学习。资源内含完整的Visual Studio解决方案结构覆盖Form界面调用、WebService封装、公共类与日志配置既能作为接口联调时的参考模板也可帮助排查签名失败、参数格式错误等常见对接问题。1. 项目背景与对接价值分析1.1 为什么酒店商家都需要对接携程接口我做酒店系统对接这块有些年头了经手过大大小小十几个渠道的接口说实话携程这套接口属于“绕不开又必须啃下来”的那种。为什么因为不管是民宿、公寓还是连锁酒店携程的订单量在OTA渠道里占比相当高尤其节假日高峰期很多店的携程渠道能占到总订单量的四到五成。如果不做接口对接靠人工在EBK后台一间间录订单、改房价、同步房态旺季的时候根本忙不过来而且人工操作出错的概率特别高。所谓接口对接简单说就是让咱们自己的酒店管理系统PMS或者自研系统跟携程的系统“对话”携程有客人下单了把订单数据推给我们我们的房价、房态变了回传给携程让前台避免超卖或卖不出去。这套事情捋顺了之后前台不再需要来回切换后台页面库存在两个系统之间自动同步收益管理的调价也能实时生效。这个项目适合谁看如果你正在做酒店信息化、民宿管理系统、OTA分销相关的开发或者老板让你负责对接渠道接口那这篇文章应该能帮你省掉不少踩坑的时间。我会把从申请账号到联调上线全流程的思路、关键代码、以及我们实际碰到的坑都写出来尽量给出一份能直接用的实操参考。1.2 对接前需要搞清楚的两个关键问题开始动手之前有两件事必须提前弄清楚否则后面会来回返工。第一件事你们系统跟携程之间的数据流方向是什么。大多数酒店的诉求是双向的携程的订单要拉回来或者接收推送我们这边的房态和房价要同步过去。但有的PMS系统只做单向比如只接收订单不同步房价那对接范围就小很多工程量也完全不一样。做方案之前要把需求边界划清楚最好列成表格发给对接的商务和技术确认。第二件事你们准备用携程的哪种对接模式。携程提供给供应商的接口体系不是一套有专门针对渠道商的API也有EBK后台的 bookingsync 类接口还有针对批发商的系统对接。我接触比较多的是携程开放平台里的“供应商API”这套它是基于 HTTP XML/JSON 的接口集合可以覆盖订单、房态、房价、酒店信息等核心业务。这两个问题确认不清晰后面申请权限、拿测试账号、选接口文档都会走弯路。所以我的建议是第一步不是写代码而是先把自己的业务需求和接口模式确定下来形成一份简短的对接说明发给携程那边的技术对接人确认。2. 准备工作与接口协议核心细节2.1 账号申请、权限开通与联调环境对接携程的第一步是拿到正式的对接资质。如果你所在的公司已经和携程有合作关系比如已经是携程的供应商那直接联系你的客户经理或者商务对接人说明要做系统直连他们会帮你开通开放平台的开发者权限。如果是从零开始就得先走供应商入驻流程这中间会涉及到营业执照、酒店资质、结算账户之类的审核周期比较长快的两周慢的一个月以上建议提前规划。权限开通之后携程会给你一套联调环境的信息通常包含测试用的请求地址不同于正式环境的域名一个渠道商编号类似 authId / supplierId 的角色用于签名计算的密钥文件或字符串这里必须强调一点正式环境和测试环境是分开的密钥也完全不同。我见过有人拿着测试环境的密钥去请求正式地址然后一直报签名错误排查了一个下午才发现是环境搞混了。所以拿到资料之后第一件事就是把正式和测试的配置分开存好最好写在项目的配置文件里用 profile 区分。2.2 接口协议基础请求方式、报文格式与签名规则携程供应商API的底层协议逻辑比较传统但很稳定核心要点如下。请求方式上基本都是 POST数据格式支持 XML 和 JSON具体用哪种看每个接口的要求。我们项目里统一用的 JSON因为和内部系统的序列化方式匹配调试时也更容易看清内容。每个请求都会包含公共参数这些参数放在 Headers 里常见的几个authId你的渠道商身份标识timestamp当前时间戳单位毫秒sign请求签名session登录态标识部分接口需要先做登录认证拿到 session签名是整套对接里最容易出问题的环节。携程用的签名算法大致是把所有参与签名的参数按照字典序排序拼接成字符串再拼接上密钥做 SHA1 或 MD5 哈希最后转成大写或小写字符串。具体算法每个接口文档里都有说明但注意不同接口的签名参与字段可能不一样有的只签公共参数有的要把业务参数也拼进去。我用 Java 代码举个我们自己封装签名方法的例子这段代码在我们的项目里跑了两年多了import java.security.MessageDigest; import java.util.*; public class CtripSignUtil { /** * 生成携程接口请求签名 * * param params 参与签名的参数key-value形式 * param secretKey 渠道密钥 * return 签名字符串 */ public static String generateSign(MapString, String params, String secretKey) { // 1. 将参数按照 key 的字典序排序 ListString keys new ArrayList(params.keySet()); Collections.sort(keys); // 2. 拼接成 keyvaluekeyvalue 形式的字符串 StringBuilder sb new StringBuilder(); for (String key : keys) { String value params.get(key); if (value null || value.isEmpty()) { continue; } if (sb.length() 0) { sb.append(); } sb.append(key).append().append(value); } // 3. 拼接密钥 sb.append(secretKey); // 4. SHA1 加密 try { MessageDigest md MessageDigest.getInstance(SHA-1); byte[] digest md.digest(sb.toString().getBytes(UTF-8)); StringBuilder hexString new StringBuilder(); for (byte b : digest) { String hex Integer.toHexString(0xff b); if (hex.length() 1) { hexString.append(0); } hexString.append(hex); } return hexString.toString(); } catch (Exception e) { throw new RuntimeException(签名计算失败, e); } } }这个签名方法大家看看思路就好实际的参与参数、拼接顺序以及加密方式一定要以携程最新的接口文档为准。另外不同渠道的密钥可能不是字符串而是一个密钥文件那就需要用文件内容参与签名处理逻辑会稍微复杂一些。2.3 核心接口清单订单、房态、房价一个都不能少携程的供应商API接口数量不算少但站在酒店日常运营的角度核心的就是三类订单类、房态类、房价类。我列一下我们项目实际用到的接口清单基本上可以覆盖PMS渠道管理的核心链路接口分类接口名称用途说明订单类订单推送接收携程订单实时推送到我方系统订单类订单确认/拒绝接收后返回确认结果告知携程是否接单订单类订单详情查询主动查询订单详情用于对账和异常处理房态类房态同步将酒店房态可售/不可售推送给携程房态类房态查询查询携程侧当前房态用于排查不一致房价类房价同步推送直连价格或协议价房价类房价计划查询查询携程侧当前价格计划理论上只要把这七类接口做好做稳日常运营就可以不再依赖EBK人工操作了。但注意“做好做稳”这四个字后面藏着不少细节比如订单推送的重试机制、房态同步失败后的补偿策略、房价批量同步的限流控制等等这些我放到后面章节细说。3. 关键实现订单接收、房态房价同步的代码落地3.1 订单推送的接收与确认链路订单推送是整个对接里最核心的链路。携程的推送机制一般是客人下单后携程服务器把我们配好的回调地址接口URL发送一个请求把订单数据传过来。这个回调地址是在开放平台配置接口功能时填写的。我们的接收接口思路大致是这样第一暴露一个 POST 接口接收携程推送的订单数据先做签名校验校验通过后直接返回“成功收到”的应答。这里有个很关键的点接收接口一定要先把携程的数据落库再返回成功标识不要一边处理业务一边返回响应。如果业务处理中报错导致响应超时携程会认为推送失败然后重复推送重复推送又会造成订单重复创建的隐患。第二落库之后丢进消息队列或者线程池里做异步处理处理内容包括解析订单内容、核对房型和价格、写入本系统订单表、触发确认回传等。这里我写一个简化的订单接收伪代码展示一下思路PostMapping(/ctrip/order/receive) public String receiveOrder(HttpServletRequest request) { String body readBody(request); // 1. 签名校验 if (!signValid(request, body)) { log.warn(签名校验失败拒绝接收); return {\result\:\fail\}; } // 2. 幂等处理根据携程订单号判断是否已接收过 String ctripOrderId parseOrderId(body); if (orderService.isExists(ctripOrderId)) { return {\result\:\success\}; } // 3. 先落库入库成功即返回成功 orderService.saveRawOrder(body); // 4. 异步处理后续业务 orderProcessExecutor.execute(() - { processOrder(body); }); return {\result\:\success\}; }多说一句幂等的事情实际生产环境里携程推送的重复率比想象中高原因可能是网络超时后携程自动重试也可能是我们响应稍慢导致对方超时重推。所以接收接口不做幂等线上迟早要出事。我们用携程订单号建了唯一索引中间件层面也做了去重判断双重保险才放心。3.2 订单确认回传与异常处理订单纯接收还不够接收到之后需要向携程回传一个确认结果告诉对方这个订单我们接还是我们不接。确认回传是单独的一个接口调用不是接收接口返回一个 text 就完事。接单的情况下回传确认接口携程看到确认报文后会把订单状态置为“已确认”然后客人的预订就正式生效。不接单的情况比如满房、价格维护错误等需要回传拒绝报文并且附上拒绝原因代码携程那边会展示给客人或者引导客人改订。拒单这个操作要非常慎重因为会直接影响酒店的转化率和排名权重。我们系统里对这个逻辑做了两个保护第一只有管理员权限才能操作拒单前台默认只能接单第二拒单理由选择必须通过下拉框不允许自由填写防止随便选了个错误代码导致后续客诉。3.3 房态房价同步的实现与数据一致性保障房态房价同步说白了就是“我们改了房态要马上告诉携程我们改了价格也要马上告诉携程”。如果不做实时同步就会出现客人看到携程上还有房实际酒店已经满房了下单之后来前台办入住才发现没房客诉和差评就来了。我们项目的实现方案有三种触发方式修改触发PMS里某一房型状态变更时立即触发同步接口定时对账每隔15分钟做一次全量对账把两边数据比对发现不一致就自动修正手动触发运营人员可以在后台主动发起同步用于紧急修正这三种方式各有各的用途缺一不可。修改触发保证实时性定时对账保证最终一致手动触发作为运营兜底。房价同步的实现类似但涉及的数据维度更复杂一些因为携程的房价支持多种价格计划比如门市价、协议价、促销价每个计划的价格逻辑不一样。我们同步时把价格计划的编码映射关系做在配置表里修改价格时按计划逐个推送。同步接口的代码逻辑其实不复杂核心是拼好请求报文做好日志记录重点在于失败重试策略。我们用的策略是同步失败先记录失败日志然后进入重试队列每5分钟重试一次最多重试12次如果最终还是失败则发出告警通知给运维人员。4. 常见问题与排查技巧实录4.1 签名错误最频繁的“拦路虎”签名错误是接口对接初期出现频率最高的报错我们项目组第一次联调时光签名问题就折腾了大半天。常见的几个原因一是签名拼接时参数漏了或拼多了。携程文档里写的是需要参与签名的参数列表但有些接口文档更新不及时实际参与签名的字段和文档写的可能不完全一致。遇到这种情况最快的办法是打开携程接口平台的“签名调试工具”把参数敲进去在线生成一个签名然后和咱们代码算出来的对比一个字段一个字段核对很快就能定位谁多谁少。二是编码问题。如果参数里有中文比如酒店名称、房型名称拼接签名前和拼接后都要保证用 UTF-8 编码尤其做加密时字符串转字节数组的那一步编码不一致签名字符串就完全不一样。三是密钥配错。这个前面提过测试环境和正式环境的密钥不一样密钥字段串复制时前面多一个空格也会导致失败。我们后来把密钥放在配置中心管理环境之间彻底隔离问题少了很多。4.2 订单重复推送与处理幂等前面虽然提到了幂等设计但在实际运行中还会有特殊场景。比如我们本地已经处理完一个订单也向携程回传了确认但由于回传时网络抖动携程没收到确认报文它就会再次推送这个订单。这种场景下如果接口只根据订单号判断已存在就返回成功不做任何后续操作那携程那边会一直等不到确认订单卡在待确认状态客人那里也一直显示预订处理中。我们的解法是接收接口发现订单已存在但状态是“已接收未确认”就主动再次触发确认回传逻辑如果订单已经是“已确认”状态才直接返回成功。这样既保证幂等又能让这种“半成功”状态最终收敛到正确结果。4.3 房态不一致定时对账与补偿机制房态不一致问题往往不是同步接口本身没调而是同步接口调了但携程那边处理失败或者我们这边有房态变更没触发同步。出现过一次比较典型的事故前台上夜班时把一间续住房间的房态改成“维修”但改的时候PMS崩了一下变更事件没发出来结果那间房在携程上一整晚都是可售状态差一点就超卖。从那之后我们加强了定时对账的力度从每小时一次改成每15分钟一次。对账逻辑是这样查出我们本地的可售房型列表调用携程的房态查询接口拿携程的可售列表做对比差异数据自动修正并记录日志。这样即使某个变更事件丢了15分钟内也能自愈。4.4 接口限流与批量操作携程接口对调用频率是有控制的尤其是批量操作比如批量改房价如果同时提交太多请求会被限流甚至封禁IP。我们一开始做房价批量同步时没注意一次性提交了几百个请求结果瞬间被限流后面的请求全部超时。后来我们在代码里加了一个简单的限流器用令牌桶控制请求频率比如每秒钟最多发起5个请求同时把批量操作改成分批提交每批50个房型。调整之后再也没出现过被限流的情况。5. 最后再分享几个实战心得这个项目做下来我的整体感受是携程接口对接本身并不难难的是把各种边界情况处理好把数据一致性保障好。如果你正在做或者准备做这个项目下面几条建议可能会帮到你。第一对接文档一定要以携程开放平台上的最新版本为准不要直接相信网上搜到的旧代码或者旧文档接口版本升级之后字段名称和签名算法都可能变化。我们用的所有接口都手动去开放平台拉取过最新文档逐个核对过才写代码。第二日志一定要打全。每个请求的URL、请求报文、响应报文、耗时都要记录下来尤其是订单相关的数据必须长期保留。排查线上问题的时候这些日志就是你唯一的线索。我们后来给关键的接口接上了完整的日志追踪链路出了问题能直接定位到是哪一步、哪段报文出了问题。第三测试不能只测正常路径。携程有提供模拟数据和测试工具但测试环境下很多异常场景比如重复推送、签名错误、房态冲突不一定能完整覆盖到。我们自己准备了一套模拟数据脚本把常见的异常报文都构造出来测试过联调上线的过程顺利很多。第四建议对接过程中保持和携程技术对接人的沟通频率。携程的技术支持响应速度还可以但有时候问题描述不清楚反而来来回回浪费时间。我们每次遇到问题都习惯把详细的请求日志和报文整理好一次性发过去这样对方能直接定位效率高很多。对我来说这套系统上线后最直观的变化是前台再也不用每天花一两个小时去EBK后台手动同步房态和核对订单了这些东西都自动跑了。虽然对接期间熬了几个大夜但回头看这个项目挺值的。本文还有配套的精品资源点击获取
返回列表