# python 接入

7c云网络验证提供了官方的 python 库,方便 python 开发者接入。

# 接入须知

# 对接视频

python对接视频 (opens new window)

# 获取方式

下载地址: 或者加群675107742在群文件下载SDK,有问题也可在此群交流。

# 使用方式

QCYSDK文件夹解压放入你的项目中即可,然后在脚本中通过 from QCYSDK import * 引入。 压缩包中的main.py是一个示例。

# 卡密登录例子

from QCYSDK import *
import os
import time

# 执行pip install wmi
# 安装wmi用来获取设备号
import wmi

# 初始化 appKey 和 appSecret 在开发者后台新建软件获取, tokenPath 保存token的文件路径
appKey = "";
appSecret = ""
token_path = './token.txt'
qcysdk = QCYSDK(appKey=appKey, appSecret=appSecret, tokenPath=token_path)
qcysdk.debug = False
# 开启断线重连
isLoginAgain = True # False关闭断线重连

# 主板序列号
def get_mainboard_info():
    mainboard = []
    for board_id in wmi.WMI().Win32_BaseBoard():
        mainboard.append(board_id.SerialNumber.strip().strip('.'))
    return mainboard


# cpu序列号
def get_CPU_info():
    cpu = []
    cp = wmi.WMI().Win32_Processor()
    for u in cp:
        cpu.append({"Name": u.Name, "SerialNumber": u.ProcessorId, "CoreNum": u.NumberOfCores})
    return cpu

def generate_random_str(randomlength=16):
    random_str =''
    base_str ='ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
    length =len(base_str) -1
    for i in range(randomlength):
        random_str +=base_str[random.randint(0, length)]
    return random_str


# 获取设备号
def get_device():
    main_board_device = get_mainboard_info()
    CPU_device = get_CPU_info()
    if len(main_board_device) >= 1 and len(CPU_device) >= 1:
        if CPU_device[0]['SerialNumber'] not in (None, '') and main_board_device[0] not in (None, ''):
            device_id = main_board_device[0] + CPU_device[0]['SerialNumber']
            return device_id
        elif CPU_device[0]['SerialNumber'] in (None, '') and main_board_device[0] not in (None, ''):
            device_id = main_board_device[0]
            return device_id
        elif CPU_device[0]['SerialNumber'] not in (None, '') and main_board_device[0] in (None, ''):
            device_id = CPU_device[0]['SerialNumber']
            return device_id
        else:
            try:
                with open("./device_id", encoding='utf-8') as fs:
                    device_id = fs.read()
                    return device_id
            except FileNotFoundError:
                with open("./device_id", mode='w', encoding='utf-8') as fs:
                    device_id = generate_random_str()
                    fs.write(device_id)
                    return device_id
    else:
        try:
            with open("./device_id", encoding='utf-8') as fs:
                device_id = fs.read()
                return device_id
        except FileNotFoundError:
            with open("./device_id", mode='w', encoding='utf-8') as fs:
                device_id = generate_random_str()
                fs.write(device_id)
                return device_id


# 心跳失败回调
def on_heartbeat_failed(hret):
    print(f"心跳失败:{hret.message}")
    if hret.message == "登录状态已失效" and isLoginAgain:
        for i in range(0, 3):
            print("心跳失败,尝试重登...")
            login_ret = qcysdk.card_login()
            if login_ret.code == 0:
                print("重登成功")
                return
            else:
                print(login_ret.message)  # 重登失败
                if i >= 2:
                    os._exit(1)  # 退出脚本
            time.sleep(60)
        os._exit(1)  # 退出脚本
    else:
        os._exit(1)  # 退出脚本





def login():
    qcysdk.on_heartbeat_failed = on_heartbeat_failed
    device_id = get_device()
    qcysdk.set_device_id(md5(device_id.encode()).hexdigest()[0:16])  # 设置设备唯一ID,长度在6-50位
    qcysdk.set_card('')  # 设置卡密

    # 如果开启 限制登录次数 每次卡密登录前需要调用退出登录, 没有开启,限制登录次数,这里不用管
    # 从token_path路径读取token
    try:
        with open(token_path, encoding='utf-8') as fs:
            token = fs.read()
    except FileNotFoundError:
        with open(token_path, mode='w', encoding='utf-8') as fs:
            pass

    if token not in (None, ''):
        qcysdk.card_logout(token)

    ret = qcysdk.card_login()  # 卡密登录
    print(f"ret:{ret}")

    if ret.code != 0:  # 登录失败
        print(ret.message)
        os._exit(1)  # 退出脚本

    print(f"cardType:{ret.result.cardType}  expires:{ret.result.expires}")
    # 登录成功,后面写你的业务代码
    i = 0
    while 1:  # 测试用,hold住主线程不要退出,记得删除,后面是你的代码
        i += 1
        print(f"i:{i}")
        time.sleep(10)
        # os._exit(1)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

