Python 接入指南

使用 urllib 与 cryptography 完成激活、Ed25519 验签与停用。

本指南覆盖完整闭环:激活 → 本地保存 → 启动校验 → 停用。示例假设你已经拿到工作区与一份授权码。

HTTP 使用标准库 urllib;验签使用 cryptography 包(pip install cryptography)。

1. 激活

license.py
import json
import urllib.request

BASE = "https://keygate.unionuser.com"

def activate(license_key, device_id):
    payload = json.dumps({
        "license_key": license_key,
        "identifier": device_id,
        "identifier_type": "device",
    }).encode()
    req = urllib.request.Request(
        BASE + "/api/v1/license/activate",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=15) as res:
        body = json.loads(res.read())
    if not body.get("success"):
        raise RuntimeError(body["error"]["code"])
    return body["data"]["token"]

2. 离线验签

verify.py
import base64
import json
import time
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

RAW_PUBLIC = bytes.fromhex("bf17435ee7b937b3592808941683c21d37c4e124d95d4e8fdd86fe775dd23b11")
public_key = Ed25519PublicKey.from_public_bytes(RAW_PUBLIC)

def b64url(value: str) -> bytes:
    return base64.urlsafe_b64decode(value + "=" * (-len(value) % 4))

def verify_token(token, device_id):
    payload_b64, sig_b64 = token.split(".")
    public_key.verify(b64url(sig_b64), payload_b64.encode("ascii"))

    claims = json.loads(b64url(payload_b64))
    if claims["did"] != device_id:
        raise ValueError("DEVICE_MISMATCH")
    if claims["exp"] < time.time():
        raise ValueError("TOKEN_EXPIRED")
    return claims

3. 停用

deactivate.py
def deactivate(license_key, device_id):
    payload = json.dumps({
        "license_key": license_key,
        "identifier": device_id,
    }).encode()
    req = urllib.request.Request(
        BASE + "/api/v1/license/deactivate",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=15) as res:
        return json.loads(res.read())

打包提示

  • PyInstaller 打包时把 cryptography 作为隐藏依赖测试一遍。
  • QSettings / platformdirs 保存 token,不要写进只读安装目录。
  • 异常先区分网络错误与业务错误,再决定是否重试。