ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

微信小程序火车票查询实战:从技术选型到填坑记录

微信小程序火车票查询实战:从技术选型到填坑记录 简介面向微信小程序开发者的火车票查询示例工程基于小程序框架调用接口完成车次、余票等信息的查询展示适合入门及进阶者学习API对接与页面交互。压缩包共23个文件内部以8个js逻辑脚本、5个json配置文件、5个wxss样式表、4个wxml页面模板及1个md说明文档为主js负责请求封装与业务逻辑json管理全局与页面配置wxml/wxss负责界面布局与样式整体结构清晰紧凑便于按模块查阅。资源包仅11KB下载与阅读都很轻量目前已有1643人学习下载。借助这份源码可快速理解从接口请求到数据渲染的完整流程包括request请求封装、app.json全局配置以及index/train等页面的写法描述中也注明可在现有基础上继续开发适合用作课程设计或实际项目的起步模板按需扩展筛选、订单等功能。 火车票查询天然适合做成微信小程序。不用下载App用完即走在微信里随手搜一下车次、余票比打开浏览器方便得多。不过真要把这个“查”字做好并不只是拼两个输入框再点个按钮那么简单。我最近刚好接手了一个“微信小程序-火车票查询”的实战项目从需求梳理到联调上线中间蹚过不少弯。这篇文章不聊大而全的理论只讲我在做这个项目时踩过的坑、验证过的方案以及可以直接复用的代码片段。如果你是正在做交通运输类小程序的同学或者想在小程序里接入第三方数据API这篇内容基本能把开发链路给你捋清楚。1. 项目整体设计与技术选型思路1.1 需求界定为什么只做“查询”不做“购票”一开始产品给的PRD标题就是“火车票查询”但需求里混着“下单”“支付”的字眼。后来我们把范围砍到只剩查询车次、时刻、余票、价格。不碰订单、不碰支付、也不做用户登录。这个决策其实是在背锅之前做的。做购票意味着要整合12306的库存逻辑、要做支付网关、要处理抢票高峰的并发还要处理退款、改签、占座超时释放等一大堆状态机。一旦出问题损失的不只是钱还有用户的信任。而纯查询业务数据源有偏差顶多被吐槽数据不准不会造成资损。对于个人开发者、毕设项目、企业内部辅助工具从查询切入是最稳妥的第一步。后续如果想扩展购票再去叠加交易闭环节这套查询架构也能作为底层复用。所以我个人比较推荐MVP思路先用最轻量的方式跑通核心链路把用户的查询习惯养起来再逐步加增值服务。1.2 数据源选型第三方API、爬虫、还是官方接口火车票数据不像天气数据那么开放12306官方并没有公开的开发者API。常见路数有三条聚合数据/阿里云市场等聚合API、自行爬取12306接口、以及静态数据本地模拟。我把它们放在同一维度做了对比方案数据实时性成本稳定性合规风险聚合数据/阿里云市场等聚合API高对接12306按次收费有免费额度高低需要企业资质自行爬取12306接口高初始免费但维护成本高中易被屏蔽封禁高违反服务协议静态数据本地模拟低无高但数据假无我在项目里用的是聚合数据提供的火车票查询API。原因主要有几点一是接入快注册后拿key就能调文档清晰二是数据实时性满足需求三是免费额度足够调试阶段用。你可能会担心收费实际上量小的时候费用很低等用户量上来再做商务谈判。我特别不建议以爬虫为主力数据源。就算你用代理池绕过了IP限制只要对方接口的返回字段一改整个服务就崩了。而且类似的做法可能触犯对方平台的用户协议做上线产品风险极大。调试阶段偶尔模拟一下网络包没问题生产环境要用正规数据源。1.3 框架选择原生、uni-app还是Taro技术选型这件事我吃过“过度架构”的亏。一个查询功能的小程序没必要为“将来多端复用”提前上重型框架。这次我选了原生小程序开发理由很直接官方工具链最稳定调试报错能直接定位到代码对原生组件如picker、map支持最彻底项目体量小不需要跨端。如果你团队的代码能力在Vue/React上又确实有App端、H5端复用的诉求那uni-app或Taro是合理的。但要注意转换层会屏蔽部分细节比如iOS和安卓的safe-area差异在跨端框架里往往需要用条件编译单独处理反而增加心智负担。选型没有绝对正确只有适合。我的判断标准很简单项目要在未来一个月内上线团队只有两三个人原生是最省心的。2. 核心功能模块拆解2.1 数据模型与字段设计先定好查询接口的请求/响应结构再去写页面否则前后端会扯皮。我定义的查询请求参数包括出发站code、到达站code、日期和车次类型比如{ from: BJP, to: SHH, date: 2025-04-15, type: 1 }响应里的关键字段是车次对象包含车次号、出发站、到达站、出发时间、到达时间、历时以及各席别的余票和票价。这里要特别提醒stock_flag是个重点。第三方API常见返回“有”“无”或剩余数字数字可能是张数也可能是“有/无”标记。接口文档记得看仔细字段类型别猜我当时就因为这个多花了半天。页面端我给查询链路定义了几种状态加载中、成功、空数据、失败。这样代码里不需要各种if塞在一起直接switch状态渲染逻辑清爽很多。如果你后面还要做条件筛选把筛选条件也放进state里统一管理避免页面多个变量互相影响。2.2 站点选择与定位联动用户最烦的是手动输入城市名。我在首页加了定位能力通过wx.getLocation拿到经纬度后再用腾讯地图WebService API逆地址解析成城市名把匹配到的城市自动带入出发站。这里有两个坑一是小程序的getLocation需要用户授权没有授权要给出友好的引导不能直接白屏二是逆地址解析结果跟火车站列表不匹配的情况比如解析到“上海市”但库里存的是“上海”需要做一个映射表或模糊匹配。城市选择器我用了字母索引列表右侧是A到Z的滑动条。选择完出发站后到达站自动清空防止出现出发地和到达地重复的无效查询。热门城市北京、上海、广州、深圳、成都、杭州单独放在顶部减少点击路径。2.3 车次列表与细节展示结果页是核心。一个车次卡片里用户最在意的信息顺序是出发时间、到达时间、历时、票价、余票状态。我把出发时间做成大号字到达站和到达时间放在第二行历时放中间靠下余票用不同颜色标注有票绿色无票红色数字票额用橙色。车次卡片点击后进入详情页用表格形式展示所有席别的价格和余票并提供“只看有票”的筛选开关。这个开关虽然简单却能显著提升用户体验尤其是当某个车次只剩无座时用户根本不想看商务座有没有票。列表性能也要注意如果一次返回上百个车次直接setData整个数组会卡顿。我做了分页加载每页20条滚动到底部再加载下一页。另外因为页面简单不用虚拟滚动但如果有更多富交互可以后续优化。3. 关键代码与实操流程3.1 项目初始化与页面结构我用微信开发者工具创建的是原生小程序项目目录结构如下project/ ├─ app.json ├─ app.js ├─ app.wxss ├─ pages/ │ ├─ index/index # 查询首页 │ ├─ city-list/index # 城市选择页 │ └─ result/index # 车次列表页 └─ utils/ ├─ request.js # 请求封装 ├─ cityData.js # 站点基础数据 └─ storage.js # 缓存工具app.json里先配置好页面路由和导航栏。我是用了自定义导航栏方便后续统一做样式适配。配置里有一个容易被忽略的点定位权限描述文案要写得清晰比如“用于自动定位当前城市以查询出发车站”否则审核时可能被驳回。{ pages: [ pages/index/index, pages/city-list/index, pages/result/index ], window: { navigationBarBackgroundColor: #3875F6, navigationBarTextStyle: white, navigationStyle: custom }, permission: { scope.userLocation: { desc: 用于自动定位当前城市以查询出发车站 } }, style: v2 }3.2 网络请求封装与错误处理我会把请求统一放在request.js里做封装避免每个页面都写wx.request。封装的点包括每次请求带上第三方API的key、统一设置超时时间、对返回码做预处理、页面卸载时取消请求。function request({ url, method GET, data {}, timeout 10000 }) { return new Promise((resolve, reject) { wx.request({ url, method, data, timeout, header: { Content-Type: application/json; charsetutf-8, apikey: getApiKey() }, success: (res) { if (res.statusCode 200 res.statusCode 300) { resolve(res.data) } else { if (res.statusCode 401) { wx.showToast({ title: 接口鉴权失败请检查配置, icon: none }) } else { wx.showToast({ title: 请求失败(${res.statusCode}), icon: none }) } reject(res) } }, fail: (err) { wx.showToast({ title: 网络异常请稍后重试, icon: none }) reject(err) } }) }) }注意请求里不要写死key要用全局配置。我踩过的一个坑是第三方API要求把key放在header里但我一开始放进query参数直接报“认证失败”。另外如果接口有调用量限制建议在全局封装里做一个简易计数器和并发控制避免瞬间打爆免费额度。3.3 缓存与性能优化城市列表的站点数据有几百个站不适宜全部放缓存但常用城市必须缓存。设置一天过期过期后重新请求。我用storage存了两类数据一是“热门城市最近选择”每次查询前先读缓存没有再请求。二是逆地址解析结果缓存在本地避免频繁调用地图API。function setCityCache(data) { wx.setStorageSync(city_cache, { timestamp: Date.now(), data }) } function getCityCache() { const cache wx.getStorageSync(city_cache) if (!cache) return null if (Date.now() - cache.timestamp 24 * 60 * 60 * 1000) { wx.removeStorageSync(city_cache) return null } return cache.data }页面数据的setData要遵循“局部更新”原则。比如更新某个车次的余票不要setData整个列表用this.setData({ [list[2].seat_stock]: newStock })。这种方式在列表渲染时能明显减少渲染卡顿尤其在iOS低端机上对比非常明显。4. 填坑实录你可能也会遇到这些问题4.1 自定义导航栏适配与顶部安全区导航栏高度不是固定的。不同机型上顶部状态栏高度不一样尤其是有刘海屏的安卓/iPhone。我用了自定义导航需要动态计算核心代码是用wx.getWindowInfo拿状态栏高度再用wx.getMenuButtonBoundingClientRect拿胶囊按钮位置。const { statusBarHeight } wx.getWindowInfo() const menuRect wx.getMenuButtonBoundingClientRect() // 导航栏总高度 状态栏高度 胶囊高度 上下间距 const navHeight (menuRect.top - statusBarHeight) * 2 menuRect.height拿到高度后在布局里给header占位否则内容会顶进状态栏。注意不要把height写死否则某些机型上会出现胶囊按钮错位。如果你在开发时发现模拟器正常但真机错位优先检查是不是这里用了固定px值。4.2 软键盘遮挡查询表单首页的出发/到达输入我用input让用户自由输入车站时部分安卓机型会把输入框遮住。解决思路是把adjust-position设为false然后监听键盘高度变化手动挪页面。具体做法是在输入框上绑定bindkeyboardheightchange事件拿到键盘高度后给页面底部加padding把输入框顶到键盘上方。这个方案的坑在于iOS上事件触发的时机比安卓晚需要做个延迟处理否则页面会闪一下。如果只是城市选择用picker而不是输入基本不会遇到键盘遮挡问题所以能不用input输入就不用input。4.3 真机环境联调常见问题与排查模拟器上一切正常真机一跑就各种报错这一般是环境差异导致。我这边总结了排查清单域名校验小程序线上环境要求request的域名必须HTTPS、已在后台配置为合法域名。开发工具里勾选“不校验合法域名”在真机上不生效必须先配置合法域名。超时时间模拟器网速快真机弱网下容易超时。把超时设长一点同时做重试机制。地图SDK逆地址解析如果用服务端接口不会有SDK问题但如果用前端SDK真机需要在控制台添加业务域名或downloadFile合法域名。4.4 抓包调试的正确打开方式为了排查真机上请求参数和响应我用过Burp Suite抓PC端微信小程序的流量。大致流程是配置HTTP代理将Burp监听的127.0.0.1:8080作为系统代理安装Burp证书到系统信任区然后在微信开发者工具里关闭“校验合法域名”把代理指向Burp。这样可以看到小程序发出的请求明细。需要提醒的是抓包工具只能用于调试自己开发的小程序或已获得授权的目标千万别去抓别人的小程序数据。另外很多第三方接口有签名机制如果你发现自己抓到的包和实际发送的不一样先检查是否被系统二次签名再考虑是加密方案。合规边界要守住调试归调试不碰别人的数据和隐私。5. 后期扩展从查询到购票5.1 想接入支付先搞定这三件事如果你的火车票查询小程序想从“查”升级成“买”一定要提前了解微信支付v3的接入逻辑。v2接口已经逐步下线新商户必须走v3。而v3最大的特点是把证书换成了平台证书商户需要先申请商户号下载API证书并且在商户平台配置API证书序列号三个证书文件一个都不能少。具体参数配置很繁琐不是一天能搞完的。更关键的三个点第一微信支付要求小程序的主体必须是企业或个体工商户个人主体无法开通第二支付回调必须部署在可公网访问的HTTPS服务器上且要对腾讯服务器的request做签名校验第三如果需要管理火车票订单你要额外设计座位占用的状态机避免重复出票。单是这些复杂度就会翻倍。所以如果只是内部体验建议先用查询版上线别急着碰支付。等用户量和运营节奏跑顺了再上线支付闭环也不迟。5.2 关于合规的最后几句做火车票相关的小程序很多同学会想靠爬虫抓官方数据或者抓取他人接口。我理解你可能是为了快速验证但上线运营前一定要把数据源换成合规的授权API。即便只是查询也请勿将非官方数据用于商业场景。合规的代价是银子但不可控的代价是风险。我们不鼓励任何形式的黑产和数据灰产。开发工具和抓包手法是用来调试自己的程序不要拿去做非法用途。踩过的坑多了之后我更确信正规产品数据源越干净越好。火车票查询是一个很好的练手项目但要在规则内做创新。最后再分享一个小经验查询类的小程序上线后一定要监控第三方的调用量。我遇到过免费额度突然用完导致接口返回code错误如果不做告警用户端没有任何预兆。建议加一个当日调用量统计超过阈值自动推送短信或邮件。这个细节能让你少收不少投诉。本文还有配套的精品资源点击获取
返回列表