# 初始化SDK

# 语法

QCYSDK(appKey, appSecret, tokenPath)
1

# 参数

参数名 必传 类型 参数说明
appKey string 软件的appKey,开发者后台获取
appSecret string 软件的appSecret,开发者后台获取
tokenPath string 登录成功保存登录令牌的文本路径

# 初始化设备号

# 语法

qcysdk.set_device_id(device_id)
1

# 参数

参数名 必传 类型 参数说明
device_id string 用户设备唯一标识(长度不超过45位)

# 初始化卡密

# 语法

qcysdk.set_card(card)
1

# 参数

参数名 必传 类型 参数说明
card string 用户填写的卡密(长度不超过45位)

# 初始化用户账号

# 语法

qcysdk.set_user(username, password)
1

# 参数

参数名 必传 类型 参数说明
username string 用户名(长度不能超过20位)
password string 用户密码(长度6-30位)

# 获取时间戳(网络时间)

# 语法

ret = qcysdk.timestamp()
1

# 参数

# 返回值

数字类型,列如: 1624110613

# 获取心跳结果

# 语法

ret = qcysdk.get_heartbeat_result()
1

# 参数

# 返回值

Object类型,例:{"code": 0, "message": "ok"}

# 获取剩余时长

# 语法

ret = qcysdk.get_time_remaining()
1

# 参数

# 返回值

数字类型,剩余多少秒,例:1024

# 卡密登录

注意

调用此接口前需调用 qcysdk.set_card(card) 初始化卡密 登录成功后将自动启动一个线程发送心跳包,开发者就无需关注发送心跳包的细节。 开发者只需在自己的脚本中通过调用 qcysdk.get_heartbeat_result() 获取当前心跳结果。

# 语法

ret = qcysdk.card_login()
1

# 参数

# 返回值

Object类型,例:{ result: { cardType: '月卡', token: '8wr17hGcTs5lVVJ0liL97d6McNEaDTKk', expires: '2021-09-17 01:49:38', expires_ts: '1631814578', config: '', server_time: 1624110506 }, message: 'ok', code: 0 }

# 卡密退出登录

# 语法

ret = qcysdk.card_logout(token)
1

# 参数

参数名 必传 类型 参数说明
token string 卡密登录成功获取的登录凭证

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 卡密解绑设备

注意

请先进入开发者后台软件管理页面,配置软件开启设备绑定且可解除绑定。

# 语法

ret = qcysdk.card_unbind_device()
1

# 参数

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 卡密绑定设备上解绑

注意

请先进入开发者后台软件管理页面,配置软件开启设备绑定且可解除绑定。

# 语法

ret = qcysdk.Card_unbind_devicebybind_device()
1

# 参数

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 卡密设置解绑密码

说明

请先进入开发者后台软件管理页面,配置软件开启设备绑定且可解除绑定。 该密码用于绑定设备丢失或者其它原因导致无法在老设备登录时解绑设备。

# 语法

ret = qcysdk.set_card_unbind_password(password)
1

# 参数

参数名 必传 类型 参数说明
password string 解绑密码(6-10位数字和字母组合的字符串)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 卡密通过密码解绑设备

说明

请先进入开发者后台软件管理页面,配置软件开启设备绑定且可解除绑定。 该接口用于绑定设备丢失或者其它原因导致无法在老设备登录时,通过解绑密码解绑设备。

# 语法

ret = qcysdk.card_unbind_device_by_password(password)
1
参数名 必传 类型 参数说明
password string 解绑密码(6-10位数字和字母组合的字符串)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 卡密充值(以卡充卡)

# 语法

ret = qcysdk.card_recharge(card, useCard)
1

# 参数

参数名 必传 类型 参数说明
card string 被充值的卡密(长度不超过45位)
useCard string 充值使用的卡密(长度不超过45位)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 用户注册(通过卡密)

# 语法

ret = qcysdk.user_register(username, password, card)
1

# 参数

参数名 必传 类型 参数说明
username string 用户名(长度不能超过20位)
password string 用户密码(长度6-30位)
card string 注册使用的卡密(长度不超过45位)

# 返回值

Object类型,例:{"code": 0, "message": "ok"}

# 用户登录

注意

调用此接口前需调用 qcysdk.set_user(username, password) 初始化用户账号密码 登录成功后将自动启动一个线程发送心跳包,开发者就无需关注发送心跳包的细节。 开发者只需在自己的脚本中通过调用 qcysdk.get_heartbeat_result() 获取当前心跳结果。

# 语法

qcysdk.set_user(username, password)
ret = qcysdk.user_login()
1
2

# 参数

# 返回值

Object类型

# 用户退出登录

# 语法

ret = qcysdk.user_logout(token)
1

# 参数

参数名 必传 类型 参数说明
token string 卡密登录成功获取的登录凭证

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 用户修改密码

# 语法

