realname_996.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # -*- coding: utf-8 -*-
  2. """
  3. realname_996.py —— 996盒子账号实名认证(防沉迷实名)
  4. ====================================================
  5. 官方实名通道(逆向自 newpc.996db.com 前端 webpack chunk 35/36/37/40/46/80,
  6. 与盒子内置实名表单完全一致):
  7. POST https://user-api.996hezi.com/v1/Identify/index
  8. headers: token(JWT) + X-BOX-AUTHORIZATION(BOXAPP-SHA256 签名)
  9. body: {"real_name": "<真实姓名>", "idcard": "<18位身份证号>"}
  10. 服务端做公安系统实名校验(姓名与身份证号必须真实匹配)。
  11. 认证成功后 auth_status 0→2,进游戏不再被 81111 拦截。
  12. 用法:
  13. .venv-mac/bin/python realname_996.py -u cqlongwu1988001 -p Longwu1988001 \
  14. --name "张三" --idcard "110101199001011237"
  15. # 只查状态不提交:
  16. .venv-mac/bin/python realname_996.py -u <账号> -p <密码> --check
  17. """
  18. import argparse
  19. import json
  20. import random
  21. import string
  22. import sys
  23. import time
  24. import requests as rq
  25. import urllib3
  26. urllib3.disable_warnings()
  27. HERE = __import__("os").path.dirname(__import__("os").path.abspath(__file__))
  28. sys.path.insert(0, HERE)
  29. sys.path.insert(0, __import__("os").path.join(HERE, "已经开发的部分代码", "chuanqi-main", "code", "GeekedTest"))
  30. from login_996pc import do_login, box_auth, box_headers # noqa: E402
  31. USER_API = "https://user-api.996hezi.com"
  32. IDENTIFY_PATH = "/v1/Identify/index"
  33. USERINFO_PATH = "/v1/UserInfo/getByRefresh"
  34. def call(session, token, method, path, body_obj=None):
  35. body = json.dumps(body_obj, separators=(",", ":")) if body_obj is not None else ""
  36. h = box_headers(token)
  37. if body_obj is not None:
  38. h["Content-Type"] = "application/json;charset=UTF-8"
  39. h["X-BOX-AUTHORIZATION"] = box_auth(method, path, body, token)
  40. r = session.request(method, USER_API + path,
  41. data=body.encode() if body else None,
  42. headers=h, timeout=25, verify=False)
  43. try:
  44. return r.json()
  45. except Exception:
  46. return {"code": r.status_code, "msg": r.text[:150]}
  47. def get_auth_status(session, token):
  48. j = call(session, token, "POST", USERINFO_PATH, {})
  49. info = ((j.get("data") or {}).get("userinfo")) or {}
  50. return info.get("auth_status"), info.get("real_name"), info.get("idcard")
  51. def validate_idcard(idcard: str) -> str | None:
  52. """18位身份证校验码验证(GB 11643-1999),提交前本地拦截格式错误。"""
  53. if len(idcard) != 18:
  54. return "身份证号必须是18位"
  55. weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  56. codes = "10X98765432"
  57. try:
  58. total = sum(int(idcard[i]) * weights[i] for i in range(17))
  59. except ValueError:
  60. return "身份证前17位必须为数字"
  61. if idcard[17].upper() != codes[total % 11]:
  62. return "身份证校验码不符合GB11643规则(请核对号码)"
  63. return None
  64. def main():
  65. ap = argparse.ArgumentParser(description="996盒子账号实名认证")
  66. ap.add_argument("-u", "--user", required=True, help="996盒子账号")
  67. ap.add_argument("-p", "--password", required=True, help="密码")
  68. ap.add_argument("--name", help="真实姓名(身份证上的姓名)")
  69. ap.add_argument("--idcard", help="18位身份证号")
  70. ap.add_argument("--check", action="store_true", help="只查询实名状态,不提交")
  71. args = ap.parse_args()
  72. s = rq.Session()
  73. print(f"[*] 登录账号: {args.user}")
  74. j, _ = do_login(s, args.user, args.password)
  75. if j.get("code") != 200 or not (j.get("data") or {}).get("token"):
  76. raise SystemExit(f"[!] 登录失败: code={j.get('code')} msg={j.get('msg')}")
  77. token = j["data"]["token"]
  78. info = j["data"].get("userInfo") or {}
  79. print(f"[✓] 登录成功 uid={info.get('id')} 昵称={info.get('nick_name')}")
  80. status, real_name, idcard = get_auth_status(s, token)
  81. print(f"[*] 当前实名状态: auth_status={status}"
  82. f"({'未实名' if status == 0 else '已实名' if status == 2 else status})"
  83. f"{' real_name=' + real_name if real_name else ''}")
  84. if args.check:
  85. return
  86. if status == 2:
  87. print("[✓] 该账号已实名,无需重复认证")
  88. return
  89. if not args.name or not args.idcard:
  90. raise SystemExit("[!] 需要 --name <真实姓名> --idcard <18位身份证号>")
  91. err = validate_idcard(args.idcard)
  92. if err:
  93. raise SystemExit(f"[!] {err}")
  94. print(f"[*] 提交实名: {args.name} / {args.idcard[:6]}********{args.idcard[-4:]}")
  95. r = call(s, token, "POST", IDENTIFY_PATH,
  96. {"real_name": args.name, "idcard": args.idcard})
  97. code = r.get("code")
  98. if code == 200:
  99. print("[✓] 实名认证提交成功!")
  100. else:
  101. raise SystemExit(f"[!] 实名失败: code={code} msg={r.get('msg')}")
  102. # 回查确认
  103. time.sleep(1)
  104. status, real_name, _ = get_auth_status(s, token)
  105. print(f"[*] 复核: auth_status={status} real_name={real_name}")
  106. if status == 2:
  107. print("[✓] 认证生效,进游戏 81111 拦截已解除")
  108. if __name__ == "__main__":
  109. main()