{"id":"a746666d-18fc-499a-92b2-edac0473e8e0","entityType":"agent","slug":"clawhub-linkfox-ai-linkfox-amazon-store-auth","name":"亚马逊-店铺授权","canonicalUrl":"https://www.xpersona.co/agent/clawhub-linkfox-ai-linkfox-amazon-store-auth","canonicalPath":"/agent/clawhub-linkfox-ai-linkfox-amazon-store-auth","generatedAt":"2026-10-10T10:43:31.574Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":null},"description":"亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。 Skill: 亚马逊-店铺授权 Owner: linkfox-ai Summary: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。 Tags: latest:1.0.8 Version history: v1.0.8 | 2026-09-14","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.7K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s171g8b6m2khwdy9ye8bxj0wx183vd4z:linkfox-amazon-store-auth","sourceUrl":"https://clawhub.ai/linkfox-ai/linkfox-amazon-store-auth","homepage":"https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/linkfox-ai/linkfox-amazon-store-auth","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":65,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":null},"stars":null,"forks":null,"downloads":1679,"packageName":null,"latestVersion":"1.0.8","tractionLabel":"1.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:37:32.750Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T04:37:32.751Z","lastCrawledAt":"2026-10-10T04:37:32.750Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T04:37:32.751Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.8","createdAt":"2026-09-14T04:55:47.000Z","changelog":"Update from 1.0.7 to 1.0.8","fileCount":17,"zipByteSize":46735},{"version":"1.0.7","createdAt":"2026-08-14T14:44:20.849Z","changelog":"Update from 1.0.6 to 1.0.7","fileCount":16,"zipByteSize":38325},{"version":"1.0.6","createdAt":"2026-08-07T10:41:29.570Z","changelog":"Update from 1.0.5 to 1.0.6","fileCount":16,"zipByteSize":38269},{"version":"1.0.5","createdAt":"2026-07-13T12:04:15.123Z","changelog":"Update from 1.0.4 to 1.0.5","fileCount":13,"zipByteSize":28417},{"version":"1.0.4","createdAt":"2026-07-06T11:11:47.447Z","changelog":"Update from 1.0.3 to 1.0.4","fileCount":13,"zipByteSize":27454},{"version":"1.0.3","createdAt":"2026-07-03T08:11:07.855Z","changelog":"Update from 1.0.2 to 1.0.3","fileCount":12,"zipByteSize":25992},{"version":"1.0.2","createdAt":"2026-07-03T04:36:21.501Z","changelog":"Update from 1.0.1 to 1.0.2","fileCount":12,"zipByteSize":25946},{"version":"1.0.1","createdAt":"2026-05-20T07:03:05.155Z","changelog":"Update from 1.0.0 to 1.0.1","fileCount":12,"zipByteSize":24053}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171g8b6m2khwdy9ye8bxj0wx183vd4z:linkfox-amazon-store-auth","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T10:43:31.570Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-linkfox-ai-linkfox-amazon-store-auth/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":null},"readme":"Skill: 亚马逊-店铺授权\n\nOwner: linkfox-ai\n\nSummary: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。\n\nTags: latest:1.0.8\n\nVersion history:\n\nv1.0.8 | 2026-09-14T04:55:47.000Z | user\n\nUpdate from 1.0.7 to 1.0.8\n\nv1.0.7 | 2026-08-14T14:44:20.849Z | user\n\nUpdate from 1.0.6 to 1.0.7\n\nv1.0.6 | 2026-08-07T10:41:29.570Z | user\n\nUpdate from 1.0.5 to 1.0.6\n\nv1.0.5 | 2026-07-13T12:04:15.123Z | user\n\nUpdate from 1.0.4 to 1.0.5\n\nv1.0.4 | 2026-07-06T11:11:47.447Z | user\n\nUpdate from 1.0.3 to 1.0.4\n\nv1.0.3 | 2026-07-03T08:11:07.855Z | user\n\nUpdate from 1.0.2 to 1.0.3\n\nv1.0.2 | 2026-07-03T04:36:21.501Z | user\n\nUpdate from 1.0.1 to 1.0.2\n\nv1.0.1 | 2026-05-20T07:03:05.155Z | user\n\nUpdate from 1.0.0 to 1.0.1\n\nv1.0.0 | 2026-04-30T08:55:11.140Z | user\n\nInitial release\n\nArchive index:\n\nArchive v1.0.8: 17 files, 46735 bytes\n\nFiles: _meta.json (144b), README.md (2526b), references/api.md (7466b), references/authorization-flow.md (13258b), references/onboarding.md (1999b), references/quick-start.md (7899b), scripts/_lf_output.py (6404b), scripts/_token_status_output.py (1059b), scripts/authorize_url.py (4073b), scripts/authorized_stores.py (2535b), scripts/cancel_authorization.py (13069b), scripts/onboarding.py (24027b), scripts/README.md (2599b), scripts/refresh_token.py (3073b), scripts/store_tokens.py (3017b), skill-card.md (3100b), SKILL.md (15005b)\n\nFile v1.0.8:SKILL.md\n\n---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、授权状态查询、令牌刷新与本地取消授权**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。下游业务经 `developerProxy` 传入 `sellerId`+`region` 即可，**无需**先取 raw token。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens（授权状态，非 raw token 下发）\n\n`POST /spApi/storeTokens` 返回**状态与元数据**（具体字段以网关为准），供确认授权是否有效、何时过期。**不要**将响应当作下游 `developerProxy` 的 token 来源。\n\n| Field | Type | Description |\n|-------|------|-------------|\n| status | string | 授权/令牌状态（如有效、过期、缺失） |\n| authRecordId | integer | 授权记录 ID（如有） |\n| expiresIn | integer | 距 accessToken 过期的秒数（如有） |\n| tokenExpiresAt | string | 绝对过期时间（如有） |\n| message | string | 补充说明 |\n| errcode / errmsg | integer / string | 网关错误（失败时） |\n\n> 兼容说明：旧版网关可能仍返回 `accessToken`/`refreshToken`；Agent **不应**优先读取或传递给下游。下游应使用 `sellerId`+`region` 调 `developerProxy`。\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**；解绑时按 Scenario 5 明确目标区域。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken|cancelAuthorization}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗算力；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## 解决认证和算力问题\n发生以下异常情况时，采用 references/onboarding.md 引导解决问题：\n\n### 异常情况\n- **未配置API Key**：环境变量未配置 `LINKFOX_AGENT_API_KEY`，也未配置 `LINKFOXAGENT_API_KEY`。\n- **响应401或402状态码**\n- **响应提示算力或余额不足**：消息含\"算力余额不足/计费不足/余额不足/quota exceeded/insufficient balance/套餐到期/需充值/请充值\"，或类似含义的内容。\n\n## Usage Scenarios\n\n### Scenario 1: Authorize New Store\n\n**User request**：「我要授权我的亚马逊北美站点」\n\n**Steps**：\n1. **询问店铺名 `sellerName`**（若用户未提供）。`/spApi/authorizeUrl` 要求 `sellerName` 为非空字符串；向用户说明这只是在 LinkFox 里识别店铺的标签，建议与 Seller Central 后台名字保持一致。\n2. 调用 `/spApi/authorizeUrl`，传入 `region` 与 `sellerName`\n3. 把返回的 `authorizeUrl` 给用户，让其在浏览器中打开\n4. 用户在 Amazon 完成授权 → Amazon 回调系统 → 系统自动保存授权\n5. 可选：调用 `/spApi/authorizedStores` 确认授权成功\n\n### Scenario 2: View Authorized Stores\n\n**User request**：「列一下我已授权的亚马逊店铺」\n\n**Steps**：\n1. 调用 `/spApi/authorizedStores`\n2. 展示店铺列表（sellerName / sellerId / region）\n3. 按 sellerId、region 排序\n\n### Scenario 3: Refresh Expired Token\n\n**User request**：「我店铺的令牌过期了，帮我刷新」\n\n**Steps**：\n1. 调用 `/spApi/refreshToken`，传入 `sellerId`（可选 `region`）\n2. 返回刷新**状态与元数据**（如 `status`、`message`、`expiresIn`）；服务端更新令牌\n3. 下游可直接重试 `developerProxy`（传入相同 `sellerId`+`region`），**无需**读取 raw token\n\n### Scenario 4: Query Store Token Status\n\n**User request**：「查一下北美站点 A123 店铺的授权/令牌状态」\n\n**Steps**：\n1. 调用 `/spApi/storeTokens`，传入 `sellerId` 与 `region`\n2. 向用户展示**状态字段**（`status`、`expiresIn`、`tokenExpiresAt`、`message` 等）\n3. **不要**把响应当作下游 proxy 的 token；业务调用直接带 `sellerId`+`region`\n\n### Scenario 5: Cancel Local Authorization\n\n**User request**：「取消/解绑我的亚马逊店铺授权」\n\n仅在用户要求时执行。当前用户按 API key 对应的成员身份识别；共用该身份的使用者会一起受影响。\n\n**Steps**：\n\n1. 从用户指定目标或 `/spApi/authorizedStores` 确定 `sellerId + region`；不使用默认区域，有歧义时让用户选择。\n2. 说明解绑覆盖整个区域；若用户只要求单站点，须先取得对整个区域解绑的明确同意。\n3. 调用 `/spApi/cancelAuthorization`，传入选定的 `sellerId` 与 `region`。\n4. 按 `references/api.md` 解释结果；后续重新查询店铺，不自动重新授权。\n\n### Scenario 6: Prepare Account Selector for Any Store Operation (Standard Preparation Workflow)\n\n当用户提出任何涉及卖家后台数据的请求（拉报告、查库存、看订单等），**本 skill 负责前置的「选店 → 确认授权」**，具体业务由相应的下游 skill 接手。\n\n**Steps**：\n1. **列出已授权店铺**：调用 `/spApi/authorizedStores`\n2. **让用户选择店铺**：如果有多家店铺，请用户明确选哪一家，确定 `sellerId` 与 `region`\n3. （可选）调用 `/spApi/storeTokens` **仅作状态确认**（过期则先 `refreshToken`）\n4. **把 `sellerId`+`region` 交给下游 skill**（例如 `linkfox-amazon-store-report`），由下游直接调 `developerProxy`\n\n**Why this workflow is critical**：\n- 用户可能同时授权了多家不同区域的店铺\n- 每家店铺的令牌与权限彼此独立\n- 必须使用与店铺匹配的 `sellerId`+`region`，跳过「选店」会导致歧义和错误\n\n## Display Rules\n\n1. **先有店铺名再生成授权链接**：若用户未提供 `sellerName`，**必须先问**，不允许带空值调用 `/spApi/authorizeUrl`。\n2. **只呈现数据**：展示授权结果、店铺列表、令牌信息即可，不做业务建议。\n3. **安全意识**：响应若含 legacy token 字段，不要明文展示；优先呈现 `status` / 过期时间等元数据。\n4. **清晰引导**：返回授权链接时，明确告知用户在浏览器中打开并完成授权。\n5. **错误说明**：授权失败时，基于错误码解释原因并给出建议。\n6. **成功确认**：授权完成后与用户确认，可选择展示该店铺基本信息。\n\n## Important Limitations\n\n- **sellerName 必填**：`/spApi/authorizeUrl` 必须传入非空 `sellerName`；脚本与 agent 在调用前务必校验。\n- **令牌有效期**：`accessToken` 1 小时过期，需及时刷新。\n- **区域专属**：每次店铺授权都与具体区域绑定，不同区域需分别授权。\n- **用户隔离**：用户只能查看/管理自己授权的店铺。\n- **回调白名单**：系统回调 URL 必须在授权方（紫鸟）处加白名单。\n\n## User Expression & Scenario Quick Reference\n\n**Applicable** — 授权与令牌管理场景：\n\n| User Says | Scenario |\n|-----------|----------|\n| \"授权我的亚马逊店铺\" / \"Authorize my Amazon store\" | 新店铺授权 |\n| \"看看已授权的亚马逊店铺\" / \"Show my authorized stores\" | 列出已授权店铺 |\n| \"令牌过期了\" / \"My token expired\" | 刷新令牌 |\n| \"查 XXX 店铺授权状态\" / \"Check store token status\" | 查询授权状态（storeTokens） |\n| \"绑定我的亚马逊账号\" / \"Connect my Amazon seller account\" | 新店铺授权 |\n| \"取消授权\" / \"解绑这个亚马逊店铺\" / \"Disconnect seller account\" | 本地取消/解绑授权 |\n\n**Not applicable** — 超出本 skill 的业务：\n\n- **拉取亚马逊报告** → 请使用 `linkfox-amazon-store-report`\n- 产品 listing 管理、订单处理、库存管理、广告投放 → 由其他 skill 负责\n\n**Boundary judgment**：\n- 本 skill 只负责「授权 + 管店铺 + 令牌刷新/状态查询 + 为下游准备 `sellerId`+`region` 选店信息」。\n- **不要**为下游 `developerProxy` 调用 `storeTokens` 取 raw `accessToken`（除非兼容极旧客户端且用户明确要求）。\n- 当用户要做具体卖家后台业务（如拉报告）时：\n  1. 本 skill 执行 Scenario 6 的标准前置流程（选店）\n  2. 随后切换到对应下游 skill，直接 `developerProxy` + `sellerId`+`region`\n- 不要直接越过本 skill 去调具体 Amazon 开放接口。\n\n## Quick Reference\n\n### Authorization & Token Management APIs\n\n| API | Path | Purpose | Auth Required |\n|-----|------|---------|---------------|\n| Get Authorization URL | /spApi/authorizeUrl | 生成授权链接（需要 sellerName） | ✅ Yes |\n| List Authorized Stores | /spApi/authorizedStores | 查询用户的店铺列表 | ✅ Yes |\n| Refresh Token | /spApi/refreshToken | 刷新访问令牌 | ✅ Yes |\n| Query Store Token Status | /spApi/storeTokens | 查询某店铺授权/令牌状态（非下游 token 来源） | ✅ Yes |\n| Cancel Authorization | /spApi/cancelAuthorization | 本地取消/解绑当前用户的店铺授权 | ✅ Yes |\n\n详细请求参数、响应结构、错误码，见 `references/api.md`。完整授权流程图，见 `references/authorization-flow.md`。快速上手示例，见 `references/quick-start.md`。\n\n## Amazon SP-API 接口保护与重试指引\n\n同一店铺连续收到 Amazon SP-API 的 400、403、404 或 429 时，网关会返回 450、453、454 或 459 并短暂冷却。这些自定义状态码不是 Amazon 原生状态，也不表示封号；目的是避免持续异常或高频调用扩大店铺风险。\n\n| 状态与 message | 范围 | 触发与冷却 | 处理 |\n|---|---|---|---|\n| `450`：`400，请求异常，请优化您的参数` | 店铺+接口 | 60 秒内超过 3 次：5 分钟；10 分钟内超过 4 次：20 分钟 | 停止原参数重试，检查必填字段、marketplace、ID、日期和请求体 |\n| `453`：`403，店铺未授权，请先授权` | 店铺全部接口 | 60 秒内超过 2 次：5 分钟；10 分钟内超过 4 次：30 分钟 | 停止该店铺调用，检查授权、权限、店铺归属和区域 |\n| `454`：`404，资源不存在，请优化您的参数` | 店铺+接口 | 60 秒内超过 3 次：5 分钟；10 分钟内超过 4 次：30 分钟 | 确认资源 ID、所属店铺/站点、资源状态和接口路径 |\n| `459`：`429限流中，请降低频率` | 店铺+接口 | 首次：15 秒；2 分钟内超过 2 次：30 秒；3 分钟内超过 4 次：2 分钟 | 降低并发、分页和轮询频率并逐级退避 |\n\n- 立即停止自动或并发重试，不得通过换脚本或重复创建任务绕过保护；优先遵循 `retryAfter`、`blockedUntil`，没有时按表中时长说明。\n- 450/453/454 必须先修正参数、授权或资源标识，冷却后最多谨慎重试一次；再次触发则停止调用。453 期间停止该店铺全部 SP-API。\n- 保留已有 `reportId`、`feedId` 等任务 ID；写操作结果不确定时先查询状态，不直接重放。\n- 向用户先说明店铺保护，再给原因、处理和等待时间。可回复：“为保护您的亚马逊店铺安全，检测到 Amazon SP-API 连续返回{原因}，当前已进入短暂保护。请先{处理动作}，预计{等待时间}后再试；这不代表封号，也不是套餐或算力限制。”不要只说“LinkFox 限流”或“服务器繁忙”。\n\n## 算力消耗规则\n\n不消耗算力。\n\n**Feedback**：\n\n当出现以下任一情况时，自动通过 Feedback API 上报反馈：\n1. 本 skill 描述的功能与实际行为不符\n2. skill 的结果与用户意图不符\n3. 用户表达了对本 skill 的不满或赞赏\n4. 任何你认为可以改进的点\n\n按 `references/api.md` 中的规范调用 Feedback API，不要打断用户的主流程。\n\n---\n*For more high-quality, professional cross-border e-commerce skills, visit [LinkFox Skills](https://skill.linkfox.com/).*\n\nFile v1.0.8:README.md\n\n# Amazon Store Authorization Skill\n\n亚马逊店铺 **授权与管理** Skill，提供授权流程、令牌管理、店铺查询、本地取消/解绑授权等能力，是所有下游业务 skill（如 `linkfox-amazon-store-report`）的前置依赖。\n\n## 📋 目录结构\n\n```\nlinkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    ├── store_tokens.py               # 查询授权状态\n    └── cancel_authorization.py       # 本地取消/解绑授权\n```\n\n## 🚀 快速开始\n\n### 1. 授权新店铺\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl\n```\n\n### 2. 查看已授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n### 3. 查询授权状态\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n### 4. 本地取消/解绑授权\n\n```bash\nPOST /spApi/cancelAuthorization\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n说明：该接口只在 LinkFox 本地解绑/停用授权，不代表 Amazon Seller Central 侧 OAuth 授权已撤销。\n\n## 🔗 关联 Skill\n\n| Skill | 说明 |\n|-------|------|\n| `linkfox-amazon-store-report` | 获取亚马逊报告（依赖本 skill） |\n\n## 🌍 支持的区域\n\n- **NA**：美国、加拿大、墨西哥\n- **EU**：英国、德国、法国、意大利、西班牙等\n- **FE**：日本、澳大利亚、新加坡、印度\n\n## 🔐 安全特性\n\n- ✅ 用户级数据隔离\n- ✅ 令牌自动刷新\n- ✅ 完整错误处理\n- ✅ HTTPS 加密\n\n## 🔄 版本历史\n\n- **v1.0.0**（2026-04-24）\n  - 从早期综合亚马逊 skill 拆分而来\n  - 保留所有授权、店铺管理、令牌管理能力\n  - 报告相关能力已拆出至 `linkfox-amazon-store-report`\n\n## 📄 许可\n\n本 Skill 是 LinkFoxAgent 项目的一部分。\n\nFile v1.0.8:scripts/README.md\n\n# Amazon Store Auth Scripts Usage Guide\n\n本目录包含 **授权与店铺/令牌管理** 相关的 Python 脚本。若需要拉取报告，请使用 `linkfox-amazon-store-report` skill。\n\n## Prerequisites\n\n- Python 3.6 或更高\n- 已设置 `LINKFOXAGENT_API_KEY` 环境变量\n- 可访问 LinkFox 后端 API（默认 `https://tool-gateway.linkfox.com`）\n\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-api-key-here\"\n```\n\n## Available Scripts\n\n### 1. authorize_url.py\n\n为新店铺生成授权 URL。\n\n**`sellerName`（店铺名）必填**：必须为非空字符串。脚本会在缺失或为空白时直接退出并报错——调用前请先向用户询问一个可识别的店铺名。\n\n```bash\npython authorize_url.py '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### 2. authorized_stores.py\n\n列出当前用户已授权的所有亚马逊店铺。\n\n```bash\npython authorized_stores.py\n```\n\n### 3. refresh_token.py\n\n刷新某店铺的 accessToken。\n\n```bash\npython refresh_token.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 4. store_tokens.py\n\n查询某店铺的授权/令牌状态。响应只用于状态确认，不作为下游 raw token 来源。\n\n```bash\npython store_tokens.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 5. cancel_authorization.py\n\n本地取消/解绑某店铺授权。该脚本调用 `/spApi/cancelAuthorization`，不会撤销 Amazon Seller Central 侧授权。\n\n```bash\npython cancel_authorization.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| LINKFOXAGENT_API_KEY | API 鉴权 key | 必需 |\n| STORE_API_BASE_URL / SPAPI_BASE_URL | 后端网关 base URL（优先读前者） | https://tool-gateway.linkfox.com |\n\n## Error Codes\n\n- `0`：成功\n- `1`：缺少 API key、参数错误、网络/HTTP/权限错误\n\n## Troubleshooting\n\n**API Key 未配置**\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-key-here\"\n```\n\n**Connection Refused / 网络错误**\n- 确认 `https://tool-gateway.linkfox.com` 能从你的网络访问（或设置 `STORE_API_BASE_URL` / `SPAPI_BASE_URL` 指向其他网关）\n- 检查防火墙、代理设置\n\n**403 Unauthorized**\n- 店铺可能缺少必要的亚马逊接口权限\n- 用更完整的权限集合重新授权\n\n**查询令牌返回 1004**\n- 核对 sellerId 与 region\n- 确认该店铺已完成授权\n\n## Further Documentation\n\n- API Reference: `../references/api.md`\n- 授权流程详解: `../references/authorization-flow.md`\n- 快速上手: `../references/quick-start.md`\n- Skill 文档: `../SKILL.md`\n\nFile v1.0.8:_meta.json\n\n{\n  \"ownerId\": \"kn7dmc1t4j28hem1twwyav85p182pb1j\",\n  \"slug\": \"linkfox-amazon-store-auth\",\n  \"version\": \"1.0.8\",\n  \"publishedAt\": 1789361747000\n}\n\nFile v1.0.8:references/api.md\n\n# Amazon 店铺授权 API Reference\n\n本文档描述 **授权与店铺/令牌管理** 相关的 API。若需经网关代理拉取报告或 **Listing 单条查询** 等，请参考 `linkfox-amazon-store-report`、`linkfox-amazon-store-listings` skill。\n\n## Calling Conventions\n\n- **Base URL**: `${LINKFOX_TOOL_GATEWAY}`（默认 `https://tool-gateway.linkfox.com`；可用 `LINKFOX_TOOL_GATEWAY` 覆盖，兼容旧名 `STORE_API_BASE_URL` / `SPAPI_BASE_URL`）\n- **Request Method**: 所有接口均为 POST\n- **Content-Type**: `application/json`\n- **Authentication**: Header `Authorization: <api_key>`，API key 优先读取环境变量 `LINKFOX_AGENT_API_KEY`，未设置时回退到兼容旧名 `LINKFOXAGENT_API_KEY`（如未配置 按 SKILL.md 的 **## 解决认证和算力问题** 处理）\n\n- **解绑脚本**: `LinkFox-Skill/2.0`；透传 `SESSION_ID` / `MESSAGE_ID` / `MODE_ID` / `APP_NAME`，超时 150s，不缓存、不自动重试。\n\n## API Endpoints\n\n### 1. Get Authorization URL\n\n**Endpoint**: `/spApi/authorizeUrl`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description | Example |\n|-----------|------|----------|-------------|---------|\n| region | string | Yes | 区域代码：NA / EU / FE | \"NA\" |\n| sellerName | string | **Yes** | 店铺展示名（店铺名）— **必填，非空**；用于在已授权店铺列表中识别账号 | \"My Store\" |\n\n**Response**:\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n> 说明：授权完成后的回调由 Amazon 直接回调服务端内部接口处理，属于系统内部流程，不作为本 skill 的用户调用接口。\n\n---\n\n### 2. List Authorized Stores\n\n**Endpoint**: `/spApi/authorizedStores`\n\n**Request Parameters**: 无（使用当前用户上下文）\n\n**Response**:\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n---\n\n### 3. Refresh Token\n\n**Endpoint**: `/spApi/refreshToken`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | No | 区域代码（精确匹配可选） |\n\n**Response**:\n\n```json\n{\n  \"authRecordId\": 123,\n  \"success\": true,\n  \"message\": \"刷新成功并已更新数据库，token 已后台化管理\"\n}\n```\n\n---\n\n### 4. Query Store Tokens\n\n**Endpoint**: `/spApi/storeTokens`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | Yes | 区域代码 |\n\n**Response**:\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"status\": \"ACTIVE\",\n  \"tokenExpiresAt\": 3600,\n  \"message\": \"授权信息已后台化管理，token 不再经由 Agent 返回\"\n}\n```\n\n返回值只用于确认授权状态，不作为下游 token 来源。下游业务应通过 `developerProxy` 传入 `sellerId` + `region`。\n\n---\n\n### 5. Cancel Authorization\n\n**Endpoint**: `/spApi/cancelAuthorization`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | 非空 Seller ID，最多 64 字符 |\n| region | string | Yes | NA / EU / FE；必传，不支持单站点解绑 |\n\n**Response**:\n\n```json\n{\n  \"success\": true,\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"removedBindings\": 1,\n  \"localAuthorizationRevoked\": false,\n  \"amazonRevoked\": false,\n  \"message\": \"已解除当前用户的店铺绑定；授权与 token 保留，其他用户不受影响；未撤销 Amazon 授权\"\n}\n```\n\n语义说明：\n\n- 仅解除当前成员的 `sellerId + region` 绑定；授权主记录和 token 保留，其他成员不受影响。\n- 未绑定或重复解绑仍返回 `success=true`、`removedBindings=0`；两个 revoked 字段固定为 `false`。\n- 已发出的请求和未完成的授权回调不受影响，后者可能恢复绑定。Amazon 官方撤销需卖家在 Seller Central → Manage Your Apps → Disable authorization 操作。\n\n---\n\n## Error Codes\n\n| errcode | 含义 | 建议动作 |\n|---------|------|----------|\n| 200 | 成功 | 正常解析 |\n| 400 | 解绑参数格式错误 | 检查 sellerId 与 region |\n| 401 | 认证失败 | HTTP 401 或 authorized error：按 SKILL.md 的 **## 解决认证和算力问题** 处理。|\n| 402 | 算力不足 | HTTP 402：按 SKILL.md 的 **## 解决认证和算力问题** 处理。|\n| 1002 | 缺参数或认证失败 | 检查必填参数与认证 |\n| 1003 | 第三方服务调用失败 | 稍后重试，检查网络与白名单 |\n| 1004 | 授权记录不存在或不属于当前用户 | 核对 sellerId/region 或重新授权 |\n| 1005 | 授权已取消或失效 | 重新授权 |\n\n**Error Response Example**:\n\n```json\n{\n  \"errcode\": 1002,\n  \"errmsg\": \"Missing required parameter: region\"\n}\n```\n\n---\n\n## curl Examples\n\n### Get Authorization URL\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizeUrl \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### List Authorized Stores\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizedStores \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\"\n```\n\n### Refresh Token\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/refreshToken \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### Query Store Tokens\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/storeTokens \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### Cancel Authorization\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/cancelAuthorization \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n---\n\n## Feedback API\n\n> 本接口与上面的工具 API **是不同 base URL**，请勿混用。\n\n- **POST** `https://skill-api.linkfox.com/api/v1/public/feedback`\n- **Content-Type**: `application/json`\n\n```json\n{\n  \"skillName\": \"linkfox-amazon-store-auth\",\n  \"sentiment\": \"POSITIVE\",\n  \"category\": \"OTHER\",\n  \"content\": \"Authorization flow worked smoothly, user was satisfied.\"\n}\n```\n\n**Field rules**:\n- `skillName`: 使用本 skill 的 YAML frontmatter `name`\n- `sentiment`: `POSITIVE` / `NEUTRAL` / `NEGATIVE`\n- `category`: `BUG` / `COMPLAINT` / `SUGGESTION` / `OTHER`\n- `content`: 用户说的话、实际发生了什么、为什么是问题或赞赏\n\n---\n\n## Important Notes\n\n1. **Token 安全**：不要打印完整 accessToken/refreshToken，仅展示前 10 字符掩码。\n2. **Token 生命周期**：accessToken 1 小时过期，使用前检查并按需刷新。\n3. **区域专属**：同一卖家在不同区域需要分别授权。\n4. **用户隔离**：所有 API 都强制用户级访问控制。\n5. **回调白名单**：系统回调 URL 必须在授权提供方（紫鸟）处加白名单。\n6. **取消授权语义**：`cancelAuthorization` 只做 LinkFox 当前成员解绑，不代表 Amazon 侧 OAuth 授权已撤销。\n\n完整授权流程与实现细节：见 `authorization-flow.md`。\n\nFile v1.0.8:references/authorization-flow.md\n\n# Amazon Store 授权流程详细说明\n\n本文档提供所有授权相关接口的详细说明，包括请求参数、返回值、错误处理等。\n\n---\n\n## 1. 获取授权URL\n\n### 接口信息\n\n- **路径**: `/spApi/authorizeUrl`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:52`\n\n### 请求参数 (SpApiAuthorizeUrlReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| region | String | ✅ 是 | 区域代码：NA/EU/FE | \"NA\" |\n| sellerName | String | ✅ **是（必填）** | 店铺名 / 卖家展示名称，用于在已授权店铺列表中区分账号；**调用前必须向用户确认并传入非空字符串**，不可省略 | \"My Amazon Store\" |\n| central | String | ❌ 否 | 中心站点 | - |\n| marketplace | String | ❌ 否 | 市场代码 | - |\n\n### 返回结果 (SpApiAuthorizeUrlVo)\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/...\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authorizeUrl | String | 亚马逊授权链接，用户需在浏览器中打开 |\n\n### 业务逻辑\n\n1. 校验 region 参数（必须为 NA/EU/FE）；**本 Skill 约定**：`sellerName` 须为非空字符串（与用户在 LinkFox 侧展示、区分店铺一致），AI/脚本在调用前应向用户确认店铺名。\n2. 构建 state 参数：\n   - 包含 gateway.url + /spApi/oauth/callback\n   - 附加 userId, region, sellerName\n3. 调用紫鸟代理接口 `/developer-proxy/v1/authorize/url`\n4. 返回授权链接给用户\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 缺少 region 参数 | 必须提供 region (NA/EU/FE) |\n| 1003 | 获取授权地址失败 | 检查网络连接和白名单配置，稍后重试 |\n\n### 使用示例\n\n**请求**:\n```json\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?application_id=xxx&state=xxx\"\n}\n```\n\n**后续操作**:\n用户在浏览器中打开 `authorizeUrl`，在亚马逊页面完成授权后，会自动重定向到回调地址。\n\n---\n\n## 2. 授权回调处理（服务端内部）\n\n### 接口信息\n\n- **路径**: 服务端内部回调接口（不对客户端/Agent暴露）\n- **方法**: POST (RouteMapping)\n- **鉴权**: 不需要（auth=false）\n- **实现**: `SpApiController.java:111`\n\n### 请求参数 (SpApiAuthorizeCallbackReq)\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| userId | String | ✅ 是 | 用户ID（从 state 中解析） |\n| sellingPartnerId | String | ✅ 是 | 亚马逊卖家ID |\n| accessToken | String | ✅ 是 | 访问令牌 |\n| refreshToken | String | ✅ 是 | 刷新令牌 |\n| tokenType | String | ❌ 否 | 令牌类型（默认 bearer） |\n| expiresIn | String | ❌ 否 | 过期时间（秒） |\n| region | String | ✅ 是 | 区域代码 |\n| sellerName | String | ❌ 否 | 卖家名称 |\n| mwsAuthToken | String | ❌ 否 | MWS 授权令牌 |\n\n### 返回结果 (SpApiAuthorizeCallbackVo)\n\n```json\n{\n  \"saved\": true,\n  \"authRecordId\": 123,\n  \"bindUserId\": 456,\n  \"message\": \"已新增授权\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| saved | Boolean | 是否保存成功 |\n| authRecordId | Long | 授权记录ID（sp_api_amazon_auth 表） |\n| bindUserId | Long | 绑定记录ID（sp_api_bind_user 表） |\n| message | String | 处理结果消息 |\n\n### 业务逻辑\n\n1. 检查是否已存在同一店铺的授权（sellingPartnerId + region）\n2. 如果存在，更新原有授权记录；否则新增\n3. 创建或更新用户与授权的绑定关系\n4. 返回保存结果\n\n### 注意事项\n\n- 此接口无需鉴权，因为是亚马逊重定向回调\n- userId 从 state 参数中解析，必须在获取授权URL时正确设置\n- 同一店铺的授权会更新而非重复创建\n\n---\n\n## 3. 查看已授权店铺列表\n\n### 接口信息\n\n- **路径**: `/spApi/authorizedStores`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:126`\n\n### 请求参数\n\n无（从 Token 中自动获取当前用户 userId）\n\n### 返回结果 (SpApiAuthorizedStoresVo)\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"EU Store\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| stores | Array | 店铺列表 |\n| stores[].sellerName | String | 卖家名称 |\n| stores[].sellerId | String | 卖家ID |\n| stores[].region | String | 区域代码 |\n| total | Integer | 店铺总数 |\n\n### 业务逻辑\n\n1. 根据 gatewayUserId 查询 sp_api_bind_user 表\n2. 获取所有关联的 amazonAuthId\n3. 查询对应的授权记录\n4. 去重并按 sellerId 和 region 排序\n5. 返回店铺列表\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 无法识别当前用户 | 请重新登录 |\n\n---\n\n## 4. 刷新访问令牌\n\n### 接口信息\n\n- **路径**: `/spApi/refreshToken`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:134`\n\n### 请求参数 (SpApiRefreshTokenReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ❌ 否 | 区域代码（用于精确匹配） | \"NA\" |\n\n### 返回结果 (SpApiRefreshTokenVo)\n\n```json\n{\n  \"authRecordId\": 123,\n  \"success\": true,\n  \"message\": \"刷新成功并已更新数据库，token 已后台化管理\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authRecordId | Long | 授权记录ID |\n| success | Boolean | 刷新是否成功 |\n| message | String | 处理结果 |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 调用紫鸟代理接口 `/developer-proxy/{region}/auth/o2/token`\n4. 使用 refresh_token 换取新的 access_token\n5. 更新数据库中的令牌信息\n6. 返回刷新状态，不下发 raw token\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId | 必须提供卖家ID |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查 sellerId 是否正确，或重新授权 |\n| 1004 | 缺少 refresh_token | 授权记录异常，需重新授权 |\n| 1003 | 刷新令牌请求失败 | 检查网络连接，稍后重试 |\n\n### 注意事项\n\n- refresh_token 可能在刷新时更新，由服务端保存\n- 如果 region 未提供，会匹配该 sellerId 的第一条记录；生产调用建议传 region\n\n---\n\n## 5. 查询授权状态\n\n### 接口信息\n\n- **路径**: `/spApi/storeTokens`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:142`\n\n### 请求参数 (SpApiStoreTokensReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ✅ 是 | 区域代码 | \"NA\" |\n\n### 返回结果 (SpApiStoreTokensVo)\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"status\": \"ACTIVE\",\n  \"tokenExpiresAt\": 3600,\n  \"message\": \"授权信息已后台化管理，token 不再经由 Agent 返回\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| sellerId | String | 卖家ID |\n| region | String | 区域代码 |\n| authRecordId | Long | 授权记录ID |\n| status | String | 授权状态：ACTIVE / EXPIRED / REVOKED |\n| tokenExpiresAt | Long | token 过期时间信息 |\n| message | String | 说明 |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 读取本地授权状态（不调用刷新）\n4. 返回状态与元数据，不下发 raw token\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId 或 region | 必须同时提供卖家ID和区域 |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查参数或重新授权 |\n\n### 使用场景\n\n- 在调用亚马逊卖家开放接口前确认本地授权是否存在\n- 检查授权状态是否 ACTIVE\n- 如果令牌过期，调用 refreshToken 接口更新\n\n---\n\n## 6. 本地取消/解绑授权\n\n用户操作流程见 [SKILL.md 场景 5](../SKILL.md#scenario-5-cancel-local-authorization)，参数、响应及解绑边界统一见 [API §5](api.md#5-cancel-authorization)。\n\n---\n\n## 区域与站点映射\n\n### 北美 (NA)\n\n- 美国: amazon.com\n- 加拿大: amazon.ca\n- 墨西哥: amazon.com.mx\n\n### 欧洲 (EU)\n\n- 英国: amazon.co.uk\n- 德国: amazon.de\n- 法国: amazon.fr\n- 意大利: amazon.it\n- 西班牙: amazon.es\n- 荷兰: amazon.nl\n- 瑞典: amazon.se\n- 波兰: amazon.pl\n\n### 远东 (FE)\n\n- 日本: amazon.co.jp\n- 澳大利亚: amazon.com.au\n- 新加坡: amazon.sg\n\n---\n\n## 数据库表结构\n\n### sp_api_amazon_auth (授权信息表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| region | String | 区域代码 (NA/EU/FE) |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| sellingPartnerId | String | 卖家ID |\n| sellerName | String | 卖家名称 |\n| mwsAuthToken | String | MWS 授权令牌 |\n| status | String | ACTIVE / REVOKED |\n| revokedByGatewayUserId | String | 本地停用授权的用户 |\n| revokedDate | Date | 本地停用时间 |\n| revokedTime | Long | 本地停用时间戳 |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n### sp_api_bind_user (用户绑定表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| gatewayUserId | String | 网关用户ID |\n| amazonAuthId | Long | 授权记录ID（外键） |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n---\n\n## 完整授权示例\n\n### 步骤 1: 获取授权链接\n\n**请求**:\n```bash\nPOST /spApi/authorizeUrl\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n### 步骤 2: 用户授权\n\n用户在浏览器中打开 `authorizeUrl`，登录亚马逊卖家中心并同意授权。\n\n### 步骤 3: 自动回调\n\n亚马逊重定向到:\n```\nhttps://<gateway.url>/spApi/oauth/callback?\n  userId=<userId>&\n  region=NA&\n  sellerName=MyStore&\n  selling_partner_id=A1234567890&\n  access_token=Atza|...&\n  refresh_token=Atzr|...&\n  token_type=bearer&\n  expires_in=3600\n```\n\n系统自动保存授权信息。\n\n### 步骤 4: 查看授权结果\n\n**请求**:\n```bash\nPOST /spApi/authorizedStores\nHeaders: Authorization: Bearer <token>\n```\n\n**响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"MyStore\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n### 步骤 5: 调用卖家开放接口\n\n**请求**:\n```bash\nPOST /spApi/developerProxy\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"path\": \"orders/v0/orders\",\n  \"method\": \"GET\"\n}\n```\n\n服务端会根据 `sellerId` + `region` 取用后台 token，并在检测到过期时尝试刷新一次。\n\n---\n\n## 故障排查\n\n### 问题 1: 授权链接无法访问\n\n**可能原因**:\n- 网络连接问题\n- 紫鸟代理服务异常\n- 白名单配置错误\n\n**解决方案**:\n1. 检查网络连接\n2. 确认白名单配置\n3. 稍后重试或联系技术支持\n\n### 问题 2: 回调未保存授权信息\n\n**可能原因**:\n- state 参数中缺少 userId\n- 数据库连接异常\n\n**解决方案**:\n1. 确认获取授权URL时正确传入用户信息\n2. 检查数据库连接\n3. 查看服务日志\n\n### 问题 3: 刷新令牌失败\n\n**可能原因**:\n- refresh_token 已过期或失效\n- 紫鸟代理服务异常\n\n**解决方案**:\n1. 如果 refresh_token 失效，需重新授权\n2. 检查紫鸟服务状态\n3. 确认白名单配置\n\n### 问题 4: 查询令牌返回 1004 错误\n\n**可能原因**:\n- sellerId 或 region 错误\n- 授权记录不属于当前用户\n\n**解决方案**:\n1. 调用 /spApi/authorizedStores 确认店铺信息\n2. 确认 sellerId 和 region 正确\n3. 如果确实未授权，需先完成授权流程\n\n---\n\n## 安全最佳实践\n\n1. **令牌存储**:\n   - 令牌存储在数据库中，不暴露给前端\n   - 仅通过后端接口访问令牌\n\n2. **访问控制**:\n   - 所有接口都进行用户鉴权\n   - 用户只能访问自己授权的店铺\n\n3. **令牌刷新**:\n   - 定期检查令牌是否即将过期\n   - 自动刷新即将过期的令牌\n\n4. **日志记录**:\n   - 记录所有授权操作\n   - 记录令牌刷新操作\n   - 不记录令牌明文内容\n\n5. **错误处理**:\n   - 不在错误消息中暴露敏感信息\n   - 提供清晰的错误码和处理建议\n\nFile v1.0.8:references/onboarding.md\n\n# 解决认证和算力问题\n\n调用本 skill 时若网关返回 **auth** 或 **billing** 错误，走本 skill 自带的 `scripts/onboarding.py` 完成引导。\n\n**auth 场景**：`errcode=401` 或消息含 `authorized error`/`鉴权失败`/`未授权`/`unauthorized`；或 `LINKFOX_AGENT_API_KEY` 与 `LINKFOXAGENT_API_KEY` 均为空。\n1. 若已配置 key → 先让用户重启会话（最常见误判），仍失败让用户重新取 key 或换手机号重注册\n2. 未配置 → 询问：自助去 https://agent.linkfox.com/ 取 key，或提供手机号让脚本注册\n3. 手机号路径：\n   - `python scripts/onboarding.py send-code <phone>` → 展示 JSON 里的 phone/agreements\n   - 收到验证码后：`python scripts/onboarding.py login <phone> <code>`\n   - 拿到 `api_key` 后把下面三平台配置转发给用户，提示重启会话生效：\n     - Windows PowerShell（永久）：`setx LINKFOX_AGENT_API_KEY \"<key>\"`\n     - macOS zsh：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.zshrc && source ~/.zshrc`\n     - Linux bash：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.bashrc && source ~/.bashrc`\n     - 变量名 `LINKFOX_AGENT_API_KEY`（主推）或 `LINKFOXAGENT_API_KEY`（老规范）任一即可\n\n**billing 场景**：`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。\n- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单，否则输出编号清单让用户选\n- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`（通常 `wechat/alipay`）\n- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG > `pay_url` > `ascii_qr`（标注兜底）\n- 已付款可选调 `python scripts/onboarding.py query <order_id>`，不主动轮询\n\n排除 `errcode=403`（无权限，不归入这两类）。所有子命令输出 stdout JSON，`error` 字段已含阶段前缀，透传给用户即可。完整用法：`python scripts/onboarding.py --help`。\n\nFile v1.0.8:references/quick-start.md\n\n# Amazon Store 授权快速开始指南\n\n本指南帮助你快速上手使用亚马逊店铺授权功能。\n\n## 前置条件\n\n1. **已部署的服务**:\n   - linkfox-agent-ecom-plat 服务已启动\n   - 紫鸟代理服务可访问\n   - 数据库已正确配置\n\n2. **已配置的环境**:\n   - 回调地址已添加到紫鸟白名单\n   - gateway.url 配置正确\n\n3. **用户认证**:\n   - 用户已登录并获取 Token\n\n## 5分钟快速授权\n\n> **重要：店铺名（`sellerName`）必填**  \n> 调用 `/spApi/authorizeUrl` 时**必须**传入非空的 `sellerName`，用于在系统中标识该授权店铺（多店铺时便于区分）。若用户未提供，请先询问用户填写后再请求授权链接。脚本 `authorize_url.py` 会在本地校验该字段。\n\n### 第一步：获取授权链接\n\n**调用接口**:\n```bash\nPOST /spApi/authorizeUrl\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"我的店铺\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n**操作**: 复制 `authorizeUrl` 的值\n\n### 第二步：浏览器授权\n\n1. 在浏览器中打开上一步获取的 `authorizeUrl`\n2. 使用亚马逊卖家账号登录\n3. 查看并同意授权请求\n4. 点击\"确认\"或\"Authorize\"按钮\n5. 等待页面跳转（自动完成授权保存）\n\n### 第三步：验证授权成功\n\n**调用接口**:\n```bash\nPOST /spApi/authorizedStores\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n```\n\n**预期响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n如果看到店铺信息，说明授权成功！\n\n## 使用授权状态\n\n### 查询授权状态\n\n**调用接口**:\n```bash\nPOST /spApi/storeTokens\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"status\": \"ACTIVE\",\n  \"tokenExpiresAt\": 3600,\n  \"message\": \"授权信息已后台化管理，token 不再经由 Agent 返回\"\n}\n```\n\n### 调用卖家开放接口\n\n下游业务不要读取 raw token。直接调用 `/spApi/developerProxy`，并传入同一个 `sellerId` + `region`：\n\n```bash\nPOST /spApi/developerProxy\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"path\": \"orders/v0/orders\",\n  \"method\": \"GET\"\n}\n```\n\n## 令牌管理\n\n### 令牌过期时间\n\n- **accessToken**: 通常 1 小时（3600秒）\n- **refreshToken**: 长期有效，用于刷新 accessToken\n\n### 检查令牌是否即将过期\n\n从 `/spApi/storeTokens` 响应中查看 `status` / `tokenExpiresAt` / `message`：\n- `ACTIVE`：可继续通过 `developerProxy` 调用\n- `EXPIRED` 或调用返回 token 失效：调用 `/spApi/refreshToken` 刷新\n- 当前用户连接已解绑时，需重新授权后才能使用该连接；解绑接口不将共享授权标记为 REVOKED\n\n### 刷新过期令牌\n\n**调用接口**:\n```bash\nPOST /spApi/refreshToken\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authRecordId\": 123,\n  \"success\": true,\n  \"message\": \"刷新成功并已更新数据库，token 已后台化管理\"\n}\n```\n\n刷新后，继续通过 `/spApi/developerProxy` 传 `sellerId` + `region` 调用业务接口。\n\n### 本地取消/解绑授权\n\n按 [SKILL.md 场景 5](../SKILL.md#scenario-5-cancel-local-authorization) 确定目标与范围后执行；参数及示例见 [API §5](api.md#5-cancel-authorization)。\n\n## 多店铺管理\n\n### 授权第二个店铺\n\n重复授权流程，但使用不同的区域或账号：\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"EU\",\n  \"sellerName\": \"欧洲店铺\"\n}\n```\n\n### 查看所有授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n响应会包含所有已授权的店铺：\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"欧洲店铺\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n### 为不同店铺获取令牌\n\n只需指定不同的 `sellerId` 和 `region`：\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A9876543210\",\n  \"region\": \"EU\"\n}\n```\n\n## 常见场景\n\n### 场景 1: 定时任务调用卖家开放接口\n\n1. 任务保存或接收 `sellerId` + `region`\n2. 通过 `/spApi/developerProxy` 调用卖家开放接口\n3. 如返回 token 失效，调用 `/spApi/refreshToken` 刷新\n4. 使用相同 `sellerId` + `region` 重试一次\n\n### 场景 2: 多店铺数据同步\n\n1. 调用 `/spApi/authorizedStores` 获取所有店铺\n2. 遍历店铺列表\n3. 可选调用 `/spApi/storeTokens` 确认状态\n4. 用每个店铺的 `sellerId` + `region` 调 `developerProxy`\n\n### 场景 3: 用户重新授权\n\n如果用户在亚马逊卖家中心撤销了授权：\n\n1. 老令牌会失效\n2. 调用卖家开放接口 会返回 401 Unauthorized\n3. 需要用户重新授权（重复获取授权链接的流程）\n4. 系统会自动更新数据库中的令牌\n\n### 场景 4: 用户取消本地授权\n\n1. 先用 `/spApi/authorizedStores` 确认要解绑的店铺\n2. 调用 `/spApi/cancelAuthorization`\n3. 告知用户 LinkFox 已不再使用该授权；如需 Amazon 侧彻底撤销，请到 Seller Central 授权管理页手动 Disable authorization\n\n## 故障排查\n\n### 问题：获取授权链接失败（错误码 1003）\n\n**可能原因**: 网络问题或白名单配置错误\n\n**解决方法**:\n1. 检查网络连接到紫鸟代理服务\n2. 确认回调地址已添加到白名单\n3. 查看服务日志获取详细错误信息\n\n### 问题：授权完成但未保存（查询不到店铺）\n\n**可能原因**: 回调参数缺失或数据库异常\n\n**解决方法**:\n1. 检查浏览器回调 URL 是否包含所有参数\n2. 查看服务日志，确认回调是否被触发\n3. 检查数据库连接和表结构\n\n### 问题：刷新令牌失败（错误码 1004）\n\n**可能原因**: refresh_token 已失效\n\n**解决方法**:\n1. refresh_token 一旦失效，无法恢复\n2. 需要用户重新完成授权流程\n3. 建议定期刷新令牌，避免长时间不使用导致失效\n\n### 问题：调用卖家开放接口 返回 401\n\n**可能原因**: accessToken 过期或无效\n\n**解决方法**:\n1. 调用 `/spApi/refreshToken` 刷新令牌\n2. 如果刷新失败，需要重新授权\n3. 使用新令牌重试 API 调用\n\n## 最佳实践\n\n### 1. 令牌缓存策略\n\n```\n获取令牌时：\n  ↓\n检查缓存是否存在且未过期\n  ↓\n如果是，直接使用缓存的令牌\n  ↓\n如果否，从数据库读取并检查过期时间\n  ↓\n如果即将过期（< 5分钟），先刷新\n  ↓\n将新令牌写入缓存\n```\n\n### 2. 错误重试机制\n\n```\n调用卖家开放接口\n  ↓\n如果返回 401\n  ↓\n刷新令牌\n  ↓\n重试 API 调用（最多1次）\n  ↓\n如果仍失败，返回错误\n```\n\n### 3. 批量操作优化\n\n```\n获取所有店铺列表\n  ↓\n批量获取所有店铺的令牌\n  ↓\n并行调用卖家开放接口（控制并发数）\n  ↓\n汇总结果\n```\n\n### 4. 安全建议\n\n- ✅ 令牌仅存储在后端，不传递给前端\n- ✅ 使用 HTTPS 传输令牌\n- ✅ 定期检查并刷新令牌\n- ✅ 记录所有授权操作日志\n- ❌ 不在日志中记录完整令牌\n- ❌ 不在前端 JavaScript 中存储令牌\n\n## 下一步\n\n- 查看 [完整接口文档](authorization-flow.md) 了解所有接口的详细说明\n- 查看 [SKILL.md](../SKILL.md) 了解 skill 的完整功能\n- 参考后端工程中店铺网关相关 Controller 实现（包名与类名以你们仓库为准）\n\n## 技术支持\n\n如遇到问题，请：\n1. 查看服务日志\n2. 参考故障排查章节\n3. 联系技术团队\n\nFile v1.0.8:skill-card.md\n\n## Description:\n\nHelps agents manage Amazon Seller store authorization, including generating authorization links, listing authorized stores, checking authorization status, refreshing access tokens, and locally disconnecting store bindings.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[linkfox-ai](https://clawhub.ai/user/linkfox-ai)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and agents use this skill to connect Amazon Seller accounts to LinkFox, choose an authorized store, verify authorization health, and prepare sellerId plus region for downstream Amazon seller workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The security scan marked the release suspicious because it includes login, billing/payment, feedback reporting, sensitive local storage, and Amazon store authorization behavior.\n\nMitigation: Review the skill before installing, run only the intended authorization or store-management flow, and avoid onboarding or payment actions unless the user explicitly intends to use LinkFox account billing.\n\nRisk: Gateway base URLs can be overridden with environment variables, which could send API keys or store authorization requests to an unintended endpoint.\n\nMitigation: Use trusted LinkFox endpoints and avoid custom gateway overrides unless the endpoint is controlled and expected.\n\nRisk: API keys, seller identifiers, authorization status, and response files can be sensitive operational data.\n\nMitigation: Store API keys in a secret manager or protected environment, avoid exposing raw tokens, and clear local linkfox response files when they may contain store identifiers or authorization data.\n\nRisk: Local disconnection only removes the current LinkFox member binding and does not revoke Amazon Seller Central authorization.\n\nMitigation: Tell users to revoke access in Amazon Seller Central when they need full OAuth authorization removal.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth)\n- [API Reference](artifact/references/api.md)\n- [Authorization Flow](artifact/references/authorization-flow.md)\n- [Quick Start](artifact/references/quick-start.md)\n- [Onboarding Guide](artifact/references/onboarding.md)\n- [Script Usage Guide](artifact/scripts/README.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with JSON API responses and shell command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Scripts save complete JSON responses under a local linkfox session directory and summarize large responses; token-status helpers remove raw access and refresh tokens before display.]\n\n## Skill Version(s):\n\n1.0.8 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.7: 16 files, 38325 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5748b), references/authorization-flow.md (13082b), references/onboarding.md (2046b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/_token_status_output.py (1059b), scripts/authorize_url.py (3843b), scripts/authorized_stores.py (2305b), scripts/onboarding.py (24089b), scripts/README.md (2361b), scripts/refresh_token.py (2843b), scripts/store_tokens.py (2787b), skill-card.md (3025b), SKILL.md (11849b)\n\nFile v1.0.7:SKILL.md\n\n---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊店铺授权与管理技能，提供完整的授权流程、令牌刷新、已授权店铺查询以及授权状态查询能力。获取授权链接时店铺名 sellerName 为必填，用于区分已授权店铺。当用户提到亚马逊店铺授权、绑定亚马逊店铺、刷新令牌、查询店铺授权状态、管理授权店铺、Amazon seller authorization, bind Amazon seller account, refresh access token, query store token status, manage authorized stores时触发此技能。只要其需求涉及亚马逊卖家账号授权、令牌生命周期管理或店铺列表查询，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、授权状态查询与令牌刷新**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。下游业务经 `developerProxy` 传入 `sellerId`+`region` 即可，**无需**先取 raw token。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens（授权状态，非 raw token 下发）\n\n`POST /spApi/storeTokens` 返回**状态与元数据**（具体字段以网关为准），供确认授权是否有效、何时过期。**不要**将响应当作下游 `developerProxy` 的 token 来源。\n\n| Field | Type | Description |\n|-------|------|-------------|\n| status | string | 授权/令牌状态（如有效、过期、缺失） |\n| authRecordId | integer | 授权记录 ID（如有） |\n| expiresIn | integer | 距 accessToken 过期的秒数（如有） |\n| tokenExpiresAt | string | 绝对过期时间（如有） |\n| message | string | 补充说明 |\n| errcode / errmsg | integer / string | 网关错误（失败时） |\n\n> 兼容说明：旧版网关可能仍返回 `accessToken`/`refreshToken`；Agent **不应**优先读取或传递给下游。下游应使用 `sellerId`+`region` 调 `developerProxy`。\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**。当用户未指定区域时，使用 NA。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗积分；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## 解决认证和积分问题\n发生以下异常情况时，采用 references/onboarding.md 引导解决问题：\n\n### 异常情况\n- **未配置API Key**：环境变量未配置 `LINKFOX_AGENT_API_KEY`，也未配置 `LINKFOXAGENT_API_KEY`。\n- **响应401或402状态码**\n- **响应提示积分或余额不足**：消息含\"积分余额不足/计费不足/余额不足/quota exceeded/insufficient balance/套餐到期/需充值/请充值\"，或类似含义的内容。\n\n## Usage Scenarios\n\n### Scenario 1: Authorize New Store\n\n**User request**：「我要授权我的亚马逊北美站点」\n\n**Steps**：\n1. **询问店铺名 `sellerName`**（若用户未提供）。`/spApi/authorizeUrl` 要求 `sellerName` 为非空字符串；向用户说明这只是在 LinkFox 里识别店铺的标签，建议与 Seller Central 后台名字保持一致。\n2. 调用 `/spApi/authorizeUrl`，传入 `region` 与 `sellerName`\n3. 把返回的 `authorizeUrl` 给用户，让其在浏览器中打开\n4. 用户在 Amazon 完成授权 → Amazon 回调系统 → 系统自动保存授权\n5. 可选：调用 `/spApi/authorizedStores` 确认授权成功\n\n### Scenario 2: View Authorized Stores\n\n**User request**：「列一下我已授权的亚马逊店铺」\n\n**Steps**：\n1. 调用 `/spApi/authorizedStores`\n2. 展示店铺列表（sellerName / sellerId / region）\n3. 按 sellerId、region 排序\n\n### Scenario 3: Refresh Expired Token\n\n**User request**：「我店铺的令牌过期了，帮我刷新」\n\n**Steps**：\n1. 调用 `/spApi/refreshToken`，传入 `sellerId`（可选 `region`）\n2. 返回刷新**状态与元数据**（如 `status`、`message`、`expiresIn`）；服务端更新令牌\n3. 下游可直接重试 `developerProxy`（传入相同 `sellerId`+`region`），**无需**读取 raw token\n\n### Scenario 4: Query Store Token Status\n\n**User request**：「查一下北美站点 A123 店铺的授权/令牌状态」\n\n**Steps**：\n1. 调用 `/spApi/storeTokens`，传入 `sellerId` 与 `region`\n2. 向用户展示**状态字段**（`status`、`expiresIn`、`tokenExpiresAt`、`message` 等）\n3. **不要**把响应当作下游 proxy 的 token；业务调用直接带 `sellerId`+`region`\n\n### Scenario 5: Prepare Account Selector for Any Store Operation (Standard Preparation Workflow)\n\n当用户提出任何涉及卖家后台数据的请求（拉报告、查库存、看订单等），**本 skill 负责前置的「选店 → 确认授权」**，具体业务由相应的下游 skill 接手。\n\n**Steps**：\n1. **列出已授权店铺**：调用 `/spApi/authorizedStores`\n2. **让用户选择店铺**：如果有多家店铺，请用户明确选哪一家，确定 `sellerId` 与 `region`\n3. （可选）调用 `/spApi/storeTokens` **仅作状态确认**（过期则先 `refreshToken`）\n4. **把 `sellerId`+`region` 交给下游 skill**（例如 `linkfox-amazon-store-report`），由下游直接调 `developerProxy`\n\n**Why this workflow is critical**：\n- 用户可能同时授权了多家不同区域的店铺\n- 每家店铺的令牌与权限彼此独立\n- 必须使用与店铺匹配的 `sellerId`+`region`，跳过「选店」会导致歧义和错误\n\n## Display Rules\n\n1. **先有店铺名再生成授权链接**：若用户未提供 `sellerName`，**必须先问**，不允许带空值调用 `/spApi/authorizeUrl`。\n2. **只呈现数据**：展示授权结果、店铺列表、令牌信息即可，不做业务建议。\n3. **安全意识**：响应若含 legacy token 字段，不要明文展示；优先呈现 `status` / 过期时间等元数据。\n4. **清晰引导**：返回授权链接时，明确告知用户在浏览器中打开并完成授权。\n5. **错误说明**：授权失败时，基于错误码解释原因并给出建议。\n6. **成功确认**：授权完成后与用户确认，可选择展示该店铺基本信息。\n\n## Important Limitations\n\n- **sellerName 必填**：`/spApi/authorizeUrl` 必须传入非空 `sellerName`；脚本与 agent 在调用前务必校验。\n- **令牌有效期**：`accessToken` 1 小时过期，需及时刷新。\n- **区域专属**：每次店铺授权都与具体区域绑定，不同区域需分别授权。\n- **用户隔离**：用户只能查看/管理自己授权的店铺。\n- **回调白名单**：系统回调 URL 必须在授权方（紫鸟）处加白名单。\n\n## User Expression & Scenario Quick Reference\n\n**Applicable** — 授权与令牌管理场景：\n\n| User Says | Scenario |\n|-----------|----------|\n| \"授权我的亚马逊店铺\" / \"Authorize my Amazon store\" | 新店铺授权 |\n| \"看看已授权的亚马逊店铺\" / \"Show my authorized stores\" | 列出已授权店铺 |\n| \"令牌过期了\" / \"My token expired\" | 刷新令牌 |\n| \"查 XXX 店铺授权状态\" / \"Check store token status\" | 查询授权状态（storeTokens） |\n| \"绑定我的亚马逊账号\" / \"Connect my Amazon seller account\" | 新店铺授权 |\n\n**Not applicable** — 超出本 skill 的业务：\n\n- **拉取亚马逊报告** → 请使用 `linkfox-amazon-store-report`\n- 产品 listing 管理、订单处理、库存管理、广告投放 → 由其他 skill 负责\n\n**Boundary judgment**：\n- 本 skill 只负责「授权 + 管店铺 + 令牌刷新/状态查询 + 为下游准备 `sellerId`+`region` 选店信息」。\n- **不要**为下游 `developerProxy` 调用 `storeTokens` 取 raw `accessToken`（除非兼容极旧客户端且用户明确要求）。\n- 当用户要做具体卖家后台业务（如拉报告）时：\n  1. 本 skill 执行 Scenario 5 的标准前置流程（选店）\n  2. 随后切换到对应下游 skill，直接 `developerProxy` + `sellerId`+`region`\n- 不要直接越过本 skill 去调具体 Amazon 开放接口。\n\n## Quick Reference\n\n### Authorization & Token Management APIs\n\n| API | Path | Purpose | Auth Required |\n|-----|------|---------|---------------|\n| Get Authorization URL | /spApi/authorizeUrl | 生成授权链接（需要 sellerName） | ✅ Yes |\n| List Authorized Stores | /spApi/authorizedStores | 查询用户的店铺列表 | ✅ Yes |\n| Refresh Token | /spApi/refreshToken | 刷新访问令牌 | ✅ Yes |\n| Query Store Token Status | /spApi/storeTokens | 查询某店铺授权/令牌状态（非下游 token 来源） | ✅ Yes |\n\n详细请求参数、响应结构、错误码，见 `references/api.md`。完整授权流程图，见 `references/authorization-flow.md`。快速上手示例，见 `references/quick-start.md`。\n\n## 积分消耗规则\n\n不消耗积分。\n\n**Feedback**：\n\n当出现以下任一情况时，自动通过 Feedback API 上报反馈：\n1. 本 skill 描述的功能与实际行为不符\n2. skill 的结果与用户意图不符\n3. 用户表达了对本 skill 的不满或赞赏\n4. 任何你认为可以改进的点\n\n按 `references/api.md` 中的规范调用 Feedback API，不要打断用户的主流程。\n\n---\n*For more high-quality, professional cross-border e-commerce skills, visit [LinkFox Skills](https://skill.linkfox.com/).*\n\nFile v1.0.7:README.md\n\n# Amazon Store Authorization Skill\n\n亚马逊店铺 **授权与管理** Skill，提供授权流程、令牌管理、店铺查询等能力，是所有下游业务 skill（如 `linkfox-amazon-store-report`）的前置依赖。\n\n## 📋 目录结构\n\n```\nlinkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    └── store_tokens.py               # 查询店铺令牌\n```\n\n## 🚀 快速开始\n\n### 1. 授权新店铺\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl\n```\n\n### 2. 查看已授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n### 3. 获取访问令牌（供下游 skill 使用）\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n## 🔗 关联 Skill\n\n| Skill | 说明 |\n|-------|------|\n| `linkfox-amazon-store-report` | 获取亚马逊报告（依赖本 skill） |\n\n## 🌍 支持的区域\n\n- **NA**：美国、加拿大、墨西哥\n- **EU**：英国、德国、法国、意大利、西班牙等\n- **FE**：日本、澳大利亚、新加坡、印度\n\n## 🔐 安全特性\n\n- ✅ 用户级数据隔离\n- ✅ 令牌自动刷新\n- ✅ 完整错误处理\n- ✅ HTTPS 加密\n\n## 🔄 版本历史\n\n- **v1.0.0**（2026-04-24）\n  - 从早期综合亚马逊 skill 拆分而来\n  - 保留所有授权、店铺管理、令牌管理能力\n  - 报告相关能力已拆出至 `linkfox-amazon-store-report`\n\n## 📄 许可\n\n本 Skill 是 LinkFoxAgent 项目的一部分。\n\nFile v1.0.7:scripts/README.md\n\n# Amazon Store Auth Scripts Usage Guide\n\n本目录包含 **授权与店铺/令牌管理** 相关的 Python 脚本。若需要拉取报告，请使用 `linkfox-amazon-store-report` skill。\n\n## Prerequisites\n\n- Python 3.6 或更高\n- 已设置 `LINKFOXAGENT_API_KEY` 环境变量\n- 可访问 LinkFox 后端 API（默认 `https://tool-gateway.linkfox.com`）\n\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-api-key-here\"\n```\n\n## Available Scripts\n\n### 1. authorize_url.py\n\n为新店铺生成授权 URL。\n\n**`sellerName`（店铺名）必填**：必须为非空字符串。脚本会在缺失或为空白时直接退出并报错——调用前请先向用户询问一个可识别的店铺名。\n\n```bash\npython authorize_url.py '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### 2. authorized_stores.py\n\n列出当前用户已授权的所有亚马逊店铺。\n\n```bash\npython authorized_stores.py\n```\n\n### 3. refresh_token.py\n\n刷新某店铺的 accessToken。\n\n```bash\npython refresh_token.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 4. store_tokens.py\n\n获取某店铺的访问令牌。下游 skill（如 `linkfox-amazon-store-report`）会调用它以拿到 `accessToken`。\n\n```bash\npython store_tokens.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| LINKFOXAGENT_API_KEY | API 鉴权 key | 必需 |\n| STORE_API_BASE_URL / SPAPI_BASE_URL | 后端网关 base URL（优先读前者） | https://tool-gateway.linkfox.com |\n\n## Error Codes\n\n- `0`：成功\n- `1`：缺少 API key、参数错误、网络/HTTP/权限错误\n\n## Troubleshooting\n\n**API Key 未配置**\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-key-here\"\n```\n\n**Connection Refused / 网络错误**\n- 确认 `https://tool-gateway.linkfox.com` 能从你的网络访问（或设置 `STORE_API_BASE_URL` / `SPAPI_BASE_URL` 指向其他网关）\n- 检查防火墙、代理设置\n\n**403 Unauthorized**\n- 店铺可能缺少必要的亚马逊接口权限\n- 用更完整的权限集合重新授权\n\n**查询令牌返回 1004**\n- 核对 sellerId 与 region\n- 确认该店铺已完成授权\n\n## Further Documentation\n\n- API Reference: `../references/api.md`\n- 授权流程详解: `../references/authorization-flow.md`\n- 快速上手: `../references/quick-start.md`\n- Skill 文档: `../SKILL.md`\n\nFile v1.0.7:_meta.json\n\n{\n  \"ownerId\": \"kn7dmc1t4j28hem1twwyav85p182pb1j\",\n  \"slug\": \"linkfox-amazon-store-auth\",\n  \"version\": \"1.0.7\",\n  \"publishedAt\": 1786718660849\n}\n\nFile v1.0.7:references/api.md\n\n# Amazon 店铺授权 API Reference\n\n本文档描述 **授权与店铺/令牌管理** 相关的 API。若需经网关代理拉取报告或 **Listing 单条查询** 等，请参考 `linkfox-amazon-store-report`、`linkfox-amazon-store-listings` skill。\n\n## Calling Conventions\n\n- **Base URL**: `${LINKFOX_TOOL_GATEWAY}`（默认 `https://tool-gateway.linkfox.com`；可用 `LINKFOX_TOOL_GATEWAY` 覆盖，兼容旧名 `STORE_API_BASE_URL` / `SPAPI_BASE_URL`）\n- **Request Method**: 所有接口均为 POST\n- **Content-Type**: `application/json`\n- **Authentication**: Header `Authorization: <api_key>`，API key 优先读取环境变量 `LINKFOX_AGENT_API_KEY`，未设置时回退到兼容旧名 `LINKFOXAGENT_API_KEY`（如未配置 按 SKILL.md 的 **## 解决认证和积分问题** 处理）\n\n## API Endpoints\n\n### 1. Get Authorization URL\n\n**Endpoint**: `/spApi/authorizeUrl`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description | Example |\n|-----------|------|----------|-------------|---------|\n| region | string | Yes | 区域代码：NA / EU / FE | \"NA\" |\n| sellerName | string | **Yes** | 店铺展示名（店铺名）— **必填，非空**；用于在已授权店铺列表中识别账号 | \"My Store\" |\n\n**Response**:\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n> 说明：授权完成后的回调由 Amazon 直接回调服务端内部接口处理，属于系统内部流程，不作为本 skill 的用户调用接口。\n\n---\n\n### 2. List Authorized Stores\n\n**Endpoint**: `/spApi/authorizedStores`\n\n**Request Parameters**: 无（使用当前用户上下文）\n\n**Response**:\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n---\n\n### 3. Refresh Token\n\n**Endpoint**: `/spApi/refreshToken`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | No | 区域代码（精确匹配可选） |\n\n**Response**:\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"Token refreshed and updated\"\n}\n```\n\n---\n\n### 4. Query Store Tokens\n\n**Endpoint**: `/spApi/storeTokens`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | Yes | 区域代码 |\n\n**Response**:\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n返回的 `accessToken` 可交给下游 skill（如 `linkfox-amazon-store-report`）用于调用亚马逊开放接口。\n\n---\n\n## Error Codes\n\n| errcode | 含义 | 建议动作 |\n|---------|------|----------|\n| 200 | 成功 | 正常解析 |\n| 401 | 认证失败 | HTTP 401 或 authorized error：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 402 | 积分不足 | HTTP 402：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 1002 | 缺参数或认证失败 | 检查必填参数与认证 |\n| 1003 | 第三方服务调用失败 | 稍后重试，检查网络与白名单 |\n| 1004 | 授权记录不存在或不属于当前用户 | 核对 sellerId/region 或重新授权 |\n\n**Error Response Example**:\n\n```json\n{\n  \"errcode\": 1002,\n  \"errmsg\": \"Missing required parameter: region\"\n}\n```\n\n---\n\n## curl Examples\n\n### Get Authorization URL\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizeUrl \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### List Authorized Stores\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizedStores \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\"\n```\n\n### Refresh Token\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/refreshToken \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### Query Store Tokens\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/storeTokens \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n---\n\n## Feedback API\n\n> 本接口与上面的工具 API **是不同 base URL**，请勿混用。\n\n- **POST** `https://skill-api.linkfox.com/api/v1/public/feedback`\n- **Content-Type**: `application/json`\n\n```json\n{\n  \"skillName\": \"linkfox-amazon-store-auth\",\n  \"sentiment\": \"POSITIVE\",\n  \"category\": \"OTHER\",\n  \"content\": \"Authorization flow worked smoothly, user was satisfied.\"\n}\n```\n\n**Field rules**:\n- `skillName`: 使用本 skill 的 YAML frontmatter `name`\n- `sentiment`: `POSITIVE` / `NEUTRAL` / `NEGATIVE`\n- `category`: `BUG` / `COMPLAINT` / `SUGGESTION` / `OTHER`\n- `content`: 用户说的话、实际发生了什么、为什么是问题或赞赏\n\n---\n\n## Important Notes\n\n1. **Token 安全**：不要打印完整 accessToken/refreshToken，仅展示前 10 字符掩码。\n2. **Token 生命周期**：accessToken 1 小时过期，使用前检查并按需刷新。\n3. **区域专属**：同一卖家在不同区域需要分别授权。\n4. **用户隔离**：所有 API 都强制用户级访问控制。\n5. **回调白名单**：系统回调 URL 必须在授权提供方（紫鸟）处加白名单。\n\n完整授权流程与实现细节：见 `authorization-flow.md`。\n\nFile v1.0.7:references/authorization-flow.md\n\n# Amazon Store 授权流程详细说明\n\n本文档提供所有授权相关接口的详细说明，包括请求参数、返回值、错误处理等。\n\n---\n\n## 1. 获取授权URL\n\n### 接口信息\n\n- **路径**: `/spApi/authorizeUrl`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:52`\n\n### 请求参数 (SpApiAuthorizeUrlReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| region | String | ✅ 是 | 区域代码：NA/EU/FE | \"NA\" |\n| sellerName | String | ✅ **是（必填）** | 店铺名 / 卖家展示名称，用于在已授权店铺列表中区分账号；**调用前必须向用户确认并传入非空字符串**，不可省略 | \"My Amazon Store\" |\n| central | String | ❌ 否 | 中心站点 | - |\n| marketplace | String | ❌ 否 | 市场代码 | - |\n\n### 返回结果 (SpApiAuthorizeUrlVo)\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/...\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authorizeUrl | String | 亚马逊授权链接，用户需在浏览器中打开 |\n\n### 业务逻辑\n\n1. 校验 region 参数（必须为 NA/EU/FE）；**本 Skill 约定**：`sellerName` 须为非空字符串（与用户在 LinkFox 侧展示、区分店铺一致），AI/脚本在调用前应向用户确认店铺名。\n2. 构建 state 参数：\n   - 包含 gateway.url + /spApi/oauth/callback\n   - 附加 userId, region, sellerName\n3. 调用紫鸟代理接口 `/developer-proxy/v1/authorize/url`\n4. 返回授权链接给用户\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 缺少 region 参数 | 必须提供 region (NA/EU/FE) |\n| 1003 | 获取授权地址失败 | 检查网络连接和白名单配置，稍后重试 |\n\n### 使用示例\n\n**请求**:\n```json\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?application_id=xxx&state=xxx\"\n}\n```\n\n**后续操作**:\n用户在浏览器中打开 `authorizeUrl`，在亚马逊页面完成授权后，会自动重定向到回调地址。\n\n---\n\n## 2. 授权回调处理（服务端内部）\n\n### 接口信息\n\n- **路径**: 服务端内部回调接口（不对客户端/Agent暴露）\n- **方法**: POST (RouteMapping)\n- **鉴权**: 不需要（auth=false）\n- **实现**: `SpApiController.java:111`\n\n### 请求参数 (SpApiAuthorizeCallbackReq)\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| userId | String | ✅ 是 | 用户ID（从 state 中解析） |\n| sellingPartnerId | String | ✅ 是 | 亚马逊卖家ID |\n| accessToken | String | ✅ 是 | 访问令牌 |\n| refreshToken | String | ✅ 是 | 刷新令牌 |\n| tokenType | String | ❌ 否 | 令牌类型（默认 bearer） |\n| expiresIn | String | ❌ 否 | 过期时间（秒） |\n| region | String | ✅ 是 | 区域代码 |\n| sellerName | String | ❌ 否 | 卖家名称 |\n| mwsAuthToken | String | ❌ 否 | MWS 授权令牌 |\n\n### 返回结果 (SpApiAuthorizeCallbackVo)\n\n```json\n{\n  \"saved\": true,\n  \"authRecordId\": 123,\n  \"bindUserId\": 456,\n  \"message\": \"已新增授权\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| saved | Boolean | 是否保存成功 |\n| authRecordId | Long | 授权记录ID（sp_api_amazon_auth 表） |\n| bindUserId | Long | 绑定记录ID（sp_api_bind_user 表） |\n| message | String | 处理结果消息 |\n\n### 业务逻辑\n\n1. 检查是否已存在同一店铺的授权（sellingPartnerId + region）\n2. 如果存在，更新原有授权记录；否则新增\n3. 创建或更新用户与授权的绑定关系\n4. 返回保存结果\n\n### 注意事项\n\n- 此接口无需鉴权，因为是亚马逊重定向回调\n- userId 从 state 参数中解析，必须在获取授权URL时正确设置\n- 同一店铺的授权会更新而非重复创建\n\n---\n\n## 3. 查看已授权店铺列表\n\n### 接口信息\n\n- **路径**: `/spApi/authorizedStores`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:126`\n\n### 请求参数\n\n无（从 Token 中自动获取当前用户 userId）\n\n### 返回结果 (SpApiAuthorizedStoresVo)\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"EU Store\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| stores | Array | 店铺列表 |\n| stores[].sellerName | String | 卖家名称 |\n| stores[].sellerId | String | 卖家ID |\n| stores[].region | String | 区域代码 |\n| total | Integer | 店铺总数 |\n\n### 业务逻辑\n\n1. 根据 gatewayUserId 查询 sp_api_bind_user 表\n2. 获取所有关联的 amazonAuthId\n3. 查询对应的授权记录\n4. 去重并按 sellerId 和 region 排序\n5. 返回店铺列表\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 无法识别当前用户 | 请重新登录 |\n\n---\n\n## 4. 刷新访问令牌\n\n### 接口信息\n\n- **路径**: `/spApi/refreshToken`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:134`\n\n### 请求参数 (SpApiRefreshTokenReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ❌ 否 | 区域代码（用于精确匹配） | \"NA\" |\n\n### 返回结果 (SpApiRefreshTokenVo)\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 新的访问令牌 |\n| refreshToken | String | 新的刷新令牌（可能更新） |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| message | String | 处理结果 |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 调用紫鸟代理接口 `/developer-proxy/{region}/auth/o2/token`\n4. 使用 refresh_token 换取新的 access_token\n5. 更新数据库中的令牌信息\n6. 返回新令牌\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId | 必须提供卖家ID |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查 sellerId 是否正确，或重新授权 |\n| 1004 | 缺少 refresh_token | 授权记录异常，需重新授权 |\n| 1003 | 刷新令牌请求失败 | 检查网络连接，稍后重试 |\n\n### 注意事项\n\n- refresh_token 可能在刷新时更新，需保存新的 refresh_token\n- 如果 region 未提供，会匹配该 sellerId 的第一条记录\n\n---\n\n## 5. 查询店铺令牌\n\n### 接口信息\n\n- **路径**: `/spApi/storeTokens`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:142`\n\n### 请求参数 (SpApiStoreTokensReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ✅ 是 | 区域代码 | \"NA\" |\n\n### 返回结果 (SpApiStoreTokensVo)\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| sellerId | String | 卖家ID |\n| region | String | 区域代码 |\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 直接从数据库读取令牌信息（不调用刷新）\n4. 返回令牌数据\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId 或 region | 必须同时提供卖家ID和区域 |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查参数或重新授权 |\n\n### 使用场景\n\n- 在调用亚马逊卖家开放接口前获取访问令牌\n- 检查令牌是否即将过期（根据 expiresIn）\n- 如果令牌过期，调用 refreshToken 接口更新\n\n---\n\n## 区域与站点映射\n\n### 北美 (NA)\n\n- 美国: amazon.com\n- 加拿大: amazon.ca\n- 墨西哥: amazon.com.mx\n\n### 欧洲 (EU)\n\n- 英国: amazon.co.uk\n- 德国: amazon.de\n- 法国: amazon.fr\n- 意大利: amazon.it\n- 西班牙: amazon.es\n- 荷兰: amazon.nl\n- 瑞典: amazon.se\n- 波兰: amazon.pl\n\n### 远东 (FE)\n\n- 日本: amazon.co.jp\n- 澳大利亚: amazon.com.au\n- 新加坡: amazon.sg\n\n---\n\n## 数据库表结构\n\n### sp_api_amazon_auth (授权信息表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| region | String | 区域代码 (NA/EU/FE) |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| sellingPartnerId | String | 卖家ID |\n| sellerName | String | 卖家名称 |\n| mwsAuthToken | String | MWS 授权令牌 |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n### sp_api_bind_user (用户绑定表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| gatewayUserId | String | 网关用户ID |\n| amazonAuthId | Long | 授权记录ID（外键） |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n---\n\n## 完整授权示例\n\n### 步骤 1: 获取授权链接\n\n**请求**:\n```bash\nPOST /spApi/authorizeUrl\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n### 步骤 2: 用户授权\n\n用户在浏览器中打开 `authorizeUrl`，登录亚马逊卖家中心并同意授权。\n\n### 步骤 3: 自动回调\n\n亚马逊重定向到:\n```\nhttps://<gateway.url>/spApi/oauth/callback?\n  userId=<userId>&\n  region=NA&\n  sellerName=MyStore&\n  selling_partner_id=A1234567890&\n  access_token=Atza|...&\n  refresh_token=Atzr|...&\n  token_type=bearer&\n  expires_in=3600\n```\n\n系统自动保存授权信息。\n\n### 步骤 4: 查看授权结果\n\n**请求**:\n```bash\nPOST /spApi/authorizedStores\nHeaders: Authorization: Bearer <token>\n```\n\n**响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"MyStore\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n### 步骤 5: 使用令牌调用卖家开放接口\n\n**请求**:\n```bash\nPOST /spApi/storeTokens\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**响应**:\n```json\n{\n  \"accessToken\": \"Atza|...\",\n  \"refreshToken\": \"Atzr|...\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n使用 `accessToken` 作为 `x-amz-access-token` header 调用亚马逊卖家开放接口。\n\n---\n\n## 故障排查\n\n### 问题 1: 授权链接无法访问\n\n**可能原因**:\n- 网络连接问题\n- 紫鸟代理服务异常\n- 白名单配置错误\n\n**解决方案**:\n1. 检查网络连接\n2. 确认白名单配置\n3. 稍后重试或联系技术支持\n\n### 问题 2: 回调未保存授权信息\n\n**可能原因**:\n- state 参数中缺少 userId\n- 数据库连接异常\n\n**解决方案**:\n1. 确认获取授权URL时正确传入用户信息\n2. 检查数据库连接\n3. 查看服务日志\n\n### 问题 3: 刷新令牌失败\n\n**可能原因**:\n- refresh_token 已过期或失效\n- 紫鸟代理服务异常\n\n**解决方案**:\n1. 如果 refresh_token 失效，需重新授权\n2. 检查紫鸟服务状态\n3. 确认白名单配置\n\n### 问题 4: 查询令牌返回 1004 错误\n\n**可能原因**:\n- sellerId 或 region 错误\n- 授权记录不属于当前用户\n\n**解决方案**:\n1. 调用 /spApi/authorizedStores 确认店铺信息\n2. 确认 sellerId 和 region 正确\n3. 如果确实未授权，需先完成授权流程\n\n---\n\n## 安全最佳实践\n\n1. **令牌存储**:\n   - 令牌存储在数据库中，不暴露给前端\n   - 仅通过后端接口访问令牌\n\n2. **访问控制**:\n   - 所有接口都进行用户鉴权\n   - 用户只能访问自己授权的店铺\n\n3. **令牌刷新**:\n   - 定期检查令牌是否即将过期\n   - 自动刷新即将过期的令牌\n\n4. **日志记录**:\n   - 记录所有授权操作\n   - 记录令牌刷新操作\n   - 不记录令牌明文内容\n\n5. **错误处理**:\n   - 不在错误消息中暴露敏感信息\n   - 提供清晰的错误码和处理建议\n\nFile v1.0.7:references/onboarding.md\n\n# 解决认证和积分问题\n\n调用本 skill 时若网关返回 **auth** 或 **billing** 错误，走本 skill 自带的 `scripts/onboarding.py` 完成引导。\n\n**auth 场景**：`errcode=401` 或消息含 `authorized error`/`鉴权失败`/`未授权`/`unauthorized`；或 `LINKFOX_AGENT_API_KEY` 与 `LINKFOXAGENT_API_KEY` 均为空。\n1. 若已配置 key → 先让用户重启会话（最常见误判），仍失败让用户重新取 key 或换手机号重注册\n2. 未配置 → 询问：自助去 https://agent.linkfox.com/ 取 key，或提供手机号让脚本注册\n3. 手机号路径：\n   - `python scripts/onboarding.py send-code <phone>` → 展示 JSON 里的 phone/agreements\n   - 收到验证码后：`python scripts/onboarding.py login <phone> <code>`（workbuddy 宿主加 `--channel workbuddy`）\n   - 拿到 `api_key` 后把下面三平台配置转发给用户，提示重启会话生效：\n     - Windows PowerShell（永久）：`setx LINKFOX_AGENT_API_KEY \"<key>\"`\n     - macOS zsh：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.zshrc && source ~/.zshrc`\n     - Linux bash：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.bashrc && source ~/.bashrc`\n     - 变量名 `LINKFOX_AGENT_API_KEY`（主推）或 `LINKFOXAGENT_API_KEY`（老规范）任一即可\n\n**billing 场景**：`errcode=402` 或消息含 `积分/余额/quota/insufficient/充值/套餐到期`。\n- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单，否则输出编号清单让用户选\n- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`（通常 `wechat/alipay`）\n- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG > `pay_url` > `ascii_qr`（标注兜底）\n- 已付款可选调 `python scripts/onboarding.py query <order_id>`，不主动轮询\n\n排除 `errcode=403`（无权限，不归入这两类）。所有子命令输出 stdout JSON，`error` 字段已含阶段前缀，透传给用户即可。完整用法：`python scripts/onboarding.py --help`。\n\nFile v1.0.7:references/quick-start.md\n\n# Amazon Store 授权快速开始指南\n\n本指南帮助你快速上手使用亚马逊店铺授权功能。\n\n## 前置条件\n\n1. **已部署的服务**:\n   - linkfox-agent-ecom-plat 服务已启动\n   - 紫鸟代理服务可访问\n   - 数据库已正确配置\n\n2. **已配置的环境**:\n   - 回调地址已添加到紫鸟白名单\n   - gateway.url 配置正确\n\n3. **用户认证**:\n   - 用户已登录并获取 Token\n\n## 5分钟快速授权\n\n> **重要：店铺名（`sellerName`）必填**  \n> 调用 `/spApi/authorizeUrl` 时**必须**传入非空的 `sellerName`，用于在系统中标识该授权店铺（多店铺时便于区分）。若用户未提供，请先询问用户填写后再请求授权链接。脚本 `authorize_url.py` 会在本地校验该字段。\n\n### 第一步：获取授权链接\n\n**调用接口**:\n```bash\nPOST /spApi/authorizeUrl\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"我的店铺\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n**操作**: 复制 `authorizeUrl` 的值\n\n### 第二步：浏览器授权\n\n1. 在浏览器中打开上一步获取的 `authorizeUrl`\n2. 使用亚马逊卖家账号登录\n3. 查看并同意授权请求\n4. 点击\"确认\"或\"Authorize\"按钮\n5. 等待页面跳转（自动完成授权保存）\n\n### 第三步：验证授权成功\n\n**调用接口**:\n```bash\nPOST /spApi/authorizedStores\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n```\n\n**预期响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n如果看到店铺信息，说明授权成功！\n\n## 使用授权令牌\n\n### 获取访问令牌\n\n**调用接口**:\n```bash\nPOST /spApi/storeTokens\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n### 使用访问令牌调用卖家开放接口\n\n使用返回的 `accessToken` 作为请求头：\n\n```bash\nGET https://<endpoint>/orders/v0/orders\nx-amz-access-token: Atza|IwEBIA...\n```\n\n## 令牌管理\n\n### 令牌过期时间\n\n- **accessToken**: 通常 1 小时（3600秒）\n- **refreshToken**: 长期有效，用于刷新 accessToken\n\n### 检查令牌是否即将过期\n\n从 `/spApi/storeTokens` 响应中获取 `expiresIn` 值：\n- 如果小于 300 秒（5分钟），建议立即刷新\n- 如果大于 300 秒，可以继续使用\n\n### 刷新过期令牌\n\n**调用接口**:\n```bash\nPOST /spApi/refreshToken\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...(新令牌)\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n刷新后，使用新的 `accessToken` 进行后续 API 调用。\n\n## 多店铺管理\n\n### 授权第二个店铺\n\n重复授权流程，但使用不同的区域或账号：\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"EU\",\n  \"sellerName\": \"欧洲店铺\"\n}\n```\n\n### 查看所有授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n响应会包含所有已授权的店铺：\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"欧洲店铺\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n### 为不同店铺获取令牌\n\n只需指定不同的 `sellerId` 和 `region`：\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A9876543210\",\n  \"region\": \"EU\"\n}\n```\n\n## 常见场景\n\n### 场景 1: 定时任务调用卖家开放接口\n\n1. 从数据库或缓存中读取 `accessToken`\n2. 检查是否过期（根据上次更新时间 + expiresIn）\n3. 如果过期，调用 `/spApi/refreshToken` 刷新\n4. 使用新令牌调用卖家开放接口\n\n### 场景 2: 多店铺数据同步\n\n1. 调用 `/spApi/authorizedStores` 获取所有店铺\n2. 遍历店铺列表\n3. 为每个店铺获取令牌 (`/spApi/storeTokens`)\n4. 并行调用卖家开放接口获取数据\n\n### 场景 3: 用户重新授权\n\n如果用户在亚马逊卖家中心撤销了授权：\n\n1. 老令牌会失效\n2. 调用卖家开放接口 会返回 401 Unauthorized\n3. 需要用户重新授权（重复获取授权链接的流程）\n4. 系统会自动更新数据库中的令牌\n\n## 故障排查\n\n### 问题：获取授权链接失败（错误码 1003）\n\n**可能原因**: 网络问题或白名单配置错误\n\n**解决方法**:\n1. 检查网络连接到紫鸟代理服务\n2. 确认回调地址已添加到白名单\n3. 查看服务日志获取详细错误信息\n\n### 问题：授权完成但未保存（查询不到店铺）\n\n**可能原因**: 回调参数缺失或数据库异常\n\n**解决方法**:\n1. 检查浏览器回调 URL 是否包含所有参数\n2. 查看服务日志，确认回调是否被触发\n3. 检查数据库连接和表结构\n\n### 问题：刷新令牌失败（错误码 1004）\n\n**可能原因**: refresh_token 已失效\n\n**解决方法**:\n1. refresh_token 一旦失效，无法恢复\n2. 需要用户重新完成授权流程\n3. 建议定期刷新令牌，避免长时间不使用导致失效\n\n### 问题：调用卖家开放接口 返回 401\n\n**可能原因**: accessToken 过期或无效\n\n**解决方法**:\n1. 调用 `/spApi/refreshToken` 刷新令牌\n2. 如果刷新失败，需要重新授权\n3. 使用新令牌重试 API 调用\n\n## 最佳实践\n\n### 1. 令牌缓存策略\n\n```\n获取令牌时：\n  ↓\n检查缓存是否存在且未过期\n  ↓\n如果是，直接使用缓存的令牌\n  ↓\n如果否，从数据库读取并检查过期时间\n  ↓\n如果即将过期（< 5分钟），先刷新\n  ↓\n将新令牌写入缓存\n```\n\n### 2. 错误重试机制\n\n```\n调用卖家开放接口\n  ↓\n如果返回 401\n  ↓\n刷新令牌\n  ↓\n重试 API 调用（最多1次）\n  ↓\n如果仍失败，返回错误\n```\n\n### 3. 批量操作优化\n\n```\n获取所有店铺列表\n  ↓\n批量获取所有店铺的令牌\n  ↓\n并行调用卖家开放接口（控制并发数）\n  ↓\n汇总结果\n```\n\n### 4. 安全建议\n\n- ✅ 令牌仅存储在后端，不传递给前端\n- ✅ 使用 HTTPS 传输令牌\n- ✅ 定期检查并刷新令牌\n- ✅ 记录所有授权操作日志\n- ❌ 不在日志中记录完整令牌\n- ❌ 不在前端 JavaScript 中存储令牌\n\n## 下一步\n\n- 查看 [完整接口文档](authorization-flow.md) 了解所有接口的详细说明\n- 查看 [SKILL.md](../SKILL.md) 了解 skill 的完整功能\n- 参考后端工程中店铺网关相关 Controller 实现（包名与类名以你们仓库为准）\n\n## 技术支持\n\n如遇到问题，请：\n1. 查看服务日志\n2. 参考故障排查章节\n3. 联系技术团队\n\nFile v1.0.7:skill-card.md\n\n## Description:\n\nHelps agents manage Amazon Seller store authorization by generating authorization links, listing authorized stores, refreshing token status, and confirming seller and region context for downstream workflows.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[linkfox-ai](https://clawhub.ai/user/linkfox-ai)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal developers and ecommerce operators use this skill to connect Amazon Seller accounts to LinkFox, manage authorized stores, refresh authorization state, and prepare sellerId plus region selectors for downstream Amazon workflows.\n\n### Deployment Geography for Use:\n\nGlobal; marketplace operations are scoped by the skill's NA, EU, and FE region codes.\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles sensitive Amazon access tokens, refresh tokens, LinkFox API keys, and local response files.\n\nMitigation: Use only in a trusted workspace, avoid exposing tokens in chat or logs, prefer status metadata over raw token values, and review saved linkfox response files before sharing or committing them.\n\nRisk: The onboarding flow can perform LinkFox login, API key issuance, plan selection, and payment order creation.\n\nMitigation: Run onboarding and payment commands only after explicit user intent, confirm LinkFox endpoints and environment variables, and treat payment selection as a separate sensitive action.\n\nRisk: The server security verdict is suspicious because the skill includes token handling, account login, payment flows, feedback reporting, and local response storage.\n\nMitigation: Review the artifact before installing, confirm the LinkFox endpoints are controlled, and avoid automatic retries or repeated paid actions without user confirmation.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth)\n- [Amazon Store Authorization Skill README](artifact/README.md)\n- [Amazon Store Authorization API Reference](artifact/references/api.md)\n- [Amazon Store Authorization Flow](artifact/references/authorization-flow.md)\n- [Amazon Store Authorization Quick Start](artifact/references/quick-start.md)\n- [Authentication and Billing Onboarding](artifact/references/onboarding.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Shell commands, JSON, Configuration]\n\n**Output Format:** [Markdown guidance with shell commands and JSON API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May save full API responses to local linkfox session files and print summaries for large responses; token query and refresh scripts strip raw token fields before display.]\n\n## Skill Version(s):\n\n1.0.7 (source: evidence.release.version; artifact _meta.json reports 1.0.0)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.6: 16 files, 38269 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5748b), references/authorization-flow.md (13082b), references/onboarding.md (2046b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/_token_status_output.py (1059b), scripts/authorize_url.py (3842b), scripts/authorized_stores.py (2304b), scripts/onboarding.py (24089b), scripts/README.md (2361b), scripts/refresh_token.py (2842b), scripts/store_tokens.py (2786b), skill-card.md (2880b), SKILL.md (11849b)\n\nFile v1.0.6:SKILL.md\n\n---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊店铺授权与管理技能，提供完整的授权流程、令牌刷新、已授权店铺查询以及授权状态查询能力。获取授权链接时店铺名 sellerName 为必填，用于区分已授权店铺。当用户提到亚马逊店铺授权、绑定亚马逊店铺、刷新令牌、查询店铺授权状态、管理授权店铺、Amazon seller authorization, bind Amazon seller account, refresh access token, query store token status, manage authorized stores时触发此技能。只要其需求涉及亚马逊卖家账号授权、令牌生命周期管理或店铺列表查询，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、授权状态查询与令牌刷新**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。下游业务经 `developerProxy` 传入 `sellerId`+`region` 即可，**无需**先取 raw token。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens（授权状态，非 raw token 下发）\n\n`POST /spApi/storeTokens` 返回**状态与元数据**（具体字段以网关为准），供确认授权是否有效、何时过期。**不要**将响应当作下游 `developerProxy` 的 token 来源。\n\n| Field | Type | Description |\n|-------|------|-------------|\n| status | string | 授权/令牌状态（如有效、过期、缺失） |\n| authRecordId | integer | 授权记录 ID（如有） |\n| expiresIn | integer | 距 accessToken 过期的秒数（如有） |\n| tokenExpiresAt | string | 绝对过期时间（如有） |\n| message | string | 补充说明 |\n| errcode / errmsg | integer / string | 网关错误（失败时） |\n\n> 兼容说明：旧版网关可能仍返回 `accessToken`/`refreshToken`；Agent **不应**优先读取或传递给下游。下游应使用 `sellerId`+`region` 调 `developerProxy`。\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**。当用户未指定区域时，使用 NA。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗积分；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## 解决认证和积分问题\n发生以下异常情况时，采用 references/onboarding.md 引导解决问题：\n\n### 异常情况\n- **未配置API Key**：环境变量未配置 `LINKFOX_AGENT_API_KEY`，也未配置 `LINKFOXAGENT_API_KEY`。\n- **响应401或402状态码**\n- **响应提示积分或余额不足**：消息含\"积分余额不足/计费不足/余额不足/quota exceeded/insufficient balance/套餐到期/需充值/请充值\"，或类似含义的内容。\n\n## Usage Scenarios\n\n### Scenario 1: Authorize New Store\n\n**User request**：「我要授权我的亚马逊北美站点」\n\n**Steps**：\n1. **询问店铺名 `sellerName`**（若用户未提供）。`/spApi/authorizeUrl` 要求 `sellerName` 为非空字符串；向用户说明这只是在 LinkFox 里识别店铺的标签，建议与 Seller Central 后台名字保持一致。\n2. 调用 `/spApi/authorizeUrl`，传入 `region` 与 `sellerName`\n3. 把返回的 `authorizeUrl` 给用户，让其在浏览器中打开\n4. 用户在 Amazon 完成授权 → Amazon 回调系统 → 系统自动保存授权\n5. 可选：调用 `/spApi/authorizedStores` 确认授权成功\n\n### Scenario 2: View Authorized Stores\n\n**User request**：「列一下我已授权的亚马逊店铺」\n\n**Steps**：\n1. 调用 `/spApi/authorizedStores`\n2. 展示店铺列表（sellerName / sellerId / region）\n3. 按 sellerId、region 排序\n\n### Scenario 3: Refresh Expired Token\n\n**User request**：「我店铺的令牌过期了，帮我刷新」\n\n**Steps**：\n1. 调用 `/spApi/refreshToken`，传入 `sellerId`（可选 `region`）\n2. 返回刷新**状态与元数据**（如 `status`、`message`、`expiresIn`）；服务端更新令牌\n3. 下游可直接重试 `developerProxy`（传入相同 `sellerId`+`region`），**无需**读取 raw token\n\n### Scenario 4: Query Store Token Status\n\n**User request**：「查一下北美站点 A123 店铺的授权/令牌状态」\n\n**Steps**：\n1. 调用 `/spApi/storeTokens`，传入 `sellerId` 与 `region`\n2. 向用户展示**状态字段**（`status`、`expiresIn`、`tokenExpiresAt`、`message` 等）\n3. **不要**把响应当作下游 proxy 的 token；业务调用直接带 `sellerId`+`region`\n\n### Scenario 5: Prepare Account Selector for Any Store Operation (Standard Preparation Workflow)\n\n当用户提出任何涉及卖家后台数据的请求（拉报告、查库存、看订单等），**本 skill 负责前置的「选店 → 确认授权」**，具体业务由相应的下游 skill 接手。\n\n**Steps**：\n1. **列出已授权店铺**：调用 `/spApi/authorizedStores`\n2. **让用户选择店铺**：如果有多家店铺，请用户明确选哪一家，确定 `sellerId` 与 `region`\n3. （可选）调用 `/spApi/storeTokens` **仅作状态确认**（过期则先 `refreshToken`）\n4. **把 `sellerId`+`region` 交给下游 skill**（例如 `linkfox-amazon-store-report`），由下游直接调 `developerProxy`\n\n**Why this workflow is critical**：\n- 用户可能同时授权了多家不同区域的店铺\n- 每家店铺的令牌与权限彼此独立\n- 必须使用与店铺匹配的 `sellerId`+`region`，跳过「选店」会导致歧义和错误\n\n## Display Rules\n\n1. **先有店铺名再生成授权链接**：若用户未提供 `sellerName`，**必须先问**，不允许带空值调用 `/spApi/authorizeUrl`。\n2. **只呈现数据**：展示授权结果、店铺列表、令牌信息即可，不做业务建议。\n3. **安全意识**：响应若含 legacy token 字段，不要明文展示；优先呈现 `status` / 过期时间等元数据。\n4. **清晰引导**：返回授权链接时，明确告知用户在浏览器中打开并完成授权。\n5. **错误说明**：授权失败时，基于错误码解释原因并给出建议。\n6. **成功确认**：授权完成后与用户确认，可选择展示该店铺基本信息。\n\n## Important Limitations\n\n- **sellerName 必填**：`/spApi/authorizeUrl` 必须传入非空 `sellerName`；脚本与 agent 在调用前务必校验。\n- **令牌有效期**：`accessToken` 1 小时过期，需及时刷新。\n- **区域专属**：每次店铺授权都与具体区域绑定，不同区域需分别授权。\n- **用户隔离**：用户只能查看/管理自己授权的店铺。\n- **回调白名单**：系统回调 URL 必须在授权方（紫鸟）处加白名单。\n\n## User Expression & Scenario Quick Reference\n\n**Applicable** — 授权与令牌管理场景：\n\n| User Says | Scenario |\n|-----------|----------|\n| \"授权我的亚马逊店铺\" / \"Authorize my Amazon store\" | 新店铺授权 |\n| \"看看已授权的亚马逊店铺\" / \"Show my authorized stores\" | 列出已授权店铺 |\n| \"令牌过期了\" / \"My token expired\" | 刷新令牌 |\n| \"查 XXX 店铺授权状态\" / \"Check store token status\" | 查询授权状态（storeTokens） |\n| \"绑定我的亚马逊账号\" / \"Connect my Amazon seller account\" | 新店铺授权 |\n\n**Not applicable** — 超出本 skill 的业务：\n\n- **拉取亚马逊报告** → 请使用 `linkfox-amazon-store-report`\n- 产品 listing 管理、订单处理、库存管理、广告投放 → 由其他 skill 负责\n\n**Boundary judgment**：\n- 本 skill 只负责「授权 + 管店铺 + 令牌刷新/状态查询 + 为下游准备 `sellerId`+`region` 选店信息」。\n- **不要**为下游 `developerProxy` 调用 `storeTokens` 取 raw `accessToken`（除非兼容极旧客户端且用户明确要求）。\n- 当用户要做具体卖家后台业务（如拉报告）时：\n  1. 本 skill 执行 Scenario 5 的标准前置流程（选店）\n  2. 随后切换到对应下游 skill，直接 `developerProxy` + `sellerId`+`region`\n- 不要直接越过本 skill 去调具体 Amazon 开放接口。\n\n## Quick Reference\n\n### Authorization & Token Management APIs\n\n| API | Path | Purpose | Auth Required |\n|-----|------|---------|---------------|\n| Get Authorization URL | /spApi/authorizeUrl | 生成授权链接（需要 sellerName） | ✅ Yes |\n| List Authorized Stores | /spApi/authorizedStores | 查询用户的店铺列表 | ✅ Yes |\n| Refresh Token | /spApi/refreshToken | 刷新访问令牌 | ✅ Yes |\n| Query Store Token Status | /spApi/storeTokens | 查询某店铺授权/令牌状态（非下游 token 来源） | ✅ Yes |\n\n详细请求参数、响应结构、错误码，见 `references/api.md`。完整授权流程图，见 `references/authorization-flow.md`。快速上手示例，见 `references/quick-start.md`。\n\n## 积分消耗规则\n\n不消耗积分。\n\n**Feedback**：\n\n当出现以下任一情况时，自动通过 Feedback API 上报反馈：\n1. 本 skill 描述的功能与实际行为不符\n2. skill 的结果与用户意图不符\n3. 用户表达了对本 skill 的不满或赞赏\n4. 任何你认为可以改进的点\n\n按 `references/api.md` 中的规范调用 Feedback API，不要打断用户的主流程。\n\n---\n*For more high-quality, professional cross-border e-commerce skills, visit [LinkFox Skills](https://skill.linkfox.com/).*\n\nFile v1.0.6:README.md\n\n# Amazon Store Authorization Skill\n\n亚马逊店铺 **授权与管理** Skill，提供授权流程、令牌管理、店铺查询等能力，是所有下游业务 skill（如 `linkfox-amazon-store-report`）的前置依赖。\n\n## 📋 目录结构\n\n```\nlinkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    └── store_tokens.py               # 查询店铺令牌\n```\n\n## 🚀 快速开始\n\n### 1. 授权新店铺\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl\n```\n\n### 2. 查看已授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n### 3. 获取访问令牌（供下游 skill 使用）\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n## 🔗 关联 Skill\n\n| Skill | 说明 |\n|-------|------|\n| `linkfox-amazon-store-report` | 获取亚马逊报告（依赖本 skill） |\n\n## 🌍 支持的区域\n\n- **NA**：美国、加拿大、墨西哥\n- **EU**：英国、德国、法国、意大利、西班牙等\n- **FE**：日本、澳大利亚、新加坡、印度\n\n## 🔐 安全特性\n\n- ✅ 用户级数据隔离\n- ✅ 令牌自动刷新\n- ✅ 完整错误处理\n- ✅ HTTPS 加密\n\n## 🔄 版本历史\n\n- **v1.0.0**（2026-04-24）\n  - 从早期综合亚马逊 skill 拆分而来\n  - 保留所有授权、店铺管理、令牌管理能力\n  - 报告相关能力已拆出至 `linkfox-amazon-store-report`\n\n## 📄 许可\n\n本 Skill 是 LinkFoxAgent 项目的一部分。\n\nFile v1.0.6:scripts/README.md\n\n# Amazon Store Auth Scripts Usage Guide\n\n本目录包含 **授权与店铺/令牌管理** 相关的 Python 脚本。若需要拉取报告，请使用 `linkfox-amazon-store-report` skill。\n\n## Prerequisites\n\n- Python 3.6 或更高\n- 已设置 `LINKFOXAGENT_API_KEY` 环境变量\n- 可访问 LinkFox 后端 API（默认 `https://tool-gateway.linkfox.com`）\n\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-api-key-here\"\n```\n\n## Available Scripts\n\n### 1. authorize_url.py\n\n为新店铺生成授权 URL。\n\n**`sellerName`（店铺名）必填**：必须为非空字符串。脚本会在缺失或为空白时直接退出并报错——调用前请先向用户询问一个可识别的店铺名。\n\n```bash\npython authorize_url.py '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### 2. authorized_stores.py\n\n列出当前用户已授权的所有亚马逊店铺。\n\n```bash\npython authorized_stores.py\n```\n\n### 3. refresh_token.py\n\n刷新某店铺的 accessToken。\n\n```bash\npython refresh_token.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 4. store_tokens.py\n\n获取某店铺的访问令牌。下游 skill（如 `linkfox-amazon-store-report`）会调用它以拿到 `accessToken`。\n\n```bash\npython store_tokens.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| LINKFOXAGENT_API_KEY | API 鉴权 key | 必需 |\n| STORE_API_BASE_URL / SPAPI_BASE_URL | 后端网关 base URL（优先读前者） | https://tool-gateway.linkfox.com |\n\n## Error Codes\n\n- `0`：成功\n- `1`：缺少 API key、参数错误、网络/HTTP/权限错误\n\n## Troubleshooting\n\n**API Key 未配置**\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-key-here\"\n```\n\n**Connection Refused / 网络错误**\n- 确认 `https://tool-gateway.linkfox.com` 能从你的网络访问（或设置 `STORE_API_BASE_URL` / `SPAPI_BASE_URL` 指向其他网关）\n- 检查防火墙、代理设置\n\n**403 Unauthorized**\n- 店铺可能缺少必要的亚马逊接口权限\n- 用更完整的权限集合重新授权\n\n**查询令牌返回 1004**\n- 核对 sellerId 与 region\n- 确认该店铺已完成授权\n\n## Further Documentation\n\n- API Reference: `../references/api.md`\n- 授权流程详解: `../references/authorization-flow.md`\n- 快速上手: `../references/quick-start.md`\n- Skill 文档: `../SKILL.md`\n\nFile v1.0.6:_meta.json\n\n{\n  \"ownerId\": \"kn7dmc1t4j28hem1twwyav85p182pb1j\",\n  \"slug\": \"linkfox-amazon-store-auth\",\n  \"version\": \"1.0.6\",\n  \"publishedAt\": 1786099289570\n}\n\nFile v1.0.6:references/api.md\n\n# Amazon 店铺授权 API Reference\n\n本文档描述 **授权与店铺/令牌管理** 相关的 API。若需经网关代理拉取报告或 **Listing 单条查询** 等，请参考 `linkfox-amazon-store-report`、`linkfox-amazon-store-listings` skill。\n\n## Calling Conventions\n\n- **Base URL**: `${LINKFOX_TOOL_GATEWAY}`（默认 `https://tool-gateway.linkfox.com`；可用 `LINKFOX_TOOL_GATEWAY` 覆盖，兼容旧名 `STORE_API_BASE_URL` / `SPAPI_BASE_URL`）\n- **Request Method**: 所有接口均为 POST\n- **Content-Type**: `application/json`\n- **Authentication**: Header `Authorization: <api_key>`，API key 优先读取环境变量 `LINKFOX_AGENT_API_KEY`，未设置时回退到兼容旧名 `LINKFOXAGENT_API_KEY`（如未配置 按 SKILL.md 的 **## 解决认证和积分问题** 处理）\n\n## API Endpoints\n\n### 1. Get Authorization URL\n\n**Endpoint**: `/spApi/authorizeUrl`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description | Example |\n|-----------|------|----------|-------------|---------|\n| region | string | Yes | 区域代码：NA / EU / FE | \"NA\" |\n| sellerName | string | **Yes** | 店铺展示名（店铺名）— **必填，非空**；用于在已授权店铺列表中识别账号 | \"My Store\" |\n\n**Response**:\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n> 说明：授权完成后的回调由 Amazon 直接回调服务端内部接口处理，属于系统内部流程，不作为本 skill 的用户调用接口。\n\n---\n\n### 2. List Authorized Stores\n\n**Endpoint**: `/spApi/authorizedStores`\n\n**Request Parameters**: 无（使用当前用户上下文）\n\n**Response**:\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n---\n\n### 3. Refresh Token\n\n**Endpoint**: `/spApi/refreshToken`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | No | 区域代码（精确匹配可选） |\n\n**Response**:\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"Token refreshed and updated\"\n}\n```\n\n---\n\n### 4. Query Store Tokens\n\n**Endpoint**: `/spApi/storeTokens`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | Yes | 区域代码 |\n\n**Response**:\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n返回的 `accessToken` 可交给下游 skill（如 `linkfox-amazon-store-report`）用于调用亚马逊开放接口。\n\n---\n\n## Error Codes\n\n| errcode | 含义 | 建议动作 |\n|---------|------|----------|\n| 200 | 成功 | 正常解析 |\n| 401 | 认证失败 | HTTP 401 或 authorized error：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 402 | 积分不足 | HTTP 402：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 1002 | 缺参数或认证失败 | 检查必填参数与认证 |\n| 1003 | 第三方服务调用失败 | 稍后重试，检查网络与白名单 |\n| 1004 | 授权记录不存在或不属于当前用户 | 核对 sellerId/region 或重新授权 |\n\n**Error Response Example**:\n\n```json\n{\n  \"errcode\": 1002,\n  \"errmsg\": \"Missing required parameter: region\"\n}\n```\n\n---\n\n## curl Examples\n\n### Get Authorization URL\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizeUrl \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### List Authorized Stores\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizedStores \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\"\n```\n\n### Refresh Token\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/refreshToken \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### Query Store Tokens\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/storeTokens \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n---\n\n## Feedback API\n\n> 本接口与上面的工具 API **是不同 base URL**，请勿混用。\n\n- **POST** `https://skill-api.linkfox.com/api/v1/public/feedback`\n- **Content-Type**: `application/json`\n\n```json\n{\n  \"skillName\": \"linkfox-amazon-store-auth\",\n  \"sentiment\": \"POSITIVE\",\n  \"category\": \"OTHER\",\n  \"content\": \"Authorization flow worked smoothly, user was satisfied.\"\n}\n```\n\n**Field rules**:\n- `skillName`: 使用本 skill 的 YAML frontmatter `name`\n- `sentiment`: `POSITIVE` / `NEUTRAL` / `NEGATIVE`\n- `category`: `BUG` / `COMPLAINT` / `SUGGESTION` / `OTHER`\n- `content`: 用户说的话、实际发生了什么、为什么是问题或赞赏\n\n---\n\n## Important Notes\n\n1. **Token 安全**：不要打印完整 accessToken/refreshToken，仅展示前 10 字符掩码。\n2. **Token 生命周期**：accessToken 1 小时过期，使用前检查并按需刷新。\n3. **区域专属**：同一卖家在不同区域需要分别授权。\n4. **用户隔离**：所有 API 都强制用户级访问控制。\n5. **回调白名单**：系统回调 URL 必须在授权提供方（紫鸟）处加白名单。\n\n完整授权流程与实现细节：见 `authorization-flow.md`。\n\nFile v1.0.6:references/authorization-flow.md\n\n# Amazon Store 授权流程详细说明\n\n本文档提供所有授权相关接口的详细说明，包括请求参数、返回值、错误处理等。\n\n---\n\n## 1. 获取授权URL\n\n### 接口信息\n\n- **路径**: `/spApi/authorizeUrl`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:52`\n\n### 请求参数 (SpApiAuthorizeUrlReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| region | String | ✅ 是 | 区域代码：NA/EU/FE | \"NA\" |\n| sellerName | String | ✅ **是（必填）** | 店铺名 / 卖家展示名称，用于在已授权店铺列表中区分账号；**调用前必须向用户确认并传入非空字符串**，不可省略 | \"My Amazon Store\" |\n| central | String | ❌ 否 | 中心站点 | - |\n| marketplace | String | ❌ 否 | 市场代码 | - |\n\n### 返回结果 (SpApiAuthorizeUrlVo)\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/...\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authorizeUrl | String | 亚马逊授权链接，用户需在浏览器中打开 |\n\n### 业务逻辑\n\n1. 校验 region 参数（必须为 NA/EU/FE）；**本 Skill 约定**：`sellerName` 须为非空字符串（与用户在 LinkFox 侧展示、区分店铺一致），AI/脚本在调用前应向用户确认店铺名。\n2. 构建 state 参数：\n   - 包含 gateway.url + /spApi/oauth/callback\n   - 附加 userId, region, sellerName\n3. 调用紫鸟代理接口 `/developer-proxy/v1/authorize/url`\n4. 返回授权链接给用户\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 缺少 region 参数 | 必须提供 region (NA/EU/FE) |\n| 1003 | 获取授权地址失败 | 检查网络连接和白名单配置，稍后重试 |\n\n### 使用示例\n\n**请求**:\n```json\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?application_id=xxx&state=xxx\"\n}\n```\n\n**后续操作**:\n用户在浏览器中打开 `authorizeUrl`，在亚马逊页面完成授权后，会自动重定向到回调地址。\n\n---\n\n## 2. 授权回调处理（服务端内部）\n\n### 接口信息\n\n- **路径**: 服务端内部回调接口（不对客户端/Agent暴露）\n- **方法**: POST (RouteMapping)\n- **鉴权**: 不需要（auth=false）\n- **实现**: `SpApiController.java:111`\n\n### 请求参数 (SpApiAuthorizeCallbackReq)\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| userId | String | ✅ 是 | 用户ID（从 state 中解析） |\n| sellingPartnerId | String | ✅ 是 | 亚马逊卖家ID |\n| accessToken | String | ✅ 是 | 访问令牌 |\n| refreshToken | String | ✅ 是 | 刷新令牌 |\n| tokenType | String | ❌ 否 | 令牌类型（默认 bearer） |\n| expiresIn | String | ❌ 否 | 过期时间（秒） |\n| region | String | ✅ 是 | 区域代码 |\n| sellerName | String | ❌ 否 | 卖家名称 |\n| mwsAuthToken | String | ❌ 否 | MWS 授权令牌 |\n\n### 返回结果 (SpApiAuthorizeCallbackVo)\n\n```json\n{\n  \"saved\": true,\n  \"authRecordId\": 123,\n  \"bindUserId\": 456,\n  \"message\": \"已新增授权\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| saved | Boolean | 是否保存成功 |\n| authRecordId | Long | 授权记录ID（sp_api_amazon_auth 表） |\n| bindUserId | Long | 绑定记录ID（sp_api_bind_user 表） |\n| message | String | 处理结果消息 |\n\n### 业务逻辑\n\n1. 检查是否已存在同一店铺的授权（sellingPartnerId + region）\n2. 如果存在，更新原有授权记录；否则新增\n3. 创建或更新用户与授权的绑定关系\n4. 返回保存结果\n\n### 注意事项\n\n- 此接口无需鉴权，因为是亚马逊重定向回调\n- userId 从 state 参数中解析，必须在获取授权URL时正确设置\n- 同一店铺的授权会更新而非重复创建\n\n---\n\n## 3. 查看已授权店铺列表\n\n### 接口信息\n\n- **路径**: `/spApi/authorizedStores`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:126`\n\n### 请求参数\n\n无（从 Token 中自动获取当前用户 userId）\n\n### 返回结果 (SpApiAuthorizedStoresVo)\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"EU Store\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| stores | Array | 店铺列表 |\n| stores[].sellerName | String | 卖家名称 |\n| stores[].sellerId | String | 卖家ID |\n| stores[].region | String | 区域代码 |\n| total | Integer | 店铺总数 |\n\n### 业务逻辑\n\n1. 根据 gatewayUserId 查询 sp_api_bind_user 表\n2. 获取所有关联的 amazonAuthId\n3. 查询对应的授权记录\n4. 去重并按 sellerId 和 region 排序\n5. 返回店铺列表\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 无法识别当前用户 | 请重新登录 |\n\n---\n\n## 4. 刷新访问令牌\n\n### 接口信息\n\n- **路径**: `/spApi/refreshToken`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:134`\n\n### 请求参数 (SpApiRefreshTokenReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ❌ 否 | 区域代码（用于精确匹配） | \"NA\" |\n\n### 返回结果 (SpApiRefreshTokenVo)\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 新的访问令牌 |\n| refreshToken | String | 新的刷新令牌（可能更新） |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| message | String | 处理结果 |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 调用紫鸟代理接口 `/developer-proxy/{region}/auth/o2/token`\n4. 使用 refresh_token 换取新的 access_token\n5. 更新数据库中的令牌信息\n6. 返回新令牌\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId | 必须提供卖家ID |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查 sellerId 是否正确，或重新授权 |\n| 1004 | 缺少 refresh_token | 授权记录异常，需重新授权 |\n| 1003 | 刷新令牌请求失败 | 检查网络连接，稍后重试 |\n\n### 注意事项\n\n- refresh_token 可能在刷新时更新，需保存新的 refresh_token\n- 如果 region 未提供，会匹配该 sellerId 的第一条记录\n\n---\n\n## 5. 查询店铺令牌\n\n### 接口信息\n\n- **路径**: `/spApi/storeTokens`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:142`\n\n### 请求参数 (SpApiStoreTokensReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ✅ 是 | 区域代码 | \"NA\" |\n\n### 返回结果 (SpApiStoreTokensVo)\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| sellerId | String | 卖家ID |\n| region | String | 区域代码 |\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 直接从数据库读取令牌信息（不调用刷新）\n4. 返回令牌数据\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId 或 region | 必须同时提供卖家ID和区域 |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查参数或重新授权 |\n\n### 使用场景\n\n- 在调用亚马逊卖家开放接口前获取访问令牌\n- 检查令牌是否即将过期（根据 expiresIn）\n- 如果令牌过期，调用 refreshToken 接口更新\n\n---\n\n## 区域与站点映射\n\n### 北美 (NA)\n\n- 美国: amazon.com\n- 加拿大: amazon.ca\n- 墨西哥: amazon.com.mx\n\n### 欧洲 (EU)\n\n- 英国: amazon.co.uk\n- 德国: amazon.de\n- 法国: amazon.fr\n- 意大利: amazon.it\n- 西班牙: amazon.es\n- 荷兰: amazon.nl\n- 瑞典: amazon.se\n- 波兰: amazon.pl\n\n### 远东 (FE)\n\n- 日本: amazon.co.jp\n- 澳大利亚: amazon.com.au\n- 新加坡: amazon.sg\n\n---\n\n## 数据库表结构\n\n### sp_api_amazon_auth (授权信息表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| region | String | 区域代码 (NA/EU/FE) |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| sellingPartnerId | String | 卖家ID |\n| sellerName | String | 卖家名称 |\n| mwsAuthToken | String | MWS 授权令牌 |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n### sp_api_bind_user (用户绑定表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| gatewayUserId | String | 网关用户ID |\n| amazonAuthId | Long | 授权记录ID（外键） |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n---\n\n## 完整授权示例\n\n### 步骤 1: 获取授权链接\n\n**请求**:\n```bash\nPOST /spApi/authorizeUrl\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n### 步骤 2: 用户授权\n\n用户在浏览器中打开 `authorizeUrl`，登录亚马逊卖家中心并同意授权。\n\n### 步骤 3: 自动回调\n\n亚马逊重定向到:\n```\nhttps://<gateway.url>/spApi/oauth/callback?\n  userId=<userId>&\n  region=NA&\n  sellerName=MyStore&\n  selling_partner_id=A1234567890&\n  access_token=Atza|...&\n  refresh_token=Atzr|...&\n  token_type=bearer&\n  expires_in=3600\n```\n\n系统自动保存授权信息。\n\n### 步骤 4: 查看授权结果\n\n**请求**:\n```bash\nPOST /spApi/authorizedStores\nHeaders: Authorization: Bearer <token>\n```\n\n**响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"MyStore\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n### 步骤 5: 使用令牌调用卖家开放接口\n\n**请求**:\n```bash\nPOST /spApi/storeTokens\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**响应**:\n```json\n{\n  \"accessToken\": \"Atza|...\",\n  \"refreshToken\": \"Atzr|...\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n使用 `accessToken` 作为 `x-amz-access-token` header 调用亚马逊卖家开放接口。\n\n---\n\n## 故障排查\n\n### 问题 1: 授权链接无法访问\n\n**可能原因**:\n- 网络连接问题\n- 紫鸟代理服务异常\n- 白名单配置错误\n\n**解决方案**:\n1. 检查网络连接\n2. 确认白名单配置\n3. 稍后重试或联系技术支持\n\n### 问题 2: 回调未保存授权信息\n\n**可能原因**:\n- state 参数中缺少 userId\n- 数据库连接异常\n\n**解决方案**:\n1. 确认获取授权URL时正确传入用户信息\n2. 检查数据库连接\n3. 查看服务日志\n\n### 问题 3: 刷新令牌失败\n\n**可能原因**:\n- refresh_token 已过期或失效\n- 紫鸟代理服务异常\n\n**解决方案**:\n1. 如果 refresh_token 失效，需重新授权\n2. 检查紫鸟服务状态\n3. 确认白名单配置\n\n### 问题 4: 查询令牌返回 1004 错误\n\n**可能原因**:\n- sellerId 或 region 错误\n- 授权记录不属于当前用户\n\n**解决方案**:\n1. 调用 /spApi/authorizedStores 确认店铺信息\n2. 确认 sellerId 和 region 正确\n3. 如果确实未授权，需先完成授权流程\n\n---\n\n## 安全最佳实践\n\n1. **令牌存储**:\n   - 令牌存储在数据库中，不暴露给前端\n   - 仅通过后端接口访问令牌\n\n2. **访问控制**:\n   - 所有接口都进行用户鉴权\n   - 用户只能访问自己授权的店铺\n\n3. **令牌刷新**:\n   - 定期检查令牌是否即将过期\n   - 自动刷新即将过期的令牌\n\n4. **日志记录**:\n   - 记录所有授权操作\n   - 记录令牌刷新操作\n   - 不记录令牌明文内容\n\n5. **错误处理**:\n   - 不在错误消息中暴露敏感信息\n   - 提供清晰的错误码和处理建议\n\nFile v1.0.6:references/onboarding.md\n\n# 解决认证和积分问题\n\n调用本 skill 时若网关返回 **auth** 或 **billing** 错误，走本 skill 自带的 `scripts/onboarding.py` 完成引导。\n\n**auth 场景**：`errcode=401` 或消息含 `authorized error`/`鉴权失败`/`未授权`/`unauthorized`；或 `LINKFOX_AGENT_API_KEY` 与 `LINKFOXAGENT_API_KEY` 均为空。\n1. 若已配置 key → 先让用户重启会话（最常见误判），仍失败让用户重新取 key 或换手机号重注册\n2. 未配置 → 询问：自助去 https://agent.linkfox.com/ 取 key，或提供手机号让脚本注册\n3. 手机号路径：\n   - `python scripts/onboarding.py send-code <phone>` → 展示 JSON 里的 phone/agreements\n   - 收到验证码后：`python scripts/onboarding.py login <phone> <code>`（workbuddy 宿主加 `--channel workbuddy`）\n   - 拿到 `api_key` 后把下面三平台配置转发给用户，提示重启会话生效：\n     - Windows PowerShell（永久）：`setx LINKFOX_AGENT_API_KEY \"<key>\"`\n     - macOS zsh：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.zshrc && source ~/.zshrc`\n     - Linux bash：`echo 'export LINKFOX_AGENT_API_KEY=\"<key>\"' >> ~/.bashrc && source ~/.bashrc`\n     - 变量名 `LINKFOX_AGENT_API_KEY`（主推）或 `LINKFOXAGENT_API_KEY`（老规范）任一即可\n\n**billing 场景**：`errcode=402` 或消息含 `积分/余额/quota/insufficient/充值/套餐到期`。\n- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单，否则输出编号清单让用户选\n- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`（通常 `wechat/alipay`）\n- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG > `pay_url` > `ascii_qr`（标注兜底）\n- 已付款可选调 `python scripts/onboarding.py query <order_id>`，不主动轮询\n\n排除 `errcode=403`（无权限，不归入这两类）。所有子命令输出 stdout JSON，`error` 字段已含阶段前缀，透传给用户即可。完整用法：`python scripts/onboarding.py --help`。\n\nFile v1.0.6:references/quick-start.md\n\n# Amazon Store 授权快速开始指南\n\n本指南帮助你快速上手使用亚马逊店铺授权功能。\n\n## 前置条件\n\n1. **已部署的服务**:\n   - linkfox-agent-ecom-plat 服务已启动\n   - 紫鸟代理服务可访问\n   - 数据库已正确配置\n\n2. **已配置的环境**:\n   - 回调地址已添加到紫鸟白名单\n   - gateway.url 配置正确\n\n3. **用户认证**:\n   - 用户已登录并获取 Token\n\n## 5分钟快速授权\n\n> **重要：店铺名（`sellerName`）必填**  \n> 调用 `/spApi/authorizeUrl` 时**必须**传入非空的 `sellerName`，用于在系统中标识该授权店铺（多店铺时便于区分）。若用户未提供，请先询问用户填写后再请求授权链接。脚本 `authorize_url.py` 会在本地校验该字段。\n\n### 第一步：获取授权链接\n\n**调用接口**:\n```bash\nPOST /spApi/authorizeUrl\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"我的店铺\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n**操作**: 复制 `authorizeUrl` 的值\n\n### 第二步：浏览器授权\n\n1. 在浏览器中打开上一步获取的 `authorizeUrl`\n2. 使用亚马逊卖家账号登录\n3. 查看并同意授权请求\n4. 点击\"确认\"或\"Authorize\"按钮\n5. 等待页面跳转（自动完成授权保存）\n\n### 第三步：验证授权成功\n\n**调用接口**:\n```bash\nPOST /spApi/authorizedStores\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n```\n\n**预期响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n如果看到店铺信息，说明授权成功！\n\n## 使用授权令牌\n\n### 获取访问令牌\n\n**调用接口**:\n```bash\nPOST /spApi/storeTokens\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n### 使用访问令牌调用卖家开放接口\n\n使用返回的 `accessToken` 作为请求头：\n\n```bash\nGET https://<endpoint>/orders/v0/orders\nx-amz-access-token: Atza|IwEBIA...\n```\n\n## 令牌管理\n\n### 令牌过期时间\n\n- **accessToken**: 通常 1 小时（3600秒）\n- **refreshToken**: 长期有效，用于刷新 accessToken\n\n### 检查令牌是否即将过期\n\n从 `/spApi/storeTokens` 响应中获取 `expiresIn` 值：\n- 如果小于 300 秒（5分钟），建议立即刷新\n- 如果大于 300 秒，可以继续使用\n\n### 刷新过期令牌\n\n**调用接口**:\n```bash\nPOST /spApi/refreshToken\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...(新令牌)\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n刷新后，使用新的 `accessToken` 进行后续 API 调用。\n\n## 多店铺管理\n\n### 授权第二个店铺\n\n重复授权流程，但使用不同的区域或账号：\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"EU\",\n  \"sellerName\": \"欧洲店铺\"\n}\n```\n\n### 查看所有授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n响应会包含所有已授权的店铺：\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"欧洲店铺\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n### 为不同店铺获取令牌\n\n只需指定不同的 `sellerId` 和 `region`：\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A9876543210\",\n  \"region\": \"EU\"\n}\n```\n\n## 常见场景\n\n### 场景 1: 定时任务调用卖家开放接口\n\n1. 从数据库或缓存中读取 `accessToken`\n2. 检查是否过期（根据上次更新时间 + expiresIn）\n3. 如果过期，调用 `/spApi/refreshToken` 刷新\n4. 使用新令牌调用卖家开放接口\n\n### 场景 2: 多店铺数据同步\n\n1. 调用 `/spApi/authorizedStores` 获取所有店铺\n2. 遍历店铺列表\n3. 为每个店铺获取令牌 (`/spApi/storeTokens`)\n4. 并行调用卖家开放接口获取数据\n\n### 场景 3: 用户重新授权\n\n如果用户在亚马逊卖家中心撤销了授权：\n\n1. 老令牌会失效\n2. 调用卖家开放接口 会返回 401 Unauthorized\n3. 需要用户重新授权（重复获取授权链接的流程）\n4. 系统会自动更新数据库中的令牌\n\n## 故障排查\n\n### 问题：获取授权链接失败（错误码 1003）\n\n**可能原因**: 网络问题或白名单配置错误\n\n**解决方法**:\n1. 检查网络连接到紫鸟代理服务\n2. 确认回调地址已添加到白名单\n3. 查看服务日志获取详细错误信息\n\n### 问题：授权完成但未保存（查询不到店铺）\n\n**可能原因**: 回调参数缺失或数据库异常\n\n**解决方法**:\n1. 检查浏览器回调 URL 是否包含所有参数\n2. 查看服务日志，确认回调是否被触发\n3. 检查数据库连接和表结构\n\n### 问题：刷新令牌失败（错误码 1004）\n\n**可能原因**: refresh_token 已失效\n\n**解决方法**:\n1. refresh_token 一旦失效，无法恢复\n2. 需要用户重新完成授权流程\n3. 建议定期刷新令牌，避免长时间不使用导致失效\n\n### 问题：调用卖家开放接口 返回 401\n\n**可能原因**: accessToken 过期或无效\n\n**解决方法**:\n1. 调用 `/spApi/refreshToken` 刷新令牌\n2. 如果刷新失败，需要重新授权\n3. 使用新令牌重试 API 调用\n\n## 最佳实践\n\n### 1. 令牌缓存策略\n\n```\n获取令牌时：\n  ↓\n检查缓存是否存在且未过期\n  ↓\n如果是，直接使用缓存的令牌\n  ↓\n如果否，从数据库读取并检查过期时间\n  ↓\n如果即将过期（< 5分钟），先刷新\n  ↓\n将新令牌写入缓存\n```\n\n### 2. 错误重试机制\n\n```\n调用卖家开放接口\n  ↓\n如果返回 401\n  ↓\n刷新令牌\n  ↓\n重试 API 调用（最多1次）\n  ↓\n如果仍失败，返回错误\n```\n\n### 3. 批量操作优化\n\n```\n获取所有店铺列表\n  ↓\n批量获取所有店铺的令牌\n  ↓\n并行调用卖家开放接口（控制并发数）\n  ↓\n汇总结果\n```\n\n### 4. 安全建议\n\n- ✅ 令牌仅存储在后端，不传递给前端\n- ✅ 使用 HTTPS 传输令牌\n- ✅ 定期检查并刷新令牌\n- ✅ 记录所有授权操作日志\n- ❌ 不在日志中记录完整令牌\n- ❌ 不在前端 JavaScript 中存储令牌\n\n## 下一步\n\n- 查看 [完整接口文档](authorization-flow.md) 了解所有接口的详细说明\n- 查看 [SKILL.md](../SKILL.md) 了解 skill 的完整功能\n- 参考后端工程中店铺网关相关 Controller 实现（包名与类名以你们仓库为准）\n\n## 技术支持\n\n如遇到问题，请：\n1. 查看服务日志\n2. 参考故障排查章节\n3. 联系技术团队\n\nFile v1.0.6:skill-card.md\n\n## Description:\n\nThis skill helps agents authorize and manage Amazon seller stores through LinkFox, including authorization links, authorized-store lists, authorization status checks, and token refresh.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[linkfox-ai](https://clawhub.ai/user/linkfox-ai)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal operators and agents use this skill to connect Amazon seller accounts to LinkFox, choose an authorized store, check authorization status, and refresh authorization tokens before downstream seller-data workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles sensitive LinkFox API keys, Amazon seller authorization metadata, and possible legacy access or refresh token fields.\n\nMitigation: Treat all API keys and token-like values as secrets; do not display or log raw tokens, and prefer status and metadata fields when reporting authorization state.\n\nRisk: Gateway host environment variables can redirect requests away from LinkFox-controlled endpoints.\n\nMitigation: Use the default LinkFox gateway unless the operator has explicitly reviewed and approved any gateway override.\n\nRisk: The artifact includes onboarding, billing/payment, and feedback-reporting behavior in addition to Amazon store authorization.\n\nMitigation: Run phone-login, payment, or feedback flows only when they are directly needed for the user's current task and the user has approved that action.\n\nRisk: Local response files may contain account metadata from authorized stores or token-status calls.\n\nMitigation: Review and periodically delete the local linkfox output directory when it may contain sensitive account metadata.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth)\n- [Amazon store authorization API reference](artifact/references/api.md)\n- [Amazon store authorization flow](artifact/references/authorization-flow.md)\n- [Quick start](artifact/references/quick-start.md)\n- [Onboarding for authentication and billing](artifact/references/onboarding.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with JSON API responses and shell command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Scripts save full responses under a local linkfox output directory and may print summaries for larger responses.]\n\n## Skill Version(s):\n\n1.0.6 (source: server release metadata; artifact _meta.json and README list 1.0.0)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.5: 13 files, 28417 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5748b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/authorize_url.py (3842b), scripts/authorized_stores.py (2304b), scripts/README.md (2361b), scripts/refresh_token.py (3228b), scripts/store_tokens.py (3363b), skill-card.md (2724b), SKILL.md (11146b)\n\nFile v1.0.5:SKILL.md\n\n---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊店铺授权与管理技能，提供完整的授权流程、令牌刷新、已授权店铺查询以及访问令牌获取能力。获取授权链接时店铺名 sellerName 为必填，用于区分已授权店铺。当用户提到亚马逊店铺授权、绑定亚马逊店铺、刷新令牌、查询店铺令牌、管理授权店铺、Amazon seller authorization, bind Amazon seller account, refresh access token, query store tokens, manage authorized stores时触发此技能。只要其需求涉及亚马逊卖家账号授权、访问令牌管理或店铺列表查询，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、访问令牌获取与刷新**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens\n\n| Field | Type | Description |\n|-------|------|-------------|\n| accessToken | string | 调用亚马逊开放接口的凭证 |\n| refreshToken | string | 用于续签 accessToken |\n| expiresIn | integer | accessToken 过期秒数 |\n| tokenType | string | 通常为 \"bearer\" |\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**。当用户未指定区域时，使用 NA。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗积分；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## 解决认证和积分问题\n发生以下异常情况时，采用以下措施来处理：\n\n### 异常情况\n- **未配置API Key**：环境变量未配置 `LINKFOX_AGENT_API_KEY`，也未配置 `LINKFOXAGENT_API_KEY`。\n- **响应401或402状态码**\n- **响应提示积分或余额不足**：消息含\"积分余额不足/计费不足/余额不足/quota exceeded/insufficient balance/套餐到期/需充值/请充值\"，或类似含义的内容。\n\n### 措施\n- 优先采用skill内的 onboarding.md 引导解决问题。\n- 如找不到 onboarding.md 文件，则加载 /linkfox-onboarding 这个skill并根据它的引导来处理。如未安装请先安装：\n    - 下载 https://agent-files.linkfox.com/skills/linkfox-onboarding/release.zip，解压后安装这个skill。如需用户授权才可下载，要询问用户获得授权，你不能自己放弃下载。\n- 兜底措施：仅当前面两个措施经过所有努力都走不通时，才提示用户依据 https://skill.linkfox.com/linkfoxskills/guide.htm 指引获取API Key，或去 https://os.linkfox.com/ 补充积分。\n\n## Usage Scenarios\n\n### Scenario 1: Authorize New Store\n\n**User request**：「我要授权我的亚马逊北美站点」\n\n**Steps**：\n1. **询问店铺名 `sellerName`**（若用户未提供）。`/spApi/authorizeUrl` 要求 `sellerName` 为非空字符串；向用户说明这只是在 LinkFox 里识别店铺的标签，建议与 Seller Central 后台名字保持一致。\n2. 调用 `/spApi/authorizeUrl`，传入 `region` 与 `sellerName`\n3. 把返回的 `authorizeUrl` 给用户，让其在浏览器中打开\n4. 用户在 Amazon 完成授权 → Amazon 回调系统 → 系统自动保存授权\n5. 可选：调用 `/spApi/authorizedStores` 确认授权成功\n\n### Scenario 2: View Authorized Stores\n\n**User request**：「列一下我已授权的亚马逊店铺」\n\n**Steps**：\n1. 调用 `/spApi/authorizedStores`\n2. 展示店铺列表（sellerName / sellerId / region）\n3. 按 sellerId、region 排序\n\n### Scenario 3: Refresh Expired Token\n\n**User request**：「我店铺的令牌过期了，帮我刷新」\n\n**Steps**：\n1. 调用 `/spApi/refreshToken`，传入 `sellerId`（可选 `region`）\n2. 返回新的 `accessToken` / `refreshToken`\n3. 数据库自动更新令牌信息\n\n### Scenario 4: Query Store Tokens\n\n**User request**：「获取北美站点 A123 店铺的访问令牌」\n\n**Steps**：\n1. 调用 `/spApi/storeTokens`，传入 `sellerId` 与 `region`\n2. 返回全部令牌信息（供下游业务调用）\n\n### Scenario 5: Prepare Tokens for Any Store Operation (Standard Preparation Workflow)\n\n当用户提出任何涉及卖家后台数据的请求（拉报告、查库存、看订单等），**本 skill 负责前置的\"选店 → 取令牌\"流程**，具体业务由相应的下游 skill 接手。\n\n**Steps**：\n1. **列出已授权店铺**：调用 `/spApi/authorizedStores`\n2. **让用户选择店铺**：如果有多家店铺，请用户明确选哪一家\n3. **获取该店铺令牌**：调用 `/spApi/storeTokens`，传入所选店铺的 `sellerId` 与 `region`\n4. **把 `accessToken` 交给下游 skill**（例如 `linkfox-amazon-store-report`）执行具体操作\n\n**Why this workflow is critical**：\n- 用户可能同时授权了多家不同区域的店铺\n- 每家店铺的令牌与权限彼此独立\n- 调用必须使用与店铺匹配的令牌，跳过\"选店\"会导致歧义和错误\n\n## Display Rules\n\n1. **先有店铺名再生成授权链接**：若用户未提供 `sellerName`，**必须先问**，不允许带空值调用 `/spApi/authorizeUrl`。\n2. **只呈现数据**：展示授权结果、店铺列表、令牌信息即可，不做业务建议。\n3. **安全意识**：不要明文显示完整的 `accessToken`/`refreshToken`，只展示前 10 个字符等掩码形式。\n4. **清晰引导**：返回授权链接时，明确告知用户在浏览器中打开并完成授权。\n5. **错误说明**：授权失败时，基于错误码解释原因并给出建议。\n6. **成功确认**：授权完成后与用户确认，可选择展示该店铺基本信息。\n\n## Important Limitations\n\n- **sellerName 必填**：`/spApi/authorizeUrl` 必须传入非空 `sellerName`；脚本与 agent 在调用前务必校验。\n- **令牌有效期**：`accessToken` 1 小时过期，需及时刷新。\n- **区域专属**：每次店铺授权都与具体区域绑定，不同区域需分别授权。\n- **用户隔离**：用户只能查看/管理自己授权的店铺。\n- **回调白名单**：系统回调 URL 必须在授权方（紫鸟）处加白名单。\n\n## User Expression & Scenario Quick Reference\n\n**Applicable** — 授权与令牌管理场景：\n\n| User Says | Scenario |\n|-----------|----------|\n| \"授权我的亚马逊店铺\" / \"Authorize my Amazon store\" | 新店铺授权 |\n| \"看看已授权的亚马逊店铺\" / \"Show my authorized stores\" | 列出已授权店铺 |\n| \"令牌过期了\" / \"My token expired\" | 刷新令牌 |\n| \"获取 XXX 店铺的访问令牌\" / \"Get access token for store\" | 查询店铺令牌 |\n| \"绑定我的亚马逊账号\" / \"Connect my Amazon seller account\" | 新店铺授权 |\n\n**Not applicable** — 超出本 skill 的业务：\n\n- **拉取亚马逊报告** → 请使用 `linkfox-amazon-store-report`\n- 产品 listing 管理、订单处理、库存管理、广告投放 → 由其他 skill 负责\n\n**Boundary judgment**：\n- 本 skill 只负责「授权 + 管店铺 + 管令牌 + 为下游准备 accessToken」。\n- 当用户要做具体卖家后台业务（如拉报告）时：\n  1. 本 skill 执行 Scenario 5 的标准前置流程\n  2. 随后切换到对应下游 skill 完成业务逻辑\n- 不要直接越过本 skill 去调具体 Amazon 开放接口。\n\n## Quick Reference\n\n### Authorization & Token Management APIs\n\n| API | Path | Purpose | Auth Required |\n|-----|------|---------|---------------|\n| Get Authorization URL | /spApi/authorizeUrl | 生成授权链接（需要 sellerName） | ✅ Yes |\n| List Authorized Stores | /spApi/authorizedStores | 查询用户的店铺列表 | ✅ Yes |\n| Refresh Token | /spApi/refreshToken | 刷新访问令牌 | ✅ Yes |\n| Query Store Tokens | /spApi/storeTokens | 获取某店铺的令牌（给下游 skill 用） | ✅ Yes |\n\n详细请求参数、响应结构、错误码，见 `references/api.md`。完整授权流程图，见 `references/authorization-flow.md`。快速上手示例，见 `references/quick-start.md`。\n\n## 积分消耗规则\n\n不消耗积分。\n\n**Feedback**：\n\n当出现以下任一情况时，自动通过 Feedback API 上报反馈：\n1. 本 skill 描述的功能与实际行为不符\n2. skill 的结果与用户意图不符\n3. 用户表达了对本 skill 的不满或赞赏\n4. 任何你认为可以改进的点\n\n按 `references/api.md` 中的规范调用 Feedback API，不要打断用户的主流程。\n\n---\n*For more high-quality, professional cross-border e-commerce skills, visit [LinkFox Skills](https://skill.linkfox.com/).*\n\nFile v1.0.5:README.md\n\n# Amazon Store Authorization Skill\n\n亚马逊店铺 **授权与管理** Skill，提供授权流程、令牌管理、店铺查询等能力，是所有下游业务 skill（如 `linkfox-amazon-store-report`）的前置依赖。\n\n## 📋 目录结构\n\n```\nlinkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    └── store_tokens.py               # 查询店铺令牌\n```\n\n## 🚀 快速开始\n\n### 1. 授权新店铺\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl\n```\n\n### 2. 查看已授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n### 3. 获取访问令牌（供下游 skill 使用）\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n## 🔗 关联 Skill\n\n| Skill | 说明 |\n|-------|------|\n| `linkfox-amazon-store-report` | 获取亚马逊报告（依赖本 skill） |\n\n## 🌍 支持的区域\n\n- **NA**：美国、加拿大、墨西哥\n- **EU**：英国、德国、法国、意大利、西班牙等\n- **FE**：日本、澳大利亚、新加坡、印度\n\n## 🔐 安全特性\n\n- ✅ 用户级数据隔离\n- ✅ 令牌自动刷新\n- ✅ 完整错误处理\n- ✅ HTTPS 加密\n\n## 🔄 版本历史\n\n- **v1.0.0**（2026-04-24）\n  - 从早期综合亚马逊 skill 拆分而来\n  - 保留所有授权、店铺管理、令牌管理能力\n  - 报告相关能力已拆出至 `linkfox-amazon-store-report`\n\n## 📄 许可\n\n本 Skill 是 LinkFoxAgent 项目的一部分。\n\nFile v1.0.5:scripts/README.md\n\n# Amazon Store Auth Scripts Usage Guide\n\n本目录包含 **授权与店铺/令牌管理** 相关的 Python 脚本。若需要拉取报告，请使用 `linkfox-amazon-store-report` skill。\n\n## Prerequisites\n\n- Python 3.6 或更高\n- 已设置 `LINKFOXAGENT_API_KEY` 环境变量\n- 可访问 LinkFox 后端 API（默认 `https://tool-gateway.linkfox.com`）\n\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-api-key-here\"\n```\n\n## Available Scripts\n\n### 1. authorize_url.py\n\n为新店铺生成授权 URL。\n\n**`sellerName`（店铺名）必填**：必须为非空字符串。脚本会在缺失或为空白时直接退出并报错——调用前请先向用户询问一个可识别的店铺名。\n\n```bash\npython authorize_url.py '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### 2. authorized_stores.py\n\n列出当前用户已授权的所有亚马逊店铺。\n\n```bash\npython authorized_stores.py\n```\n\n### 3. refresh_token.py\n\n刷新某店铺的 accessToken。\n\n```bash\npython refresh_token.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 4. store_tokens.py\n\n获取某店铺的访问令牌。下游 skill（如 `linkfox-amazon-store-report`）会调用它以拿到 `accessToken`。\n\n```bash\npython store_tokens.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| LINKFOXAGENT_API_KEY | API 鉴权 key | 必需 |\n| STORE_API_BASE_URL / SPAPI_BASE_URL | 后端网关 base URL（优先读前者） | https://tool-gateway.linkfox.com |\n\n## Error Codes\n\n- `0`：成功\n- `1`：缺少 API key、参数错误、网络/HTTP/权限错误\n\n## Troubleshooting\n\n**API Key 未配置**\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-key-here\"\n```\n\n**Connection Refused / 网络错误**\n- 确认 `https://tool-gateway.linkfox.com` 能从你的网络访问（或设置 `STORE_API_BASE_URL` / `SPAPI_BASE_URL` 指向其他网关）\n- 检查防火墙、代理设置\n\n**403 Unauthorized**\n- 店铺可能缺少必要的亚马逊接口权限\n- 用更完整的权限集合重新授权\n\n**查询令牌返回 1004**\n- 核对 sellerId 与 region\n- 确认该店铺已完成授权\n\n## Further Documentation\n\n- API Reference: `../references/api.md`\n- 授权流程详解: `../references/authorization-flow.md`\n- 快速上手: `../references/quick-start.md`\n- Skill 文档: `../SKILL.md`\n\nFile v1.0.5:_meta.json\n\n{\n  \"ownerId\": \"kn7dmc1t4j28hem1twwyav85p182pb1j\",\n  \"slug\": \"linkfox-amazon-store-auth\",\n  \"version\": \"1.0.5\",\n  \"publishedAt\": 1783944255123\n}\n\nFile v1.0.5:references/api.md\n\n# Amazon 店铺授权 API Reference\n\n本文档描述 **授权与店铺/令牌管理** 相关的 API。若需经网关代理拉取报告或 **Listing 单条查询** 等，请参考 `linkfox-amazon-store-report`、`linkfox-amazon-store-listings` skill。\n\n## Calling Conventions\n\n- **Base URL**: `${LINKFOX_TOOL_GATEWAY}`（默认 `https://tool-gateway.linkfox.com`；可用 `LINKFOX_TOOL_GATEWAY` 覆盖，兼容旧名 `STORE_API_BASE_URL` / `SPAPI_BASE_URL`）\n- **Request Method**: 所有接口均为 POST\n- **Content-Type**: `application/json`\n- **Authentication**: Header `Authorization: <api_key>`，API key 优先读取环境变量 `LINKFOX_AGENT_API_KEY`，未设置时回退到兼容旧名 `LINKFOXAGENT_API_KEY`（如未配置 按 SKILL.md 的 **## 解决认证和积分问题** 处理）\n\n## API Endpoints\n\n### 1. Get Authorization URL\n\n**Endpoint**: `/spApi/authorizeUrl`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description | Example |\n|-----------|------|----------|-------------|---------|\n| region | string | Yes | 区域代码：NA / EU / FE | \"NA\" |\n| sellerName | string | **Yes** | 店铺展示名（店铺名）— **必填，非空**；用于在已授权店铺列表中识别账号 | \"My Store\" |\n\n**Response**:\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n> 说明：授权完成后的回调由 Amazon 直接回调服务端内部接口处理，属于系统内部流程，不作为本 skill 的用户调用接口。\n\n---\n\n### 2. List Authorized Stores\n\n**Endpoint**: `/spApi/authorizedStores`\n\n**Request Parameters**: 无（使用当前用户上下文）\n\n**Response**:\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n---\n\n### 3. Refresh Token\n\n**Endpoint**: `/spApi/refreshToken`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | No | 区域代码（精确匹配可选） |\n\n**Response**:\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"Token refreshed and updated\"\n}\n```\n\n---\n\n### 4. Query Store Tokens\n\n**Endpoint**: `/spApi/storeTokens`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | Yes | 区域代码 |\n\n**Response**:\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n返回的 `accessToken` 可交给下游 skill（如 `linkfox-amazon-store-report`）用于调用亚马逊开放接口。\n\n---\n\n## Error Codes\n\n| errcode | 含义 | 建议动作 |\n|---------|------|----------|\n| 200 | 成功 | 正常解析 |\n| 401 | 认证失败 | HTTP 401 或 authorized error：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 402 | 积分不足 | HTTP 402：按 SKILL.md 的 **## 解决认证和积分问题** 处理。|\n| 1002 | 缺参数或认证失败 | 检查必填参数与认证 |\n| 1003 | 第三方服务调用失败 | 稍后重试，检查网络与白名单 |\n| 1004 | 授权记录不存在或不属于当前用户 | 核对 sellerId/region 或重新授权 |\n\n**Error Response Example**:\n\n```json\n{\n  \"errcode\": 1002,\n  \"errmsg\": \"Missing required parameter: region\"\n}\n```\n\n---\n\n## curl Examples\n\n### Get Authorization URL\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizeUrl \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### List Authorized Stores\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/authorizedStores \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\"\n```\n\n### Refresh Token\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/refreshToken \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### Query Store Tokens\n\n```bash\ncurl -X POST https://tool-gateway.linkfox.com/spApi/storeTokens \\\n  -H \"Authorization: $LINKFOXAGENT_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n---\n\n## Feedback API\n\n> 本接口与上面的工具 API **是不同 base URL**，请勿混用。\n\n- **POST** `https://skill-api.linkfox.com/api/v1/public/feedback`\n- **Content-Type**: `application/json`\n\n```json\n{\n  \"skillName\": \"linkfox-amazon-store-auth\",\n  \"sentiment\": \"POSITIVE\",\n  \"category\": \"OTHER\",\n  \"content\": \"Authorization flow worked smoothly, user was satisfied.\"\n}\n```\n\n**Field rules**:\n- `skillName`: 使用本 skill 的 YAML frontmatter `name`\n- `sentiment`: `POSITIVE` / `NEUTRAL` / `NEGATIVE`\n- `category`: `BUG` / `COMPLAINT` / `SUGGESTION` / `OTHER`\n- `content`: 用户说的话、实际发生了什么、为什么是问题或赞赏\n\n---\n\n## Important Notes\n\n1. **Token 安全**：不要打印完整 accessToken/refreshToken，仅展示前 10 字符掩码。\n2. **Token 生命周期**：accessToken 1 小时过期，使用前检查并按需刷新。\n3. **区域专属**：同一卖家在不同区域需要分别授权。\n4. **用户隔离**：所有 API 都强制用户级访问控制。\n5. **回调白名单**：系统回调 URL 必须在授权提供方（紫鸟）处加白名单。\n\n完整授权流程与实现细节：见 `authorization-flow.md`。\n\nFile v1.0.5:references/authorization-flow.md\n\n# Amazon Store 授权流程详细说明\n\n本文档提供所有授权相关接口的详细说明，包括请求参数、返回值、错误处理等。\n\n---\n\n## 1. 获取授权URL\n\n### 接口信息\n\n- **路径**: `/spApi/authorizeUrl`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:52`\n\n### 请求参数 (SpApiAuthorizeUrlReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| region | String | ✅ 是 | 区域代码：NA/EU/FE | \"NA\" |\n| sellerName | String | ✅ **是（必填）** | 店铺名 / 卖家展示名称，用于在已授权店铺列表中区分账号；**调用前必须向用户确认并传入非空字符串**，不可省略 | \"My Amazon Store\" |\n| central | String | ❌ 否 | 中心站点 | - |\n| marketplace | String | ❌ 否 | 市场代码 | - |\n\n### 返回结果 (SpApiAuthorizeUrlVo)\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/...\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authorizeUrl | String | 亚马逊授权链接，用户需在浏览器中打开 |\n\n### 业务逻辑\n\n1. 校验 region 参数（必须为 NA/EU/FE）；**本 Skill 约定**：`sellerName` 须为非空字符串（与用户在 LinkFox 侧展示、区分店铺一致），AI/脚本在调用前应向用户确认店铺名。\n2. 构建 state 参数：\n   - 包含 gateway.url + /spApi/oauth/callback\n   - 附加 userId, region, sellerName\n3. 调用紫鸟代理接口 `/developer-proxy/v1/authorize/url`\n4. 返回授权链接给用户\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 缺少 region 参数 | 必须提供 region (NA/EU/FE) |\n| 1003 | 获取授权地址失败 | 检查网络连接和白名单配置，稍后重试 |\n\n### 使用示例\n\n**请求**:\n```json\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?application_id=xxx&state=xxx\"\n}\n```\n\n**后续操作**:\n用户在浏览器中打开 `authorizeUrl`，在亚马逊页面完成授权后，会自动重定向到回调地址。\n\n---\n\n## 2. 授权回调处理（服务端内部）\n\n### 接口信息\n\n- **路径**: 服务端内部回调接口（不对客户端/Agent暴露）\n- **方法**: POST (RouteMapping)\n- **鉴权**: 不需要（auth=false）\n- **实现**: `SpApiController.java:111`\n\n### 请求参数 (SpApiAuthorizeCallbackReq)\n\n| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| userId | String | ✅ 是 | 用户ID（从 state 中解析） |\n| sellingPartnerId | String | ✅ 是 | 亚马逊卖家ID |\n| accessToken | String | ✅ 是 | 访问令牌 |\n| refreshToken | String | ✅ 是 | 刷新令牌 |\n| tokenType | String | ❌ 否 | 令牌类型（默认 bearer） |\n| expiresIn | String | ❌ 否 | 过期时间（秒） |\n| region | String | ✅ 是 | 区域代码 |\n| sellerName | String | ❌ 否 | 卖家名称 |\n| mwsAuthToken | String | ❌ 否 | MWS 授权令牌 |\n\n### 返回结果 (SpApiAuthorizeCallbackVo)\n\n```json\n{\n  \"saved\": true,\n  \"authRecordId\": 123,\n  \"bindUserId\": 456,\n  \"message\": \"已新增授权\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| saved | Boolean | 是否保存成功 |\n| authRecordId | Long | 授权记录ID（sp_api_amazon_auth 表） |\n| bindUserId | Long | 绑定记录ID（sp_api_bind_user 表） |\n| message | String | 处理结果消息 |\n\n### 业务逻辑\n\n1. 检查是否已存在同一店铺的授权（sellingPartnerId + region）\n2. 如果存在，更新原有授权记录；否则新增\n3. 创建或更新用户与授权的绑定关系\n4. 返回保存结果\n\n### 注意事项\n\n- 此接口无需鉴权，因为是亚马逊重定向回调\n- userId 从 state 参数中解析，必须在获取授权URL时正确设置\n- 同一店铺的授权会更新而非重复创建\n\n---\n\n## 3. 查看已授权店铺列表\n\n### 接口信息\n\n- **路径**: `/spApi/authorizedStores`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:126`\n\n### 请求参数\n\n无（从 Token 中自动获取当前用户 userId）\n\n### 返回结果 (SpApiAuthorizedStoresVo)\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"EU Store\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| stores | Array | 店铺列表 |\n| stores[].sellerName | String | 卖家名称 |\n| stores[].sellerId | String | 卖家ID |\n| stores[].region | String | 区域代码 |\n| total | Integer | 店铺总数 |\n\n### 业务逻辑\n\n1. 根据 gatewayUserId 查询 sp_api_bind_user 表\n2. 获取所有关联的 amazonAuthId\n3. 查询对应的授权记录\n4. 去重并按 sellerId 和 region 排序\n5. 返回店铺列表\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 无法识别当前用户 | 请重新登录 |\n\n---\n\n## 4. 刷新访问令牌\n\n### 接口信息\n\n- **路径**: `/spApi/refreshToken`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:134`\n\n### 请求参数 (SpApiRefreshTokenReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ❌ 否 | 区域代码（用于精确匹配） | \"NA\" |\n\n### 返回结果 (SpApiRefreshTokenVo)\n\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 新的访问令牌 |\n| refreshToken | String | 新的刷新令牌（可能更新） |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| message | String | 处理结果 |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 调用紫鸟代理接口 `/developer-proxy/{region}/auth/o2/token`\n4. 使用 refresh_token 换取新的 access_token\n5. 更新数据库中的令牌信息\n6. 返回新令牌\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId | 必须提供卖家ID |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查 sellerId 是否正确，或重新授权 |\n| 1004 | 缺少 refresh_token | 授权记录异常，需重新授权 |\n| 1003 | 刷新令牌请求失败 | 检查网络连接，稍后重试 |\n\n### 注意事项\n\n- refresh_token 可能在刷新时更新，需保存新的 refresh_token\n- 如果 region 未提供，会匹配该 sellerId 的第一条记录\n\n---\n\n## 5. 查询店铺令牌\n\n### 接口信息\n\n- **路径**: `/spApi/storeTokens`\n- **方法**: POST (RouteMapping)\n- **鉴权**: 需要（从 Token 中获取 userId）\n- **实现**: `SpApiController.java:142`\n\n### 请求参数 (SpApiStoreTokensReq)\n\n| 参数 | 类型 | 必填 | 说明 | 示例 |\n|------|------|------|------|------|\n| sellerId | String | ✅ 是 | 卖家ID | \"A1234567890\" |\n| region | String | ✅ 是 | 区域代码 | \"NA\" |\n\n### 返回结果 (SpApiStoreTokensVo)\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| sellerId | String | 卖家ID |\n| region | String | 区域代码 |\n| authRecordId | Long | 授权记录ID |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n\n### 业务逻辑\n\n1. 根据 sellerId + region 查询授权记录\n2. 校验该授权是否属于当前用户\n3. 直接从数据库读取令牌信息（不调用刷新）\n4. 返回令牌数据\n\n### 错误码\n\n| 错误码 | 说明 | 处理建议 |\n|--------|------|----------|\n| 1002 | 请指定 sellerId 或 region | 必须同时提供卖家ID和区域 |\n| 1004 | 未找到授权记录或不属于当前用户 | 检查参数或重新授权 |\n\n### 使用场景\n\n- 在调用亚马逊卖家开放接口前获取访问令牌\n- 检查令牌是否即将过期（根据 expiresIn）\n- 如果令牌过期，调用 refreshToken 接口更新\n\n---\n\n## 区域与站点映射\n\n### 北美 (NA)\n\n- 美国: amazon.com\n- 加拿大: amazon.ca\n- 墨西哥: amazon.com.mx\n\n### 欧洲 (EU)\n\n- 英国: amazon.co.uk\n- 德国: amazon.de\n- 法国: amazon.fr\n- 意大利: amazon.it\n- 西班牙: amazon.es\n- 荷兰: amazon.nl\n- 瑞典: amazon.se\n- 波兰: amazon.pl\n\n### 远东 (FE)\n\n- 日本: amazon.co.jp\n- 澳大利亚: amazon.com.au\n- 新加坡: amazon.sg\n\n---\n\n## 数据库表结构\n\n### sp_api_amazon_auth (授权信息表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| region | String | 区域代码 (NA/EU/FE) |\n| accessToken | String | 访问令牌 |\n| refreshToken | String | 刷新令牌 |\n| tokenType | String | 令牌类型 |\n| expiresIn | String | 过期时间（秒） |\n| sellingPartnerId | String | 卖家ID |\n| sellerName | String | 卖家名称 |\n| mwsAuthToken | String | MWS 授权令牌 |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n### sp_api_bind_user (用户绑定表)\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| id | Long | 主键 |\n| gatewayUserId | String | 网关用户ID |\n| amazonAuthId | Long | 授权记录ID（外键） |\n| createDate | Date | 创建时间 |\n| createTime | Long | 创建时间戳 |\n| lastUpdateDate | Date | 更新时间 |\n| lastUpdateTime | Long | 更新时间戳 |\n\n---\n\n## 完整授权示例\n\n### 步骤 1: 获取授权链接\n\n**请求**:\n```bash\nPOST /spApi/authorizeUrl\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"region\": \"NA\",\n  \"sellerName\": \"MyStore\"\n}\n```\n\n**响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n### 步骤 2: 用户授权\n\n用户在浏览器中打开 `authorizeUrl`，登录亚马逊卖家中心并同意授权。\n\n### 步骤 3: 自动回调\n\n亚马逊重定向到:\n```\nhttps://<gateway.url>/spApi/oauth/callback?\n  userId=<userId>&\n  region=NA&\n  sellerName=MyStore&\n  selling_partner_id=A1234567890&\n  access_token=Atza|...&\n  refresh_token=Atzr|...&\n  token_type=bearer&\n  expires_in=3600\n```\n\n系统自动保存授权信息。\n\n### 步骤 4: 查看授权结果\n\n**请求**:\n```bash\nPOST /spApi/authorizedStores\nHeaders: Authorization: Bearer <token>\n```\n\n**响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"MyStore\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n### 步骤 5: 使用令牌调用卖家开放接口\n\n**请求**:\n```bash\nPOST /spApi/storeTokens\nHeaders: Authorization: Bearer <token>\nBody: {\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**响应**:\n```json\n{\n  \"accessToken\": \"Atza|...\",\n  \"refreshToken\": \"Atzr|...\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n使用 `accessToken` 作为 `x-amz-access-token` header 调用亚马逊卖家开放接口。\n\n---\n\n## 故障排查\n\n### 问题 1: 授权链接无法访问\n\n**可能原因**:\n- 网络连接问题\n- 紫鸟代理服务异常\n- 白名单配置错误\n\n**解决方案**:\n1. 检查网络连接\n2. 确认白名单配置\n3. 稍后重试或联系技术支持\n\n### 问题 2: 回调未保存授权信息\n\n**可能原因**:\n- state 参数中缺少 userId\n- 数据库连接异常\n\n**解决方案**:\n1. 确认获取授权URL时正确传入用户信息\n2. 检查数据库连接\n3. 查看服务日志\n\n### 问题 3: 刷新令牌失败\n\n**可能原因**:\n- refresh_token 已过期或失效\n- 紫鸟代理服务异常\n\n**解决方案**:\n1. 如果 refresh_token 失效，需重新授权\n2. 检查紫鸟服务状态\n3. 确认白名单配置\n\n### 问题 4: 查询令牌返回 1004 错误\n\n**可能原因**:\n- sellerId 或 region 错误\n- 授权记录不属于当前用户\n\n**解决方案**:\n1. 调用 /spApi/authorizedStores 确认店铺信息\n2. 确认 sellerId 和 region 正确\n3. 如果确实未授权，需先完成授权流程\n\n---\n\n## 安全最佳实践\n\n1. **令牌存储**:\n   - 令牌存储在数据库中，不暴露给前端\n   - 仅通过后端接口访问令牌\n\n2. **访问控制**:\n   - 所有接口都进行用户鉴权\n   - 用户只能访问自己授权的店铺\n\n3. **令牌刷新**:\n   - 定期检查令牌是否即将过期\n   - 自动刷新即将过期的令牌\n\n4. **日志记录**:\n   - 记录所有授权操作\n   - 记录令牌刷新操作\n   - 不记录令牌明文内容\n\n5. **错误处理**:\n   - 不在错误消息中暴露敏感信息\n   - 提供清晰的错误码和处理建议\n\nFile v1.0.5:references/quick-start.md\n\n# Amazon Store 授权快速开始指南\n\n本指南帮助你快速上手使用亚马逊店铺授权功能。\n\n## 前置条件\n\n1. **已部署的服务**:\n   - linkfox-agent-ecom-plat 服务已启动\n   - 紫鸟代理服务可访问\n   - 数据库已正确配置\n\n2. **已配置的环境**:\n   - 回调地址已添加到紫鸟白名单\n   - gateway.url 配置正确\n\n3. **用户认证**:\n   - 用户已登录并获取 Token\n\n## 5分钟快速授权\n\n> **重要：店铺名（`sellerName`）必填**  \n> 调用 `/spApi/authorizeUrl` 时**必须**传入非空的 `sellerName`，用于在系统中标识该授权店铺（多店铺时便于区分）。若用户未提供，请先询问用户填写后再请求授权链接。脚本 `authorize_url.py` 会在本地校验该字段。\n\n### 第一步：获取授权链接\n\n**调用接口**:\n```bash\nPOST /spApi/authorizeUrl\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"我的店铺\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n**操作**: 复制 `authorizeUrl` 的值\n\n### 第二步：浏览器授权\n\n1. 在浏览器中打开上一步获取的 `authorizeUrl`\n2. 使用亚马逊卖家账号登录\n3. 查看并同意授权请求\n4. 点击\"确认\"或\"Authorize\"按钮\n5. 等待页面跳转（自动完成授权保存）\n\n### 第三步：验证授权成功\n\n**调用接口**:\n```bash\nPOST /spApi/authorizedStores\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n```\n\n**预期响应**:\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n如果看到店铺信息，说明授权成功！\n\n## 使用授权令牌\n\n### 获取访问令牌\n\n**调用接口**:\n```bash\nPOST /spApi/storeTokens\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"accessToken\": \"Atza|IwEBIA...\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\"\n}\n```\n\n### 使用访问令牌调用卖家开放接口\n\n使用返回的 `accessToken` 作为请求头：\n\n```bash\nGET https://<endpoint>/orders/v0/orders\nx-amz-access-token: Atza|IwEBIA...\n```\n\n## 令牌管理\n\n### 令牌过期时间\n\n- **accessToken**: 通常 1 小时（3600秒）\n- **refreshToken**: 长期有效，用于刷新 accessToken\n\n### 检查令牌是否即将过期\n\n从 `/spApi/storeTokens` 响应中获取 `expiresIn` 值：\n- 如果小于 300 秒（5分钟），建议立即刷新\n- 如果大于 300 秒，可以继续使用\n\n### 刷新过期令牌\n\n**调用接口**:\n```bash\nPOST /spApi/refreshToken\nContent-Type: application/json\nAuthorization: Bearer <your-token>\n\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n**预期响应**:\n```json\n{\n  \"authRecordId\": 123,\n  \"accessToken\": \"Atza|IwEBIA...(新令牌)\",\n  \"refreshToken\": \"Atzr|IwEBIJ...\",\n  \"tokenType\": \"bearer\",\n  \"expiresIn\": \"3600\",\n  \"message\": \"刷新成功并已更新数据库\"\n}\n```\n\n刷新后，使用新的 `accessToken` 进行后续 API 调用。\n\n## 多店铺管理\n\n### 授权第二个店铺\n\n重复授权流程，但使用不同的区域或账号：\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"EU\",\n  \"sellerName\": \"欧洲店铺\"\n}\n```\n\n### 查看所有授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n响应会包含所有已授权的店铺：\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"我的店铺\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    },\n    {\n      \"sellerName\": \"欧洲店铺\",\n      \"sellerId\": \"A9876543210\",\n      \"region\": \"EU\"\n    }\n  ],\n  \"total\": 2\n}\n```\n\n### 为不同店铺获取令牌\n\n只需指定不同的 `sellerId` 和 `region`：\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A9876543210\",\n  \"region\": \"EU\"\n}\n```\n\n## 常见场景\n\n### 场景 1: 定时任务调用卖家开放接口\n\n1. 从数据库或缓存中读取 `accessToken`\n2. 检查是否过期（根据上次更新时间 + expiresIn）\n3. 如果过期，调用 `/spApi/refreshToken` 刷新\n4. 使用新令牌调用卖家开放接口\n\n### 场景 2: 多店铺数据同步\n\n1. 调用 `/spApi/authorizedStores` 获取所有店铺\n2. 遍历店铺列表\n3. 为每个店铺获取令牌 (`/spApi/storeTokens`)\n4. 并行调用卖家开放接口获取数据\n\n### 场景 3: 用户重新授权\n\n如果用户在亚马逊卖家中心撤销了授权：\n\n1. 老令牌会失效\n2. 调用卖家开放接口 会返回 401 Unauthorized\n3. 需要用户重新授权（重复获取授权链接的流程）\n4. 系统会自动更新数据库中的令牌\n\n## 故障排查\n\n### 问题：获取授权链接失败（错误码 1003）\n\n**可能原因**: 网络问题或白名单配置错误\n\n**解决方法**:\n1. 检查网络连接到紫鸟代理服务\n2. 确认回调地址已添加到白名单\n3. 查看服务日志获取详细错误信息\n\n### 问题：授权完成但未保存（查询不到店铺）\n\n**可能原因**: 回调参数缺失或数据库异常\n\n**解决方法**:\n1. 检查浏览器回调 URL 是否包含所有参数\n2. 查看服务日志，确认回调是否被触发\n3. 检查数据库连接和表结构\n\n### 问题：刷新令牌失败（错误码 1004）\n\n**可能原因**: refresh_token 已失效\n\n**解决方法**:\n1. refresh_token 一旦失效，无法恢复\n2. 需要用户重新完成授权流程\n3. 建议定期刷新令牌，避免长时间不使用导致失效\n\n### 问题：调用卖家开放接口 返回 401\n\n**可能原因**: accessToken 过期或无效\n\n**解决方法**:\n1. 调用 `/spApi/refreshToken` 刷新令牌\n2. 如果刷新失败，需要重新授权\n3. 使用新令牌重试 API 调用\n\n## 最佳实践\n\n### 1. 令牌缓存策略\n\n```\n获取令牌时：\n  ↓\n检查缓存是否存在且未过期\n  ↓\n如果是，直接使用缓存的令牌\n  ↓\n如果否，从数据库读取并检查过期时间\n  ↓\n如果即将过期（< 5分钟），先刷新\n  ↓\n将新令牌写入缓存\n```\n\n### 2. 错误重试机制\n\n```\n调用卖家开放接口\n  ↓\n如果返回 401\n  ↓\n刷新令牌\n  ↓\n重试 API 调用（最多1次）\n  ↓\n如果仍失败，返回错误\n```\n\n### 3. 批量操作优化\n\n```\n获取所有店铺列表\n  ↓\n批量获取所有店铺的令牌\n  ↓\n并行调用卖家开放接口（控制并发数）\n  ↓\n汇总结果\n```\n\n### 4. 安全建议\n\n- ✅ 令牌仅存储在后端，不传递给前端\n- ✅ 使用 HTTPS 传输令牌\n- ✅ 定期检查并刷新令牌\n- ✅ 记录所有授权操作日志\n- ❌ 不在日志中记录完整令牌\n- ❌ 不在前端 JavaScript 中存储令牌\n\n## 下一步\n\n- 查看 [完整接口文档](authorization-flow.md) 了解所有接口的详细说明\n- 查看 [SKILL.md](../SKILL.md) 了解 skill 的完整功能\n- 参考后端工程中店铺网关相关 Controller 实现（包名与类名以你们仓库为准）\n\n## 技术支持\n\n如遇到问题，请：\n1. 查看服务日志\n2. 参考故障排查章节\n3. 联系技术团队\n\nFile v1.0.5:skill-card.md\n\n## Description: <br>\nHelps agents manage Amazon seller authorization by generating OAuth authorization links, listing authorized stores, refreshing access tokens, and retrieving store tokens for downstream workflows. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[linkfox-ai](https://clawhub.ai/user/linkfox-ai) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal e-commerce operators and agents use this skill to authorize Amazon seller stores, inspect authorized store records, and prepare store tokens before invoking downstream Amazon workflows. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Amazon seller access and refresh tokens may be retrieved, passed to downstream components, and saved locally. <br>\nMitigation: Install only when the publisher is trusted, keep local response files access-controlled, and avoid exposing full token outputs in shared logs or transcripts. <br>\nRisk: The security evidence marks token handling as too broad and under-disclosed for automatic installation. <br>\nMitigation: Require human review before installation and prefer a release that documents permissions, redacts tokens, restricts API hosts, and makes token handoff explicit. <br>\nRisk: The gateway host can be configured through environment variables, which may redirect credential-bearing API calls. <br>\nMitigation: Verify `LINKFOX_TOOL_GATEWAY`, `STORE_API_BASE_URL`, and `SPAPI_BASE_URL` before running scripts, and use only approved HTTPS endpoints. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/linkfox-ai/skills/linkfox-amazon-store-auth) <br>\n- [Amazon Store Authorization Skill README](README.md) <br>\n- [Amazon store authorization API reference](references/api.md) <br>\n- [Amazon store authorization flow](references/authorization-flow.md) <br>\n- [Amazon store authorization quick start](references/quick-start.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance, JSON] <br>\n**Output Format:** [Markdown guidance with shell command examples and JSON API responses] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Scripts write API responses to local JSON files and print either full small responses or summaries for larger responses.] <br>\n\n## Skill Version(s): <br>\n1.0.5 (source: release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.4: 13 files, 27454 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5519b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/authorize_url.py (3803b), scripts/authorized_stores.py (2265b), scripts/README.md (2361b), scripts/refresh_token.py (3189b), scripts/store_tokens.py (3324b), skill-card.md (2651b), SKILL.md (10012b)\n\nFile v1.0.4:SKILL.md\n\n---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊店铺授权与管理技能，提供完整的授权流程、令牌刷新、已授权店铺查询以及访问令牌获取能力。获取授权链接时店铺名 sellerName 为必填，用于区分已授权店铺。当用户提到亚马逊店铺授权、绑定亚马逊店铺、刷新令牌、查询店铺令牌、管理授权店铺、Amazon seller authorization, bind Amazon seller account, refresh access token, query store tokens, manage authorized stores时触发此技能。只要其需求涉及亚马逊卖家账号授权、访问令牌管理或店铺列表查询，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、访问令牌获取与刷新**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens\n\n| Field | Type | Description |\n|-------|------|-------------|\n| accessToken | string | 调用亚马逊开放接口的凭证 |\n| refreshToken | string | 用于续签 accessToken |\n| expiresIn | integer | accessToken 过期秒数 |\n| tokenType | string | 通常为 \"bearer\" |\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**。当用户未指定区域时，使用 NA。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗积分；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## Usage Scenarios\n\n### Scenario 1: Authorize New Store\n\n**User request**：「我要授权我的亚马逊北美站点」\n\n**Steps**：\n1. **询问店铺名 `sellerName`**（若用户未提供）。`/spApi/authorizeUrl` 要求 `sellerName` 为非空字符串；向用户说明这只是在 LinkFox 里识别店铺的标签，建议与 Seller Central 后台名字保持一致。\n2. 调用 `/spApi/authorizeUrl`，传入 `region` 与 `sellerName`\n3. 把返回的 `authorizeUrl` 给用户，让其在浏览器中打开\n4. 用户在 Amazon 完成授权 → Amazon 回调系统 → 系统自动保存授权\n5. 可选：调用 `/spApi/authorizedStores` 确认授权成功\n\n### Scenario 2: View Authorized Stores\n\n**User request**：「列一下我已授权的亚马逊店铺」\n\n**Steps**：\n1. 调用 `/spApi/authorizedStores`\n2. 展示店铺列表（sellerName / sellerId / region）\n3. 按 sellerId、region 排序\n\n### Scenario 3: Refresh Expired Token\n\n**User request**：「我店铺的令牌过期了，帮我刷新」\n\n**Steps**：\n1. 调用 `/spApi/refreshToken`，传入 `sellerId`（可选 `region`）\n2. 返回新的 `accessToken` / `refreshToken`\n3. 数据库自动更新令牌信息\n\n### Scenario 4: Query Store Tokens\n\n**User request**：「获取北美站点 A123 店铺的访问令牌」\n\n**Steps**：\n1. 调用 `/spApi/storeTokens`，传入 `sellerId` 与 `region`\n2. 返回全部令牌信息（供下游业务调用）\n\n### Scenario 5: Prepare Tokens for Any Store Operation (Standard Preparation Workflow)\n\n当用户提出任何涉及卖家后台数据的请求（拉报告、查库存、看订单等），**本 skill 负责前置的\"选店 → 取令牌\"流程**，具体业务由相应的下游 skill 接手。\n\n**Steps**：\n1. **列出已授权店铺**：调用 `/spApi/authorizedStores`\n2. **让用户选择店铺**：如果有多家店铺，请用户明确选哪一家\n3. **获取该店铺令牌**：调用 `/spApi/storeTokens`，传入所选店铺的 `sellerId` 与 `region`\n4. **把 `accessToken` 交给下游 skill**（例如 `linkfox-amazon-store-report`）执行具体操作\n\n**Why this workflow is critical**：\n- 用户可能同时授权了多家不同区域的店铺\n- 每家店铺的令牌与权限彼此独立\n- 调用必须使用与店铺匹配的令牌，跳过\"选店\"会导致歧义和错误\n\n## Display Rules\n\n1. **先有店铺名再生成授权链接**：若用户未提供 `sellerName`，**必须先问**，不允许带空值调用 `/spApi/authorizeUrl`。\n2. **只呈现数据**：展示授权结果、店铺列表、令牌信息即可，不做业务建议。\n3. **安全意识**：不要明文显示完整的 `accessToken`/`refreshToken`，只展示前 10 个字符等掩码形式。\n4. **清晰引导**：返回授权链接时，明确告知用户在浏览器中打开并完成授权。\n5. **错误说明**：授权失败时，基于错误码解释原因并给出建议。\n6. **成功确认**：授权完成后与用户确认，可选择展示该店铺基本信息。\n\n## Important Limitations\n\n- **sellerName 必填**：`/spApi/authorizeUrl` 必须传入非空 `sellerName`；脚本与 agent 在调用前务必校验。\n- **令牌有效期**：`accessToken` 1 小时过期，需及时刷新。\n- **区域专属**：每次店铺授权都与具体区域绑定，不同区域需分别授权。\n- **用户隔离**：用户只能查看/管理自己授权的店铺。\n- **回调白名单**：系统回调 URL 必须在授权方（紫鸟）处加白名单。\n\n## User Expression & Scenario Quick Reference\n\n**Applicable** — 授权与令牌管理场景：\n\n| User Says | Scenario |\n|-----------|----------|\n| \"授权我的亚马逊店铺\" / \"Authorize my Amazon store\" | 新店铺授权 |\n| \"看看已授权的亚马逊店铺\" / \"Show my authorized stores\" | 列出已授权店铺 |\n| \"令牌过期了\" / \"My token expired\" | 刷新令牌 |\n| \"获取 XXX 店铺的访问令牌\" / \"Get access token for store\" | 查询店铺令牌 |\n| \"绑定我的亚马逊账号\" / \"Connect my Amazon seller account\" | 新店铺授权 |\n\n**Not applicable** — 超出本 skill 的业务：\n\n- **拉取亚马逊报告** → 请使用 `linkfox-amazon-store-report`\n- 产品 listing 管理、订单处理、库存管理、广告投放 → 由其他 skill 负责\n\n**Boundary judgment**：\n- 本 skill 只负责「授权 + 管店铺 + 管令牌 + 为下游准备 accessToken」。\n- 当用户要做具体卖家后台业务（如拉报告）时：\n  1. 本 skill 执行 Scenario 5 的标准前置流程\n  2. 随后切换到对应下游 skill 完成业务逻辑\n- 不要直接越过本 skill 去调具体 Amazon 开放接口。\n\n## Quick Reference\n\n### Authorization & Token Management APIs\n\n| API | Path | Purpose | Auth Required |\n|-----|------|---------|---------------|\n| Get Authorizati\n\nArchive v1.0.3: 12 files, 25992 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5519b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/authorize_url.py (3803b), scripts/authorized_stores.py (2265b), scripts/README.md (2361b), scripts/refresh_token.py (3189b), scripts/store_tokens.py (3324b), SKILL.md (10012b)\n\nArchive v1.0.2: 12 files, 25946 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5521b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/_lf_output.py (6404b), scripts/authorize_url.py (3804b), scripts/authorized_stores.py (2266b), scripts/README.md (2361b), scripts/refresh_token.py (3190b), scripts/store_tokens.py (3325b), SKILL.md (10012b)\n\nArchive v1.0.1: 12 files, 24053 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5400b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/authorize_url.py (3658b), scripts/authorized_stores.py (2120b), scripts/README.md (2361b), scripts/refresh_token.py (3044b), scripts/store_tokens.py (3179b), skill-card.md (2761b), SKILL.md (9234b)\n\nArchive v1.0.0: 11 files, 22689 bytes\n\nFiles: _meta.json (144b), README.md (2202b), references/api.md (5337b), references/authorization-flow.md (13082b), references/quick-start.md (7115b), scripts/authorize_url.py (3658b), scripts/authorized_stores.py (2120b), scripts/README.md (2361b), scripts/refresh_token.py (3044b), scripts/store_tokens.py (3179b), SKILL.md (9234b)","readmeExcerpt":"Skill: 亚马逊-店铺授权 Owner: linkfox-ai Summary: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。 Tags: latest:1.0.8 Version history: v1.0.8 | 2026-09-14","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"linkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    ├── store_tokens.py               # 查询授权状态\n    └── cancel_authorization.py       # 本地取消/解绑授权"},{"language":"bash","snippet":"POST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl"},{"language":"bash","snippet":"POST /spApi/authorizedStores"},{"language":"bash","snippet":"POST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}"},{"language":"bash","snippet":"POST /spApi/cancelAuthorization\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}"},{"language":"bash","snippet":"export LINKFOXAGENT_API_KEY=\"your-api-key-here\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: linkfox-amazon-store-auth\ndescription: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。\n---\n\n# Amazon 店铺授权与管理\n\n本 skill 负责 **亚马逊卖家店铺的 OAuth 授权、已授权店铺列表、授权状态查询、令牌刷新与本地取消授权**，是拉取报告、查询库存、同步订单等所有下游操作的前置依赖。下游业务经 `developerProxy` 传入 `sellerId`+`region` 即可，**无需**先取 raw token。\n\n> 📌 **Related skill**：如果用户需要 **拉取亚马逊店铺报告**（库存 / 订单 / 销售 / 财务报告等），请切换到 `linkfox-amazon-store-report`。该 skill 依赖本 skill 提供的授权与令牌能力。\n\n## Core Concepts\n\nSelling Partner API 是亚马逊为卖家提供的官方接口。本 skill 负责 OAuth 2.0 授权流程与令牌生命周期管理：\n\n**授权流程**：生成授权 URL → 用户在 Amazon 完成授权 → Amazon 回调并附带授权码 → 系统用授权码换取令牌 → 令牌安全保存。\n\n**店铺名（`sellerName`）必填**：调用 `/spApi/authorizeUrl` 前**必须**向用户询问并获取一个清晰、非空的店铺名。它用来在\"已授权店铺列表\"中标记该账号；不要留空或使用空白字符串。\n\n**令牌生命周期**：`accessToken` 通常 1 小时过期；`refreshToken` 用于在不重新授权的前提下续签新的 `accessToken`。\n\n## Data Fields\n\n### Authorization URL Response\n\n| Field | Type | Description |\n|-------|------|-------------|\n| authorizeUrl | string | 让用户在浏览器打开的 Amazon 授权链接 |\n\n### Authorized Store Item\n\n| Field | Type | Description |\n|-------|------|-------------|\n| sellerId | string | Amazon Seller ID (Merchant ID) |\n| sellerName | string | 店铺名（授权时必填） |\n| region | string | 市场区域代码 NA / EU / FE |\n\n### Store Tokens（授权状态，非 raw token 下发）\n\n`POST /spApi/storeTokens` 返回**状态与元数据**（具体字段以网关为准），供确认授权是否有效、何时过期。**不要**将响应当作下游 `developerProxy` 的 token 来源。\n\n| Field | Type | Description |\n|-------|------|-------------|\n| status | string | 授权/令牌状态（如有效、过期、缺失） |\n| authRecordId | integer | 授权记录 ID（如有） |\n| expiresIn | integer | 距 accessToken 过期的秒数（如有） |\n| tokenExpiresAt | string | 绝对过期时间（如有） |\n| message | string | 补充说明 |\n| errcode / errmsg | integer / string | 网关错误（失败时） |\n\n> 兼容说明：旧版网关可能仍返回 `accessToken`/`refreshToken`；Agent **不应**优先读取或传递给下游。下游应使用 `sellerId`+`region` 调 `developerProxy`。\n\n## Supported Regions\n\n| Code | Name | Marketplaces |\n|------|------|--------------|\n| NA | 北美 | 美国、加拿大、墨西哥 |\n| EU | 欧洲 | 英国、德国、法国、意大利、西班牙、荷兰等 |\n| FE | 远东 | 日本、澳大利亚、新加坡、印度 |\n\n默认区域为 **NA**；解绑时按 Scenario 5 明确目标区域。\n\n## 调用方式\n\n- **API 端点**：`POST /spApi/{authorizeUrl|storeTokens|authorizedStores|refreshToken|cancelAuthorization}`（完整参数/响应/错误码见 `references/api.md`）\n- **Python 脚本**：`python scripts/<脚本名>.py '<JSON 参数>' [--inline]`（可用脚本见上文）\n- **成本约束**：本工具会消耗算力；失败/空结果不得自动连续试探；需要继续检索时先向用户说明会产生额外消耗。\n\n**输出策略（脚本默认行为）**：\n- **始终**将完整响应写入 `<cwd>/linkfox/<YYYY-MM-DD>/<session>/data/<skill-name>-<timestamp>.json`（`<cwd>` 为脚本执行时的工作目录，在 Claude Code 里即当前项目目录；`<session>` 取自环境变量 `SESSION_ID`，按用户任务自动聚合；**禁止写入 /tmp**，当前目录不可写则报错）\n- 响应体 ≤ 8 KB：落盘后把完整 JSON 打印到 stdout\n- 响应体 > 8 KB：落盘后 stdout 只输出摘要（顶层字段、常见计数、最大列表字段的长度 + 前 3 条样本）\n- 加 `--inline` 强制全量打印到 stdout（同样落盘）\n\n**读数据建议**：先看摘要判断是否足够；需要具体字段时优先用 `jq`或`ConvertFrom-Json` 从保存的 json 文件按需抽取，避免整份 JSON 进入上下文。\n\n## 解决认证和算力问题\n发生以下异常情况时，采用 references/onboarding.md 引导"},{"path":"README.md","content":"# Amazon Store Authorization Skill\n\n亚马逊店铺 **授权与管理** Skill，提供授权流程、令牌管理、店铺查询、本地取消/解绑授权等能力，是所有下游业务 skill（如 `linkfox-amazon-store-report`）的前置依赖。\n\n## 📋 目录结构\n\n```\nlinkfox-amazon-store-auth/\n├── SKILL.md                          # Skill 主文档\n├── _meta.json                        # Skill 元数据\n├── README.md                         # 本文件\n├── references/\n│   ├── api.md                        # API 详细说明\n│   ├── authorization-flow.md         # 完整授权流程\n│   └── quick-start.md                # 5 分钟快速授权\n└── scripts/\n    ├── README.md                     # 脚本使用指南\n    ├── authorize_url.py              # 生成授权 URL\n    ├── authorized_stores.py          # 列出已授权店铺\n    ├── refresh_token.py              # 刷新访问令牌\n    ├── store_tokens.py               # 查询授权状态\n    └── cancel_authorization.py       # 本地取消/解绑授权\n```\n\n## 🚀 快速开始\n\n### 1. 授权新店铺\n\n```bash\nPOST /spApi/authorizeUrl\n{\n  \"region\": \"NA\",\n  \"sellerName\": \"My Store\"   # ⚠️ 必填：用于识别该授权店铺\n}\n# 在浏览器打开返回的 authorizeUrl\n```\n\n### 2. 查看已授权店铺\n\n```bash\nPOST /spApi/authorizedStores\n```\n\n### 3. 查询授权状态\n\n```bash\nPOST /spApi/storeTokens\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n### 4. 本地取消/解绑授权\n\n```bash\nPOST /spApi/cancelAuthorization\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\"\n}\n```\n\n说明：该接口只在 LinkFox 本地解绑/停用授权，不代表 Amazon Seller Central 侧 OAuth 授权已撤销。\n\n## 🔗 关联 Skill\n\n| Skill | 说明 |\n|-------|------|\n| `linkfox-amazon-store-report` | 获取亚马逊报告（依赖本 skill） |\n\n## 🌍 支持的区域\n\n- **NA**：美国、加拿大、墨西哥\n- **EU**：英国、德国、法国、意大利、西班牙等\n- **FE**：日本、澳大利亚、新加坡、印度\n\n## 🔐 安全特性\n\n- ✅ 用户级数据隔离\n- ✅ 令牌自动刷新\n- ✅ 完整错误处理\n- ✅ HTTPS 加密\n\n## 🔄 版本历史\n\n- **v1.0.0**（2026-04-24）\n  - 从早期综合亚马逊 skill 拆分而来\n  - 保留所有授权、店铺管理、令牌管理能力\n  - 报告相关能力已拆出至 `linkfox-amazon-store-report`\n\n## 📄 许可\n\n本 Skill 是 LinkFoxAgent 项目的一部分。"},{"path":"scripts/README.md","content":"# Amazon Store Auth Scripts Usage Guide\n\n本目录包含 **授权与店铺/令牌管理** 相关的 Python 脚本。若需要拉取报告，请使用 `linkfox-amazon-store-report` skill。\n\n## Prerequisites\n\n- Python 3.6 或更高\n- 已设置 `LINKFOXAGENT_API_KEY` 环境变量\n- 可访问 LinkFox 后端 API（默认 `https://tool-gateway.linkfox.com`）\n\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-api-key-here\"\n```\n\n## Available Scripts\n\n### 1. authorize_url.py\n\n为新店铺生成授权 URL。\n\n**`sellerName`（店铺名）必填**：必须为非空字符串。脚本会在缺失或为空白时直接退出并报错——调用前请先向用户询问一个可识别的店铺名。\n\n```bash\npython authorize_url.py '{\"region\": \"NA\", \"sellerName\": \"My Store\"}'\n```\n\n### 2. authorized_stores.py\n\n列出当前用户已授权的所有亚马逊店铺。\n\n```bash\npython authorized_stores.py\n```\n\n### 3. refresh_token.py\n\n刷新某店铺的 accessToken。\n\n```bash\npython refresh_token.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 4. store_tokens.py\n\n查询某店铺的授权/令牌状态。响应只用于状态确认，不作为下游 raw token 来源。\n\n```bash\npython store_tokens.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n### 5. cancel_authorization.py\n\n本地取消/解绑某店铺授权。该脚本调用 `/spApi/cancelAuthorization`，不会撤销 Amazon Seller Central 侧授权。\n\n```bash\npython cancel_authorization.py '{\"sellerId\": \"A1234567890\", \"region\": \"NA\"}'\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| LINKFOXAGENT_API_KEY | API 鉴权 key | 必需 |\n| STORE_API_BASE_URL / SPAPI_BASE_URL | 后端网关 base URL（优先读前者） | https://tool-gateway.linkfox.com |\n\n## Error Codes\n\n- `0`：成功\n- `1`：缺少 API key、参数错误、网络/HTTP/权限错误\n\n## Troubleshooting\n\n**API Key 未配置**\n```bash\nexport LINKFOXAGENT_API_KEY=\"your-key-here\"\n```\n\n**Connection Refused / 网络错误**\n- 确认 `https://tool-gateway.linkfox.com` 能从你的网络访问（或设置 `STORE_API_BASE_URL` / `SPAPI_BASE_URL` 指向其他网关）\n- 检查防火墙、代理设置\n\n**403 Unauthorized**\n- 店铺可能缺少必要的亚马逊接口权限\n- 用更完整的权限集合重新授权\n\n**查询令牌返回 1004**\n- 核对 sellerId 与 region\n- 确认该店铺已完成授权\n\n## Further Documentation\n\n- API Reference: `../references/api.md`\n- 授权流程详解: `../references/authorization-flow.md`\n- 快速上手: `../references/quick-start.md`\n- Skill 文档: `../SKILL.md`"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7dmc1t4j28hem1twwyav85p182pb1j\",\n  \"slug\": \"linkfox-amazon-store-auth\",\n  \"version\": \"1.0.8\",\n  \"publishedAt\": 1789361747000\n}"},{"path":"references/api.md","content":"# Amazon 店铺授权 API Reference\n\n本文档描述 **授权与店铺/令牌管理** 相关的 API。若需经网关代理拉取报告或 **Listing 单条查询** 等，请参考 `linkfox-amazon-store-report`、`linkfox-amazon-store-listings` skill。\n\n## Calling Conventions\n\n- **Base URL**: `${LINKFOX_TOOL_GATEWAY}`（默认 `https://tool-gateway.linkfox.com`；可用 `LINKFOX_TOOL_GATEWAY` 覆盖，兼容旧名 `STORE_API_BASE_URL` / `SPAPI_BASE_URL`）\n- **Request Method**: 所有接口均为 POST\n- **Content-Type**: `application/json`\n- **Authentication**: Header `Authorization: <api_key>`，API key 优先读取环境变量 `LINKFOX_AGENT_API_KEY`，未设置时回退到兼容旧名 `LINKFOXAGENT_API_KEY`（如未配置 按 SKILL.md 的 **## 解决认证和算力问题** 处理）\n\n- **解绑脚本**: `LinkFox-Skill/2.0`；透传 `SESSION_ID` / `MESSAGE_ID` / `MODE_ID` / `APP_NAME`，超时 150s，不缓存、不自动重试。\n\n## API Endpoints\n\n### 1. Get Authorization URL\n\n**Endpoint**: `/spApi/authorizeUrl`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description | Example |\n|-----------|------|----------|-------------|---------|\n| region | string | Yes | 区域代码：NA / EU / FE | \"NA\" |\n| sellerName | string | **Yes** | 店铺展示名（店铺名）— **必填，非空**；用于在已授权店铺列表中识别账号 | \"My Store\" |\n\n**Response**:\n\n```json\n{\n  \"authorizeUrl\": \"https://sellercentral.amazon.com/apps/authorize/consent?...\"\n}\n```\n\n> 说明：授权完成后的回调由 Amazon 直接回调服务端内部接口处理，属于系统内部流程，不作为本 skill 的用户调用接口。\n\n---\n\n### 2. List Authorized Stores\n\n**Endpoint**: `/spApi/authorizedStores`\n\n**Request Parameters**: 无（使用当前用户上下文）\n\n**Response**:\n\n```json\n{\n  \"stores\": [\n    {\n      \"sellerName\": \"My Store\",\n      \"sellerId\": \"A1234567890\",\n      \"region\": \"NA\"\n    }\n  ],\n  \"total\": 1\n}\n```\n\n---\n\n### 3. Refresh Token\n\n**Endpoint**: `/spApi/refreshToken`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | No | 区域代码（精确匹配可选） |\n\n**Response**:\n\n```json\n{\n  \"authRecordId\": 123,\n  \"success\": true,\n  \"message\": \"刷新成功并已更新数据库，token 已后台化管理\"\n}\n```\n\n---\n\n### 4. Query Store Tokens\n\n**Endpoint**: `/spApi/storeTokens`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | Seller ID |\n| region | string | Yes | 区域代码 |\n\n**Response**:\n\n```json\n{\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"authRecordId\": 123,\n  \"status\": \"ACTIVE\",\n  \"tokenExpiresAt\": 3600,\n  \"message\": \"授权信息已后台化管理，token 不再经由 Agent 返回\"\n}\n```\n\n返回值只用于确认授权状态，不作为下游 token 来源。下游业务应通过 `developerProxy` 传入 `sellerId` + `region`。\n\n---\n\n### 5. Cancel Authorization\n\n**Endpoint**: `/spApi/cancelAuthorization`\n\n**Request Parameters** (JSON):\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| sellerId | string | Yes | 非空 Seller ID，最多 64 字符 |\n| region | string | Yes | NA / EU / FE；必传，不支持单站点解绑 |\n\n**Response**:\n\n```json\n{\n  \"success\": true,\n  \"sellerId\": \"A1234567890\",\n  \"region\": \"NA\",\n  \"removedBindings\": 1,\n  \"localAuthorizationRevoked\": false,\n  \"amazonRevoked\": false,\n  \"message\": \"已解除当前用户的店铺绑定；授权与 token 保留，其他用户不受影响；未撤销 Amazon 授权\"\n}\n`"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。 Skill: 亚马逊-店铺授权 Owner: linkfox-ai Summary: 亚马逊卖家店铺授权与账号连接管理。用于生成授权链接、绑定店铺、查询已授权店铺、检查授权状态、刷新访问令牌和本地取消/解绑授权；生成授权链接时需要 sellerName 区分店铺。用户提到亚马逊店铺授权、绑定或连接 Amazon Seller 账号、查看已授权店铺、授权失效、刷新令牌、token 状态、取消授权、解绑店铺、停用授权、Amazon seller authorization、bind seller account、refresh access token、disconnect seller account 时触发。即使未明确说“授权”，只要其他亚马逊店铺操作因未绑定店铺、凭证过期或需要选择授权账号而无法继续，也应触发此技能。 Tags: latest:1.0.8 Version history: v1.0.8 | 2026-09-14","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":902,"uniquenessScore":45,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T04:37:32.751Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:43:31.574Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}