POST /v1/actions/subscription-order/cancel-order
此端点也有 customer 侧的 session-token 调用流程:见 取消订阅(Customer)。
取消行为
| 当前状态 | 操作 | 结果状态 |
|---|---|---|
pending | 立即取消 | canceled |
active | 在周期结束时取消(通过 PSP) | canceling -> 周期结束时变为 canceled |
- pending:直接取消,状态变为
canceled - active:触发 PSP 取消(在计费周期结束时生效)。本地状态变为
canceling,然后在周期结束时通过 Webhook 更新为canceled
请求体
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
orderId | string | 是 | 订阅订单 ID(Short ID 格式 ORD_xxx) |
请求示例
import { WaffoPancake } from "@waffo/pancake-ts";
const client = new WaffoPancake({
merchantId: process.env.WAFFO_MERCHANT_ID!,
privateKey: process.env.WAFFO_PRIVATE_KEY!,
});
const result = await client.orders.cancelSubscription({
orderId: "ORD_2aUyqjCzEIiEcYMKj7TZtw",
});
console.log(result.orderId); // "ORD_2aUyqjCzEIiEcYMKj7TZtw"
console.log(result.status); // "canceling" or "canceled"
// Assumes callApi() is defined as shown in the Authentication guide
const result = await callApi("POST", "/v1/actions/subscription-order/cancel-order", {
orderId: "ORD_2aUyqjCzEIiEcYMKj7TZtw",
});
// Assumes callApi() is defined as shown in the Authentication guide
String result = callApi("POST", "/v1/actions/subscription-order/cancel-order",
"{\"orderId\":\"ORD_2aUyqjCzEIiEcYMKj7TZtw\"}");
# Assumes call_api() is defined as shown in the Authentication guide
result = call_api("POST", "/v1/actions/subscription-order/cancel-order", {
"orderId": "ORD_2aUyqjCzEIiEcYMKj7TZtw",
})
// Assumes callAPI() is defined as shown in the Authentication guide
result, err := callAPI("POST", "/v1/actions/subscription-order/cancel-order",
`{"orderId":"ORD_2aUyqjCzEIiEcYMKj7TZtw"}`)
// Assumes call_api() is defined as shown in the Authentication guide
let result = call_api("POST", "/v1/actions/subscription-order/cancel-order",
r#"{"orderId":"ORD_2aUyqjCzEIiEcYMKj7TZtw"}"#
).await?;
// Assumes call_api() is defined as shown in the Authentication guide
call_api("/v1/actions/subscription-order/cancel-order",
"{\"orderId\":\"ORD_2aUyqjCzEIiEcYMKj7TZtw\"}");
// Assumes call_api() is defined as shown in the Authentication guide
auto result = call_api("/v1/actions/subscription-order/cancel-order",
R"({"orderId":"ORD_2aUyqjCzEIiEcYMKj7TZtw"})");
MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP=$(date +%s)
BODY='{"orderId":"ORD_2aUyqjCzEIiEcYMKj7TZtw"}'
BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 | tr -d '\n')
CANONICAL="POST
/v1/actions/subscription-order/cancel-order
$TIMESTAMP
$BODY_HASH"
SIGNATURE=$(echo -n "$CANONICAL" | openssl dgst -sha256 -sign private_key.pem | base64 | tr -d '\n')
curl -X POST "https://api.waffo.ai/v1/actions/subscription-order/cancel-order" \
-H "Content-Type: application/json" \
-H "X-Merchant-Id: $MERCHANT_ID" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: $SIGNATURE" \
-d "$BODY"
MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
TIMESTAMP=$(date +%s)
BODY='{"orderId":"ORD_2aUyqjCzEIiEcYMKj7TZtw"}'
BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 | tr -d '\n')
CANONICAL="POST
/v1/actions/subscription-order/cancel-order
$TIMESTAMP
$BODY_HASH"
SIGNATURE=$(echo -n "$CANONICAL" | openssl dgst -sha256 -sign private_key.pem | base64 | tr -d '\n')
wget -qO- --post-data="$BODY" \
--header="Content-Type: application/json" \
--header="X-Merchant-Id: $MERCHANT_ID" \
--header="X-Timestamp: $TIMESTAMP" \
--header="X-Signature: $SIGNATURE" \
"https://api.waffo.ai/v1/actions/subscription-order/cancel-order"
成功响应 (200) — 活跃订阅
{
"data": {
"orderId": "ORD_2aUyqjCzEIiEcYMKj7TZtw",
"status": "canceling"
}
}
成功响应 (200) — 待处理订阅
{
"data": {
"orderId": "ORD_2aUyqjCzEIiEcYMKj7TZtw",
"status": "canceled"
}
}
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
orderId | string | 订单 ID(Short ID) |
status | string | 新的订单状态(canceling 或 canceled) |
错误响应
重试策略:4xx 一律不要重试 — 修正请求后重发。5xx 指数退避重试(起步 5s,最多 3 次)。
| 状态码 | errors[0].message | 含义 | 推荐处理 |
|---|---|---|---|
| 400 | Missing X-Context-Merchant-Id header | API Key 认证下 merchant 上下文缺失 | 检查认证流水线 |
| 400 | Missing required field: orderId | 请求体未提供 orderId | 修正请求体后重新提交 |
| 400 | Expected format: ORD_xxx, got "..." | orderId Short ID 解码失败 | 修正 orderId 格式后重新提交 |
| 400 | Subscription cannot be canceled, current status: X | 订单状态非 pending 或 active(如已 canceled、canceling、expired) | 该订阅已不可取消 |
| 401 | Authentication failed | API Key 签名无效 | 检查认证请求头 |
| 403 | Order does not belong to user | 归属校验失败 | 验证调用方拥有该订单 |
| 404 | Order not found | 订单不存在 | 验证 order ID |
| 500 | Internal server error | 服务端意外失败 | 指数退避重试(起步 5s,最多 3 次) |
| 502 | Failed to cancel subscription | 本地更新或 PSP 取消失败 | 指数退避重试(起步 5s,最多 3 次) |