授权码开放接口文档

v1.0

授权码开放接口文档

本文面向需要把「支付 → 发码 → 激活 → 校验」做进自己软件的开发者(客户端软件 / 仅推广产品)。文档按接口逐个说明调用时机、请求参数、返回字段、错误码

一、核心概念

概念 字段 / 术语 说明
软件发码密钥 licenseApiSecret 产品开启「授权激活」时系统自动生成,在开发者中心产品编辑表单可查看。软件服务端用它计算 HMAC 签名,平台用它验签;只能保存在你的软件服务端,严禁写入客户端
授权码 licenseCode 平台生成的唯一授权码,用户凭它激活软件。
机器码 machineCode 客户端软件生成的设备标识(每台电脑唯一,建议对机器指纹做哈希,至少 8 位)。
激活凭证 activationToken 平台在激活 / 发码时签发的凭证,软件保存后每次启动校验时回传。
订单号 clientOrderId 软件内支付订单号(客户端或服务端生成)。平台按「产品 + 订单号」幂等,防止重复扣费重复发码。

二、接入准备

  1. 发布产品时开启「授权激活」,保存系统生成的软件发码密钥(licenseApiSecret)
  2. 在发布表单配置版本列表(如 BASIC/PRO/ULTIMATE)与升级策略(SAME_CODE 原码升级 / NEW_CODE 换新码);
  3. 将密钥保存在软件服务端,客户端只保留授权码与激活凭证。

三、接口总览

接口前缀:https://www.powersoftware.app/frontApi(本地 / 测试环境按你的部署域名替换)。

接口 调用时机 鉴权 签名
POST /license/software/generate 软件内支付成功后 无(验签) 需要
POST /license/software/upgrade 续费 / 升级版本支付成功后 无(验签) 需要
POST /license/activate 用户首次激活 / 换新设备 不需要
POST /license/verify 软件每次启动 不需要
POST /license/deactivate 用户解绑旧设备(个人中心) 登录 不需要

四、签名规则(发码 / 升级接口必须)

签名串:按以下固定顺序、以换行符 \n 拼接(缺省字段填空值:edition 空串、expiryDays 填 0):

productId \n machineCode \n edition \n expiryDays \n clientOrderId \n licenseCode \n timestamp

签名HMAC-SHA256(软件发码密钥 licenseApiSecret, 签名串),结果用 Base64URL 编码后放入 signature 字段。

防重放timestamp 为毫秒时间戳,平台要求与服务器时间差不超过 5 分钟,超时直接返回 signatureInvalid

Node.js 示例:

const crypto = require("crypto");
const payload = [productId, machineCode, edition, expiryDays, clientOrderId, licenseCode, timestamp].join("\n");
const signature = crypto.createHmac("sha256", API_SECRET).update(payload).digest("base64url");

Python 示例:

import hashlib, hmac, base64
payload = "\n".join([str(productId), machineCode, edition, str(expiryDays), clientOrderId, licenseCode, str(timestamp)])
signature = base64.urlsafe_b64encode(hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).digest()).decode().rstrip("=")

(Base64URL 即标准 Base64 将 +-/_,并去掉末尾 = 填充。)

五、接口详情

5.1 生成授权码(软件内支付后调用)

调用时机:用户在软件内完成支付后,由软件服务端立即调用一次并保存返回的授权码与激活凭证。同一订单只应调用一次;重复调用因幂等不会重复发码。

POST /license/software/generate

请求参数(JSON body):

参数 类型 必填 来源 说明
productId number 软件内置 / 服务端配置 产品 ID,与平台发布的产品一致
machineCode string 客户端生成 当前设备机器码,≥8 位
edition string 客户端支付时选择 版本标识,须在产品版本列表内;缺省取产品默认第一个版本
expiryDays number 客户端支付时选择 有效期天数,0=永久;范围 0-3650
clientOrderId string 客户端 / 服务端生成 软件内支付订单号,1-64 字符;幂等键
timestamp number 软件服务端生成 毫秒时间戳
signature string 软件服务端计算 HMAC 签名,≥10 字符

