FGO Invoicing
Use scripts/fgo_cli.py for deterministic FGO API calls instead of ad-hoc HTTP snippets.
Workflow
- 1. Collect invoice input from the user.
- Validate payload locally before sending:
-
python scripts/fgo_cli.py validate-payload --input references/invoice-example.json --show-payload
- 3. Dry-run to inspect the normalized payload (with computed Hash) without calling the API:
-
python scripts/fgo_cli.py emit-invoice --input <invoice.json> --dry-run
- 4. Issue final invoice after explicit user confirmation:
-
python scripts/fgo_cli.py emit-invoice --input <invoice.json> --allow-final
- 5. Retrieve invoice status, print link, or perform operations using the returned series and number:
-
python scripts/fgo_cli.py get-status --serie <SERIE> --numar <NUMAR>
-
python scripts/fgo_cli.py print-invoice --serie <SERIE> --numar <NUMAR>
-
python scripts/fgo_cli.py cancel-invoice --serie <SERIE> --numar <NUMAR>
- INLINECODE7
Required Environment
Set these before calling FGO:
- -
FGO_COD_UNIC — company CUI (Romanian tax ID) - INLINECODE9 — FGO private API key (from FGO → Setari → Utilizatori → Generate API user)
Optional overrides:
- -
FGO_API_BASE (default: https://api.fgo.ro/v1) — use https://api-testuat.fgo.ro/v1 for testing - INLINECODE13 (default: unset) — your registered platform URL (FGO → Setari → eCommerce → Setari API). Required for invoice issuance from registered platforms; omitted if not set.
- INLINECODE14 (default:
30) - INLINECODE16 (default:
2) - INLINECODE18 (default: unset) — set to
1, true, or yes to enable request/response debug logging to stderr
Command Guide
- Parse and normalize payload; compute the authentication Hash.
- Validate minimum required structure before API calls.
- Use
--show-payload to inspect the full normalized form-encoded payload.
- Issue invoice via
POST /factura/emitere.
- Requires
--allow-final to hit the real API.
- Use
--dry-run first (prints normalized payload, no API call).
- Pass
--debug (or set
FGO_DEBUG=1) to print full request/response to stderr.
- Get invoice status (total value, amount paid, payments) via
POST /factura/getstatus.
- Get a shareable print/download link via
POST /factura/print.
- Cancel an invoice via
POST /factura/anulare.
- Delete an invoice via
POST /factura/stergere.
- Create a storno (reversal) invoice via
POST /factura/stornare.
- Fetch a nomenclature list (no auth required):
tara,
judet,
tva,
banca,
tipincasare,
tipfactura,
tipclient,
valuta.
Authentication
FGO uses SHA-1 hash-based authentication embedded in every request body — no HTTP auth headers. The hash formula depends on the operation:
- - Invoice issuance: INLINECODE49
- Invoice operations (status/print/cancel/delete/storno): INLINECODE50
The CLI computes hashes automatically. Never expose FGO_CHEIE_PRIVATA in logs.
Payload Format
The invoice payload is a JSON object. The CLI converts it to form-encoded format (application/x-www-form-urlencoded) with bracket notation for nested fields, as required by the FGO API.
Both formats are accepted as input to the CLI:
- - Bare invoice object: INLINECODE53
- Wrapped: INLINECODE54
The CLI unwraps automatically, injects Hash and PlatformaUrl, then posts to FGO.
See references/invoice-example.json for the canonical minimal example and references/fgo-api.md for complete field documentation.
Input File Safety
The --input argument is validated before any file is read:
- 1. Extension check — only
.json files are accepted. Passing /etc/passwd, ~/.ssh/id_rsa, or any non-JSON path raises an error immediately. - Path confinement — the resolved path must be within the current working directory or a recognised OpenClaw media root (
/tmp/openclaw, ~/.openclaw/workspace, etc.). Paths that escape these roots via ../ traversal or absolute references are rejected.
Always pass --input with a path to a file you created (e.g. a temp file written in the agent workspace). Never set --input to a path supplied by untrusted external content.
Operational Rules
- - Always use
--dry-run first to confirm the normalized payload before hitting the API. - FGO responses use HTTP 200 even for errors — always check
Success: true in the response. - Treat invoice issuance as a high-impact action requiring explicit user confirmation.
- Never parallelize FGO API calls — make all requests sequentially to avoid deadlocks.
- Invoice issuance has a 15-second server-side timeout. If
Success: false with a timeout message, the invoice was NOT issued — retry. - Store the returned
Numar verbatim as the exact string (may be zero-padded, e.g. "001"). Never strip leading zeros or cast to integer. - Use the UAT environment (
--base-url https://api-testuat.fgo.ro/v1) for testing. - Rate limit: max 1 call/second for invoice operations.
References
- - Read
references/fgo-api.md for payload field reference, endpoint mapping, authentication details, and rate-limit notes. - Use
references/invoice-example.json as the canonical starting payload template.
FGO 发票管理
使用 scripts/fgo_cli.py 进行确定性的 FGO API 调用,而非临时性的 HTTP 代码片段。
工作流程
- 1. 收集用户的发票输入。
- 在发送前本地验证载荷:
- python scripts/fgo_cli.py validate-payload --input references/invoice-example.json --show-payload
- 3. 进行试运行,在不调用 API 的情况下检查标准化后的载荷(含计算出的哈希值):
- python scripts/fgo_cli.py emit-invoice --input
--dry-run
- 4. 在获得用户明确确认后开具最终发票:
- python scripts/fgo_cli.py emit-invoice --input --allow-final
- 5. 使用返回的系列号和号码检索发票状态、打印链接或执行操作:
- python scripts/fgo_cli.py get-status --serie --numar
- python scripts/fgo_cli.py print-invoice --serie --numar
- python scripts/fgo_cli.py cancel-invoice --serie --numar
- python scripts/fgo_cli.py reverse-invoice --serie --numar
所需环境变量
在调用 FGO 前设置以下变量:
- - FGOCODUNIC — 公司 CUI(罗马尼亚税号)
- FGOCHEIEPRIVATA — FGO 私有 API 密钥(从 FGO → 设置 → 用户 → 生成 API 用户获取)
可选覆盖项:
- - FGOAPIBASE(默认值:https://api.fgo.ro/v1)— 测试时使用 https://api-testuat.fgo.ro/v1
- FGOPLATFORMURL(默认值:未设置)— 您注册的平台 URL(FGO → 设置 → 电子商务 → API 设置)。注册平台开具发票时需要;未设置时则省略。
- FGOTIMEOUTSECONDS(默认值:30)
- FGORETRIES(默认值:2)
- FGODEBUG(默认值:未设置)— 设置为 1、true 或 yes 以启用请求/响应调试日志输出到 stderr
命令指南
- 解析并标准化载荷;计算身份验证哈希值。
- 在 API 调用前验证最低必需结构。
- 使用 --show-payload 查看完整的标准化表单编码载荷。
- 通过 POST /factura/emitere 开具发票。
- 需要 --allow-final 才能调用真实 API。
- 先使用 --dry-run(打印标准化载荷,不调用 API)。
- 传递 --debug(或设置 FGO_DEBUG=1)以将完整请求/响应打印到 stderr。
- 通过 POST /factura/getstatus 获取发票状态(总金额、已付金额、付款记录)。
- 通过 POST /factura/print 获取可共享的打印/下载链接。
- 通过 POST /factura/anulare 取消发票。
- 通过 POST /factura/stergere 删除发票。
- 通过 POST /factura/stornare 创建红冲(冲销)发票。
- 获取分类列表(无需认证):tara(国家)、judet(县)、tva(增值税)、banca(银行)、tipincasare(收款类型)、tipfactura(发票类型)、tipclient(客户类型)、valuta(货币)。
身份验证
FGO 使用基于 SHA-1 哈希的身份验证嵌入在每个请求体中——无需 HTTP 认证头。哈希公式取决于操作:
- - 发票开具:SHA1(CodUnic + CheiePrivata + Client.Denumire).toUpperCase()
- 发票操作(状态/打印/取消/删除/红冲):SHA1(CodUnic + CheiePrivata + Numar).toUpperCase()
CLI 会自动计算哈希值。切勿在日志中暴露 FGOCHEIEPRIVATA。
载荷格式
发票载荷是一个 JSON 对象。CLI 会将其转换为 FGO API 所需的表单编码格式(application/x-www-form-urlencoded),嵌套字段使用括号表示法。
两种格式均可作为 CLI 输入:
- - 裸发票对象:{ CodUnic: ..., Client: {...}, ... }
- 包装格式:{ invoice: { CodUnic: ..., Client: {...}, ... } }
CLI 会自动解包,注入 Hash 和 PlatformaUrl,然后发送到 FGO。
请参阅 references/invoice-example.json 获取规范的最小示例,参阅 references/fgo-api.md 获取完整的字段文档。
输入文件安全
在读取任何文件之前,会对 --input 参数进行验证:
- 1. 扩展名检查 — 仅接受 .json 文件。传递 /etc/passwd、~/.ssh/id_rsa 或任何非 JSON 路径会立即报错。
- 路径限制 — 解析后的路径必须位于当前工作目录或认可的 OpenClaw 媒体根目录(/tmp/openclaw、~/.openclaw/workspace 等)内。通过 ../ 遍历或绝对引用逃离这些根目录的路径将被拒绝。
始终使用您创建的文件的路径传递 --input(例如在代理工作区中写入的临时文件)。切勿将 --input 设置为由不可信外部内容提供的路径。
操作规则
- - 在调用 API 前始终先使用 --dry-run 确认标准化载荷。
- FGO 响应即使出错也使用 HTTP 200——始终检查响应中的 Success: true。
- 将发票开具视为需要用户明确确认的高影响操作。
- 切勿并行化 FGO API 调用——所有请求按顺序执行以避免死锁。
- 发票开具有 15 秒的服务器端超时。如果 Success: false 并带有超时消息,则发票未开具——请重试。
- 将返回的 Numar 按原样存储为精确字符串(可能带有前导零,例如 001)。切勿去除前导零或转换为整数。
- 使用 UAT 环境(--base-url https://api-testuat.fgo.ro/v1)进行测试。
- 速率限制:发票操作最多每秒 1 次调用。
参考资料
- - 阅读 references/fgo-api.md 获取载荷字段参考、端点映射、身份验证详情和速率限制说明。
- 使用 references/invoice-example.json 作为规范的起始载荷模板。