开放平台 API 第三方接入 2026-09-14

MaeTown 开放平台 API 接入文档

本文档面向接入 MaeTown 开放平台的第三方合作方开发者,说明如何完成账号绑定、商品报价、下单支付、订单状态查询等对接工作。

内部设计细节参见 docs/20260914_第三方开放平台接入API设计方案.md(内部工程文档,第三方开发者无需阅读)。

1. 概述

MaeTown 开放平台允许已经与我方签约的第三方平台,在自己的产品内为已拥有 MaeTown 账号的用户提供"一键购买"能力:由贵方展示商品信息,用户点击购买后,通过本文档描述的接口在 MaeTown 完成报价确认与余额支付,实际的采购、物流、售后仍由 MaeTown 承担。

接入前提

  • 用户必须已拥有 MaeTown 账号(手机号或微信注册均可),MaeTown 不提供免密自动开户,未注册用户需要先在 MaeTown 完成注册。
  • 支付方式固定为 MaeTown 账号余额支付,用户余额不足时下单会直接失败,不支持透支或使用信用额度。
  • 商品必须是 MaeTown 已支持的采购平台商品(即贵方需要知道商品所属平台的 platformCode,由我方在签约时提供对照表),不支持任意网址直接下单。

2. 接入准备

  1. 联系 MaeTown 商务/技术对接人完成签约,请提前准备好贵方用来接收授权绑定跳转回调的域名(见第4节的 redirectUrl),我方会在后台为贵方创建一个"渠道"并登记该域名,同时生成:
    • appKey:渠道身份标识,明文,长期使用
    • appSecret:签名密钥,仅在创建时展示一次,请妥善保存;一旦泄露请立即联系我方重置(重置后旧密钥立即失效)
    • 渠道编号(channelCode):账号绑定跳转链接中会用到
    • 出于安全考虑,redirectUrl 只有当其域名与我方登记的回调域名一致(或是其子域名)时,MaeTown 授权页才会自动跳转回去;不一致会被拒绝跳转,请确保贵方使用的回调域名和签约时登记的一致,域名变更需提前通知我方更新。
  2. 我方会同步提供当前支持的 platformCode 对照表(如 Mercari、Yahoo 等各平台对应的编码)。
  3. 所有开放 API 均为 HTTPS 接口,域名以我方实际提供的对接环境为准(测试环境/生产环境域名不同)。

3. 签名认证机制