成功响应 content 字段:

字段 类型 说明
licenseId number 授权码记录 ID
licenseCode string 授权码(写入软件授权信息)
productId number 产品 ID
edition string 版本标识
machineId number 已绑定机器记录 ID
activatedAt string 激活时间(ISO8601)
expiryTime string/null 到期时间(ISO8601),null=永久
maxMachines number 最大可绑定机器数
activationToken string 激活凭证,软件保存用于启动校验

响应示例:

{
  "code": "SUCCESS",
  "requestId": "xxx",
  "success": true,
  "content": {
    "licenseId": 1001,
    "licenseCode": "AB12-CD34-EF56-GH78",
    "productId": 88,
    "edition": "PRO",
    "machineId": 2001,
    "activatedAt": "2026-08-05T10:00:00.000Z",
    "expiryTime": "2027-08-05T10:00:00.000Z",
    "maxMachines": 1,
    "activationToken": "eyJhbGciOiJIUzI1NiJ9..."
  }
}

本接口错误码:productIdRequiredmachineCodeInvalidorderIdRequiredproductNotFoundproductNotEnabledapiSecretMissingsignatureInvalidorderAlreadyUsed

5.2 升级版本 / 续费(支付后调用)

调用时机:用户在软件内完成续费或升级版本支付后调用;同一订单只应调用一次。

POST /license/software/upgrade

请求参数(JSON body):

参数 类型 必填 来源 说明
productId number 软件内置 / 服务端配置 产品 ID
licenseCode string 软件本地保存 当前授权码,≥10 位
machineCode string 客户端生成 当前机器码;换新码策略迁移绑定、补绑机器时传
edition string 客户端支付时选择 目标版本标识
expiryDays number 客户端支付时选择 新增有效期天数,0=永久;范围 0-3650
clientOrderId string 客户端 / 服务端生成 本次订单号;幂等键
timestamp number 软件服务端生成 毫秒时间戳
signature string 软件服务端计算 HMAC 签名

处理策略(由产品配置决定):

  • SAME_CODE(原码升级):授权码不变,机器绑定不失效,有效期顺延(永久授权保持永久);响应在 5.1 字段基础上增加 upgraded: true
  • NEW_CODE(换新码):吊销旧码、生成新码并迁移机器绑定;响应额外返回 oldLicenseIdlicenseCode 为新码。

成功响应 content 字段:与 5.1 相同,另加 upgraded: true;NEW_CODE 策略下返回 oldLicenseId(旧授权码记录 ID,旧码已被吊销)。

本接口错误码:productIdRequiredlicenseCodeRequiredorderIdRequiredproductNotFoundproductNotEnabledapiSecretMissingsignatureInvalidcodeNotFoundrevokedorderAlreadyUsededitionRequired

5.3 激活授权(用户首次激活 / 换新设备)

调用时机:用户拿到授权码(自助发码、后台发码等场景)后,在客户端软件激活页输入授权码并激活;换新设备时在新设备调用。

POST /license/activate

请求参数(JSON body):

参数 类型 必填 来源 说明
licenseCode string 用户输入 授权码,≥10 位
machineCode string 客户端生成 当前设备机器码,≥8 位

成功响应 content:同 5.1(licenseId、licenseCode、productId、edition、machineId、activatedAt、expiryTime、maxMachines、activationToken)。

说明:

  • 同一授权码可绑定多台机器,受 maxMachines 限制(默认取产品配置);
  • 同一机器重复激活:复用原绑定并重新签发激活凭证(幂等);
  • 激活失败会按 IP + 授权码计数限流,多次失败返回 tooManyAttempts

本接口错误码:codeNotFoundrevokedexpiredmachineLimittooManyAttempts

5.4 校验授权(软件启动时)

调用时机:软件每次启动(或解锁功能前)调用;软件须保存 5.1 / 5.2 / 5.3 返回的 activationToken

POST /license/verify

请求参数(JSON body):

参数 类型 必填 来源 说明
licenseCode string 软件本地保存 授权码,≥10 位
machineCode string 客户端生成 当前设备机器码,≥8 位
activationToken string 平台签发、软件保存 激活凭证,≥20 位

