事倍功半是蠢蛋 31 微信公众号上传草稿 40007

接口文档:
https://developers.weixin.qq.com/doc/subscription/api/draftbox/draftmanage/api_draft_add.html
官方文档有错误?是我理解错了吗 图文消息必填为‘否’ 但是事实上他的必填为‘是’ 否则就会报40007缺乏media_id的错误
如果图片消息跟图文消息都必须要资源的话,那他不应该是必填吗
错误:
demo:
cursor生成的demo代码 亲测可以使用。
import requests
import os
import json
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 配置信息把这改了 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
APP_ID = ""
APP_SECRET = ""
IMAGE_PATH = "cover.png" # 本地图片路径
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
def get_access_token(app_id: str, app_secret: str) -> str:
"""获取access_token"""
token_url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={app_id}&secret={app_secret}"
try:
token_res = requests.get(token_url).json()
access_token = token_res.get("access_token")
if not access_token:
logger.error(f"获取access_token失败: {token_res}")
raise Exception(f"获取access_token失败: {token_res.get('errmsg', '未知错误')}")
logger.info(f"获取access_token成功: {access_token[:20]}...")
return access_token
except requests.RequestException as e:
logger.error(f"网络请求失败: {str(e)}")
raise
except json.JSONDecodeError as e:
logger.error(f"JSON解析失败: {str(e)}")
raise
except Exception as e:
logger.error(f"获取access_token异常: {str(e)}")
raise
def upload_image(access_token: str, image_path: str) -> str:
"""使用永久素材接口上传图片并返回media_id"""
upload_url = f"https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={access_token}&type=image"
try:
with open(image_path, 'rb') as file:
files = {'media': file}
response = requests.post(upload_url, files=files)
result = response.json()
# 检查返回结果
if 'errcode' in result and result['errcode'] != 0:
logger.error(f"上传永久图片失败: {result}")
raise Exception(f"上传永久图片失败: {result.get('errmsg', '未知错误')}")
media_id = result.get('media_id')
if not media_id:
logger.error(f"获取media_id失败: {result}")
raise Exception("上传成功但未返回有效的media_id")
logger.info(f"永久图片上传成功! media_id: {media_id}")
# 如果是图片类型,返回的url也可以记录(可选)
if 'url' in result:
logger.info(f"图片URL: {result['url']}")
return media_id
except FileNotFoundError:
logger.error(f"图片文件不存在: {image_path}")
raise
except requests.RequestException as e:
logger.error(f"永久图片上传网络请求失败: {str(e)}")
raise
except json.JSONDecodeError as e:
logger.error(f"永久图片上传响应解析失败: {str(e)}")
raise
except Exception as e:
logger.error(f"永久图片上传异常: {str(e)}")
raise
def create_draft(access_token: str, draft_data: dict) -> str:
"""创建草稿并返回media_id"""
draft_url = f"https://api.weixin.qq.com/cgi-bin/draft/add?access_token={access_token}"
headers = {"Content-Type": "application/json"}
try:
draft_res = requests.post(draft_url, headers=headers, data=json.dumps(draft_data, ensure_ascii=False)).json()
media_id = draft_res.get("media_id")
if not media_id:
logger.error(f"草稿创建失败: {draft_res}")
raise Exception(f"草稿创建失败: {draft_res.get('errmsg', '未知错误')}")
logger.info(f"草稿创建成功! media_id: {media_id}")
return media_id
except requests.RequestException as e:
logger.error(f"创建草稿时网络请求失败: {str(e)}")
raise
except json.JSONDecodeError as e:
logger.error(f"解析创建响应失败: {str(e)}")
raise
except Exception as e:
logger.error(f"创建草稿异常: {str(e)}")
raise
def main():
"""主函数"""
try:
# 1. 获取access_token
access_token = get_access_token(APP_ID, APP_SECRET)
# 2. 上传封面图片
thumb_media_id = upload_image(access_token, IMAGE_PATH)
# 3. 准备草稿数据(包含有效的thumb_media_id)
draft_data = {
"articles": [
{
"title": "测试文章标题123",
"author": "作者名称321",
"digest": "这里是文章摘要1234567",
"content": "<p>文章正文内容999</p>",
"thumb_media_id": thumb_media_id, # 使用上传获取的有效ID
"content_source_url": "https://example.com", # 原文链接
"need_open_comment": 1, # 开启评论
"only_fans_can_comment": 0 # 所有人可评论
}
]
}
# 4. 创建草稿
draft_media_id = create_draft(access_token, draft_data)
print(f"🎉 操作成功!草稿ID: {draft_media_id}")
except Exception as e:
logger.exception("操作失败")
print(f"❌ 操作失败: {str(e)}")
if __name__ == "__main__":
main()

浙公网安备 33010602011771号