DEVELOPER API

API 文档

通过以下 7 个商户接口查询余额与商品、创建订单并查询或下载卡密交付结果。

基础地址https://mailaohao.com/v1/merchant

调用约定

  • GET 查询接口携带 X-App-Id 和 X-Api-Key;API Key 只允许保存在商户服务端。
  • POST 写接口不发送 X-Api-Key,改用 X-Api-Timestamp、X-Api-Nonce 和 X-Api-Signature。
  • 写请求时间戳与服务器时间最多相差 300 秒;nonce 每次必须重新生成,重复 nonce 返回 HTTP 409。
  • 商户余额统一使用 USD;balanceCents、priceCents 和 chargedAmountCents 均以 0.01 USD 为单位。
  • 余额低于 10.00 USD 时,以上全部 7 个接口均返回 HTTP 402,包括余额查询接口。
  • USD 商品直接按美元分扣款;其他币种按后台最新汇率换算一次到 USD,并在数据库事务中原子扣款。
  • externalOrderNo 在同一 App ID 下必须唯一;相同编号仅允许重试完全相同的商品、规格和数量,否则返回 409。
  • 请求和响应均使用 UTF-8 JSON;POST 请求需设置 Content-Type: application/json。
  • 创建订单限制为每分钟最多 30 次;商品价格、库存、汇率和扣款金额以后端结果为准。
  • 服务端请求失败时返回 error.code 和 error.message,请按 HTTP 状态码处理。

GET 查询认证

X-App-Id: app_0123456789abcdef0123456789abcdef
X-Api-Key: key_your_api_key

POST 写请求签名

使用 API Key 对规范字符串执行 HMAC-SHA256。正文先按对象键递归排序并压缩为 JSON, 再计算 SHA-256;签名格式为 sha256=<64 位小写十六进制>

FAORBIT-HMAC-V1
<Unix 秒级时间戳>
<nonce>
POST
/v1/merchant/orders
<规范 JSON 正文的 SHA-256>
X-App-Id: app_0123456789abcdef0123456789abcdef
X-Api-Timestamp: 1786172400
X-Api-Nonce: 0123456789abcdef0123456789abcdef
X-Api-Signature: sha256=<HMAC-SHA256 结果>
Content-Type: application/json

Node.js 完整签名示例

import { createHash, createHmac, randomBytes } from "node:crypto";

const appId = process.env.FAORBIT_APP_ID;
const apiKey = process.env.FAORBIT_API_KEY;
const baseUrl = "https://mailaohao.com";
const path = "/v1/merchant/orders";
const body = {
  externalOrderNo: "merchant-order-1001",
  productId: "22222222-2222-4222-8222-222222222222",
  variantId: "33333333-3333-4333-8333-333333333333",
  quantity: 1
};

function stableJson(value) {
  if (value === null || typeof value !== "object") return JSON.stringify(value);
  if (Array.isArray(value)) return "[" + value.map(stableJson).join(",") + "]";
  return "{" + Object.keys(value).sort().map(
    (key) => JSON.stringify(key) + ":" + stableJson(value[key])
  ).join(",") + "}";
}

const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = randomBytes(16).toString("base64url");
const bodyHash = createHash("sha256").update(stableJson(body)).digest("hex");
const canonical = [
  "FAORBIT-HMAC-V1", timestamp, nonce, "POST", path, bodyHash
].join("\n");
const signature = "sha256=" + createHmac("sha256", apiKey)
  .update(canonical)
  .digest("hex");

const response = await fetch(baseUrl + path, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-App-Id": appId,
    "X-Api-Timestamp": timestamp,
    "X-Api-Nonce": nonce,
    "X-Api-Signature": signature
  },
  body: JSON.stringify(body)
});

Key 轮换与撤销

  • 管理员在 API 管理页点击“轮换”,新 API Key 只展示一次。
  • 可设置 0–10080 分钟旧 Key 宽限期;填 0 表示旧 Key 立即失效。
  • 停用凭证会立即撤销该 App ID 下的新旧 Key,全部接口返回 HTTP 401。
  • 尚未轮换的旧凭证暂时兼容原 POST 认证;轮换后请在宽限期结束前切换到 HMAC。

签名错误

  • MERCHANT_API_SIGNATURE_REQUIRED:写请求缺少签名头。
  • MERCHANT_API_SIGNATURE_EXPIRED:时间戳与服务器相差超过 300 秒。
  • MERCHANT_API_SIGNATURE_INVALID:请求头格式错误、正文被修改或使用了错误的 Key。
  • MERCHANT_API_REPLAY_DETECTED:nonce 已使用,必须生成新 nonce。

余额不足 10 USD

{
  "error": {
    "code": "MERCHANT_BALANCE_BELOW_ACCESS_MINIMUM",
    "message": "商户 USD 余额低于 10.00,暂时无法访问商户 API"
  }
}
01

查询商户余额

查询当前 App ID 对应的商户余额。余额统一按 USD 计算,balanceCents 以 0.01 USD 为单位。

GEThttps://mailaohao.com/v1/merchant/balance

无需参数

响应示例

