登录 注册

API 文档

用程序读取商品、查询库存、自动下单和取货。适合把本站商品接到你自己的网站、机器人或管理系统。

快速开始

  1. 登录后打开 个人资料,复制 API-ID 和 API密钥。
  2. 按 签名算法 计算签名,调用 账号信息 接口。返回 code: 200 就说明已接通。
  3. 调用 商品列表 拿到 SKU 的 id、你的进货价和下单需要填写的控件。
  4. 充值账户余额。下单时直接从余额扣款,没有单独的支付步骤。
  5. 调用 下单 接口。自动发货的商品会在返回的 contents 里直接给出内容。
API密钥 等同于账户的扣款权限,只能放在服务器上,不要写进网页、App 或公开的代码仓库。

调用约定

项目说明
接口地址https://maitg.com
请求方法全部使用 POST,其他方法返回 HTTP 405
参数格式application/x-www-form-urlencoded 表单。不支持 JSON 请求体,发 JSON 会提示签名验证失败
字符编码UTF-8
请求头 Api-Id你的 API-ID,也就是用户 ID
请求头 Api-Signature32 位小写 MD5 签名

返回格式

所有接口都返回 JSON。请以 code 判断成败:200 成功,0 失败,失败原因在 msg 里。业务失败时 HTTP 状态码同样是 200。

{"code": 200, "msg": "success", "data": {}}
{"code": 0, "msg": "签名验证失败"}

签名算法

  1. 取本次 POST 的全部参数,去掉 sign、值为空字符串的参数和数组参数。
  2. 按参数名升序排序,用 参数名=参数值 的形式以 & 连接。这里的值用原文,不做 URL 编码。
  3. 在末尾加上 &key=你的API密钥。
  4. 对整个字符串做 MD5,结果放进请求头 Api-Signature。

示例

API 密钥为 your_api_secret,参数为 sku_id=92、quantity=1、trade_no=2611040a1b2c3d4e5f60718293a4b5c6d7e8f9:

待签名:quantity=1&sku_id=92&trade_no=2611040a1b2c3d4e5f60718293a4b5c6d7e8f9&key=your_api_secret
签名:  3eb7b4b2f1dc144e15561365049c3021

没有任何参数时(如账号信息接口),待签名字符串就是 &key=your_api_secret,签名为 a9b1ca478d18596e13ab947246104ae8。

参数值里不要带 <、> 等 HTML 字符。服务器会先过滤这些字符再验签,签名会对不上。

代码示例

<?php
function sign(array $params, string $secret): string
{
    unset($params['sign']);
    ksort($params);
    $pairs = [];
    foreach ($params as $key => $value) {
        if ($value !== '' && !is_array($value)) {
            $pairs[] = $key . '=' . $value;
        }
    }
    return md5(implode('&', $pairs) . '&key=' . $secret);
}

$params = ['page' => 1, 'limit' => 20];
$ch = curl_init('https://maitg.com/plugin/open-api/items');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($params),
    CURLOPT_HTTPHEADER => [
        'Api-Id: 你的API-ID',
        'Api-Signature: ' . sign($params, '你的API密钥'),
    ],
]);
$result = json_decode(curl_exec($ch), true);
import hashlib
import requests

def sign(params, secret):
    pairs = [f"{k}={params[k]}" for k in sorted(params)
             if k != "sign" and params[k] != "" and not isinstance(params[k], (list, dict))]
    return hashlib.md5(("&".join(pairs) + "&key=" + secret).encode("utf-8")).hexdigest()

params = {"page": 1, "limit": 20}
result = requests.post(
    "https://maitg.com/plugin/open-api/items",
    data=params,
    headers={"Api-Id": "你的API-ID", "Api-Signature": sign(params, "你的API密钥")},
    timeout=30,
).json()
const crypto = require('crypto');

function sign(params, secret) {
  const pairs = Object.keys(params).sort()
    .filter((k) => k !== 'sign' && params[k] !== '' && typeof params[k] !== 'object')
    .map((k) => k + '=' + params[k]);
  return crypto.createHash('md5').update(pairs.join('&') + '&key=' + secret, 'utf8').digest('hex');
}

const params = { page: 1, limit: 20 };
const response = await fetch('https://maitg.com/plugin/open-api/items', {
  method: 'POST',
  headers: { 'Api-Id': '你的API-ID', 'Api-Signature': sign(params, '你的API密钥') },
  body: new URLSearchParams(params),
});
const result = await response.json();
API_ID='你的API-ID'
API_KEY='你的API密钥'
SIGN=$(printf '%s' "limit=20&page=1&key=$API_KEY" | md5sum | cut -d' ' -f1)

curl -X POST 'https://maitg.com/plugin/open-api/items' \
  -H "Api-Id: $API_ID" \
  -H "Api-Signature: $SIGN" \
  -d 'page=1' -d 'limit=20'

账号信息

POST/plugin/open-api/connect

