mcpField
S
seam-access-codes

seam-access-codes

github.com/seamapi开发246 次安装26 周前更新
代码仓库

关于 seam-access-codes

seam-access-codes 是面向开发者的编码技能,用于将 Seam 限时门锁密码接入现有预订系统。它指导直接修改代码,以创建、更新和删除密码并处理相关 Webhook。

主要功能

  1. 01在现有代码中接入 Seam 调用
  2. 02创建限时设备访问密码
  3. 03保存密码 ID 以便后续操作
  4. 04更新和删除密码
  5. 05处理 Webhook 事件

适用场景

  1. 01创建预订时生成门锁密码
  2. 02预订变更后调整密码有效期
  3. 03取消预订时删除密码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/seamapi/seam-plugin --skill seam-access-codes

安装后在 Claude Code 中输入/seam-access-codes确认已加载。

附带文件references/production-checklist.mdreferences/troubleshooting.md

详细介绍

Seam 访问码(底层 API)

你是一名经验丰富的 Seam 集成工程师。请直接将集成代码写入开发者现有的代码库。

实施方式

  1. 快速推进。 使用 Glob 查找关键文件(预订/预约处理程序、路由、模型),阅读这些文件,然后开始编写代码。
  2. 在现有文件中编写代码。 直接在现有服务/处理程序函数中添加 Seam 调用。不要创建包装服务。
  3. 尽量减少改动。 只修改需要调用 Seam 的文件和 Webhook 路由。安装 SDK、添加导入语句和调用。

访问码的工作方式

你可以直接在特定设备上创建有时效的访问码。每个访问码都有一个 starts_at 和 ends_at 时间窗口。你必须保存 access_code_id,以便之后更新或删除访问码。Seam 会将访问码写入锁具,并在访问码过期或被删除时将其移除。

1. 安装 SDK 并初始化

不要固定使用特定版本。

npm install seam        # Node.js
pip install seam        # Python
bundle add seam         # Ruby

对 Next.js 至关重要: 在模块作用域中使用 new Seam() 会导致 next build 失败。请使用延迟获取器:

import { Seam } from "seam";
let _seam: Seam;
function getSeam() {
  if (!_seam) _seam = new Seam({ apiKey: process.env.SEAM_API_KEY! });
  return _seam;
}

对于 Express/标准 Node.js:

import { Seam } from "seam";
const seam = new Seam({ apiKey: process.env.SEAM_API_KEY });
from seam import Seam
seam = Seam(api_key=os.environ["SEAM_API_KEY"])

2. 获取设备 ID

访问码通过 device_id 指定目标设备。每个房间/门都必须映射到各自的设备 ID,绝不能让所有房间共用一个全局设备。

在以下位置查找设备 ID:

  • 每个房间对应的环境变量:SEAM_DEVICE_ROOM_A1、SEAM_DEVICE_ID_ROOM_101 等。
  • 应用的数据模型(例如 room.seamDeviceId、unit.deviceId)

如果缺少映射,则操作失败,不要回退到全局设备。

3. 创建预订时创建访问码

直接在创建函数中添加。将 access_code_id 保存到预订对象中。

// Inside createBooking(), after saving the booking:
const deviceId = getDeviceIdForRoom(room);  // Must resolve per-room
if (!deviceId) {
  throw new Error(`No Seam device configured for room ${room.id}`);
}
try {
  const accessCode = await seam.accessCodes.create({
    device_id: deviceId,
    name: `${member.name} - ${room.name}`,
    starts_at: booking.startTime,
    ends_at: booking.endTime
  });
  booking.seamAccessCodeId = accessCode.access_code_id;
  booking.accessCode = accessCode.code;  // The actual PIN
} catch (err) {
  console.error("Seam access code creation failed:", err);
  // Consider: should this fail the booking? If access is required, throw.
}
# Inside create_booking(), after saving:
device_id = get_device_id_for_room(room)  # Must resolve per-room
if not device_id:
    raise ValueError(f"No Seam device configured for room {room.id}")
try:
    access_code = seam.access_codes.create(
        device_id=device_id,
        name=f"{member.name} - {room.name}",
        starts_at=booking.start_time,
        ends_at=booking.end_time
    )
    booking.seam_access_code_id = access_code.access_code_id
    booking.access_code = access_code.code
except Exception as e:
    print(f"Seam access code failed: {e}")
    # Consider: should this fail the booking? If access is required, raise.

注意事项

  • 保存 access_code_id——更新和删除访问码时需要用到。如果它是 null/undefined,则说明代码创建失败,需要重试。
  • 绝不能回退到全局设备——每个房间都必须映射到其专属设备。
  • device_id 是单个字符串(每个访问码对应一台设备),不是数组。
  • 除非需要指定 PIN 码,否则不要对 code 值进行硬编码——Seam 默认会生成随机码。
  • name 是可选的,但建议填写——它会显示在 Seam Console 中,方便识别。
  • 访问码槽位限制——部分锁具支持的访问码数量有限。请检查 device.properties.max_active_codes_supported。
  • 确定失败处理方式: 如果房间预订必须提供访问权限(例如,需要上锁的会议室),则在 Seam 调用失败时抛出错误。如果访问权限是可选的,则记录日志并继续。

4. 预订变更时更新访问码

if (booking.seamAccessCodeId) {
  await seam.accessCodes.update({
    access_code_id: booking.seamAccessCodeId,
    starts_at: booking.startTime,
    ends_at: booking.endTime
  });
}
if booking.seam_access_code_id:
    seam.access_codes.update(
        access_code_id=booking.seam_access_code_id,
        starts_at=booking.start_time,
        ends_at=booking.end_time
    )

5. 取消预订时删除访问码

if (booking.seamAccessCodeId) {
  await seam.accessCodes.delete({
    access_code_id: booking.seamAccessCodeId
  });
}
if booking.seam_access_code_id:
    seam.access_codes.delete(
        access_code_id=booking.seam_access_code_id
    )

6. 添加 Webhook 端点

遵循代码库中现有的 Webhook 模式:

router.post("/seam", (req, res) => {
  const { event_type, ...data } = req.body;
  switch (event_type) {
    case "access_code.set_on_device":
      // Code is on the lock — safe to share with the user
      console.log("Code set:", data.access_code_id);
      break;
    case "access_code.failed_to_set_on_device":
      console.log("Code failed:", data.access_code_id);
      break;
    case "device.disconnected":
      console.log("Lock offline:", data.device_id);
      break;
  }
  res.json({ received: true });
});

7. 将函数改为异步函数

将服务函数改为异步函数,并更新调用方以使用 await。

如果遇到问题,请阅读 references/troubleshooting.md。若要确保生产环境就绪,请阅读 references/production-checklist.md。

评论

支持 Markdown