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()
|