无参数。常用来检查密钥是否正确和读取当前余额。

{"code": 200, "msg": "success", "data": {"username": "demo", "balance": "100.00"}}

商品列表

POST/plugin/open-api/items

返回当前账号可以进货的全部商品,价格已按你的用户组、等级和专属价计算。商品多时请使用分页。

参数必填类型说明
page否int页码,从 1 开始,最大 1000
limit否int每页数量,1~100,只传 page 时默认 100

两个参数都不传时返回全部商品,这种方式每 5 秒只能调用一次。分页时 data 不足 limit 条不一定代表已到末页,因为没有可售 SKU 的商品会被隐藏,请翻到 data 为空为止。

商品字段

字段类型说明
idint商品 ID,用于 商品详情
namestring商品名称
introducestring商品介绍,HTML 格式
picture_url / picture_thumb_urlstring商品图和缩略图
widgetstring下单控件,JSON 字符串,需要再解析一次,见 下单控件
attrstring商品属性,JSON 字符串
repertory_category_idint分类 ID
categoryobject分类信息:id、name、icon
skuarray规格列表,下单用的是这里的 id

SKU 字段

字段类型说明
idintSKU ID,下单和查库存时传给 sku_id
namestring规格名称
stock_pricestring你的进货单价
stockstring库存(缓存值)。可能是数字,也可能是“充足”这类文字
picture_url / picture_thumb_urlstring规格图和缩略图
messagestring | null规格备注
market_controlbool是否启用了控价和限购。为 true 时下面几项才生效
market_control_min_price / market_control_max_pricestring允许的最低、最高售价
market_control_min_num / market_control_max_numint单次最少、最多购买数量,0 表示不限
market_control_only_numint累计限购数量,0 表示不限

返回示例

{
  "code": 200,
  "msg": "success",
  "data": [{
    "id": 71,
    "name": "示例商品",
    "introduce": "<p>商品介绍</p>",
    "widget": "[]",
    "attr": "[]",
    "picture_url": "/favicon.ico",
    "picture_thumb_url": "/favicon.ico",
    "repertory_category_id": 8,
    "category": {"id": 8, "name": "默认分类", "icon": "/favicon.ico"},
    "sku": [{
      "id": 92,
      "name": "默认规格",
      "stock_price": "3.5",
      "stock": "22",
      "message": null,
      "market_control": false,
      "market_control_min_num": 0,
      "market_control_max_num": 0,
      "market_control_only_num": 0
    }]
  }]
}

下单控件

有些商品下单时要填写内容,比如充值账号。把 widget 解析成数组后,每个控件的 name 就是下单时要多传的参数名。设置了 regex 的控件必填,不符合规则时下单会失败,提示内容就是 error。

[{"name": "account", "title": "充值账号", "type": "text", "placeholder": "请输入账号", "regex": "^\\d+$", "error": "账号格式不正确"}]

商品详情

POST/plugin/open-api/item
参数必填类型说明
id是int商品 ID,不是 SKU ID

data 是单个商品对象,字段同 商品列表。商品不存在或你无权进货时返回“货源不存在”。

SKU 库存

POST/plugin/open-api/sku/stock
参数必填类型说明
sku_id是intSKU ID
{"code": 200, "msg": "success", "data": {"stock": "22"}}

stock 是字符串,可能是数字,也可能是“充足”这类文字,由商品的库存显示设置决定,而且是缓存值,可能有短暂延迟。

SKU 是否可买

POST/plugin/open-api/sku/state
参数必填类型说明
sku_id是intSKU ID
quantity否int购买数量,默认 1
{"code": 200, "msg": "success", "data": {"state": true}}
这个结果按 SKU 缓存,不能当作数量校验:刚查过 1 件后马上查一个很大的数量,也可能返回 true。批量购买前请用 SKU 库存 里的数字核对。

下单

POST/plugin/open-api/trade

从账户余额扣款并发货。

参数必填类型说明
sku_id是intSKU ID
quantity否int购买数量,默认 1
trade_no是string你自己生成的订单号:6 位日期 + 32 位字母数字(共 38 位),如 2611040a1b2c3d4e5f60718293a4b5c6d7e8f9。历史的 24 位订单号也可以用
async_url否string接收 异步通知 的地址,必须是可公网访问的 http 或 https 地址,不支持内网地址,也不跟随跳转
控件参数视商品string参数名取自 下单控件 的 name

返回字段

字段类型说明
contentsstring发货内容,多张卡密用换行分隔。未发货时是提示文字,请结合 status 判断
statusint订单状态,见 订单状态
trade_nostring本站系统生成的订单号
item_trade_nostring你传入的 trade_no
amountstring实际扣款金额
trade_timestring下单时间
{
  "code": 200,
  "msg": "success",
  "data": {
    "contents": "CARD-0001\nCARD-0002",
    "status": 1,
    "trade_no": "261104YfSD460SEsnHwa8fSPcEfnjO2iSWbyZl",
    "item_trade_no": "2611040a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "amount": "3.00",
    "trade_time": "2026-11-04 18:24:40"
  }
}