ret = qcysdk.user_change_password(username, password, newPassword)
1

# 参数

参数名 必传 类型 参数说明
username string 用户名(长度不能超过20位)
password string 用户密码(长度6-30位)
newPassword string 新密码(长度6-30位)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 用户充值(通过卡密)

# 语法

ret = qcysdk.user_recharge(username, card)
1

# 参数

参数名 必传 类型 参数说明
username string 用户名(长度不能超过20位)
card string 充值使用的卡密(长度不超过45位)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 用户解绑设备

# 语法

ret = qcysdk.user_unbind_device()
1

# 参数

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 试用登录

注意

登录成功后将自动启动一个线程发送心跳包,开发者就无需关注发送心跳包的细节。 只需在自己的脚本中通过调用 qcysdk.get_heartbeat_result() 获取当前心跳结果。

# 语法

ret = qcysdk.trial_login()
1

# 参数

# 返回值

Object类型

# 试用退出登录

# 语法

ret = qcysdk.trial_logout()
1

# 参数

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 获取卡密配置

# 语法

ret = qcysdk.get_card_config()
1

# 参数

# 返回值

Object类型,例:{ result: { config: '', server_time: 1624120946 }, message: 'ok', code: 0 }

# 更改卡密配置

# 语法

ret = qcysdk.update_card_config(config)
1

# 参数

参数名 必传 类型 参数说明
config string 自定义配置(长度不能超过512位)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 获取用户配置

# 语法

ret = qcysdk.get_user_config()
1

# 参数

# 返回值

Object类型,例:{ result: { config: '迪迦', server_time: 1624121563 }, message: 'ok', code: 0 }

# 更改用户配置

# 语法

ret = qcysdk.update_user_config(config)
1

# 参数

参数名 必传 类型 参数说明
config string 自定义配置(长度不能超过512位)

# 返回值

Object类型,例:{"code": 0, "message": "OK"}

# 获取软件配置

# 语法

ret = qcysdk.get_software_config()
1

# 参数

# 返回值

Object类型,例:{ result: { config: '迪迦', server_time: 1624121758 }, message: 'ok', code: 0 }

# 获取软件公告

# 语法

ret = qcysdk.get_software_notice()
1

# 参数

# 返回值

Object类型,例:{ result: { server_time: 1624121862, notice: '泰罗' }, message: 'ok', code: 0 }

# 获取软件版本号和下载链接

# 语法

ret = qcysdk.get_software_version()
1

# 参数

# 返回值

Object类型,例:{ result: { server_time: 1624121862, version: '1.0.1', url:'www.baidu.com' }, message: 'ok', code: 0 }

# 获取远程变量

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.get_remote_var(key)
1

# 参数

参数名 必传 类型 参数说明
key string 远程变量名(长度不能超过64位)

# 返回值

Object类型,例:{ result: { server_time: 1624122124, varValue: '斯奥特曼' }, message: 'ok', code: 0 }

# 获取远程数据

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.get_remote_data(key)
1

# 参数

参数名 必传 类型 参数说明
key string 远程数据key(长度不能超过64位)

# 返回值

Object类型,例:{ result: { server_time: 1624122295, value: '奥特曼' }, message: 'ok', code: 0 }

# 操作远程数据

# 新增远程数据

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.create_remote_data(key, value)
1

# 参数

参数名 必传 类型 参数说明
key string 远程数据key(长度不能超过64位)
value string 远程数据值(长度不能超过256位)

# 返回值

Object类型,例:{ result: { server_time: 1624122453 }, message: 'ok', code: 0 }

# 修改远程数据

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.update_remote_data(key, value)
1

# 参数

参数名 必传 类型 参数说明
key string 远程数据key(长度不能超过64位)
value string 远程数据值(长度不能超过256位)

# 返回值

Object类型,例:{ result: { server_time: 1624122453 }, message: 'ok', code: 0 }

# 删除远程数据

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.delete_remote_data(key)
1

# 参数

参数名 必传 类型 参数说明
key string 远程数据key(长度不能超过64位)

# 返回值

Object类型,例:{ result: { server_time: 1624122453 }, message: 'ok', code: 0 }

# 云函数

注意

调用此接口前 需要登录成功后才能调用。

# 语法

ret = qcysdk.CallRemoteFn(fnName, params);
1

# 参数

参数名 必传 类型 参数说明
fnName string 云函数名(长度不能超过64位)
params string 调用云函数时传入的参数

# 返回值

Object类型,例:{"result":{"return":"55","server_time":1689788200},"message":"ok","sign":"236cd75d551fb991ac88684761778a17","nonce":"vwWSKfwOgbLocFzg15OX","code":0}

例子:

let ret = qcysdk.call_remote_fn("add", "21, 34");
if (ret.code == 0){
  console.log("云函数调用结果:", ret.result.return)
}else{
  console.log("云函数调用失败:", ret.message)
}
1
2
3
4
5
6