1. 概述
澜湄联盟官网对外开放数据接口,供第三方系统调用获取联盟相关数据。
open.api.auth-enabled=true 即可。
| 项目 | 说明 |
|---|---|
| 接口前缀 | /api/open/v1/** |
| Base URL | https://lm.linkco.yoois.com(请替换为实际域名) |
| 认证方式 | 默认关闭;可配置 auth-enabled: true 启用 HMAC 签名 |
| 权限控制 | 鉴权开启后,后台为每个应用勾选 Scope |
| 响应格式 | JSON,统一 { code, message, data } 包装 |
架构示意(鉴权开启时)
2. 管理后台使用
鉴权开启后,需在管理后台创建应用并分配权限。入口:系统管理 → 开放接口。
2.1 创建应用
- 进入 系统管理 → 开放接口
- 点击 创建应用,填写应用名称
- 勾选 数据权限(Scope)
- 保存后弹窗展示 AppId 和 AppSecret(仅展示一次,请立即复制保存)
2.2 应用配置项
| 字段 | 说明 |
|---|---|
| 应用名称 | 合作方名称,如「XX 旅游平台」 |
| 状态 | 启用 / 禁用 |
| 限流/分钟 | 默认 100 次/分钟 |
| IP 白名单 | 逗号分隔,留空不限制 |
| 过期时间 | 留空表示永不过期 |
| 数据权限 | Scope 多选,可随时调整 |
3. 鉴权开关
open:
api:
auth-enabled: true # 或环境变量 OPEN_API_AUTH_ENABLED=true
4. 签名认证(auth-enabled=true 时生效)
4.1 请求 Header
| Header | 说明 |
|---|---|
X-App-Id |
应用 AppId,如 lm_a1b2c3d4e5f6 |
X-Timestamp |
Unix 时间戳(秒),与服务端时差 ≤ 300 秒 |
X-Nonce |
随机字符串,16~32 位,不可重复使用 |
X-Sign |
HMAC-SHA256 签名,十六进制小写 |
4.2 签名算法
signContent = appId + "\n"
+ timestamp + "\n"
+ nonce + "\n"
+ METHOD + "\n"
+ path + "\n"
+ sortedQueryString + "\n"
+ sha256(body)
sign = HMAC-SHA256(appSecret, signContent).toHexLowerCase()
- path:不含域名,如
/api/open/v1/regions/countries - sortedQueryString:Query 参数按 key 字典序,URL 编码后用
&连接;无参数时为空字符串 - body:GET 为空字符串的 SHA256;POST/PUT 为 raw body 的 SHA256
5. 接口列表
5.1 快速开始(当前无需鉴权)
直接 GET 请求即可,示例(请将域名替换为实际地址):
5.2 连通性测试
鉴权开启时用于验证 AppId 与签名是否正确。
5.3 地区数据 已开放
鉴权开启时需 Scope:region:read
| 方法 | 路径 | 参数 | 说明 |
|---|---|---|---|
| GET | /api/open/v1/regions/countries |
lang(默认 zh-CN) |
六国国家列表(level=1) |
| GET | /api/open/v1/regions/children |
parentId(必填)、lang |
子级地区(省州等) |
响应示例 — countries
{
"code": 200,
"message": "success",
"data": [
{ "id": 1, "code": "CN", "name": "中国", "sort": 1 },
{ "id": 2, "code": "TH", "name": "泰国", "sort": 2 }
]
}
响应示例 — children
{
"code": 200,
"message": "success",
"data": [
{ "id": 10, "code": "110000", "name": "北京市", "parentId": 1, "level": 2, "sort": 1 }
]
}
5.4 CMS 分类 已开放
鉴权开启时需 Scope:cms:category:read
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/open/v1/cms/category |
分类树,支持 lang |
| GET | /api/open/v1/cms/category/slug/{slug} |
按 slug 获取分类详情 + i18n |
字段说明 — category 节点
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 分类 ID |
parentId |
number | 父级 ID,0 表示顶级 |
slug |
string | URL 标识,可为空 |
name |
string | 分类名称(按 lang 参数回填,fallback:请求语言 → en → 任意可用语言) |
sort |
number | 排序值,升序 |
status |
number | 状态,1=启用(接口仅返回启用分类) |
children |
array | 子分类列表,树形嵌套;无子级时为 [] |
createTime |
string | 创建时间 |
updateTime |
string | 更新时间 |
deleted |
null | 逻辑删除标记,正常数据为 null |
响应示例 — category 树(完整数据,lang=zh-CN)
GET /api/open/v1/cms/category?lang=zh-CN
{
"code": 200,
"message": "Success",
"data": [
{
"id": 1,
"deleted": null,
"createTime": "2026-05-16 09:28:29",
"updateTime": "2026-07-05 17:06:11",
"parentId": 0,
"slug": "news",
"sort": 0,
"status": 1,
"name": "中国文旅",
"children": []
},
{
"id": 2,
"deleted": null,
"createTime": "2026-06-01 17:03:31",
"updateTime": "2026-07-01 20:45:42",
"parentId": 0,
"slug": "other_news",
"sort": 0,
"status": 1,
"name": "国际视野",
"children": []
},
{
"id": 9,
"deleted": null,
"createTime": "2026-07-05 17:06:23",
"updateTime": "2026-07-05 17:06:23",
"parentId": 0,
"slug": "",
"sort": 0,
"status": 1,
"name": "柬埔寨文旅",
"children": []
},
{
"id": 11,
"deleted": null,
"createTime": "2026-07-05 17:06:44",
"updateTime": "2026-07-05 17:06:44",
"parentId": 0,
"slug": "老挝文旅",
"sort": 0,
"status": 1,
"name": "老挝文旅",
"children": []
},
{
"id": 12,
"deleted": null,
"createTime": "2026-07-05 17:06:55",
"updateTime": "2026-07-05 17:06:55",
"parentId": 0,
"slug": "缅甸文旅",
"sort": 0,
"status": 1,
"name": "Category-12",
"children": []
},
{
"id": 13,
"deleted": null,
"createTime": "2026-07-05 17:07:02",
"updateTime": "2026-07-05 17:07:02",
"parentId": 0,
"slug": "泰国文旅",
"sort": 0,
"status": 1,
"name": "Category-13",
"children": []
},
{
"id": 14,
"deleted": null,
"createTime": "2026-07-05 17:07:12",
"updateTime": "2026-07-05 17:07:12",
"parentId": 0,
"slug": "越南文旅",
"sort": 0,
"status": 1,
"name": "Category-14",
"children": []
}
]
}
5.5 CMS 标签 已开放
鉴权开启时需 Scope:cms:tag:read
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/open/v1/cms/tag |
标签列表,支持 lang |
| GET | /api/open/v1/cms/tag/slug/{slug} |
按 slug 获取标签详情 + i18n |
字段说明 — tag 节点
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 标签 ID |
slug |
string | URL 标识,可为空 |
name |
string | 标签名称(按 lang 参数回填,fallback:请求语言 → en → 任意可用语言) |
sort |
number | 排序值,升序 |
status |
number | 状态,1=启用(接口仅返回启用标签) |
createTime |
string | 创建时间 |
updateTime |
string | 更新时间 |
deleted |
null | 逻辑删除标记,正常数据为 null |
响应示例 — tag 列表(lang=zh-CN)
GET /api/open/v1/cms/tag?lang=zh-CN
{
"code": 200,
"message": "Success",
"data": [
{
"id": 1,
"deleted": null,
"createTime": "2026-07-05 10:00:00",
"updateTime": "2026-07-05 10:00:00",
"slug": "tag1",
"sort": 0,
"status": 1,
"name": "标签一"
},
{
"id": 2,
"deleted": null,
"createTime": "2026-07-05 10:00:00",
"updateTime": "2026-07-05 10:00:00",
"slug": "tag2",
"sort": 1,
"status": 1,
"name": "标签二"
},
{
"id": 3,
"deleted": null,
"createTime": "2026-07-05 10:00:00",
"updateTime": "2026-07-05 10:00:00",
"slug": "policy_updates",
"sort": 2,
"status": 1,
"name": "政策动态"
}
]
}
5.6 CMS 文章推送 已开放
允许外部第三方平台通过 Open API 将文章推送到澜湄联盟平台,支持创建和更新操作。
鉴权开启时需 Scope:cms:article:write
cms:article:write。
创建成功后会返回平台生成的文章 id,请务必保存,后续更新需要用它。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/open/v1/cms/article/{id} |
获取文章详情(主表 + 全语言 i18n + 标签) |
| POST | /api/open/v1/cms/article |
推送/创建文章 |
| PUT | /api/open/v1/cms/article/{id} |
更新文章(部分更新,仅覆盖传入字段;i18n 按语言增量更新) |
| DELETE | /api/open/v1/cms/article/{id} |
撤稿(逻辑删除,级联清理 i18n 与 tag 关联) |
请求参数(JSON Body)
下表字段同时适用于创建与更新接口。创建时 categoryId、i18n 为必填;更新时为部分更新,所有字段均可选,仅传入字段被覆盖。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
categoryId |
Long | 创建:是 / 更新:否 | 平台分类 ID(必须存在且 status=1) |
coverImg |
String | 否 | 封面图 URL |
isRecommend |
Integer | 否 | 是否推荐,默认 0 |
isTop |
Integer | 否 | 是否置顶,默认 0 |
sort |
Long | 否 | 排序值,默认 0(取值范围较 Integer 更大) |
status |
Integer | 否 | 发布状态:1=直接发布,0=草稿,默认 1 |
publishTime |
String | 否 | 发布时间(格式 yyyy-MM-dd HH:mm:ss),默认当前时间 |
tagIds |
List<Long> | 否 | 标签 ID 列表(必须存在且 status=1) |
i18n |
List<I18n> | 创建:是 / 更新:否 | 多语言内容。更新时仅传需修改的语言条目(按 lang 增量更新),未传入语言保持不变;新增语言时该条目的 title 必填 |
I18n 子对象
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
lang |
String | 是 | 语言代码(如 zh-CN, en, th, vi, my, lo, km) |
title |
String | 是 | 标题 |
subtitle |
String | 否 | 副标题 |
summary |
String | 否 | 摘要 |
content |
String | 否 | 正文 HTML 内容 |
author |
String | 否 | 作者 |
source |
String | 否 | 来源平台名称 |
seoTitle |
String | 否 | SEO 标题 |
seoKeywords |
String | 否 | SEO 关键词 |
seoDescription |
String | 否 | SEO 描述 |
请求示例 — 推送文章
POST /api/open/v1/cms/article
Content-Type: application/json
{
"categoryId": 1,
"coverImg": "https://example.com/cover.jpg",
"isRecommend": 0,
"isTop": 0,
"sort": 0,
"status": 1,
"publishTime": "2026-08-05 10:00:00",
"tagIds": [1, 2],
"i18n": [
{
"lang": "zh-CN",
"title": "澜湄合作新进展",
"subtitle": "多国共同推进区域互联互通",
"summary": "近日,澜湄合作机制迎来新进展...",
"content": "<p>详细正文内容...</p>",
"author": "联盟秘书处",
"source": "合作伙伴平台A",
"seoTitle": "澜湄合作新进展 - 官网",
"seoKeywords": "澜湄,合作,区域互联",
"seoDescription": "澜湄合作机制最新进展报告"
},
{
"lang": "en",
"title": "New Progress in Lancang-Mekong Cooperation",
"subtitle": "Countries Jointly Promote Regional Connectivity",
"summary": "Recently, the LMC mechanism has made new progress...",
"content": "<p>Detailed content...</p>",
"author": "LMC Secretariat",
"source": "Partner Platform A"
}
]
}
成功响应示例
{
"code": 200,
"message": "success",
"data": {
"article": {
"id": 123,
"categoryId": 1,
"coverImg": "https://example.com/cover.jpg",
"isRecommend": 0,
"isTop": 0,
"sort": 0,
"status": 1,
"publishTime": "2026-08-05 10:00:00",
"viewCount": 0,
"createTime": "2026-08-05 10:00:00",
"updateTime": "2026-08-05 10:00:00"
},
"i18n": [
{
"id": 456,
"articleId": 123,
"lang": "zh-CN",
"title": "澜湄合作新进展",
"subtitle": "多国共同推进区域互联互通",
"summary": "近日,澜湄合作机制迎来新进展...",
"content": "<p>详细正文内容...</p>",
"author": "联盟秘书处",
"source": "合作伙伴平台A",
"seoTitle": "澜湄合作新进展 - 官网",
"seoKeywords": "澜湄,合作,区域互联",
"seoDescription": "澜湄合作机制最新进展报告",
"createTime": "2026-08-05 10:00:00",
"updateTime": "2026-08-05 10:00:00"
},
{
"id": 457,
"articleId": 123,
"lang": "en",
"title": "New Progress in Lancang-Mekong Cooperation",
"subtitle": "Countries Jointly Promote Regional Connectivity",
"summary": "Recently, the LMC mechanism has made new progress...",
"content": "<p>Detailed content...</p>",
"author": "LMC Secretariat",
"source": "Partner Platform A",
"seoTitle": "",
"seoKeywords": "",
"seoDescription": "",
"createTime": "2026-08-05 10:00:00",
"updateTime": "2026-08-05 10:00:00"
}
]
}
}
获取文章详情
路径参数:id — 平台生成的文章 ID。
Query 参数:lang(可选,默认 en)— 仅用于标签名称的回退语言;文章正文与标题始终返回全部语言版本。
返回该文章的完整信息:article 主表记录、i18n 该文章所有语言版本列表、tags 标签列表(含 tagId 与按 lang fallback 解析出的 name)。
GET /api/open/v1/cms/article/73?lang=zh-CN
# 成功
{
"code": 200,
"message": "Success",
"data": {
"article": {
"id": 73,
"deleted": null,
"createTime": "2026-08-12 10:00:58",
"updateTime": "2026-08-12 10:00:58",
"categoryId": 1,
"coverImg": "https://example.com/cover.jpg",
"isRecommend": 0,
"isTop": 0,
"viewCount": 0,
"sort": 0,
"status": 0,
"publishTime": "2026-08-05 10:00:00",
"title": null,
"subtitle": null,
"summary": null,
"author": null,
"source": null,
"categoryName": null
},
"i18n": [
{
"id": 155,
"createTime": "2026-08-12 10:00:58",
"updateTime": "2026-08-12 10:00:58",
"articleId": 73,
"lang": "en",
"title": "New Progress in Lancang-Mekong Cooperation",
"subtitle": "Countries Jointly Promote Regional Connectivity",
"summary": "Recently, the LMC mechanism has made new progress...",
"content": "Detailed content...
",
"author": "LMC Secretariat",
"source": "Partner Platform A",
"seoTitle": null,
"seoKeywords": null,
"seoDescription": null
},
{
"id": 154,
"createTime": "2026-08-12 10:00:58",
"updateTime": "2026-08-12 10:00:58",
"articleId": 73,
"lang": "zh-CN",
"title": "澜湄合作新进展-更新了",
"subtitle": "多国共同推进区域互联互通",
"summary": "近日,澜湄合作机制迎来新进展...",
"content": "详细正文内容...
",
"author": "联盟秘书处",
"source": "合作伙伴平台A",
"seoTitle": "澜湄合作新进展 - 官网",
"seoKeywords": "澜湄,合作,区域互联",
"seoDescription": "澜湄合作机制最新进展报告"
}
],
"tags": [
{
"tagId": 1,
"name": "New Tag 1"
},
{
"tagId": 2,
"name": "标签2"
}
]
}
}
# 文章不存在
{ "code": 2001, "message": "文章不存在" }
·
lang 仅影响 tags[].name 的解析(请求语言 → en → 任意可用语言);若无匹配则 name 为 null。·
i18n 始终返回文章已有的全部语言,不受 lang 限制,便于调用方按需取用。
更新文章
路径参数:id — 平台生成的文章 ID(创建时返回的 article.id)
请求体与创建接口字段一致,但均为可选。接口采用部分更新(patch 语义):仅覆盖请求体中传入的字段,未传入的字段与未传入的语言版本保持原值不变。响应结构与创建接口相同(article 为更新后主表记录,i18n 仅返回本次传入的语言列表)。
# 仅修改 zh-CN 的标题,其余字段与 en 版本均不变
PUT /api/open/v1/cms/article/123
{
"i18n": [
{ "lang": "zh-CN", "title": "新标题" }
]
}
# 仅下架(status=0),其余全不变
PUT /api/open/v1/cms/article/123
{ "status": 0 }
# 清空标签:传空数组(不传 tagIds 字段则保留原标签)
PUT /api/open/v1/cms/article/123
{ "tagIds": [] }
· 主表字段:仅传入非 null 的字段被覆盖(
viewCount 等未传字段永不被改动)。· tagIds:仅当请求体包含该字段时才整体替换该文章标签;传
[] 表示清空,不传则保留原标签。· i18n:按
lang 增量更新——已存在的语言只更新请求中的非空字段、保留其余;未传入的语言完全不动;若 lang 不存在则插入新记录(此时 title 必填)。
撤稿(逻辑删除)
路径参数:id — 平台生成的文章 ID(创建时返回的 article.id)。
撤销已推送的文章。采用逻辑删除:主表 cms_article 置 deleted=1,数据保留、可恢复;同时级联物理清理 cms_article_i18n、cms_article_tag 关联行,避免孤儿数据。门户侧按 deleted=0 过滤后将不再展示该文章。
DELETE /api/open/v1/cms/article/123
# 成功
{
"code": 200,
"message": "success",
"data": null
}
# 文章不存在
{
"code": 2002,
"message": "Article not found",
"data": null
}
deleted=1)。
若需重新发布,请调用 PUT /api/open/v1/cms/article/{id} 更新并恢复 status=1。
关键返回字段说明
| 字段 | 用途 |
|---|---|
article.id |
核心 — 外部平台必须保存,后续更新必需 |
article.status |
确认是否已发布(1=发布,0=草稿) |
i18n[].lang |
确认各语言版本入库成功 |
i18n[].title |
确认核心内容无误 |
外部平台接入指引
- 联系管理员创建 OpenApp,勾选 Scope
cms:article:write - 获取
AppId和AppSecret(仅展示一次) - 实现 HMAC-SHA256 签名算法(见第 4 章)
- 调用
GET /api/open/v1/cms/category?lang=zh-CN获取分类树,确定categoryId - 调用
GET /api/open/v1/cms/tag?lang=zh-CN获取标签列表,确定tagIds - 构造请求体,计算签名,调用
POST /api/open/v1/cms/article - 保存返回的
article.id,后续更新必需 - 如需更新,调用
PUT /api/open/v1/cms/article/{id} - 如需撤稿,调用
DELETE /api/open/v1/cms/article/{id}
sourceId → articleId 映射。
同一篇文章重复推送时,建议先查本地映射,存在则调用 PUT 更新。
推送接口错误码
| HTTP 状态码 | Code | 说明 |
|---|---|---|
| 400 | 2001 | 分类不存在 |
| 400 | 2003 | 标签不存在 |
| 404 | 2002 | 文章不存在(更新 / 撤稿时) |
| 401 | 1604 | 签名无效 |
| 401 | 1605 | 时间戳过期 |
| 401 | 1606 | Nonce 重复使用 |
| 403 | 1607 | IP 不在白名单 |
| 429 | 1608 | 超出限流 |
| 403 | 1609 | 无对应 Scope 权限 |
| 400 | 1400 | 参数校验失败(如 lang 重复) |
6. Scope 权限一览(鉴权开启时生效)
| Scope | 说明 | 状态 |
|---|---|---|
region:read |
地区/国家 | 已开放 |
cms:category:read |
CMS 分类 | 已开放 |
cms:tag:read |
CMS 标签 | 已开放 |
cms:article:read |
CMS 文章读取 | 待扩展 |
cms:article:write |
CMS 文章写入/推送 | 已开放 |
cms:page:read |
CMS 单页 | 待扩展 |
biz:org:read |
商务机构 | 待扩展 |
biz:resource:read |
商务资源 | 待扩展 |
media:read |
媒体名录 | 待扩展 |
material:read |
素材库 | 待扩展 |
data:report:read |
数据报告 | 待扩展 |
product:read |
商城商品 | 待扩展 |
search:read |
统一搜索 | 待扩展 |
7. 错误码
| Code | 说明 |
|---|---|
| 200 | 成功 |
| 1400 | 请求参数错误 |
| 1601 | 应用不存在 |
| 1602 | 应用已禁用 |
| 1603 | 应用已过期 |
| 1604 | 签名无效 |
| 1605 | 时间戳过期 |
| 1606 | Nonce 重复使用 |
| 1607 | IP 不在白名单 |
| 1608 | 超出限流 |
| 1609 | 无对应 Scope 权限 |
8. 代码示例
8.1 直接调用(当前,无需鉴权)
# curl
curl "https://your-domain.com/api/open/v1/regions/countries?lang=zh-CN"
# Python
import requests
r = requests.get("https://your-domain.com/api/open/v1/regions/countries", params={"lang": "zh-CN"})
print(r.json())
8.2 Python 签名示例(鉴权开启时)
import hashlib, hmac, time, uuid, urllib.parse, requests
APP_ID = "lm_xxxxxxxxxxxx"
APP_SECRET = "your-secret-here"
BASE = "https://your-domain.com"
def sha256_hex(s):
return hashlib.sha256(s.encode("utf-8")).hexdigest()
def build_query(params):
items = []
for key in sorted(params.keys()):
val = params[key]
if val is None: continue
items.append(f"{urllib.parse.quote(key, safe='')}={urllib.parse.quote(str(val), safe='')}")
return "&".join(items)
def sign(method, path, params, body=""):
ts = str(int(time.time()))
nonce = uuid.uuid4().hex
content = "\n".join([APP_ID, ts, nonce, method.upper(), path, build_query(params), sha256_hex(body)])
sig = hmac.new(APP_SECRET.encode(), content.encode(), hashlib.sha256).hexdigest()
return ts, nonce, sig
path = "/api/open/v1/regions/countries"
params = {"lang": "zh-CN"}
ts, nonce, sig = sign("GET", path, params)
r = requests.get(BASE + path, params=params, headers={
"X-App-Id": APP_ID, "X-Timestamp": ts, "X-Nonce": nonce, "X-Sign": sig,
})
print(r.json())
8.3 curl 签名示例(鉴权开启时)
curl -G "https://your-domain.com/api/open/v1/regions/countries" \
-H "X-App-Id: lm_xxxxxxxxxxxx" \
-H "X-Timestamp: 1719900000" \
-H "X-Nonce: abc123def4567890" \
-H "X-Sign: <computed_hmac>" \
--data-urlencode "lang=zh-CN"
9. 服务端配置(运维参考)
open:
api:
auth-enabled: ${OPEN_API_AUTH_ENABLED:false}
encrypt-key: ${OPEN_API_ENCRYPT_KEY:lm-open-api-key!}
timestamp-skew-seconds: 300
nonce-ttl-seconds: 600