所有 /openapi/** 接口都需要在 HTTP 请求头中携带签名信息,未通过验签的请求会被直接拒绝。

3.1 请求头

Header说明
X-App-Key分配给贵方的 appKey
X-Timestamp当前 Unix 时间戳(秒级
X-Nonce随机字符串,建议 UUID,每次请求必须唯一
X-Sign签名值,见下方计算方法

3.2 签名计算方法

  1. 收集全部参与签名的参数:
    • appKeytimestampnonce(即上面三个请求头的值,参数名不带 X- 前缀、小写)
    • GET 请求:全部 URL 查询参数
    • POST/PUT 请求:请求体 JSON 的所有顶层字段(要求请求体是扁平结构,不支持嵌套对象/数组作为签名参数——本期所有接口的入参都是扁平结构)
    • 不包含 sign 本身
  2. 按参数名的字典序(ASCII)排序,拼接成 key1=value1&key2=value2&... 的字符串
  3. 在末尾拼接 &key={appSecret}
  4. 对拼接后的完整字符串计算 HMAC-SHA256(密钥为 appSecret),取十六进制小写字符串,即为 X-Sign

伪代码示例:

params = { appKey: "xxx", timestamp: "1757836800", nonce: "a1b2c3", openUserId: "u_001", platformCode: "Mercari", goodsId: "m123456789" }
# 按 key 字典序排序后拼接
stringToSign = "appKey=xxx&goodsId=m123456789&nonce=a1b2c3&openUserId=u_001&platformCode=Mercari×tamp=1757836800&key={appSecret}"
sign = hex(hmac_sha256(stringToSign, key=appSecret))

3.3 校验规则(请注意,触发以下任一情况都会直接拒绝请求)

  • X-Timestamp 与服务器当前时间偏差超过 ±5分钟,判定为过期请求
  • 同一个 (appKey, nonce) 组合在 10分钟内重复出现,判定为重放请求(请确保 nonce 真正随机,不要固定值或自增序列)
  • 渠道不存在,或渠道已被我方停用
  • 签名值与服务端计算结果不一致

3.4 签名失败返回示例

{ "success": false, "code": 21007, "message": "E21007: 签名校验失败" }

4. 用户账号绑定

在调用报价/下单接口之前,用户必须先完成一次"授权绑定",把贵方的用户标识(openUserId,由贵方自行定义,只需保证在你方系统内唯一)关联到该用户的 MaeTown 账号。

4.1 绑定方式

绑定动作在 MaeTown 自己的页面上完成(用户输入手机号/微信登录等敏感操作全部发生在我方域名下,贵方拿不到用户的 MaeTown 账号密码,也拿不到任何 MaeTown 侧的登录凭证)。

推荐方式:调接口生成短链接(不用自己拼接又长又要手动URL编码的完整地址):

POST/openapi/auth/link

请求参数:

字段类型必填说明
openUserIdstring贵方的用户标识
redirectUrlstring绑定完成后跳回的地址,不需要自己做URL编码,接口内部会处理

返回数据(data):

字段类型说明
shortUrlstring短链接,直接嵌入商品卡片/推送消息,用户点击后会自动跳转到授权绑定页
expireSecondsint有效期(秒),当前为 604800(7天)

请求示例:

{ "openUserId": "u_10001", "redirectUrl": "https://partner.com/callback?userId=10001" }

返回示例:

{ "success": true, "code": 10000, "message": "操作成功", "data": { "shortUrl": "https://<我方接口域名>/web/openapi/authlink/1a2b3c4d5e", "expireSeconds": 604800 } }

短链接有效期内可以重复点击(不是一次性的),过期后需要重新调用本接口生成新的。

备用方式:自己拼接完整地址(如果不想多调一次接口):

https://<MaeTown-H5域名>/#/pages/openapi/auth/auth?channelCode={渠道编号}&openUserId={你方用户标识}&redirectUrl={绑定完成后跳回的地址}

具体域名以我方实际提供的对接环境为准;注意路由是hash模式(地址里有个 #);redirectUrl 需要自己做 URL 编码。

  1. 用户点击后:
    • 已安装 MaeTown App 且已登录:直接进入"确认绑定"页
    • 未安装/未登录:引导登录(手机验证码/微信/账号密码,MaeTown 现有登录方式),登录后进入"确认绑定"页
  2. 用户点击"确认授权"后,MaeTown 侧完成绑定,页面跳转回贵方提供的 redirectUrl
  3. 后续调用报价/下单接口时,只需要在业务参数里带上这个 openUserId,我方会自动换算成对应的 MaeTown 账号,贵方无需也不能感知具体是哪个账号

4.2 绑定的唯一性约束

  • 同一渠道下,一个 openUserId 只能绑定一个 MaeTown 账号;一个 MaeTown 账号在同一渠道下也只能绑定一个 openUserId
  • 用户可以随时在 MaeTown「我的 → 已授权的第三方平台」里自主解绑,解绑后该 openUserId 调用需要身份的接口会失败(报价接口不受影响,下单接口会报"绑定关系不存在"),需要引导用户重新走一遍绑定流程
  • MaeTown 客服也可能因用户投诉等原因发起强制解绑,贵方应对"绑定关系不存在"这个错误码做好兜底处理(引导用户重新授权),不要假设绑定关系永久有效

5. 接口列表

接口方法说明
/openapi/auth/linkPOST生成授权绑定短链接(见第4节)
/openapi/product/quotePOST商品报价
/openapi/order/payPOST下单 + 余额扣款
/openapi/order/statusGET订单状态查询

统一返回结构:

{
  "success": true,
  "code": 10000,
  "message": "操作成功",
  "data": { }
}

success=falsedata 通常为空,请以 code/message 判断具体错误原因(错误码见第7节)。

6. 接口详情

6.1 商品报价

POST/openapi/product/quote

下单前必须先调用本接口获取报价和 quoteToken,报价有一定时效性,避免用户确认购买时的价格与实际扣款价格不一致。

请求参数

字段类型必填说明
openUserIdstring贵方的用户标识
platformCodestring商品所属平台编码(我方提供的对照表)
goodsIdstring商品在该平台的 ID
countint购买数量,默认 1

请求示例

{
  "openUserId": "u_10001",
  "platformCode": "Mercari",
  "goodsId": "m123456789",
  "count": 1
}

返回数据(data)

字段类型说明
goodsNamestring商品标题
goodsImagestring商品图片
originalPricedecimal商品原价(原币种,如日元)
payPricedecimal应付价(含手续费/汇率折算后)
exchangeRatedecimal本次报价使用的汇率
quoteTokenstring报价凭证,下单时必须携带
expireSecondsint有效期(秒),当前为 600(10分钟)

返回示例

{
  "success": true,
  "code": 10000,
  "message": "操作成功",
  "data": {
    "goodsName": "任天堂 Switch 游戏卡带",
    "goodsImage": "https://xxx/goods.jpg",
    "originalPrice": 5980,
    "payPrice": 328.50,
    "exchangeRate": 0.048,
    "quoteToken": "1234567890123456789",
    "expireSeconds": 600
  }
}

重要说明

  • quoteToken 一次性使用,且10分钟内有效,过期或已被使用需要重新调用报价接口获取
  • 用户在贵方页面上停留过久才点击购买时,建议贵方在用户点击"立即购买"的那一刻才调用报价接口,而不是提前批量报价缓存

6.2 下单 + 余额扣款

POST/openapi/order/pay

请求参数

字段类型必填说明
openUserIdstring贵方的用户标识,须与报价接口传入的一致
quoteTokenstring报价接口返回的凭证

请求示例

{
  "openUserId": "u_10001",
  "quoteToken": "1234567890123456789"
}

返回数据(data)

字段类型说明
orderCodestringMaeTown 订单编号,后续查询状态用
orderStatusint订单状态码(见下方状态表)
orderStatusNamestring订单状态中文名称
payPricedecimal实际支付金额

返回示例

{
  "success": true,
  "code": 10000,
  "message": "操作成功",
  "data": {
    "orderCode": "MO20260914000123",
    "orderStatus": 9,
    "orderStatusName": "待采购",
    "payPrice": 328.50
  }
}

重要说明——同步结果 vs 后续状态变化

  • 本接口返回的是"下单+扣款"这一瞬间的结果:成功即代表余额已经扣款成功、订单已创建
  • 余额不足时接口会直接返回失败(见错误码 60001),请引导用户前往 MaeTown 完成余额充值后重新下单,不会自动重试或排队等待余额到账
  • 订单创建成功后,MaeTown 还会进行真实的"采购"(从对应电商平台买下商品)动作,采购结果(成功发货 / 采购失败退款)是异步的,本接口不会等待采购结果。请调用下方 6.3 订单状态查询接口轮询获取最新状态
  • 本期暂不提供状态变化的主动推送(webhook),需要贵方主动轮询;如果轮询体验有问题,请与我方对接人反馈,后续版本会评估补充主动通知能力

6.3 订单状态查询

GET/openapi/order/status?orderCode=MO20260914000123

请求参数

字段类型必填说明
orderCodestring下单接口返回的订单编号

(本接口无请求体,orderCode 作为签名参数的方式和请求头三项一起参与签名计算,见第3节)

返回数据(data)

字段类型说明
orderCodestring订单编号
orderStatusint订单状态码
orderStatusNamestring订单状态中文名称
payPricedecimal支付金额

订单状态码对照表(贵方只需重点关注是否到达"已发货"或"购买失败/已取消"这类终态,中间状态仅供展示参考)

状态码名称说明
8未支付正常不会出现(开放API下单即扣款)
9待采购已扣款,MaeTown 正在准备采购
10已采购待发货采购成功
11已发货待入库已从海外发出,正在往 MaeTown 仓库运输
12已入库已到达 MaeTown 仓库
16交易完成全流程完成(终态)
21已取消订单取消,会有相应退款处理(终态)
25购买失败采购失败(如商品被抢先买走),会自动退款到用户余额(终态)

说明:只有贵方渠道自己带来的订单才能查询到,查询他人订单会返回"订单来源记录不存在"的错误。

7. 错误码

7.1 开放平台专属错误码(21xxx)

code说明建议处理方式
21000渠道不存在检查 appKey 是否正确
21001渠道已停用联系我方对接人确认渠道状态
21004签名参数缺失检查请求头是否完整携带四项签名信息
21005请求时间戳已过期检查本地服务器时间是否准确(NTP同步),偏差需在±5分钟内
21006请求已被处理,请勿重复提交检查 nonce 是否真正随机、未复用
21007签名校验失败检查签名算法、参数拼接顺序、appSecret 是否正确
21008绑定关系不存在引导用户重新走一遍第4节的授权绑定流程
21009该账号已绑定此渠道通常发生在重复调用绑定确认接口时,可忽略
21011报价已过期,请重新获取quoteToken 超过10分钟未使用,重新调用报价接口
21012报价已被使用,请重新获取quoteToken 只能使用一次,重新调用报价接口
21013订单来源记录不存在查询了不属于本渠道的订单,检查 orderCode 来源
21016商品链接解析失败platformCode/goodsId 有误,或该商品已下架/不存在
21017请求过于频繁,请稍后再试触发了按渠道维度的限流(默认每渠道每60秒最多120次请求,含报价/下单/查询三个接口合计),降低调用频率后重试;如果贵方业务量确实需要更高的限额,请联系我方对接人评估调整
21018授权链接不存在或已过期短链接有效期7天,过期需要重新调用 /openapi/auth/link 生成新的(这个错误只会出现在用户浏览器点击短链接时,不是调用签名API时返回的)

7.2 常见通用错误码

code说明
10000成功
60001用户余额不足
11009订单不存在

8. 典型调用时序

① 用户在贵方App/H5浏览商品(数据来自贵方自己的订阅/推送) ② 用户点击"去MaeTown购买" → 跳转MaeTown授权页(见4.1) → 用户确认绑定 → 跳回贵方页面 (已绑定过的老用户跳过这一步) ③ 用户点击"立即购买" → 贵方后端调用 /openapi/product/quote → 展示报价给用户确认 ④ 用户确认购买 → 贵方后端调用 /openapi/order/pay(携带③返回的quoteToken) ⑤ 贵方展示"下单成功,正在为你采购",并保存返回的 orderCode ⑥ 贵方定时轮询 /openapi/order/status,更新展示给用户的订单状态,直到终态

9. 联调与上线检查清单

  • 已拿到测试环境的 appKey/appSecret,并确认签名算法联调通过(可先用 /openapi/order/status 查一个不存在的订单号,确认能收到签名校验通过、但订单不存在的响应,验证签名链路本身是通的)
  • 已确认所需商品对应的 platformCode 在我方支持范围内
  • 已实现绑定跳转链接的拼接与 redirectUrl 回调处理
  • 已实现余额不足、报价过期、绑定关系不存在等异常情况的用户引导文案
  • 已实现订单状态轮询机制(建议间隔不低于30秒,避免过于频繁的请求触发限流)

如有疑问请联系 MaeTown 技术对接人。