务必注意

  • code: 200 只代表订单已创建并已扣款,不代表已发货。一定要再判断 status。
  • 库存不足时直接拒单。下单时按实际购买数量校验库存,不够就返回 code: 0,不扣款、不生成订单。这个订单号没有被占用,补货后可以继续使用。
  • 订单号不能重复。重复提交会返回“订单号已存在”,不会再次扣款。如果请求超时、不确定结果,请用同一个 trade_no 调用 查询订单 确认后再决定是否重下。
  • 余额不足、商品下架、控件校验不通过时同样返回 code: 0,不会扣款。
  • 多人同时抢购时可能返回“当前下单繁忙”(code: 0),同样不扣款,稍后用同一个 trade_no 重试即可。
  • 库存校验通过后,如果上游发货出错,订单已经创建并扣款:返回 code: 200、未发货的 status,contents 是提示文字,请联系客服或申请售后。

查询订单

POST/plugin/open-api/query
参数必填类型说明
trade_no是string下单时你传入的订单号,不是返回的系统订单号
{"code": 200, "msg": "success", "data": {"contents": "CARD-0001", "status": 1, "trade_time": "2026-11-04 18:24:39"}}

只能查询自己账号下的订单,查不到时返回“订单不存在”。

异步通知

下单时传了 async_url,之后订单状态变化(如人工发货、退款)时,本站会向这个地址发一次 POST 表单。

下单时当场完成的自动发货不会触发通知,结果直接在下单接口的返回里。通知的超时时间是 5 秒,失败后不会重发,所以对未完成的订单请同时用 查询订单 定时兜底。
字段类型说明
statusint订单状态
contentsstring发货内容
item_trade_nostring你的订单号
trade_nostring本站系统订单号
amountstring订单金额
trade_timestring下单时间

验证来源

请求头 Api-Signature 是用你的 API 密钥按 相同算法 对上面字段计算的签名。收到通知后请先验签,再处理订单。同一笔订单可能收到多次通知,请按 item_trade_no 和 status 去重。

<?php
$signature = $_SERVER['HTTP_API_SIGNATURE'] ?? '';
if (!hash_equals(sign($_POST, '你的API密钥'), strtolower($signature))) {
    http_response_code(403);
    exit('invalid signature');
}
// 处理订单 $_POST['item_trade_no']
echo 'ok';

订单状态

status含义建议处理
0等待发货人工发货、上游处理中,或上游发货出错。稍后查询,长时间不变请联系客服
1已发货读取 contents
2发货失败联系客服或申请售后
3已退款款项已退回,结束订单

频率限制

按账号计算。所有接口合计每秒最多 30 次,单个接口的限制如下。超出后返回 HTTP 429,Retry-After 响应头是需要等待的秒数。

接口限制
/items 分页每秒 2 次
/items 不分页每 5 秒 1 次
/item每秒 10 次
/sku/stock、/sku/state各每秒 15 次
/trade每秒 10 次
/query每秒 20 次
/connect每秒 10 次

站点在高负载时还有整体保护,同样返回 HTTP 429。请按 Retry-After 等待后重试,不要循环猛刷。

错误处理

HTTP提示原因和处理
401鉴权参数无效缺少 Api-Id 或 Api-Signature,或格式不对
405请求方法不允许没有使用 POST
429请求过于频繁见 频率限制
200签名验证失败对照 示例 检查排序、空值、密钥,以及是否误发了 JSON
200未找到该用户Api-Id 填错
200您的账号暂不可用账号被停用,请联系客服
200缺少SKU-ID / SKU 不存在检查 sku_id,注意不是商品 ID
200订单号必须是历史24位或新版38位格式按 下单 里的格式生成 trade_no
200订单号已存在更换订单号,或用 查询订单 取结果
200订单不存在订单号有误,或不是当前账号的订单

旧版协议

已经对接旧版萌次元 V3/V4 协议的程序可以继续使用,填写站点根地址和同一组 API-ID、API 密钥即可。新项目请使用上面的接口。

鉴权方式不同:所有接口都在 POST 参数里传 app_id、app_key 和 sign,签名算法相同,app_id 和 app_key 也要参与签名。

接口业务参数返回 data
/shared/commodity/connect无username、balance
/shared/commodity/items无按分类分组的商品,每个 SKU 一条
/shared/commodity/itemcode 或 sharedCode(SKU ID)单个商品
/shared/commodity/stockcodestock
/shared/commodity/inventorysharedCodecount
/shared/commodity/inventoryStateshared_code、numstate
/shared/commodity/tradeshared_code、num、request_no(你的订单号,64 位以内)secret(发货内容)

旧版下单和新接口有两点不同:除库存不足外,发货失败时也直接报错、不扣款;重复提交相同的 request_no 会返回原订单内容。