订单管理
订单管理支持查询订单、取消订单和查看付款状态。可以使用开发者后台的 交易 → 订单 页面,也可以通过公开 API 开发自己的后台,两者使用相同业务规则。
订单按当前接入方企业、应用、产品和环境隔离,无需先选择客户公司。
开通与授权
- 订单管理默认可用于当前应用自有范围,无需额外开通。进入「商业管理 → 订单」;无权或已关闭时按页面说明核对本人职责及当前应用状态。
- 在“API 与权限”的用户身份中选择“订单管理”,配置需要的 Scope,记录 Application ID、API Product ID 和 Base URL,明确本次使用的
sandbox|production环境;Client 与 Audience 由有效配置派生。 - 使用该应用的用户 OAuth 授权码 + PKCE 登录。Token 必须由该用户 Client 签发,包含所需 Audience 和 Scope。自建后台可保存自己的用户会话,浏览器通过自己的服务端请求 API。
- 操作者使用当前接入方企业,并确认本人授权:
resource_scope为{"resource_type":"appmarket_product","resource_ids":["your-product"]}。授权必须绑定同一 Application、环境、API Product 和 Scope,并且未过期或撤销。操作流程见用户授权。
此 API 仅支持用户 Token。调用者需要有效的企业成员关系和应用管理关系。应用所有者可查看本应用订单,并取消符合条件的订单;其他成员需单独获得订单查看或取消职责。
能力配置和 API 权限不会授予其他企业订单或财务执行权限。
| Scope | 操作 |
|---|---|
operations.order.read | 查看可用状态、订单列表和详情 |
operations.order.cancel | 取消允许取消的订单;不包含查看 Scope |
operations.payment.read | 查看原订单的付款证据;独立核验付款查看职责 |
公开接口
| 方法与路径 | Scope | 返回 |
|---|---|---|
GET /open-platform/v1/appmarket/orders:context | operations.order.read | 当前能力是否启用、产品、允许动作及原因 |
GET /open-platform/v1/appmarket/orders | operations.order.read | 有界订单列表和下一页游标 |
GET /open-platform/v1/appmarket/orders/{order_id} | operations.order.read | 当前订单及允许动作 |
POST /open-platform/v1/appmarket/orders/{order_id}/cancel | operations.order.cancel | 原取消请求的成功回执 |
GET /open-platform/v1/appmarket/orders:payment-context | operations.payment.read | 当前付款查看职责及允许动作 |
GET /open-platform/v1/appmarket/orders/{order_id}/payment | operations.payment.read | 原订单关联付款单的实际状态、金额、已完成退款汇总和时间 |
每次请求携带以下请求头,每项仅支持一个值:
| 请求头 | 内容 |
|---|---|
Authorization: Bearer <用户Token> | 当前应用的用户 Token |
X-GV-Organization-ID | 接入方企业 |
X-GV-Application-ID | 当前应用 |
X-GV-Environment | 明确选择 sandbox 或 production |
X-GV-API-Product-ID | 本次调用的 API 产品 |
X-GV-Delegated-Grant-ID | 本人授权 |
X-GV-Product-Code | 当前产品 |
环境必须与本人授权和当前应用来源一致。请求不接受内部环境绑定、目标客户或所有者证明来扩大访问范围。响应使用 Cache-Control: no-store。
从控制台复制本环境的 Base URL 与 Audience,不将 Sandbox、Production 或其他应用的配置混用。以下全部为示例占位值,Token 不应进入代码、日志或下载文件。
const context = {
baseURL: `${process.env.GOODVISION_API_BASE}/open-platform/v1`, // 本环境签发的 API Base URL,例如 https://api.example.test
headers: {
Authorization: `Bearer ${process.env.ORDER_USER_TOKEN}`,
'X-GV-Organization-ID': process.env.ORDER_ORGANIZATION_ID,
'X-GV-Application-ID': process.env.ORDER_APPLICATION_ID,
'X-GV-Environment': process.env.ORDER_ENVIRONMENT,
'X-GV-API-Product-ID': process.env.ORDER_API_PRODUCT_ID,
'X-GV-Delegated-Grant-ID': process.env.ORDER_DELEGATED_GRANT_ID,
'X-GV-Product-Code': process.env.ORDER_PRODUCT_CODE,
},
};
const response = await fetch(`${context.baseURL}/appmarket/orders?limit=25&kind=one_time`, {
headers: context.headers,
cache: 'no-store',
});
if (!response.ok) throw new Error(`Order API returned ${response.status}`);
const page = await response.json();
// page.items 为当前页;page.next_cursor 为空表示没有下一页。查询与结果说明
列表查询参数如下:
| 参数 | 必填性 | 说明 |
|---|---|---|
limit | 可选 | 1~100,省略时 25 |
search | 可选 | 订单号子串,最多 200 字符;省略时不搜索 |
status | 可选 | 省略时不按状态筛选 |
kind | 可选 | subscription、one_time 或 token_package;省略时不限类型 |
cursor | 可选 | 首页省略;翻页原样使用 next_cursor |
订单状态包括 draft、pending_approval、approved、awaiting_payment、paid、fulfilling、fulfilled、cancelled、payment_unknown、refund_pending 和 refunded。
订单按 ID 升序返回。读取下一页时,保持原筛选并原样传回 next_cursor。切换筛选、企业、应用、产品或环境后,从第一页重新查询。
游标无需解析,也不能拼接不同范围的页面。已加载数量只表示当前页面数据。每页反映查询时的状态,订单持续变化时请刷新。
plan_code/plan_version、total、items 和 accepted_at 描述购买时的订单。金额由整数 value、小数位 scale 和 currency 组成,例如 500 / 10² = USD 5.00,展示时保留精度。
customer_organization_id 仅标识购买客户,不提供客户成员资料或管理权限。
订单与当前订阅分别返回:
| 字段 | 说明 |
|---|---|
status | 订单商业/交付进度 |
payment_status | 订单记录中的付款摘要,可为 not_started、awaiting_payment、paid、refund_pending、refunded、unknown |
subscription_id、subscription_status | 当前订阅及状态 |
current_plan_code/版本 | 当前订阅套餐,可能与购买时套餐不同 |
current_period_start/end | 当前订阅周期 |
没有订阅时,对应字段为空,版本为 0。付款、交付、成员分配和产品使用资格需分别查询。
取消与原请求恢复
先读取详情,仅当该订单的 allowed_actions 包含 order.cancel 时允许提交。当前支持尚未开始付款且采用当前付款安全流程的一次性订单;订阅、Token 套餐、已付款、付款处理中/结果未知及需要核对的历史订单不提供取消。已购订阅的生命周期管理沿订阅 API,订单取消不退款、不撤销使用权益。
const original = {
key: crypto.randomUUID(),
body: { resource_version: order.resource_version, reason: '客户取消本次购买' },
};
const response = await fetch(`${context.baseURL}/appmarket/orders/${order.id}/cancel`, {
method: 'POST',
headers: { ...context.headers, 'Content-Type': 'application/json', 'Idempotency-Key': original.key },
body: JSON.stringify(original.body),
});取消后无法恢复订单。付款开始和取消操作检查同一资源版本,其中一项成功后,另一项不能继续使用旧版本。
- 网络中断或
503:保留原订单、版本、原因和Idempotency-Key,重复相同请求恢复。 - 同键不同正文:返回
409。 - 取消成功:GET 详情查看当前状态,回执只描述原请求结果。
- 版本冲突
409:保留原因,读取最新订单,让用户确认后以新版本和新键提交。
不要自动重试取消。控制台使用相同恢复流程。
错误处理
| HTTP | 处理 |
|---|---|
| 400/422 | 缺失、重复或非法上下文/参数;修正后提交。详情与取消不接受查询参数 |
| 401 | 重新使用当前应用用户身份登录 |
| 403 | 能力关闭、Scope/本人授权/企业成员/应用关系或订单权限不满足;立即清除旧资料并重新核验 |
| 404 | 订单不在当前范围或不存在,不尝试其他客户标识 |
| 409 | 订单版本或原请求冲突、付款已开始或订单不可取消;重新读取并人工确认 |
| 429 | 按 Retry-After 等待;保持原请求键 |
| 503 | 暂时无法查询或确认结果;读取可重试,取消使用原键恢复,不展示为空目录或成功 |
关闭订单能力后,菜单隐藏,后续业务请求被拒绝,原订单保留。重新开通后查询当前订单。自建后台应在退出、撤权或切换企业/应用/环境时清除订单和草稿,并忽略旧请求的迟到响应。
完整字段及错误结构见API 产品参考和 订单 OpenAPI。
名称展示
订单响应可包含customer_display_name(客户名称)与plan_display_name(原成交方案名称)。优先显示名称;字段缺失或为空时显示“未命名企业”和“未命名方案”。当前订阅的方案代码表示当前方案,可能与原成交不同。标识保留在明确的详情或复制入口,不根据ID推测客户身份。
订单内的付款证据
订单详情点击“查看付款证据”后,复用当前登录按需核验独立付款查看职责。企业管理员通过现有角色分配该职责;应用所有权或订单可读都不会自动授予付款证据。失败只影响付款区块,点击重新核验即可恢复,无需再次登录。
| 返回情况 | 说明 |
|---|---|
availability=available | 返回关联付款单的当前状态、精确缩放金额、已完成退款汇总、付款单版本和创建/更新时间 |
not_linked | 原订单未关联付款单,不能据此认定未扣款 |
| 查询失败 | 显示错误,不用订单付款摘要替代 |
退款汇总仅包含已完成退款。发票、账务收入、结算余额和使用资格需另行查询。此接口只读,不发起付款、退款或支付供应商状态刷新。