import json
from Crypto.Cipher import AES
import base64
import requests
import hashlib
import time
import os
import binascii
URL = "https://wlc.nppa.gov.cn/test/authentication/check" #接口調(diào)用地址(實(shí)名認(rèn)證)
KEY = "d10d8642c66c1c785aa32b194aba2afa" #訪問密鑰
APPID = "9177929f5010481b858f661a409fd764" #接口調(diào)用唯一憑證 由系統(tǒng)發(fā)放
BIZID = "1101999999" #業(yè)務(wù)權(quán)限標(biāo)識(shí) 與游戲備案識(shí)別碼一致
#測(cè)試用例
TEST_PARAMS = {"ai":"100000000000000001",
"name":"某一一",
"idNum":"110000190101010001"}
class AES_GCM(object):
def __init__(self, key):
self.key = key #秘鑰
self.MODE = AES.MODE_GCM
self.iv = os.urandom(12)
def aes_encrypt(self, params):
aes = AES.new(binascii.unhexlify(self.key), self.MODE, self.iv)
params, tag=aes.encrypt_and_digest(json.dumps(params).encode("utf-8"))
base64_data= self.iv + params + tag
encrypted_text = str(base64.b64encode(base64_data), encoding='utf-8')
return encrypted_text
def aes_decrypt(self, encrypted_text):
encrypted_text = base64.b64decode(encrypted_text)
cipher = AES.new(binascii.unhexlify(self.key), self.MODE, encrypted_text[:12])
cc = cipher.decrypt_and_verify(encrypted_text[12:-16], encrypted_text[-16:])
return json.loads(cc)
def hash256(pre_hash_text):
hs256 = hashlib.sha256()
hs256.update(pre_hash_text.encode())
return hs256.hexdigest()
def sorted_params(params, param_="%s%s", none_keys = []):
return "".join([
param_ % i for i in
sorted(params.items(), key=lambda d:d[0]) if i[0] not in none_keys
])
def main():
aesobject = AES_GCM(KEY)
_time = str(int(time.time() * 1000))
#############上報(bào)用戶行為(上線 下線),直接替換TEST_PARAMS 接口調(diào)用地址 http:// api2.wlc.nppa.gov.cn/behavior/collection/loginout 實(shí)名認(rèn)證接結(jié)果查詢接口http:// api2.wlc.nppa.gov.cn/idcard/authentication/query
#no:[條目編碼]在批量模式中標(biāo)識(shí)一條行為數(shù)據(jù),取值范圍 1-128
#si:[游戲內(nèi)部會(huì)話標(biāo)識(shí)]一個(gè)會(huì)話標(biāo)識(shí)只能對(duì)應(yīng)唯一的實(shí)名用戶,一個(gè)實(shí)名用戶可以擁有多個(gè)會(huì)話標(biāo)識(shí);同一用戶單次游戲會(huì)話中,上下線動(dòng)作必須使用同一會(huì)話標(biāo)識(shí)上報(bào)備注:
# 會(huì)話標(biāo)識(shí)僅標(biāo)識(shí)一次用戶會(huì)話,生命周期僅為一次上線和與之匹配的一次下線,不會(huì)對(duì)生命周期之外的任何業(yè)務(wù)有任何影響
#bt:[用戶行為類型]游戲用戶行為類型0:下線,1:上線
#ot:[行為發(fā)生時(shí)間]行為發(fā)生時(shí)間戳,單位秒
#ct:[上報(bào)類型]用戶行為數(shù)據(jù)上報(bào)類型,0:已認(rèn)證通過用戶,2:游客用戶
#di:[設(shè)備標(biāo)識(shí)]游客模式設(shè)備標(biāo)識(shí),由游戲運(yùn)營(yíng)單位生成,游客用戶下必填
#pi:[用戶唯一標(biāo)識(shí)]已通過實(shí)名認(rèn)證用戶的唯一標(biāo)識(shí),已認(rèn)證通過用戶必填 由38位的字符串構(gòu)成,其中包括用戶出生日期和用戶編碼兩部分。用戶出生日期以26進(jìn)制(10個(gè)數(shù)字+英文字母表前16個(gè)字母)的方式編碼,位于用戶唯一標(biāo)識(shí)前6位;用戶編碼由網(wǎng)絡(luò)游戲防沉迷實(shí)名認(rèn)證系統(tǒng)生成,位于用戶唯一標(biāo)識(shí)的后32位。
# 例如:用戶唯一標(biāo)識(shí) 1hpfml09b57f3f8185f8cb5094ea3f26278efb 用戶生日部分是1hpfml 用戶編碼部分是09b57f3f8185f8cb5094ea3f26278efb
player_data = {'collections':[{"no":1,"si":"w7ligxjw355ftctm94yqt9dcew4zd723","bt":0,"ot":_time,"ct":0,"di":"uyiv6clpf7cu296pd4ppv11le820dhkw","pi":"1fffbjzos82bs9cnyj1dna7d6d29zg4esnh99u"}]}
##############
aes_gcm = aesobject.aes_encrypt(TEST_PARAMS)
body_data='{"data":"%s"}' % aes_gcm ## 國(guó)家游戲防沉迷的api試了不能進(jìn)行json.dumps()
## 加入請(qǐng)求頭報(bào)文
headers = {"Content-Type":"application/json; charset=utf-8","appId":APPID,"bizId":BIZID,"timestamps":_time}
## 對(duì)請(qǐng)求頭報(bào)文排序并排除 不必要的字段進(jìn)行字符串拼接
params_str = sorted_params(headers, none_keys=["Content-Type"])
headers["sign"] = hash256("".join([KEY, params_str, body_data]))
# print(aesobject.aes_decrypt(aes_gcm)) ## 解碼
response = requests.post(URL, headers=headers, data= body_data)
print(response.json())
if __name__ == '__main__':
main()
附錄: 響應(yīng)參數(shù)
字段 類型 名稱 字段說明
errcode Int 狀態(tài)碼 狀態(tài)碼
errmsg String 狀態(tài)描述 狀態(tài)描述
data Object 響應(yīng)對(duì)象 響應(yīng)結(jié)果
data.result Object 響應(yīng)結(jié)果對(duì)象 響應(yīng)結(jié)果內(nèi)容
data.result.status Int 實(shí)名認(rèn)證結(jié)果 認(rèn)證結(jié)果 0:認(rèn)證成功 1:認(rèn)證中 2:認(rèn)證失敗
data.result.pi String 用戶唯一標(biāo)識(shí) 已通過實(shí)名認(rèn)證用戶的唯一標(biāo)識(shí)
接口返回狀態(tài)碼
狀態(tài)碼 狀態(tài)描述 狀態(tài)說明
0 OK 請(qǐng)求成功
1001 SYS ERROR 系統(tǒng)錯(cuò)誤
1002 SYS REQ RESOURCE NOT EXIST 接口請(qǐng)求的資源不存在
1003 SYS REQ METHOD ERROR 接口請(qǐng)求方式錯(cuò)誤
1004 SYS REQ HEADER MISS ERROR 接口請(qǐng)求核心參數(shù)缺失
1005 SYS REQ IP ERROR 接口請(qǐng)求IP地址非法
1006 SYS REQ BUSY ERROR 接口請(qǐng)求超出流量限制
1007 SYS REQ EXPIRE ERROR 接口請(qǐng)求過期
1008 SYS REQ PARTNER ERROR 接口請(qǐng)求方身份非法
1009 SYS REQ PARTNER AUTH DISABLE 接口請(qǐng)求方權(quán)限未啟用
1010 SYS REQ AUTH ERROR 接口請(qǐng)求方無(wú)該接口權(quán)限
1011 SYS REQ PARTNER AUTH ERROR 接口請(qǐng)求方身份核驗(yàn)錯(cuò)誤
1012 SYS REQ PARAM CHECK ERROR 接口請(qǐng)求報(bào)文核驗(yàn)失敗
實(shí)名認(rèn)證業(yè)務(wù)異常
2001 BUS AUTH IDNUM ILLEGAL 身份證號(hào)格式校驗(yàn)失敗
2002 BUS AUTH RESOURCE LIMIT 實(shí)名認(rèn)證條目已達(dá)上限
2003 BUS AUTH CODE NO AUTH RECODE 無(wú)該編碼提交的實(shí)名認(rèn)證記錄
2004 BUS AUTH CODE ALREADY IN USE 編碼已經(jīng)被占用
游戲用戶行為數(shù)據(jù)上報(bào)業(yè)務(wù)異常
3001 BUS COLL PARTIAL ERROR 行為數(shù)據(jù)部分上報(bào)失敗
3002 BUS COLL BEHAVIOR NULL ERROR 行為數(shù)據(jù)為空
3003 BUS COLL OVER LIMIT COUNT 行為數(shù)據(jù)超出條目數(shù)量限制
3004 BUS COLL NO INVALID 行為數(shù)據(jù)編碼錯(cuò)誤
3005 BUS COLL BEHAVIOR TIME ERROR 行為發(fā)生時(shí)間錯(cuò)誤
3006 BUS COLL PLAYER MODE INVALID 用戶類型無(wú)效
3007 BUS COLL BEHAVIOR MODE INVALID 行為類型無(wú)效
3008 BUS COLL PLAYERID MISS 缺失PI(用戶唯一標(biāo)識(shí))值
3009 BUS COLL DEVICEID MISS 缺失DI(設(shè)備標(biāo)識(shí))值 3
010 BUS COLL PLAYERID INVALID PI (用戶唯一標(biāo)識(shí))值無(wú)效