面向白名单运营商与持有方商家:自助完成创建、调价、户型维护、逐晚房态、上下架,并接住客户订单(查单 / 确认 / 拒单);C 端目录只展示 online 房源。鉴权复用平台商家开放接口同一套 HMAC-SHA256 机制(与家政开放接口同签名算法、同密钥体系)。
房源开放接口是平台商家开放接口的房源分支:路径前缀 /api/juzhu/housing/vendor/*,全部为 POST,请求/响应均为 JSON。鉴权、密钥、错误码风格与家政开放接口(/api/juzhu/jiazheng/vendor/*)完全一致,一套密钥两个业务共用。
status ∈ draft(草稿,默认)/ online(上架)/ offline(下架);C 端目录只出 status=online 且 rating_status=passed(双闸)。目录有 ≤ 15 秒缓存,上下架最迟 15 秒生效。online 创建会被拒);上架前须通过平台评级审核(rating_status:draft → pending → passed / rejected),提审与查进度走开放接口 projects/rating/submit / projects/rating/status(见 4.11)。已上架房源的内容更新免审即时生效。vendor_id + hmac_key。regions/list + projects/list(只读)。projects/create 建草稿(默认不入 C 端),补户型、图片与价格。projects/rating/submit 提交自评分进入平台复核,projects/rating/status 查进度与驳回原因。projects/status 上架;日常用房态接口做关房/夜价,随用随调。| 环境 | Base | 说明 |
|---|---|---|
| 联调/演示 | https://sytest.meizu.life(本页同源,调试台直接可用) | 演示库,数据可随时清理重建 |
| 生产 | 以平台接入单下发的域名为准 | 同一套接口与签名,仅换 Base |
/api/juzhu/housing/vendor/* 即可;跨域接入方按上表 Base 拼全路径。
每个商家一个 vendor_id + 一把 hmac_key,由平台统一配置并线下下发。hmac_key 等同密码:只放服务端或自己的联调机,不要写进前端代码、不要提交仓库。
body,加上 vendor_id;剔除 sign 字段。父键.子键 点号展平;null、''(空串)的键不参与签名。true→'True'、false→'False');数组 → ['a', 'b'](单引号、逗号空格分隔)。k1=v1&k2=v2&…(& 连接,无转义)。timestamp(毫秒时间戳)参与上述串;用 hmac_key 做 HMAC-SHA256,取 hex 小写 为 sign。vendor_id + timestamp + sign,POST JSON 发送。时间戳与服务器偏差 ±5 分钟 内有效。// Node 签名示例
const crypto = require('crypto');
function pyStr(v) {
if (v === true) return 'True';
if (v === false) return 'False';
if (Array.isArray(v)) return '[' + v.map(x => (typeof x === 'string' ? "'" + x + "'" : pyStr(x))).join(', ') + ']';
return String(v);
}
function flatten(data, prefix) {
const flat = {};
for (const [k, v] of Object.entries(data || {})) {
if (v == null || v === '') continue; // 空值不参与签名
const key = prefix ? prefix + '.' + k : k;
if (v && typeof v === 'object' && !Array.isArray(v)) Object.assign(flat, flatten(v, key));
else flat[key] = pyStr(v);
}
return flat;
}
function sign(secretKey, body) {
const payload = { ...body };
delete payload.sign;
const timestamp = Date.now();
const flat = flatten(payload);
flat.timestamp = String(timestamp);
const stringToSign = Object.keys(flat).sort().map(k => k + '=' + flat[k]).join('&');
payload.timestamp = timestamp;
payload.sign = crypto.createHmac('sha256', secretKey).update(stringToSign, 'utf8').digest('hex');
return payload; // 直接作为 POST body
}
const body = sign(HMAC_KEY, { vendor_id: VENDOR_ID });
await fetch(BASE + '/api/juzhu/housing/vendor/projects/list', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
tags=['演示', '回归']),与 JSON 序列化不同;② 嵌套对象(如 units 数组里的对象)会被点号展平进签名,直接把最终 body 交给 sign 函数即可,不要手工拼;③ 重试时须重新签名(timestamp 会过期)。
响应统一为 JSON:成功 { "code": 0, "message": "success", … };失败 HTTP 状态码 + { "code": 4xx, "message": "原因" }(见 错误码)。
字段与平台房源模型一致、即接口契约本身;带 ★ 为商家写入接口接受的字段。
| 字段 | 类型 | 说明 |
|---|---|---|
id | int | 平台生成,创建后返回;后续接口用 id 定位房源 |
name | string | ★必填 | 房源/项目名
channel | string | ★ 业务频道:rental 租赁住宿(长租+旅居,监管同口径)/ minsu 惠居民宿 / newhouse 新房 / resale 二手 / trade 卖旧买新;缺省 rental,创建后不可改。「保租房」不是频道,用 tags 表达(["保租房"],平台侧专题) |
city_id | int | ★必填 | 城市 id(
district_id | int | ★ 行政区 id(districts.id),须属于 city_id;可不传 |
address | string | ★ 详细地址;缺省自动拼「城市 · 名称」。暂无经纬度字段(如需 POI 打点请向平台提需求) |
slug | string | URL 标识(C 端深链词),同 channel 内唯一。建议直接传贵方房源编号;不传则按名称自动生成。注意:传入已存在的 slug 不报错,会静默加 -2/-3 后缀——创建前请先 projects/list 核对防重;改 name 会同步重生成 slug |
cover_image | string | ★ 封面图 URL;室内图集走 photos/add(4.11),上架须 ≥ 8 张照片 |
tags | string[] | ★ 标签数组(如 ["保租房","近地铁"]) |
price_from | int | ★ 起价,单位元。rental 口径为「元/月」,minsu 为「元/晚」;上架前置条件,同时是默认夜价的兜底(rental 折算 价/30)。平日/周末/节假日分档不走它,走房态日历逐晚覆盖(见 5.1) |
sort_order / is_featured / old_house_hint | — | ★ 排序权重 / 平台精选(一般由平台设置)/ 卖旧买新提示 |
contact_phone | string | ★ 真实联系电话,11 位手机号(1 开头;400 号码不接受)。仅入库用于 C 端拨号的虚拟号实时绑定,任何查询接口不回显;可经 projects/update 更新 |
owner_vendor_id | int | 数据归属商家(签名商家自动写入,不可改)。所有接口按它做行级隔离;订单佣金快照按它取商家档费率 |
status | string | ★ draft 草稿(默认,新建强制)/ online 上架 / offline 下架 |
ext | object | ★ 频道差异属性:insurance(保险标识数组,见 7)+ min_stay_nights(最短连住,见 5.2)+ stay_bookable(按晚预订开关,见 5.3,缺省 false = 仅 400 电话咨询) |
rating_status / rating | — | 审核/评级位:draft → pending → passed / rejected。passed 是上架前置;提审走 projects/rating/submit、进度与驳回原因走 projects/rating/status(4.12),列表/详情出参也随行返回 |
户型 = 房源下的实体售卖库存单元:预订、逐晚房态、免费取消政策都挂在户型维度;整栋 / 不限房型走项目级(unit_id=0)。projects/create 可带 units[] 一次建全,后续 units/create 追加。
| 字段 | 类型 | 说明 |
|---|---|---|
project_id | int | ★必填 | 所属房源 id
name | string | ★必填 | 户型名(如「两居 68㎡」「整栋 · 6 室」)。可传
area_sqm | number | ★ 面积(㎡) |
layout_label | string | ★ 户型标签(2室1厅) |
rent_monthly | int | ★ 月租(元/月),照实传贵方月租即可;月租→夜价的 /30 折算发生在平台侧(C 端按晚售卖口径),rental 频道默认夜价 = round(月租/30),并作为下单兜底价 |
price_total | int | ★ 总价(元),newhouse/resale 频道用 |
promo_price | int | ★ 优惠价(元)。当前为展示位:C 端据此打「首月特惠」标签,不参与订单计价(营销价真实成交需另行排期) |
price_night | int | ★ 夜价(元/晚),写入 units.ext.price_night;仅 minsu 频道参与计价(缺省回落 price_from)。rental 频道忽略它,夜价一律 月租/30 + 日历逐晚覆盖 |
cancel_policy | object | ★ 免费取消政策(房型级),写入 units.ext.cancel_policy:{enabled, days_before, cutoff_time};免费取消窗口 = 入住日往前推 days_before(0-30,0=入住当天)天的 cutoff_time(HH:mm)时刻,窗口外 / 未开通一律不可取消不可退 |
tags / unit_spec / cover_image / sort_order | — | ★ 标签 / 房型说明 / 封面 / 排序(sort_order 升序展示,缺省 99,用于主推房型排前) |
amenities | string[] | ★ 配套标识数组,按下表 10 个 id 传(C 端按 id 渲染图标) |
ac 空调 · washer 洗衣机 · fridge 冰箱 · heater 热水器 · lock 智能锁 ·
wifi 宽带 · tv 电视 · hood 油烟机 · microwave 微波炉 · induction 电磁炉。
不传 = C 端回落展示全部 10 项;传未知 id 不渲染。枚举字典化(随接口下发)在平台排期内。
| 字段 | 说明 |
|---|---|
project_id + unit_id | 库存归属;unit_id=0 或缺省表示项目级(整栋 / 不限房型)。下单冲突口径:整栋单查全项目任一户型,指定户型单查「项目级 + 该户型」 |
stay_date | 晚(YYYY-MM-DD,入住当晚)。写入窗口:单次 ≤ 400 晚、可多次滚动写更远(存储无总上限);C 端日历可订窗口 = 当月起 12 个月,建议对账口径与其对齐 |
status | open 可订(默认,未设置过的晚即可订)/ blocked 关房(商家)/ booked 已订(平台订单写入,接口不可改,取消自动释放) |
price_night | 当晚价格覆盖(元),未覆盖回落默认夜价;户型级 > 项目级 > 默认。2026-09-10 起参与下单计价:订单金额 = 逐晚(覆盖价 || 默认夜价)合计,与 C 端日历展示同口径——周末 / 节假日分档即按日期批量覆盖实现 |
blocked=关房(可带价可不带);open + price_night=覆盖价(只改价不改态也这样传);open + price_night:null=恢复默认价并清除差异行。一次调用一个 status 作用于整批 dates。
GET /api/juzhu/projects/{id}/stay-calendar?month=YYYY-MM&unit_id=(公开只读,用于上下架 / 房态验收)返回逐晚三态 + 价格 + 最短连住 + 保险标识,与 C 端日历渲染一致。
以下示例省略签名三件套(vendor_id / timestamp / sign),实际每个请求体都必须携带(见 §2,或直接用 §7 调试台)。
{}
→ 200 {
"code": 0, "list": [
{ "id": 4, "name": "贵阳", "slug": "guiyang",
"districts": [ { "id": 41, "name": "观山湖区", "slug": "guanshanhu" } ] }
], "total": 1
}
{
"channel": "rental", // 可选过滤:channel / status / city_id / keyword
"status": "online"
}
→ 200
{
"code": 0, "message": "success",
"list": [
{
"id": 1611, "name": "示例·观山遇见旅居", "channel": "rental",
"status": "online", "price_from": 2400,
"min_stay_nights": 15,
"insurance": ["switch_rental", "property"],
"insurance_types": [ { "key": "switch_rental", "label": "换租保险", "icon": "🔄" }, /*…*/ ]
}
],
"total": 1
}
{ "id": 1611 }
→ 200 { "code": 0, "project": { /* 同 4.1,另含 address/tags/ext 等 */ }, "units": [ /* 户型数组 */ ] }
{
"name": "观山湖·遇见旅居",
"channel": "rental",
"city_id": 4,
"district_id": 41,
"address": "观山湖区 · 示例大道 88 号",
"tags": ["旅居", "近地铁"],
"price_from": 2400,
"contact_phone": "13800001234", // 仅入库(虚拟号绑定),永不回显
"min_stay_nights": 15, // 最短连住,写入 ext(见 §5)
"insurance": ["switch_rental", "property"], // 保险标识(见 §6)
"units": [
{ "name": "一居 45㎡", "layout_label": "1室1厅", "area_sqm": 45, "rent_monthly": 2400 }
],
"status": "draft" // 缺省 draft;draft/offline 不出 C 端
}
→ 200 { "code": 0, "message": "success", "project": { "id": 1611, "status": "draft", /*…*/ } }
{
"id": 1611,
"price_from": 2680,
"tags": ["旅居", "近地铁", "含早"],
"insurance": ["hotel_cancel", "property"],
"min_stay_nights": 20,
"stay_bookable": true
}
→ 200 { "code": 0, "project": { /* 更新后全量 */ } }
不可改:city_id、channel、owner_vendor_id;改 name 会同步重生成唯一 slug。
{ "id": 1611, "status": "online" } // online 上架 / offline 下架 / draft 转草稿
→ 200 { "code": 0, "message": "success", "id": 1611, "status": "online" }
price_from 且至少有 1 个户型,否则 400。C 端目录有 ≤ 15 秒缓存,上架后最迟 15 秒可见、下架后最迟 15 秒消失。
{ "project_id": 1611, "name": "两居 68㎡", "layout_label": "2室1厅",
"area_sqm": 68, "rent_monthly": 3200 }
→ 200 { "code": 0, "unit": { "id": 3101, /*…*/ } }
{ "id": 3101, "rent_monthly": 3380, "price_night": 128,
"cancel_policy": { "enabled": true, "days_before": 1, "cutoff_time": "18:00" } }
→ 200 { "code": 0, "unit": { /*…*/ } }
cancel_policy(非法 days_before/cutoff_time 返回 400);传 null 清除(= 未开通,客户不可取消)。免费取消窗口 = 入住日往前推 days_before 天的 cutoff_time 时刻;客户在窗口内取消自动退款并释放房态。{ "id": 3101 }
→ 200 { "code": 0, "message": "success" }
{ "project_id": 1611, "unit_id": 0, "month": "2026-12" }
→ 200 {
"code": 0, "month": "2026-12", "base_price_night": 80,
"min_stay_nights": 15, "insurance": ["switch_rental", "property"],
"days": [
{ "date": "2026-12-19", "status": "booked", "price": 80, "source": "booking", "booking_id": 36 },
{ "date": "2026-12-20", "status": "open", "price": 80 }
]
}
is_cover 自动换封面并同步 cover_image{
"project_id": 1611,
"unit_id": 3101, // 可选;缺省 = 房源级图集
"file_path": "https://cdn.example.com/p1.jpg", // 必填,URL ≤ 500 字符
"is_cover": true, // 设为封面(同实体原封面自动让位)
"sort_order": "" // 缺省追加到末尾
}
→ 200 { "code": 0, "photo": { /* id / entity_type / file_path / is_cover / sort_order */ } }
projects/status online 返回 400「上架前须至少上传 8 张房源照片」。
上架闸之一是平台评级审核(rating_status:draft → pending → passed / rejected;rental=好房子 4 维,minsu=旅居彩贝 5 维)。提审与查进度直接走开放接口,不必线下催单:
{
"id": 1611,
"dims": { "comfort": 4.5, "green": 4, "tech": 4.6, "safety": 4.4 }
// minsu 频道为 scenery / facilities / service / location / culture
}
→ 200 { "code": 0, "rating_status": "pending", "rating_code": "SY-RENT-1611", "dims": { /*…*/ } }
{ "id": 1611 }
→ 200 {
"rating_status": "rejected", "rating_code": "SY-RENT-1611",
"dims": { /* 已提交自评分 */ }, "missing_dims": [],
"dims_meta": [ { "key": "comfort", "label": "舒适", "icon": "🛋" } /*…*/ ],
"note": "安全维度证明材料不足", // 驳回原因;passed/rejected 的复核时间见 reviewed_at
"submitted_at": "2026-09-10T03:20:11Z", "reviewed_at": "2026-09-10T07:41:00Z"
}
dims 须覆盖该频道全部维度、数值 0–5;缺维度 / 越界 / 未知维度返回 400 并指明字段。rejected)修订后可重新提审;提审会清除上一轮 note。平台复核通过(passed)后 projects/status online 才会放行。客户在 C 端提交预订单后,商家经开放接口完成接单闭环:定时拉取订单 → 确认生效或拒单 → 拒单自动释放房态。订单按签约商家隔离,联系人手机号只回掩码(139****5678)。
rental = round(月租/30)、minsu = 房型 price_night(缺省回落 price_from)。佣金按订单金额快照锁定(规则 20)。
{
"status": "pending", // 可选过滤:status / pay_status / project_id
"project_id": 1611
}
→ 200 { "code": 0, "list": [ {
"id": 36, "order_no": "BKG-RENTAL-00036", "project_name": "观山湖·遇见旅居",
"checkin": "2026-12-19", "checkout": "2027-01-08", "nights": 20,
"price_total": 1600, "commission_rate": 8.00, "commission_fee": 128.00,
"status": "pending", "pay_status": null,
"contact_name": "张**", "contact_phone": "139****5678"
} ] }
commission_rate / commission_fee 为下单时锁定的费率与佣金快照(元),结算按快照执行、商家后续费率调整不追溯;未差异化商家按全局基准(缺省 10%)。{ "id": 36 } → 200 { "code": 0, "booking": { /* 同上,单条 */ } }
{ "id": 36 } → 200 { "code": 0, "status": "confirmed" }
{ "id": 36 }
→ 200 { "code": 0, "status": "cancelled", "pay_status": null }
| 字段 | 取值 | 说明 |
|---|---|---|
status | pending → confirmed / cancelled | 确认后订单生效;取消为终态,不可再变更 |
pay_status | unpaid / paid / refunded 或 空 | 民宿民宿为预付(先付后确认);租赁住宿预订单为空(商家确认后线下收款) |
| 确认前置 | — | unpaid 的订单不可确认(400),支付完成后可确认;cancelled 不可再变更 |
| 拒单/取消 | — | 自动释放占用的房态晚;已支付订单 pay_status 标记 refunded |
客户动作触发的订单变更,平台会主动推送签名事件到你为商家配置的通知地址(接入单里提供 URL 即可),不必轮询等单:
| event | 触发时机 | 商家应做什么 |
|---|---|---|
booking.created | 客户提交预订单 | 备房;预付单等待支付到账 |
booking.paid | 预付单支付完成(民宿民宿) | 此时方可确认订单 |
booking.cancelled | 客户取消(商家自己拒单不会推送) | 释放已备房源 |
推送为 POST JSON,body 即开放接口同款结构:event + vendor_id + order(订单对象,手机号不外传)+ timestamp + sign。验签与开放接口同一算法(对去掉 sign/timestamp 的参数扁平排序后 HMAC-SHA256),收到后先验签再处理:
// Node 验签示例(与平台 hmac_auth.cjs 同算法)
app.post('/hooks/booking', (req, res) => {
const body = req.body;
const payload = { ...body };
delete payload.sign;
const flat = flatten(payload); // 与请求签名同一套 flatten
flat.timestamp = String(body.timestamp);
const expect = crypto.createHmac('sha256', HMAC_KEY)
.update(Object.keys(flat).sort().map(k => k + '=' + flat[k]).join('&')).digest('hex');
if (expect !== String(body.sign).toLowerCase()) return res.status(401).end();
// 处理 body.event / body.order …
res.status(200).end('ok'); // 2xx 即视为送达
});
bookings/list 定时对账兜底(推荐粒度:每分钟拉一次 status='pending')。订单明细里不含客户明文手机号。
{
"project_id": 1611,
"unit_id": 0, // 0 或缺省 = 项目级(整栋 / 不限房型)
"dates": ["2026-12-10", "2026-12-11"],
"status": "blocked", // blocked 关房;open 开房
"price_night": null // blocked 可同时设价;open + 价格 = 夜价覆盖;open + null = 恢复默认
}
→ 200 { "code": 0, "affected": 2, "dates": 2 }
booked(订单占用)返回 400 并列出日期,须先取消订单。open + price_night;平日不传即回落默认。订单占用的晚翻为 booked 时保留当晚覆盖价,取消释放后该晚差异行随之清除(须重设)。旅居/短住按连续入住售卖:平台缺省口径为 rental=15 晚、minsu=1 晚,商家可用 ext.min_stay_nights(1–365)按房源覆盖。三处同口径校验:C 端日历选段、下单页、平台下单接口 POST /api/juzhu/booking(不足返回 400「该房源须连住至少 N 晚」)。下单成功即占用这些晚,取消自动释放。
房源默认仅 400 电话咨询(C 端不展示价格日历、下单接口拒绝)。projects/create / projects/update 传 "stay_bookable": true 开通后,C 端才展示日历并支持在线下单(catalog / 详情 / 房态日历出参均带 bookable 能力位)。关闭传 false(已生成订单不受影响,可正常确认/取消)。判断由平台服务端唯一执行,tag / 频道不参与。
商家为房源配置的「入住保障」,随 catalog / 详情 / 房态日历下发 C 端展示。枚举由平台统一维护,接口只接受以下 key,未知 key 返回 400:
| key | 名称 | 保障口径 |
|---|---|---|
switch_rental | 换租保险 | 租期到期换租衔接期内的房租损失与搬迁费用 |
hotel_cancel | 酒店取消险 | 行程变更按规则退改,未入住部分房费可退 |
property | 财产保险 | 入住期间屋内财产与房屋主体意外损坏 |
配置入口:projects/create / projects/update 传 insurance 数组;清空传 []。出参同时给出 insurance(key 数组)与 insurance_types(含 label/icon,可直接渲染)。
以下为首批接入方答疑结论,与线上实现同步校准;与本页正文冲突处以正文为准。
| 问题 | 结论 |
|---|---|
| channel 怎么传?保租房是不是 channel? | 字符串枚举 rental / minsu / newhouse / resale / trade,缺省 rental,创建后不可改。长租 + 旅居统一 rental;「保租房」是平台专题(topic)不是频道,用 tags 表达(["保租房"])。支持在线预订的只有 rental / minsu。 |
| city_id / district_id 有枚举接口吗? | 有:regions/list(4.1),只出该商家开放城市及其行政区;未配置城市约束则出全量。 |
| 有经纬度字段吗? | 暂无,只有 address 文本。房源级 POI 打点属新需求,请书面提给平台评估。 |
| slug 可以传我方房源 / 房型编号吗? | 可以(同频道内唯一,未做字符集限制)。传入已存在的 slug 不报错、会静默加 -2 后缀,创建前先 projects/list 核对防重;接口暂无按 slug 幂等 upsert,已列入平台排期。 |
| 只有封面图吗? | 不止:图集走 photos/add(4.11),上架硬性要求 ≥ 8 张 + 封面。 |
| price_from 是基础价吗?平日 / 周末 / 节假日价怎么表达? | price_from 是起价(rental=元/月、minsu=元/晚)+ 默认夜价兜底,不分档。分档 = 房态日历逐晚 price_night 覆盖(5.1),订单金额按逐晚覆盖合计——2026-09-10 起覆盖价真实参与成交计价。 |
| 月租 /30 折算发生在哪侧? | 平台侧(C 端按晚售卖口径):默认夜价 = round(月租/30)。商家照实传 rent_monthly 即可;rental 房源的 units.price_night 不参与计价(仅 minsu 用)。 |
| promo_price 会影响成交价吗? | 不会,当前是「首月特惠」展示标签位;营销价真实成交需另行排期。 |
| amenities 没有枚举怎么映射? | 按下表 10 个 id 传(3.2):ac / washer / fridge / heater / lock / wifi / tv / hood / microwave / induction。不传 = C 端回落展示全部;未知 id 不渲染。枚举字典化在平台排期。 |
| 联系电话必须是 400 吗?后续能改吗? | 相反:须为 11 位手机号(1 开头),400 号码会被拒。号码仅入库用于 C 端虚拟号实时绑定、任何接口不回显;可用 projects/update 更新。 |
| owner_vendor_id 是什么? | 签名商家自动写入的数据归属标记,不可传不可改;一切接口按它行级隔离,订单佣金按它取商家档费率。 |
| 首推后是什么状态?有审核吗?不通过呢? | 新建一律草稿(传 online 创建直接 400)。上架前须过平台评级审核:rating/submit 提审 → pending → 平台复核 passed / rejected(附驳回原因 note,修订后可重新提审)。进度用 rating/status 自查(4.12)。 |
| 上架后更新房源信息要重新提审吗?外网会下架吗? | 不须提审、不下架:内容更新免审即时生效(目录 ≤ 15 秒缓存),外网持续可售。当前契约即「免审直更」,如业务要求重大变更走审核请向平台提出。 |
| 房态 / 房价日历最长设多久?C 端展示多久? | 单次 ≤ 400 晚、可滚动写更远;C 端可订窗口 = 当月起 12 个月,建议按 12 个月滚动维护。 |
| 某间夜的房态和价格必须同时传吗? | 不必,二者独立:blocked 关房;open + price 覆盖价;open + price:null 恢复默认价。一次调用一个 status 作用于整批 dates。 |
在本页直接签名并调用真实接口:选择接口 → 填业务参数 JSON(无需自己写 vendor_id/timestamp/sign)→ 发送。签名在你的浏览器本地完成,hmac_key 只留在本机(可选「记住」,存 localStorage,换机不带)。
常用模板:上架 {"id":123,"status":"online"} · 关房 {"project_id":123,"dates":["2026-12-10"],"status":"blocked"} · 建房源见 §4.3 示例 · 接单 {"id":36}(confirm/cancel 同参,id 取 bookings/list 返回值)。
| HTTP | code | 含义 | 处置 |
|---|---|---|---|
| 401 | — | 缺失签名(sign)或时间戳(timestamp)参数 | 检查签名三件套是否都在 body 里 |
| 401 | — | 请求已过期(±5 分钟窗口) | 校准服务器时间后重签 |
| 401 | — | 签名校验失败 / vendor_id 密钥未配置 | 核对 hmac_key 与签名算法(数组、空值、嵌套展平) |
| 400 | — | name / city_id / project_id 等必填缺失 | 按 message 补齐 |
| 400 | — | channel 非法 / city_id 不属于商家开放城市 / district_id 不属于城市 | 先用 projects/list 或平台侧确认主数据 |
| 400 | — | 上架被拒:缺 price_from / 无户型 / 照片不足 8 张 / 无封面 / 评级未通过 / 商家未过审 | 按 message 补齐;评级走 rating/submit(4.12),图片走 photos/add(4.11) |
| 400 | — | 评级:dims 缺维度 / 越界(0-5)/ 未知维度;或已在复核队列中重复提审 | 按 4.12 维度表修正;进度用 rating/status 查 |
| 400 | — | insurance 含未知标识 / min_stay_nights 不在 1–365 | 按 §6 / §5 枚举修正 |
| 400 | — | 房态:以下日期已有预订占用 | 先取消订单再改房态 |
| 400 | — | 无可更新字段 / city_id 不支持修改 | 按 message 调整 |
| 400 | — | 订单未支付不可确认 / 订单已取消不可变更 | 支付走收银台后重试确认;取消为终态 |
| 404 | 404 | 订单不存在或不属于该商家(房源 / 户型同理) | 统一 404,不区分「不存在」与「越权」,防探测 |
| 404 | 404 | 未知 vendor 路由 | 核对路径(本页调试台清单) |
| 405 | — | 非 POST 请求 | 全部接口仅支持 POST |
平台提供端到端回归脚本(Node,走真实 HTTP 签名链路),接入方可用它自检签名实现是否正确:
# 覆盖:regions 枚举→创建→评级提审/状态→上架→C 端可见→保险/连住更新→房态/夜价→
# 下单逐晚计价→订单闭环(webhook)→下架→越权负例→清理
node scripts/housing_vendor_hmac_regression.cjs [base_url] # 默认 http://127.0.0.1:8766
node scripts/vendor_hmac_regression.cjs # 家政开放接口同机制回归
版本:v2.1(2026-09-10)· 文档与线上实现同步校准。v2.1 变更:新增 regions/list、photos/add、rating/submit|status 端点;夜价覆盖价参与下单计价;amenities 10-id 映射与上架前置清单补全;新增「常见接入疑问」节。
密钥与凭证:由平台统一配置并线下下发;遗失须走平台重置,不要在多个业务间共享 hmac_key。
试点阶段接口字段以本页为准,扩展字段只增不破坏;重大变更会提前在「接入单」里同步。发布节奏随政策与试点进展而定。