{
  "appId": "app_0123456789abcdef0123456789abcdef",
  "merchantName": "示例商户",
  "balanceCents": 12850,
  "currency": "USD"
}
02

分类列表

仅获取该 App ID 所属店铺已开放的父分类和子分类;父分类未开放时,其子分类也不会返回。可使用 parentId 还原分类层级。

GEThttps://mailaohao.com/v1/merchant/categories

无需参数

响应示例

{
  "categories": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "parentId": null,
      "name": "Facebook",
      "slug": "facebook",
      "status": "active"
    }
  ]
}
03

商品列表

商品列表仅支持按子分类查询,且该子分类必须已对当前店铺开放。category 为必填的子分类 slug,不支持省略或传入父分类,也不接受其他店铺的分类;只返回该店铺已上架且所属分类已开放的商品,金额统一以 USD 返回。

GEThttps://mailaohao.com/v1/merchant/products

参数

字段是否必填说明
category查询参数:子分类 slug;不支持父分类,例如 facebook-accounts

响应示例

{
  "products": [
    {
      "id": "22222222-2222-4222-8222-222222222222",
      "categoryId": "11111111-1111-4111-8111-111111111111",
      "title": "商品名称",
      "slug": "product-slug",
      "priceCents": 150,
      "currency": "USD",
      "availableInventory": 25,
      "variants": []
    }
  ]
}
04

商品详情

按商品 slug 获取实时详情。仅允许访问该店铺已上架且所属分类已开放的商品,否则返回 404。下单前应重新获取,确认商品状态、USD 价格、库存和规格。

GEThttps://mailaohao.com/v1/merchant/products/{slug}

参数

字段是否必填说明
slug路径参数:商品唯一 slug

响应示例

{
  "product": {
    "id": "22222222-2222-4222-8222-222222222222",
    "title": "商品名称",
    "slug": "product-slug",
    "priceCents": 150,
    "currency": "USD",
    "availableInventory": 25,
    "variants": [
      {
        "id": "33333333-3333-4333-8333-333333333333",
        "name": "10 个",
        "priceCents": 1400,
        "availableInventory": 8,
        "quantityStep": 1
      }
    ]
  }
}
05

创建订单

使用 HMAC-SHA256 签名后创建订单,并立即使用商户 USD 余额付款。只能购买该店铺已上架且所属分类已开放的商品;USD 商品直接扣款,其他币种只换算一次到 USD;相同 externalOrderNo 重试不会重复扣款。

POSThttps://mailaohao.com/v1/merchant/orders

参数

字段是否必填说明
externalOrderNo商户侧唯一订单号,最长 120 个字符,仅支持 ASCII 字母、数字及 . _ : -;同编号重试必须保持商品、规格和数量一致
productId商品 UUID
variantId规格 UUID;多规格商品必填
quantity购买数量,1–1000

请求示例

{
  "externalOrderNo": "merchant-order-1001",
  "productId": "22222222-2222-4222-8222-222222222222",
  "variantId": "33333333-3333-4333-8333-333333333333",
  "quantity": 1
}

响应示例

{
  "externalOrderNo": "merchant-order-1001",
  "chargedAmountCents": 1400,
  "currency": "USD",
  "idempotent": false,
  "order": {
    "orderNo": "FO202608080001",
    "status": "paid",
    "totalAmountCents": 10080,
    "currency": "CNY"
  },
  "items": [
    {
      "productId": "22222222-2222-4222-8222-222222222222",
      "variantId": "33333333-3333-4333-8333-333333333333",
      "productTitle": "商品名称 · 10 个",
      "quantity": 1
    }
  ],
  "delivery": {
    "count": 0,
    "mode": "inline",
    "items": []
  }
}
06

查询订单

查询本 App ID 创建的订单状态和卡密。orderNo 可传商户订单号、平台订单号或平台订单 UUID;交付不超过 50 条时在 items 内返回,超过 50 条时通过 downloadUrl 下载。

GEThttps://mailaohao.com/v1/merchant/orders/{orderNo}

参数

字段是否必填说明
orderNo路径参数:商户订单号、平台订单号或订单 UUID

响应示例

{
  "externalOrderNo": "merchant-order-1001",
  "chargedAmountCents": 1400,
  "currency": "USD",
  "order": {
    "orderNo": "FO202608080001",
    "status": "completed"
  },
  "items": [
    {
      "productTitle": "商品名称 · 10 个",
      "quantity": 1
    }
  ],
  "delivery": {
    "count": 100,
    "mode": "download",
    "items": [],
    "downloadUrl": "/v1/merchant/orders/FO202608080001/delivery.txt"
  }
}
07

下载订单卡密

下载本 App ID 创建且已完成发货的订单卡密。使用与其他 GET 接口相同的认证请求头,响应为 UTF-8 纯文本,每行一条卡密;未完成发货时返回 HTTP 409。

GEThttps://mailaohao.com/v1/merchant/orders/{orderNo}/delivery.txt

参数

字段是否必填说明
orderNo路径参数:商户订单号、平台订单号或订单 UUID

响应示例

card-1
card-2