import requests import sys import os import subprocess def get_api_key(key_name): """从api-key-vault读取Key""" vault_path = os.path.join( os.path.dirname(__file__), "..", "..", # 从scripts/退到logistics-tracker/再退到OpenClaw/ "api-key-vault", "scripts", "vault.py" ) vault_path = os.path.normpath(vault_path) result = subprocess.run( ["python", vault_path, "get", key_name], capture_output=True, text=True ) key = result.stdout.strip() if not key or key == "ERROR:KEY_NOT_FOUND": return None return key def check_entitlement(skill_slug): auth_base = (os.getenv("JIANGCHANG_AUTH_BASE_URL") or "").strip().rstrip("/") if not auth_base: return True, "" user_id = (os.getenv("JIANGCHANG_USER_ID") or "").strip() if not user_id: return False, "鉴权失败:缺少用户身份(JIANGCHANG_USER_ID)" auth_api_key = (os.getenv("JIANGCHANG_AUTH_API_KEY") or "").strip() timeout = int((os.getenv("JIANGCHANG_AUTH_TIMEOUT_SECONDS") or "5").strip()) headers = {"Content-Type": "application/json"} if auth_api_key: headers["Authorization"] = f"Bearer {auth_api_key}" payload = { "user_id": user_id, "skill_slug": skill_slug, "trace_id": (os.getenv("JIANGCHANG_TRACE_ID") or "").strip(), "context": {"entry": "main.py"}, } try: res = requests.post( f"{auth_base}/api/entitlements/check", json=payload, headers=headers, timeout=timeout, ) except requests.RequestException as exc: return False, f"鉴权请求失败:{exc}" if res.status_code != 200: return False, f"鉴权服务异常:HTTP {res.status_code}" try: body = res.json() except ValueError: return False, "鉴权服务异常:返回非 JSON" code = body.get("code") data = body.get("data") or {} if code != 200: return False, str(body.get("msg") or "鉴权失败") if not data.get("allow", False): return False, str(data.get("reason") or "未购买或已过期") return True, "" def query_tracking(tracking_number): api_key = get_api_key("17track") if not api_key: return "错误:未找到17track的API Key,请先运行:\npython api-key-vault/scripts/vault.py set 17track 你的Key" url = "https://api.17track.net/track/v2.2/gettrackinfo" headers = { "Content-Type": "application/json", "17token": api_key } body = { "data": [{"number": tracking_number}] } try: response = requests.post(url, json=body, headers=headers, timeout=10) result = response.json() accepted = result.get("data", {}).get("accepted", []) if not accepted: return f"抱歉,单号 {tracking_number} 查询不到信息,可能还未入网,请稍后再试。" track_info = accepted[0].get("track", {}) providers = track_info.get("tracking", {}).get("providers", []) if not providers or not providers[0].get("events"): return f"📦 单号:{tracking_number}\n该单号已入网,暂无轨迹更新,请稍后再查。" events = providers[0]["events"] latest = events[0] recent_lines = [] for e in events[:3]: time = e.get("time_iso", "") location = e.get("location", "") or "未知" desc = e.get("description", "") recent_lines.append(f" · {time} {location} {desc}") recent_text = "\n".join(recent_lines) return ( f"📦 单号:{tracking_number}\n" f"📍 最新状态:{latest.get('description', '未知')}\n" f"🕐 更新时间:{latest.get('time_iso', '未知')}\n" f"🗺 最新位置:{latest.get('location', '未知')}\n\n" f"最近轨迹:\n{recent_text}" ) except requests.exceptions.Timeout: return "查询超时,请稍后重试。" except Exception as e: return f"查询失败:{str(e)}" def main(argv=None) -> int: args = argv if argv is not None else sys.argv[1:] if len(args) < 1: print("用法:python main.py <单号>") return 1 ok, reason = check_entitlement("logistics-tracker") if not ok: print(f"❌ {reason}") return 1 print(query_tracking(args[0])) return 0 if __name__ == "__main__": raise SystemExit(main())