给大家一个能用的免费大厂图床接口

lixing23 2026-07-21 21:37 1

一个微信接口,拿去用吧,最大支持10M大小




演示图片 https://chatbotcos.weixin.qq.com/chatbot/unlimited-openaiassets_1794c938ff3ffd23f1fb3f9d36603e0b_5679931784639978482.jpg




开源地址 https://github.com/lixing23/wechat-chatbot-image-api







import hashlib
import hmac
import json
import mimetypes
import os
import time
import uuid
import requests

APP_ID = "V4poszKZgOynfZUpQvoMWtJcprqIOK"
APP_KEY = "openchatai!2o19"
SECRET = "d637ab9fb119a1e652ab3d3dec89f7e744e4d5a0e0f"

PAGE_URL = f"https://chatbot.weixin.qq.com/webapp/{APP_ID}?robotName=17173%E5%B0%8F%E5%A6%96"
TOKEN_URL = f"https://chatbot.weixin.qq.com/weixinh5/webapp/gettoken/{APP_ID}"
UPLOAD_URL = f"https://chatbot.weixin.qq.com/weixinh5/webapp/{APP_ID}/cos/upload?permanent=false"

ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif"}
MAX_SIZE = 10 * 1024 * 1024

def normalize_data(value):
if isinstance(value, dict):
return {key: normalize_data(value[key]) for key in sorted(value)}
if isinstance(value, list):
return [normalize_data(item) for item in value]
return value

def make_sign(timestamp, nonce, data=None):
if data is None:
data = {}

data_json = json.dumps(
normalize_data(data),
ensure_ascii=False,
separators=(",", ":")
)

parts = [
f"appKey={APP_KEY}",
f"timestamp={timestamp}",
f"nonce={nonce}",
f"data={data_json}",
]

sign_text = "".join(sorted(parts)).replace("=", "")

return hmac.new(
SECRET.encode("utf-8"),
sign_text.encode("utf-8"),
hashlib.sha256
).hexdigest()

def build_signed_headers(extra_headers=None, data=None):
timestamp = int(time.time())
nonce = uuid.uuid4().hex[:16]
sign = make_sign(timestamp, nonce, data or {})

headers = {
"Accept": "application/json, text/plain, */*",
"Origin": "https://chatbot.weixin.qq.com",
"Referer": PAGE_URL,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
"timestamp": str(timestamp),
"nonce": nonce,
"sign": sign,
}

if extra_headers:
headers.update(extra_headers)

return headers

def get_token():
headers = build_signed_headers()

resp = requests.get(TOKEN_URL, headers=headers, timeout=30)
resp.raise_for_status()

data = resp.json()

token = data.get("token") or data.get("data", {}).get("token")

if not token:
raise RuntimeError(f"获取 token 失败: {data}")

return token

def validate_image(file_path):
ext = os.path.splitext(file_path)[1].lower()

if ext not in ALLOWED_EXTENSIONS:
raise RuntimeError(f"不支持的图片格式: {ext}")

size = os.path.getsize(file_path)

if size >= MAX_SIZE:
raise RuntimeError("图片必须小于 10MB")

def upload_image(file_path):
validate_image(file_path)

token = get_token()

mime_type = mimetypes.guess_type(file_path)[0] or "application/octet-stream"

headers = build_signed_headers({
"x-client-token": token,
"request_id": str(uuid.uuid4()),
})

filename = os.path.basename(file_path)

with open(file_path, "rb") as f:
files = {
"media": (filename, f, mime_type)
}

resp = requests.post(
UPLOAD_URL,
headers=headers,
files=files,
timeout=120
)

resp.raise_for_status()

data = resp.json()

if data.get("code") != 0 or not data.get("url"):
raise RuntimeError(f"上传失败: {data}")

return data["url"], data

def check_public_image_url(url):
resp = requests.get(
url,
headers={
"User-Agent": "Mozilla/5.0",
"Referer": "https://chatbot.weixin.qq.com/",
},
timeout=30
)

content_type = resp.headers.get("Content-Type", "")

if resp.status_code == 200 and content_type.startswith("image/"):
return True

return False

if __name__ == "__main__":
url, raw = upload_image("test.png")

print("返回 URL:", url)
print("原始响应:", raw)

if check_public_image_url(url):
print("直链可访问")
else:
print("上传成功,但直链不可公开访问")
最新回复 (6)
  • timi1024 07-21 21:38
    1

    APP_ID = "V4poszKZgOynfZUpQvoMWtJcprqIOK"

    APP_KEY = "openchatai!2o19"

    SECRET = "d637ab9fb119a1e652ab3d3dec89f7e744e4d5a0e0f" 这个哪来的啊

  • lixing23 楼主 07-21 21:38
    2

    @timi1024 #1 抓的

  • 553399 07-21 21:48
    3

    @lixing23 #2 有时效性吗

  • lixing23 楼主 07-21 21:49
    4

    @553399 #3 图片格式结尾的都没有时效性

  • bacon159 07-21 22:33
    5

    牛逼啊

  • ycj 07-21 22:52
    6

    bd

* 帖子来源NodeSeek
返回