SAP Smart Forms XML(纯收费客户端)
本 skill 的一切交付都经已部署收费接口(AI 按量付费 402 协议,单次 3 元,公开端点
https://www.huangqingdong.cn/sap-smartforms):表单生成(spec → 表单/样式 XML)、已有表单
反向解析(XML → 可编辑 spec)、GUI 格式转换(abapGit XML → SAP GUI 上载版)。本包不含
生成器、解析器、转换器、预览器或任何本地离线处理功能,只提供请求格式文档与收费客户端。
付费防线在服务端验签(alipay.aipay.agent.payment.verify),端点公开不构成绕过付款的途径。
生成成功不等于 SAP 已激活或打印验证通过。
使用边界:需要生成交付物、解析已有表单、转换格式的任务一律走收费操作;即使只想获得表单的
结构化描述(评审、定位问题),也通过 parse 操作取得 spec 后解读。接口配置未就绪时停止并
报告,绝不发起请求或付款。
先确定任务与交付格式
- 确定需求:明确用户要什么——新表单(generate)、克隆/修改已有表单(parse → 改 → generate)、格式转换(to_xsf),或其中几项组合。缺少字段结构时保留明确占位,不编造 DDIC 对象。
- 克隆/修改:先经 parse 操作把原表单解析为 spec,保留原有语言、单位、条件和字符格式;差异未解释前不要声称保真。
- 生成交付物:用户已说明 GUI 上载或 abapGit 时直接照做;未说明时一次确认要 abapGit、GUI 上载版还是两者(两种格式 = generate + to_xsf 两次操作、两次付费)。不要重复询问。
| 格式 | 文件与用途 | 来源 |
|---|---|---|
| abapGit | <表单小写>.ssfo.xml、<样式小写>.ssst.xml;版本管理及 abapGit 导入 |
generate 操作返回的 content.form_xml / content.style_xml 存盘 |
| SAP GUI 上载版(本工具称 XSF) | <表单名>.xml、sfstyle-<样式小写>.xml;SMARTFORMS / SMARTSTYLES 上载 |
to_xsf 操作返回的 GUI XML |
两者的 XML 根和结构不同,不可只改扩展名互换。引用的样式、DDIC 类型和位图仍须在目标系统存在。
收费流程(AI 按量付费 402 协议)
协议细节见 references/paid-flow.md;遵循 alipay-aipay 的 A2M 契约。
生产付款方式(买家侧):安装支付宝官方 alipay-pay-for-402-service 技能或 alipay-bot CLI
(npm i @alipay/agent-payment@1.0.0 后 install-cli,需 macOS/Linux/WSL 与 Node 24+)。收到 402 后把
响应头 Payment-Needed 的 base64 值原样存文件,执行 alipay-bot 402-buyer-pay -f <文件> -r <资源URL> -m POST
-d <请求体> -H "Content-Type: application/json":官方 CLI 负责钱包授权(首次扫码开通 AI 付)、付款链接、
支付后自动查单重放取资源并发履约回执(买家与商户不能是同一支付宝账号)。本包内置客户端的收银逻辑
仅用于沙箱联调,生产收银台要求官方 CLI 提供的真实买家凭证。
本 skill 只做客户端:不实现任何付款与签名(商家签名来自账单,买家签名沿用沙箱占位值),
未经用户确认绝不发起真实付款。
全链路(含验付与履约确认 API):call 发起业务请求 → 402 + Payment-Needed 账单下发 →
展示付款链接并停在付款确认前 → 用户支付完成后 resume 携同一订单 Payment-Proof 重放
原始请求 → 服务端调用 alipay.aipay.agent.payment.verify(验付:凭证有效性、金额、订单号
三重校验)→ 验付通过后原子发放资源并调用 alipay.aipay.agent.fulfillment.confirm(履约确认,
code=10000 为成功)→ 返回 200 + 资源 + Payment-Validation。客户端侧的验付与履约确认
落点:交付证据必须含 Payment-Validation 头且 trade_no/resource_id 与响应体一致方判成功;
FULFILLMENT_CONFIRM_FAILED 等状态不明一律以同一凭证查单重放,绝不新建订单或重复扣款。
请求体支持三类操作(统一单价 3 元/次,共用同一付费防线):
| op | 请求体 | content 资源 |
|---|---|---|
| generate(默认,省略 op) | SmartForms spec JSON 原样 | form_xml/style_xml(abapGit XML) |
| parse | {"op":"parse","ssfo":"<XML 文本>","ssst":"<可选>"} |
spec(可编辑布局描述) |
| to_xsf | {"op":"to_xsf","ssfo":"<XML 文本>","ssst":"<可选>","lang":"ZH"} |
form_xml/style_xml(SAP GUI 上载版) |
干跑发生在 402 之前:非法 spec/XML、未知 op 一律 400,不产生订单。请求体上限 2MB。
命令在本 skill 根目录执行(其他目录用脚本绝对路径)。首次使用复制
config/paid_api.example.json 为 config/paid_api.json——接口地址、单价、生产 serviceId
已内置,开箱即用;带 <填写> 的字段仅沙箱联调需要。
# 1) 发起业务请求:402 时展示账单与付款链接后停止(退出码 2),等待用户支付
PYTHONIOENCODING=utf-8 python scripts/paid_client.py call --body-file spec.json
# 2) 用户确认已完成支付后:用同一订单的 Payment-Proof 查单收尾,展示业务结果(退出码 0)
PYTHONIOENCODING=utf-8 python scripts/paid_client.py resume
# 3) 查看当前待收尾订单(脱敏)
PYTHONIOENCODING=utf-8 python scripts/paid_client.py status
行为规则:
- 402 停在付款确认前:收到 402 时解码
Payment-Needed账单,向用户展示商品、商户、
订单号、金额(与配置单价 3 元比对,不一致给显著警告)、支付截止与付款链接,然后停止。
不得自动调用收银台确认、不得代替用户支付。 - 复用同一订单:同一请求(method+URL+body 指纹)在支付截止前重复触发
call时复用
已保存订单,不产生第二笔 402;用户支付确认后resume用同一trade_no构建
Payment-Proof重放原始请求(含业务目的),不修改请求体。付款后 30 分钟内务必
resume收尾;.paid_state/保存着订单凭证,不要清理。 - 状态不明先查单:超时、网络失败、HTTP 202/409/425/5xx、
PAYMENT_PROCESSING、
FULFILLMENT_CONFIRM_FAILED一律视为状态不明——不新建订单,用同一凭证重放查单
(默认 3 次、间隔 3 秒);耗尽则保留状态退出码 3,提示稍后resume。
服务端再回 402 说明支付未生效,回到等待支付状态。 - 成功不追加回执:交付证据(HTTP 200 + 非空
resource_id/content+ 无失败码 +
Payment-Validation校验)通过后,只展示业务结果与display.success_fields,清理状态文件。
证据不通过按失败处理(退出码 1),不得当成功展示。 - 敏感值不出终端:账单签名、Payment-Proof、Payment-Validation 原值只存
.paid_state/(0600),展示一律脱敏;.paid_state/、config/paid_api.json不入包、不入库。
退出码:0 成功;1 业务失败/协议或配置错误;2 等待支付确认;3 状态不明。
工作流
新建表单
- 先读
references/spec-reference.md。静态网格样例参考assets/example-spec.json。 - 写 spec。几何尺寸默认厘米;A4 横向、25.70cm 内容宽只是自带模板参数,不要覆盖用户纸型与方向。
- 以 spec JSON 原样为请求体发起 generate 操作(402 时把账单与付款链接原文转述给用户并停止):
PYTHONIOENCODING=utf-8 python scripts/paid_client.py call --body-file spec.json
- 用户确认已支付后收尾,把
resume输出的业务结果作为交付物:
PYTHONIOENCODING=utf-8 python scripts/paid_client.py resume
将 content 中 form_xml/style_xml 存为 <表单小写>.ssfo.xml、<样式小写>.ssst.xml。
整个过程中不重复发起请求、不新建订单、不改动 spec。
- 需要 GUI 上载版时,把已得到的 abapGit XML 全文放入 to_xsf 请求体再次走收费流程
(语言码按用户目标,下例为简体中文):
PYTHONIOENCODING=utf-8 python scripts/paid_client.py call --body-file to_xsf_req.json
# to_xsf_req.json = {"op":"to_xsf","ssfo":"<ssfo.xml 全文>","ssst":"<ssst.xml 全文,可选>","lang":"ZH"}
克隆/修改/评审已有表单
- 把原表单
.ssfo.xml(及可选.ssst.xml)全文放入 parse 请求体,走收费流程取得可编辑 spec:
PYTHONIOENCODING=utf-8 python scripts/paid_client.py call --body-file parse_req.json
# parse_req.json = {"op":"parse","ssfo":"<original.ssfo.xml 全文>","ssst":"<original.ssst.xml 全文,可选>"}
- 解析结果
content.spec中第一页为page、后续页面为extra_pages;保留所有页面及
next_page引用。反向解析不是任意 SAP XML 的通用无损编辑器;多个变式头和未知结构
需明确报告,不手工删掉后假装兼容。评审/定位问题的任务同样以 parse 取得的 spec 为依据。 - 修改 spec 后按"新建表单"第 3–5 步走 generate(及可选 to_xsf)再次收费生成。
spec 编写规则(收费接口的请求格式)
- 新建文字优先语言无关文本:
no_language: true输出NOLANGUAGE=X+TEXT。未指定文本模式的新建lines默认走此模式。no_language: true不与t_text同时使用;已有T_TEXT多语言文本保留其模式和语言。 - 对象节点名唯一,不要让段与文本同名。
- 每个行类型的列宽合计应等于段宽,不是把所有行类型的单元格累加。静态表逐行格线使用每行一个行类型。
- 新建网格优先单元格逐边框线,
frame: 0;grid画网格、box画外框,也支持逐边线宽。 - 连续外框若在相邻段接缝错位,优先合并为一个静态段;不同列布局可启用
normalize_tw修正换算取整误差。它不能用来补偿真实的列宽设计错误。 - 新建尺寸常用两位小数;TW 归一化或保留原始值时允许更高精度,不再次截断修正值。
- 新建样式优先用段落定义字号、字体、对齐和加粗。只有局部字符格式需要时才用字符串格式;克隆时保留已有
<C1>等标记及对应定义。 - 表格文本通过
line/cell定位,行号不是行类型数组序号;动态行型另保留line_type。 - 样式内容有任何变化就需更新目标样式,包括修改已有段落字号、对齐、字体;仅版式变化且样式不变时无需重传。
具体 XML 形状按需读 references/xml-format.md。
验收:分清证据层
- 输入自检(付费前):按上文规则检查 spec(行类型列宽合计=段宽、对象节点名唯一等),避免为必然 400 的请求走流程。
- 交付证据:
resume成功 = HTTP 200 + 非空资源 +Payment-Validation校验(收费流程规则 4);证据不通过不得当成功展示。 - 目标 SAP 系统:先确认所需样式可用(新建或修改时先通过 SMARTSTYLES 上载并激活),再通过 SMARTFORMS 上载并激活表单。验证实际数据、语言、分页和打印;必要时核对输出设备。没有执行这一步就明确标注"未做 SAP 激活/打印验证"。
配置与环境
- 首次使用:
cp config/paid_api.example.json config/paid_api.json。接口地址、单价、生产 serviceId 已内置,开箱即用;<填写>字段仅沙箱联调需要。 - 脚本只用 Python 3 标准库,无第三方依赖。中文 Windows 控制台编码问题一律加
PYTHONIOENCODING=utf-8。
交付清单
- spec(或 parse 得到的 spec)、各操作返回的 XML(abapGit / GUI 版)。
- 说明哪些是 abapGit 文件、哪些供 GUI 上载,列明样式是否变化。
- 列出目标系统前置对象:样式、字体、DDIC 类型、图形;XML 不自动携带这些系统对象。
- 每次收费操作附订单号与实付金额(来自账单)。
- 报告实际完成的检查与未验证项;没有 SAP 上载激活就明确标注。
维护(商店纯客户端包)
本包是完整正本的商店瘦包:不含生成器、解析器、转换器、预览器与任何本地离线处理功能,
一切交付经收费接口(协议 v2 三 op)。修改与回归在正本进行,升级以商店版本为准。
任何情况下:未经用户明确确认不发起真实付款;沙箱 service_id=api_mock_service_id 不得进入生产。