成功响应 content 字段:

字段 类型 说明
valid boolean 恒为 true(失败走错误码)
licenseId number 授权码记录 ID
productId number 产品 ID
edition string 当前版本标识
expiryTime string/null 到期时间(ISO8601),null=永久

说明:

  • 校验结果有约 60 秒缓存;吊销、解绑、升级等写操作会主动失效缓存,无需担心延迟;
  • 软件应根据 expiryTime 判断是否过期,过期后停止解锁功能。

本接口错误码:tokenInvalidmachineNotActivatedinvalidOrRevokedexpiredtooManyAttempts

5.5 解绑设备(换机前,需登录)

调用时机:用户在「个人中心 → 我的授权」对旧设备执行解绑,然后在新设备调用 5.3 激活。

POST /license/deactivate

请求参数(JSON body):

参数 类型 必填 来源 说明
licenseCode string 用户授权列表 授权码,≥10 位
machineCode string 用户授权列表 要解绑的机器码,≥8 位

成功响应 contenttrue

说明:

  • 仅授权码归属用户(购买用户或绑定机器码登记用户)可操作;
  • 解绑配额:默认 30 天内仅可解绑 1 次(运营后台可配置),超限返回 unbindQuotaExceeded

本接口错误码:noPermissionmachineNotBoundunbindQuotaExceeded

六、错误码汇总

业务错误统一返回(tip 为可读错误信息):

{
  "code": "BUSINESS_WARNING",
  "requestId": "xxx",
  "success": false,
  "errorMessage": "LICENSE_GENERATE_FAILED",
  "tip": "签名校验失败"
}

参数校验失败返回 code: "PARAM_VALIDATE_FAILED"tip 为具体字段提示。

错误码 含义
productNotEnabled 产品未启用授权激活
apiSecretMissing 产品未配置软件发码密钥(licenseApiSecret)
signatureInvalid 签名校验失败(密钥不一致、签名串顺序错误或时间戳超窗)
machineCodeInvalid 机器码无效(长度不足 8 位)
orderAlreadyUsed 该订单已生成过授权码(幂等冲突:换机器码重放)
codeNotFound 授权码不存在
revoked 授权码已被吊销或不可用
expired 授权码已过期
invalidOrRevoked 校验时授权无效或已被吊销
machineNotActivated 该机器未激活
tokenInvalid 激活凭证无效
machineLimit 授权码绑定机器数已达上限
machineNotBound 该机器未绑定
noPermission 无权操作该授权码
unbindQuotaExceeded 30 天内仅可解绑 1 次,请稍后再试
tooManyAttempts 尝试次数过多,请稍后再试
productNotFound 产品不存在
editionRequired 请选择目标版本

七、典型流程

  1. 软件内支付闭环:支付成功 → software/generate(返回授权码 + 激活凭证)→ 软件保存 → 每次启动 verify → 解锁功能;续费 / 升级 → software/upgrade
  2. 自助发码 / 后台发码:开发者中心或平台后台生成授权码 → 用户获得授权码 → 客户端 activate 绑定设备并获取激活凭证 → 启动 verify
  3. 换机:个人中心 deactivate 解绑旧设备 → 新设备 activateverify
  4. 升级策略差异:SAME_CODE 原码升级(码不变);NEW_CODE 换新码(旧码吊销、新码自动迁移机器绑定)。

八、注意事项

  • 密钥只存服务端:签名只能在你的软件服务端完成,客户端拿到密钥等于授权体系失效;
  • 机器码稳定性:建议使用稳定的机器指纹并做哈希;重装系统导致机器码变化时需先解绑再激活;
  • 幂等:clientOrderId 请保证全局唯一(如 时间戳 + 随机数),重复请求不会重复发码;
  • 缓存:verify 结果缓存约 60 秒,写操作即时失效;
  • 限流:激活 / 校验失败会限流,客户端应做好错误提示与重试间隔;
  • 以平台返回为准:有效期、版本、机器数上限等以平台判定为准,软件端不要自行放宽。