跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://docs.waffo.ai/llms.txt

Use this file to discover all available pages before exploring further.

认证概述

Waffo Pancake 支持两种 API 访问认证方式:
方式使用场景说明
API Key服务端到服务端调用使用 RSA-SHA256 签名的永久认证方式
Store Slug公开结账流程使用 X-Store-SlugX-Environment 请求头的公开访问方式

API Key 认证

API Key 提供基于 RSA-SHA256 签名的永久服务端到服务端认证。私钥始终保存在您的服务器上。

请求头

X-Merchant-Id: MER_2aUyqjCzEIiEcYMKj7TZtw
X-Timestamp: 1705312200
X-Signature: BASE64_ENCODED_SIGNATURE
Content-Type: application/json
API Key 认证不需要 X-Environment 请求头。 每个 API Key 在创建时已绑定到 test 或 prod 环境。系统通过验证签名成功的密钥来确定环境。

使用 SDK(推荐)

import { WaffoPancake } from "@waffo/pancake-ts";

const client = new WaffoPancake({
  merchantId: process.env.WAFFO_MERCHANT_ID!,
  privateKey: process.env.WAFFO_PRIVATE_KEY!,
});

// All requests are automatically signed
const { store } = await client.stores.create({ name: "My Store" });

签名算法(手动集成)

如果您不使用 SDK,需要自行实现 RSA-SHA256 请求签名:
1. Build the canonical request:
   canonicalRequest = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + SHA256_BASE64(BODY)

2. Sign with RSA-SHA256:
   signature = RSA-SHA256(canonicalRequest, privateKey)

3. Base64 encode:
   X-Signature = Base64(signature)

手动签名示例

const crypto = require('crypto');

const MERCHANT_ID = 'MER_2aUyqjCzEIiEcYMKj7TZtw';
const PRIVATE_KEY = `-----BEGIN RSA PRIVATE KEY-----
...your private key...
-----END RSA PRIVATE KEY-----`;

async function callApiWithSignature(method, path, body) {
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const bodyStr = JSON.stringify(body);
  const bodyHash = crypto.createHash('sha256').update(bodyStr).digest('base64');

  // Build canonical request
  const canonicalRequest = `${method}\n${path}\n${timestamp}\n${bodyHash}`;

  // RSA-SHA256 sign
  const signature = crypto.sign('sha256', Buffer.from(canonicalRequest), PRIVATE_KEY).toString('base64');

  const response = await fetch(`https://api.waffo.ai${path}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
      'X-Merchant-Id': MERCHANT_ID,
      'X-Timestamp': timestamp,
      'X-Signature': signature
    },
    body: bodyStr
  });

  return response.json();
}

// Usage
const result = await callApiWithSignature('POST', '/v1/actions/store/create-store', {
  name: 'My Store'
});
私钥安全
  • 切勿在客户端代码中暴露私钥
  • 不要将私钥提交到版本控制系统
  • 将私钥存储在环境变量中
  • 定期轮换密钥,尤其是团队人员变动后
  • 时间戳必须在服务器时间的 5 分钟以内

Store Slug 认证

对于面向公众的结账流程,使用 Store Slug 认证。这允许访客在无需 API Key 凭证的情况下创建结账会话和查询公开的门店数据。

请求头

X-Store-Slug: my-awesome-store-k8x2m9ab
X-Environment: test | prod
Content-Type: application/json

示例

curl -X POST https://api.waffo.ai/v1/actions/checkout/create-session \
  -H "X-Store-Slug: my-awesome-store-k8x2m9ab" \
  -H "X-Environment: test" \
  -H "Content-Type: application/json" \
  -d '{"productId": "PROD_4cWAslE1GKkGeaOMl9Vbmy", "productType": "onetime", "currency": "USD"}'

创建 API Key

1

进入开发者页面

导航至 Dashboard → Merchant → Integration → API Keys
2

创建 API Key

点击 “Create API Key” 生成新的 RSA 密钥对。公钥会自动发送到服务器。
3

命名和配置

为其设置一个描述性名称(例如 “Production Server”),并选择目标环境(Test 或 Production)。
4

下载私钥

立即下载您的私钥。 私钥不会再次显示。
删除 API Key 是即时且不可逆的操作。使用已删除密钥签名的所有请求都将返回 401 Unauthorized

认证方式对比

功能API KeyStore Slug
服务端使用
客户端使用
需要 X-Environment
签发 Session Token
创建 Checkout Session
商品管理
GraphQL 查询是(仅公开数据)
有效期永久(密钥控制)-

认证错误

状态码错误解决方案
401Invalid signature检查签名算法、私钥和时间戳新鲜度(5 分钟窗口)
401Invalid or expired token重新认证或使用有效的 API Key
403Insufficient permissions检查角色是否有权访问该端点
400Missing authentication确保所需的请求头已提供
{
  "data": null,
  "errors": [
    {
      "message": "Invalid signature",
      "layer": "gateway"
    }
  ]
}

安全最佳实践

  1. 切勿暴露私钥 — 不要放在客户端代码、版本控制或公开仓库中
  2. 使用 HTTPS 进行所有 API 请求
  3. 验证 Webhook 签名 以防止伪造请求
  4. 分离测试和生产密钥 — 为每个环境创建独立的密钥
  5. 定期轮换密钥,尤其是团队成员变动后
  6. 监控 API 使用情况 — 在 Dashboard 中查看异常活动