# 接入须知
泡椒云网络验证支持多平台、多终端、多开发环境,此文档将帮助你将泡椒云网络验证的功能集成到你的应用或脚本中。
# 签名算法(sign)
# 计算公式
sign = md5(http_method + host + path + k1=v1&k2=v2&kn=vn + app_secret)
1
注意
参数必须按照顺序放置
参数名 | 参数说明 |
---|---|
http_method | 请求方法,GET或POST |
host | 域名,例如:api.paojiaoyun.com |
path | 地址,例如:/v1/card/login |
k1=v1...kn=vn | 1.将全部请求参数格式化成k=v 2.将格式化后的参数按升序排列,然后用&符号相隔拼接在一起,不想写排序代码也可严格按照接口文档中的请求参数表写死顺序 (注意:1.不包括sign参数, 2.V不应进行url encode) |
app_secret | 软件秘钥,在开发端后台软件列表获取 |
# 以调用卡密登录接口举例
POST 请求 http://api.paojiaoyun.com/v1/card/login
伪代码如下:
app_secret = "uiS9M0G8JolpUvlf5NxZ7pwMVinKs73x" # 软件秘钥
http_method = "POST"
host = "api.paojiaoyun.com"
path = "/v1/card/login"
# 参数列表:
# app_key=blsvh14llhcr96vtboqg
# card=abc3b65KDZ9Qb7UC685D2MVFR0TPc53BCU1IPD5ad20
# device_id=123
# nonce=359c22e4-d522-4771-ba8e-4b99cf61b372
# timestamp=1574654197
# 将以上格式化的参数排序后,用 & 符号相隔拼接起来
params = "app_key=blsvh14llhcr96vtboqg&card=abc3b65KDZ9Qb7UC685D2MVFR0TPc53BCU1IPD5ad20&device_id=123&nonce=359c22e4-d522-4771-ba8e-4b99cf61b372×tamp=1574654197"
# 带入计算公式
sign = md5(http_method + host + path + params + app_secret)
print(sign) # 输出 b5f3cc619998fa45e4c11ef57e712f87
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 公共参数详细释义
- timestamp:当前时间戳,保证签名只在1分钟内有效,请求到达服务器后会将时间戳参数与当前服务器时间相比较,是否超过了60s。防止别有用心的人抓包并重放请求。
- nonce:不超过36位的随机字符串(建议用UUID),对于当前软件,服务器会记录每次请求的nonce,如果在60s内出现第二次,则会拒绝该请求。用于配合时间戳避免重放攻击。
# 双向签名
目前所有接口已支持双向签名,接口调用成功后,会额外返回nonce
和sign
两个字段,nonce
服务端保证不会有重复的返回,且nonce是趋势递增的(也就是说本次请求响应的nonce肯定是大于上一次次请求响应的nonce),sign
用来保证服务端响应内容不被篡改。
自己封装接口的开发者可以参考下面的服务端签名规则:
sign = md5(code + message + k1=v1&k2=v2&kn=vn + nonce + app_secret)
1
伪代码如下:
app_secret = "uiS9M0G8JolpUvlf5NxZ7pwMVinKs73x" # 软件秘钥
prev_nonce = None # 全局变量,用以记录服务端返回的nonce
def check_resp_sign(resp):
if prev_nonce == None: # 第一次请求
prev_nonce = resp['nonce']
else if resp['nonce'] <= prev_nonce: # 跟上一次服务端返回的nonce对比,如果本次nonce小于等于上次nonce则可判定为异常请求
return False
result = resp.get('result', {}) # {'expires': '2020-10-16 00:47:58', 'expires_ts': 1602780478, 'server_time': 1579598162}
params = []
# 将响应中的result中的所有字段按 k=v 的形式组合
for k, v in result.items():
params.append(f'{k}={v}')
# 排序
params = sorted(params) # ['expires=2020-10-16 00:47:58', 'expires_ts=1602780478', 'server_time=1579598162']
# 用 & 符号相隔拼接起来
pstr = '&'.join(params) # expires=2020-10-16 00:47:58&expires_ts=1602780478&server_time=1579598162
# 将所有参与签名的参数按规则拼接起来
ss = f"{resp['code']}{resp['message']}{pstr}{resp['nonce']}{app_secret}" # 0okexpires=2020-10-16 00:47:58&expires_ts=1602780478&server_time=1579598162bojc2kiuof2jci9b90jguiS9M0G8JolpUvlf5NxZ7pwMVinKs73x
# 本地签名
resp_sign = md5(ss.encode()).hexdigest() # 4954c9805d4040a95336150e6e5f14e2
return resp_sign == resp['sign'] # 对比签名是否一致
resp = card_heartbeat() # {"code":0,"message":"ok","result":{"expires":"2020-10-16 00:47:58","expires_ts":1602780478,"server_time":1579598162},"nonce":"bojc2kiuof2jci9b90jg","sign":"4954c9805d4040a95336150e6e5f14e2"}
check_resp_sign(resp) # True / False
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
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
# 接口返回码对照表
返回码 | 说明 |
---|---|
0 | 调用成功 |
400 | 参数错误,请检查请求参数,详细字段错误会通过errs返回 |
404 | 资源未找到 |
500 | 服务器错误,请稍后重试 |
10010 | 无效的签名,请检查签名算法 |
10011 | 签名已过期,签名只在1分钟内有效且是一次性的 |
10013 | 时间戳大于当前服务器时间,请检查timestamp参数 |
10014 | 重复的nonce,需保证nonce对于当前软件在60s内不能重复出现 |
10210 | 卡密已过期 |
10212 | 卡密已被冻结 |
10213 | 卡密超过多开上限 |
10214 | 登录状态已失效,可能原因:超时未发心跳包、被挤下线、后台冻结、卡用户修改密码。 |
10215 | 只能在首次登录绑定的设备上使用 |
10216 | 软件未开启解绑设备功能 |
10217 | 超出可绑定设备上限,请在已绑定设备上使用 |
10218 | 卡密不可用(卡密不存在) |
10230 | 软件不存在,请检查app_key |
10240 | 卡密不存在或已被使用 |
10241 | 卡密已被使用 |
10242 | 账号已存在,用户注册时返回 |
10243 | 用户登录密码错误 |
10244 | 不能对未使用的卡密进行充值 |
10250 | 用户已到期 |
10252 | 用户已被冻结 |
10253 | 用户超过多开上限 |
10254 | 解绑密码不正确 |
10255 | 该卡密不可解绑设备 |
10256 | 卡密多开配置不相等,不能充值 |
10257 | 卡密剩余时间已不足以解绑扣除 |
10304 | 已经是最新版本,获取软件最新版本返回 |
10401 | 软件未开启试用,开发者需在后台软件管理配置 |
10402 | 试用中,请勿重复登录 |
10403 | 已试用过了 |
10404 | 请先登录,原因:未登录就调用心跳接口或者登录后超过60秒再调用心跳接口 |
10405 | 试用已到期,软件配置为一次性试用,心跳接口返回 |
10406 | 本周期试用已到期,软件配置为间隔试用,心跳接口返回 |
10407 | 本周期试用次数已用完 |
10501 | 远程变量不存在 |
10521 | 远程数据不存在 |
10522 | 远程数据key已存在 |
10541 | 远程函数不存在 |
10542 | 参数(params)必须为json列表序列化后的string |
10543 | 远程函数调用错误,具体错误信息在message返回 |
卡密相关 →