应用接入验收
账号模式探针现在取得短期身份断言。负向 Launch 购买状态只是购买证据,不证明 Licentivo 运行时拒绝。运行时证明要求官方 SDK 探针;不表示已部署生产环境或发布 SDK。参见账号职责边界。
证据分为两级:受控的本地自动检查与外部商户 sandbox 探针。测试替身、成功读取目录、生成配置或健康检查通过,都绝不证明真实付款、许可证签发或激活。本开发迭代已明确延期配置外部服务。
本地自动检查
从仓库根目录运行:
go test ./...
go vet ./...
node --check internal/httpapi/web/app.js
node --check internal/httpapi/web/integration.js
node --check internal/httpapi/web/integration-prompts.js
node --test scripts/integration-prompts.test.mjs scripts/integration-state.test.mjs
python scripts/test_acceptance.py
./scripts/test-mysql.ps1
MySQL 辅助工具在 .cache 下创建独立服务器和数据库,绝不能指向客户数据库。未提供独立 DSN 时,普通 go test ./... 会跳过数据库场景。SDK 和分发包测试及构建参见 integration-packages.md。应随发布记录保留测试输出和工具版本。
本地矩阵涵盖认证、条件邮箱验证、产品与环境所有权、pending/expired/suspended 状态、支付事件重放、授权对账、续费退款、账号切换、受保护的会话持久化和离线回退决定。生命周期测试使用受控运行时;实际加密运行验证仍由官方 SDK 负责,并在发布前单独测试。
For 运营工具 → AI 快速接入, check all nine language choices, platform/project/feature selection, an unconfigured draft, and a prompt generated from validated public configuration. Check copy and download against the visible prompt, and ensure changing the product or environment cannot retain a previous validated configuration. Prompts must exclude sessions, passwords, runtime license/device credentials and management keys; generating or copying a prompt must not call an AI service. The source-bundle Node test command above exercises the pure generator. A generated prompt, or code subsequently produced by an AI tool, still needs the language tests and the external acceptance steps below.
准备外部 sandbox 验收
- 部署专用 Launch 测试实例,提供可访问的 HTTPS 来源并配置支付提供方 Webhook。保持正式销售关闭。
- 配置一个支付提供方的 sandbox 凭据,以及具有读写权限的 Licentivo 连接。支付 sandbox 记录相互隔离,但仍使用已配置的 Licentivo 服务,可能创建真实的测试许可证和设备记录。必须使用专用测试产品、策略和客户。
- Publish a sandbox plan and use 程序接入 to export
launch-config.jsonand validatedproduct.jsoninto.local/acceptance/. - 本地只安装经审核的 Launch Python 包:
python -m pip install ./sdk/python,或安装其 wheel。包中包含私有 SDK 实现。 - 使用不计次的测试功能,如
export。--activate启动官方 SDK,同步调用refresh_online(),要求在线有效状态,并调用受保护操作 API。只有缓存离线授权无法通过此探针;该探针不测试计次。
凭据通过不回显的提示输入。自动化可在私有进程环境中提供 LAUNCH_ACCEPTANCE_EMAIL 和 LAUNCH_ACCEPTANCE_PASSWORD。不得将密码放入命令参数、报告、截图或已提交文件。工具在每次认证探针后撤销自己的临时桌面会话,但普通退出不会停用设备。
python scripts/acceptance.py preflight --config .local/acceptance/launch-config.json --report .local/acceptance/01-preflight.json
python scripts/acceptance.py verify --config .local/acceptance/launch-config.json --expect not_purchased --report .local/acceptance/02-no-purchase.json
工具拒绝正式环境配置、非回环 HTTP、携带凭据的重定向、不匹配产品,以及包含运行时秘密的公开配置。发请求前会拒绝 verify 之外的激活或订单断言,以及 checkout 之外的结账创建选项。已有报告绝不覆盖。报告只包含白名单证据,不包含原始响应、访问令牌或许可证密钥。缺少服务端或 SDK 会使探针失败,不会生成虚假成功。
本地商户探针使用 scope: local_sandbox_probe 和 licensing_scope: not_called。即使商户运行在 localhost,verify --activate 仍会联系官方外部授权服务;此组合记录为 local_merchant_external_licensing_probe,并使用 licensing_scope: official_external_service。
首次付款与激活
在商户网站创建测试结账,或使用稳定的操作 UUID 创建:
$operation = [guid]::NewGuid().ToString()
python scripts/acceptance.py checkout --config .local/acceptance/launch-config.json --provider stripe --plan-version-id PLAN_VERSION_UUID --operation-id $operation --report .local/acceptance/03-checkout.json
将提供方和套餐版本替换为你已发布的 sandbox 套餐。结账创建结果不确定时,重试必须保留并复用同一操作 UUID。工具会输出订单 ID。通过商户账号中心,使用提供方官方 sandbox 结账完成此所属订单。探针明确不模拟提供方界面交互。
提供方确认付款且 Webhook 已收到后:
python scripts/acceptance.py verify --config .local/acceptance/launch-config.json --order-id ORDER_UUID --expect-order paid --expect active --activate --product-config .local/acceptance/product.json --feature export --report .local/acceptance/04-activation.json
此检查验证已认证账号、所属 sandbox 订单、权益、凭据与产品对应关系,以及一次真实的官方 SDK 受保护操作。待处理授权在有界窗口内最多尝试五次,默认 30 秒、最长 120 秒,并遵循 Retry-After。意外授权失败会记录,但不暴露 SDK 原始错误文本。
生命周期验收矩阵
每个已发布的语言与操作系统组合,都应保存带日期的记录,包含源码修订、Launch/客户端/SDK 版本、提供方环境、匿名客户标签、订单 ID、预期结果、实际结果和相关报告文件名。未执行行标为未运行。不能仅凭首次付款探针就将整个矩阵标为通过。
| 场景 | 步骤 | 必需证据 |
|---|---|---|
| 注册 / 验证 | 不购买直接注册,分别在启用和禁用验证时重复 | 禁用验证时不阻止;启用验证时,在完成前返回 EMAIL_VERIFICATION_REQUIRED |
| 未购买 | 运行 verify --expect not_purchased |
拒绝凭据,不执行受保护操作 |
| 首次购买 | 完成 sandbox 付款,再运行激活探针 | 提供方确认付款;一份已付费权益、一份同步许可证,SDK 操作成功 |
| 重启 | 关闭已记住登录的所选语言示例,启动新进程并恢复 | 不要求输入密码;使用同一账号与产品缓存及有效签名授权 |
| 离线启动 | 成功激活并记住登录后,禁用测试进程或机器的网络,再重启 | 签名缓存授权只允许策略开放的操作;禁止离线或浮动策略拒绝启动 |
| 离线到期 / 时钟回退 | 使用短期测试策略和可丢弃的测试机器 | SDK 拒绝已到期或时钟回退状态;功能回调不执行 |
| 续费 / 升级 | 通过 sandbox 商店购买续费或已报价升级 | 订单和覆盖期正确;同步及 SDK 刷新后可见新的有效期和功能 |
| 退款 | 申请并批准全额 sandbox 退款,等待提供方确认 | 提供方退款与本地覆盖一致;按情况运行 verify --expect suspended 或 --expect expired;其他付费覆盖仍可使用 |
| 退出 / 切换账号 | 退出 A,使用未购买的 B 登录;重启并观察行为 | 清除 A 已保存的会话和缓存;B 不能使用 A 的许可证、设备或功能 |
| 产品 / 环境隔离 | 使用另一产品,另行切换 sandbox/live 配置 | 凭据和缓存不能跨身份范围复用;外部探针自身拒绝 live |
| 设备已满 / 释放 | 在策略允许的最多不同测试设备上激活,再尝试增加一个,随后明确释放一个 | SDK 拒绝超额设备,确认释放后允许替换;普通关闭不消耗释放额度 |
| 处理方式 | 在待签发期间重启 Launch,重放已签名 sandbox Webhook | 只有一份订单覆盖与许可证,最终完成核对;无重复结账或扣款 |
退款或暂停对已签发离线授权的影响,仍受官方 SDK 签名离线策略约束。不保证断网时即时撤销。合约到期时,长时间 Launch 故障可能延迟上游暂停;参见合约限制。
完成与保留证据
每份探针报告明确设置 acceptance_complete: false,只记录该次调用实际执行的检查。接受发行版前,应审核矩阵和提供方记录。之后配置外部服务,再继续上述命令;不得用通过标志替代缺失结果,也不能仅因本地测试通过就启用正式销售。