跳到主要内容
walaoraWalaora

Walaora API 参考文档

连接 POS 收银系统、电商店铺或内部系统。基于 HTTPS 传输 JSON,每个集成使用一个 API 密钥。

仅在顾客知情的情况下发送其数据,且仅当顾客明确同意时才将 marketingConsent 设为 true。

身份验证

在“控制台 → API 与 Webhooks”中创建密钥(需商业版或企业版套餐)。每次请求都需携带该密钥。密钥仅显示一次;如有泄露,请立即吊销。限制:每个密钥每分钟 120 次请求。

Authorization: Bearer wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

接口

Base URL: https://walaora.com/api/v1

GET/programs

列出会员计划。

GET/customers?phone=0551234567&tag=vip

查找顾客(每页 50 条,?page=2…)。 ?tag=vip 列出带有该标签的顾客;每位顾客都包含其标签。

POST/customers

为顾客办理计划入会。请求体:{ programId, name, phone, email?, marketingConsent?, locale? }。新建时返回 201,已入会时返回 200。

GET/cards/{serial}

通过顾客卡面 / QR 码上的卡号获取会员卡。

POST/cards/{serial}/earn

集章计划:{ stamps?: 1–10 }。积分计划:{ amount },以工作区货币计。可选 { branchId }。 多印章卡:请传入卡上某个印章组的 setId。

POST/cards/{serial}/redeem

兑换一个可用奖励,或发送 {"rewardId"} 兑换奖励目录中以印章 / 积分定价的奖励。

POST/cards/{serial}/sell

预付套餐:出售一个套餐,次数加到卡上(在您的收银台付款)。Webhook:package.sold。

POST/cards/{serial}/use

预付套餐:扣除一次(用完或过期时拒绝)。员工卡:在每日上限内记录福利。Webhook:package.used、perk.used。

GET/coupons/{code}

查询优惠券但不使用:返回其所属优惠、是否可用;如不可用,说明原因(已使用、已过期或已暂停)。

POST/coupons/{code}/redeem

使用一次优惠券。可选 { amount }(消费金额,以工作区货币计)和 { branchId }。已使用或优惠已结束时返回 409。Webhook:coupon.redeemed。

GET/coupon-offers

列出优惠券优惠及其面值、截止日期,以及现在能否创建券码(usable)。

POST/coupon-offers/{id}/coupons

为某个优惠创建券码。{ customerId } 给该顾客一个券码(显示在其会员卡页面);或 { count: 1–500 } 个不绑定顾客的券码,用于打印或分享。成功返回 201 及券码;优惠已暂停或已结束时返回 409。

curl -X POST https://walaora.com/api/v1/cards/ABCDE23456/earn \
  -H "Authorization: Bearer wl_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: receipt-10045" \
  -d '{"stamps": 1}'

重试与幂等性

对于 POST 请求,请发送 Idempotency-Key 请求头(任意唯一字符串,例如您的小票编号)。24 小时内使用相同的键重试,将返回原始响应,而不会重复盖章。

错误

错误会返回 JSON 正文 { error: { code, message } } 及相应的 HTTP 状态码:401 密钥无效 · 403 plan_required · 404 未找到 · 409 cooldown / no_reward / program_inactive · 422 校验失败 · 429 请求过于频繁。

Webhooks

在控制台中添加一个 HTTPS 端点并选择事件。每次推送都是一个携带 JSON { id, type, createdAt, data } 的 POST 请求,并包含以下请求头:Walaora-Event、Walaora-Delivery 和 Walaora-Signature。请在 10 秒内返回 2xx 响应。推送失败后,将在 1 分钟、5 分钟、30 分钟、2 小时和 12 小时后重试。

事件

验证签名(Node.js)

import crypto from "node:crypto";

// rawBody: the exact request body string; header: req.headers["walaora-signature"]
export function verifyWalaora(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // replay window
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 ?? ""));
}