160 lines
5.1 KiB
Python
160 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
机构注册 + 信息填报 自动化脚本(仅调用线上对外开放接口,免鉴权)。
|
||
- 账号 = 机构中文全名;密码 = a123456;验证码手机号 = 18323128178
|
||
- #1 已注册,仅需补填报(用 syncUserToGBS 取 id)
|
||
- #2-#10 需:sendMessage(短信) -> 用户提供验证码 -> save(注册) -> org-info/save(填报) -> syncUserToGBS
|
||
|
||
用法:
|
||
python register_institutions.py 1 # #1 补填报(无需验证码)
|
||
python register_institutions.py 2 # #2 发短信(返回后等用户给码)
|
||
python register_institutions.py 2 123456 # #2 用验证码完成注册+填报
|
||
python register_institutions.py all <codes> # 暂未用
|
||
"""
|
||
import json
|
||
import os
|
||
import ssl
|
||
import sys
|
||
import glob
|
||
import urllib.parse
|
||
import urllib.request
|
||
|
||
BASE = "https://gbs-gateway.qhdsafety.com"
|
||
MD_DIR = r"E:/works/projects/safety-eval-service/docs2/institution_filling"
|
||
PHONE = "18323128178"
|
||
PASSWORD = "a123456"
|
||
|
||
NUMERIC_PLACEHOLDER = [
|
||
"fixedAssetsTotal", "workplaceArea", "archiveRoomArea",
|
||
"fulltimeEvaluatorCount", "registeredEngineerCount",
|
||
]
|
||
|
||
ctx = ssl.create_default_context()
|
||
ctx.check_hostname = False
|
||
ctx.verify_mode = ssl.CERT_NONE
|
||
|
||
|
||
def http(method, path, body=None):
|
||
url = BASE + path
|
||
data = json.dumps(body).encode("utf-8") if body is not None else None
|
||
req = urllib.request.Request(
|
||
url, data=data, method=method,
|
||
headers={"Content-Type": "application/json", "Accept": "application/json"},
|
||
)
|
||
with urllib.request.urlopen(req, timeout=30, context=ctx) as r:
|
||
return r.status, json.loads(r.read().decode("utf-8", "ignore"))
|
||
|
||
|
||
def load_institutions():
|
||
insts = []
|
||
for f in sorted(glob.glob(os.path.join(MD_DIR, "*.md"))):
|
||
if os.path.basename(f) == "README.md":
|
||
continue
|
||
text = open(f, encoding="utf-8").read()
|
||
idx = text.rfind("```json")
|
||
if idx < 0:
|
||
continue
|
||
start = idx + len("```json")
|
||
end = text.find("```", start)
|
||
j = json.loads(text[start:end].strip())
|
||
insts.append(j)
|
||
return insts
|
||
|
||
|
||
def prep_payload(j, register_user_id):
|
||
p = dict(j)
|
||
p["registerUserId"] = register_user_id
|
||
for k in NUMERIC_PLACEHOLDER:
|
||
if p.get(k) is None:
|
||
p[k] = 1
|
||
p.setdefault("authStatusCode", 1)
|
||
p.setdefault("authStatusName", "已提交")
|
||
# 业务范围编码规范化:兼容字符串/列表
|
||
sic = p.get("safetyIndustryCategoryCode")
|
||
if isinstance(sic, str):
|
||
p["safetyIndustryCategoryCode"] = [x for x in sic.split(",") if x]
|
||
return p
|
||
|
||
|
||
def get_id_by_sync(account):
|
||
status, resp = http(
|
||
"GET",
|
||
"/safetyEval/images/account/syncUserToGBS?account="
|
||
+ urllib.parse.quote(account),
|
||
)
|
||
print(" syncUserToGBS ->", status, resp.get("success"), resp.get("message"))
|
||
if resp.get("success") and resp.get("data"):
|
||
return resp["data"].get("id")
|
||
raise Exception("syncUserToGBS failed: " + str(resp))
|
||
|
||
|
||
def send_message(mobile):
|
||
status, resp = http(
|
||
"POST", "/safetyEval/images/account/sendMessage", {"mobile": mobile}
|
||
)
|
||
print(" sendMessage ->", status, resp.get("success"), resp.get("message"))
|
||
return resp
|
||
|
||
|
||
def save_account(account, mobile, password, code):
|
||
status, resp = http(
|
||
"POST", "/safetyEval/images/account/save",
|
||
{"account": account, "phone": mobile, "password": password,
|
||
"verificationCode": code, "type": 1},
|
||
)
|
||
print(" account/save ->", status, resp.get("success"), resp.get("message"))
|
||
if resp.get("success") and resp.get("data"):
|
||
return resp["data"].get("id")
|
||
raise Exception("save failed: " + str(resp))
|
||
|
||
|
||
def save_org_info(payload):
|
||
status, resp = http("POST", "/safetyEval/images/org-info/save", payload)
|
||
print(" org-info/save ->", status, resp.get("success"), resp.get("message"))
|
||
return resp
|
||
|
||
|
||
def do_fill_only(idx, inst):
|
||
"""已注册机构:取 id -> 填报"""
|
||
account = inst["unitName"]
|
||
print(f"[{idx}] 补填报(已注册): {account}")
|
||
rid = get_id_by_sync(account)
|
||
print(" registerUserId =", rid)
|
||
payload = prep_payload(inst, rid)
|
||
save_org_info(payload)
|
||
print(f"[{idx}] 填报完成\n")
|
||
|
||
|
||
def do_register(idx, inst, code=None):
|
||
account = inst["unitName"]
|
||
print(f"[{idx}] 注册: {account}")
|
||
if not code:
|
||
send_message(PHONE)
|
||
print(f"[{idx}] 已发送验证码到 {PHONE},请提供验证码后重试: "
|
||
f"python register_institutions.py {idx} <code>\n")
|
||
return
|
||
rid = save_account(account, PHONE, PASSWORD, code)
|
||
print(" registerUserId =", rid)
|
||
payload = prep_payload(inst, rid)
|
||
save_org_info(payload)
|
||
get_id_by_sync(account) # 同步 GBS
|
||
print(f"[{idx}] 注册+填报完成\n")
|
||
|
||
|
||
def main():
|
||
if len(sys.argv) < 2:
|
||
print(__doc__)
|
||
return
|
||
insts = load_institutions()
|
||
arg = sys.argv[1]
|
||
if arg == "1":
|
||
do_fill_only(1, insts[0])
|
||
return
|
||
idx = int(arg)
|
||
code = sys.argv[2] if len(sys.argv) > 2 else None
|
||
do_register(idx, insts[idx - 1], code)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|