Skip to content

Python SDK

基于 Python 标准库实现的轻量客户端,零第三方依赖,直接 import 即可使用。完整封装了 Init 握手Handle 调用

安装

无需安装第三方包,将下方代码保存为 a7client.py 即可:

bash
# Python 3.8+ 自带 urllib / hashlib,无需 pip install
python -c "import a7client; print('ok')"

完整客户端代码

python
import hashlib
import json
import time
import urllib.parse
import urllib.request

BASE = "https://www.a7p.cn/api/verify"


def rc4(key: str, data: str) -> str:
    """RC4 加密,返回 HEX 大写字符串。"""
    key_bytes = key.encode("utf-8")
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + key_bytes[i % len(key_bytes)]) % 256
        s[i], s[j] = s[j], s[i]
    i = j = 0
    out = bytearray()
    for b in data.encode("utf-8"):
        i = (i + 1) % 256
        j = (j + s[i]) % 256
        s[i], s[j] = s[j], s[i]
        out.append(b ^ s[(s[i] + s[j]) % 256])
    return out.hex().upper()


def md5(text: str) -> str:
    return hashlib.md5(text.encode("utf-8")).hexdigest()


class A7Client:
    """A7验证客户端:先 init() 再 call()。"""

    def __init__(self, app_id: str, app_key: str):
        self.app_id = app_id
        self.app_key = app_key
        self.api_password = ""

    def init(self) -> str:
        """Init 握手,返回 ApiPassword 并缓存到实例。"""
        ts = int(time.time())
        sign = md5(f"{self.app_id}{self.app_key}{ts}{self.app_key}")
        body = urllib.parse.urlencode({
            "AppId": self.app_id,
            "AppKey": self.app_key,
            "TimeStamp": ts,
            "Sign": sign,
        }).encode("utf-8")
        req = urllib.request.Request(
            BASE, data=body,
            headers={"Content-Type": "application/x-www-form-urlencoded"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read().decode("utf-8"))
        if result.get("code") != 200:
            raise RuntimeError(f"Init 失败 {result.get('code')}: {result.get('message')}")
        self.api_password = result["data"]["api_password"]
        return self.api_password

    def call(self, action: str, params: dict | None = None) -> dict:
        """通用 Handle 调用。action 为业务名,params 为其它键值对。"""
        if not self.api_password:
            raise RuntimeError("请先调用 init() 获取 ApiPassword")
        params = params or {}
        plain = "action=" + urllib.parse.quote(action, safe="")
        for k, v in params.items():
            plain += "&" + k + "=" + urllib.parse.quote(str(v), safe="")
        ts = int(time.time())
        data_hex = rc4(self.api_password, plain)
        sign = md5(f"{self.api_password}{ts}{data_hex}")
        body = urllib.parse.urlencode({
            "TimeStamp": ts,
            "Sign": sign,
            "Data": data_hex,
        }).encode("utf-8")
        req = urllib.request.Request(
            BASE,
            data=body,
            headers={
                "Content-Type": "application/x-www-form-urlencoded",
                "X-Api-Password": self.api_password,
            },
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return json.loads(resp.read().decode("utf-8"))

使用示例

python
from a7client import A7Client

client = A7Client(app_id="150018", app_key="YOUR_APP_KEY")
client.init()

# 卡密登录
r = client.call("SingleLogin", {
    "Card": "6PCG-ZRSZ-EX83-YBEH",
    "Mac": "MAC001",
})
if r["code"] == 200:
    token = r["data"]["token"]
    print("登录成功,到期", r["data"]["expire_at"])
else:
    print("失败", r["code"], r["message"])

要点

  • ApiPassword 只缓存在内存,不要写入磁盘或日志
  • 推荐用请求头 X-Api-Password 传递接口密码,避免密码出现在访问日志里。
  • 时间戳窗口为 ±300 秒,客户端系统时钟需准确。
  • 完整 API 见 12 个业务 action

A7验证 · 软件授权与网络验证平台