如题痛点
在开发工作流的时候,经常会遇到这样的问题
- 没有合适的插件解决当前的场景
- 有合适的插件,但人家收费
- 有合适的插件,但人家要你密码
这时候我们就要自己搞一个插件了。大部分同学遇到这个情况就怕了
本文就解决这个问题,有 AI 工具,不用懂代码,也可以开发自己的插件,以微信公众号信息同步为例,我们来实现一个将文档同步到微信公众号的插件。
需求梳理
如果有现成的插件(但人家要你本金的情况)那就很容易梳理需求了,如果没有就基于你想要的效果来。再去问AI,有没有实现你当前这个诉求的开源包,然后基于开源包来封装插件。

比如这个工具,他提供了 5 个能力wx_access_token配置 app_id/app_secret来获取token ,简单说,就是让微信知道你登录了,这也是把这个交给三方不安全的地方,他可以用这个去操作你的用户,当然我相信上边这个作者应该是不会这么做的(逃。wx_upload_media上传素材输入上一步获取到的token,和你要上传的图片,这个图片应该是网图的链接(注意版权)或者你的上传插件获取到的图片链接(你要没有,我再出一个自建上传插件的文章,挖坑啊~~哇呀~哇呀~哇)

wx_markdown_to_html将生成的文本带格式转成微信公众号认识的样子,给到后边发布用

wx_upload_draft上传草稿,这个参数比较多(加星的就是一定要传入的),逐个解析一下
- access_token: 第一步获取到的 token
- title,文章标题,对应 AI 生成的有吸引力的标题
- digest 摘要、副标题,对应的是 AI 生成的 SEO 优化关键词
- author,这个就是文章作者,但这个微信是否认还是要打个问号的
- Content 就是 wx_markdown_to_html 生成的 HTML,引入一下即可
- content_source_url, 文章源链,原创不需要
- need_open_comment,如图所述,我们搞个默认值,别必填了,1
- only_fans_can_comment,如图所述,默认 0
- thumb_media_id: 封面的 media_id,这个 media_id哪儿来的,应该就是wx_uplaod_media返回的,这里不设置,去人肉设置也没啥问题
wx_publish_draft发布草稿,这个风险比较高,我们就不用了,还是去线上人肉发,你要是想搞,自己去搞一个就好了。
开始上手
哦了,经过上边一番分析,把这个需求丢给 AI (如果你有 Cursor/Trae 返工率会低一点,豆包或者 deepseek 这种通用模型也凑合用),让他给你写插件代码,环境要按照 Coze 能够支持的模式来写。

1.获取 Token进来以后是空的,先创建一个工具wx_access_token

创建好了以后,切换到 “元数据” 这部分

将我们上边分析的输入和输出创建进去,点击编辑、输入,保存即可。这里的参数名就是未来代码里面读取的字段,要符合创建规范。(这里涉及到一丢丢代码知识…

切回代码,把 AI 提供给你的脚本贴在代码中,我这个是豆包给我的
Python def handler(args: Args[Input]): “”” 获取微信公众号的access_token
参数: app_id: 微信公众号的appid app_secret: 微信公众号的appsecret
返回: dict: 包含access_token和过期时间的字典 成功时格式: {“access_token”: “xxx”, “expires_in”: 7200} 失败时格式: {“error”: “错误信息”, “errcode”: 错误码, “errmsg”: “错误描述”} “”” # 微信获取access_token的API地址 url = “https://api.weixin.qq.com/cgi-bin/token”
# 请求参数 params = { “grant_type”: “client_credential”,# 固定值 “appid”: args.input.app_id, “secret”: args.input.app_secret }
try: # 发送GET请求 response = requests.get(url, params=params, timeout=10) response.raise_for_status()# 抛出HTTP请求异常
# 解析响应结果 result = response.json()
# 检查是否包含错误信息 if “errcode” in result and result[“errcode”] != 0: return { “access_token”: “”, “message”: result[“errmsg”] }
# 成功返回结果 return { “access_token”: result[“access_token”], “message”: result[“expires_in”] }
except requests.exceptions.RequestException as e: # 处理网络请求异常 return { “access_token”:””, “message”: f”网络请求异常: {str(e)}” } except json.JSONDecodeError: # 处理JSON解析异常 return { “access_token”:””, “message”: “无法解析API返回的JSON数据” } except Exception as e: # 处理其他未知异常 return { “access_token”:””, “message”: “未知错误” } |
其中需要的 app_id和 app_secret应该在微信公众号后台获取
跑一下测试(这里可能会遇到各种报错,直接丢给 AI,让他帮你解决
填入刚才获取到的 IP
测试通过了以后,就可以把这个功能发布掉了
这里有个坑,Coze 的在线 IDE 是没有固定 IP 的,我是用的本地部署的 Coze,如果是在线使用,就需要一个跳板机,然后把跳板机 IP 配置给微信公众号后端就好了。(如果你不知道如何搭建一个跳板机,我再出一个自建跳板机的文章,挖坑啊~~哇呀~哇呀~哇) |

2.上传素材我们跳过重复的动作,回到刚才你创建的插件,在右上角 继续“创建工具”,如果你没有退出在线 IDE,直接左上角点下小加号,就可以继续新建工具了。
这个过程中难免涉及到一些代码的调试手段,这部分也是有点挑战性的,我先把我的代码给到你
Python from runtime import Args from typings.wx_upload_media.wx_upload_media import Input, Output import requests import io
def handler(args: Args[Input])->Output: “”” 从网络URL下载图片并上传至微信公众号素材库,返回media_id
参数: access_token: 微信公众号的访问令牌 image_url: 网络图片的URL地址(需可直接访问,支持http/https)
返回: dict: 包含上传结果的字典 成功时格式: {“media_id”: “素材ID”, “message”: “上传成功”, “url”: “图片URL”} 失败时格式: {“media_id”: “”, “message”: “错误信息”, “errcode”: “错误码”, “errmsg”: “错误描述”} “”” # 微信上传图片素材的API地址 upload_url = f”https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={args.input.access_token}”
try: # 步骤1: 从image_url下载图片内容 response = requests.get(args.input.image_url, timeout=15) response.raise_for_status()# 抛出HTTP错误
# 检查响应内容是否为图片(简单验证Content-Type) content_type = response.headers.get(“Content-Type”, “”) if not content_type.startswith((“image/jpeg”, “image/png”, “image/gif”)): return { “media_id”: “”, “message”: f”URL指向的内容不是有效图片,Content-Type: {content_type}”, }
# 步骤2: 构造multipart/form-data请求上传至微信 # 将图片内容转为文件流 image_file = io.BytesIO(response.content) files = {“media”: (“image.jpg”, image_file, content_type)}
# 发送上传请求 upload_response = requests.post(upload_url, files=files, timeout=20) upload_result = upload_response.json()
# 步骤3: 处理上传结果 if “errcode” in upload_result and upload_result[“errcode”] != 0: return { “media_id”: “”, “message”: f”上传失败:{upload_result[‘errmsg’]}”, }
# 成功返回结果(微信API返回的url为图片永久链接) return { “media_id”: upload_result[“media_id”], “message”: “图片上传成功”, }
except requests.exceptions.RequestException as e: # 处理网络请求异常(下载图片或上传过程失败) return { “media_id”: “”, “message”: f”网络请求失败:{str(e)}”, } except Exception as e: # 处理其他未知异常 return { “media_id”: “”, “message”: f”处理失败:{str(e)}”, } |
其实这段代码实现的功能就是微信公众号提供的 API 能力,也没多啥,你可以直接去微信公众号后台拿到这样的一些 API 调用示例,然后把这个调用示例给 AI,让他按照这个接口的样式来写
这里有个坑是默认只支持 jpeg 而不支持 png,我就不知道为啥了。 |
3.上传草稿跟上边一样,直接上代码
Python from runtime import Args from typings.wx_upload_draft.wx_upload_draft import Input, Output import requests import json
“”” Each file needs to export a function named `handler`. This function is the entrance to the Tool.
Parameters: args: parameters of the entry function. args.input – input parameters, you can get test input value by args.input.xxx. args.logger – logger instance used to print logs, injected by runtime.
Remember to fill in input/output in Metadata, it helps LLM to recognize and use tool.
Return: The return data of the function, which should match the declared output parameters. “”” def handler(args: Args[Input])->Output: “”” 上传文章草稿到微信公众号(符合Coze函数签名规范)
参数: args: 包含输入参数的Args对象,内部input属性为DraftInput类型 返回: DraftOutput: 包含草稿ID或错误信息的输出对象 “””
# 微信官方接口地址 url = f”https://api.weixin.qq.com/cgi-bin/draft/add?access_token={args.input.access_token}”
# 构造请求体(严格匹配官方格式) draft_data = { “articles”: [ { “title”: args.input.title, “content”: args.input.content, “digest”: args.input.digest, “author”: args.input.author, “content_source_url”: args.input.content_source_url, “thumb_media_id”: args.input.thumb_media_id, “need_open_comment”: args.input.need_open_comment, “only_fans_can_comment”: args.input.only_fans_can_comment } ] }
try: # 发送POST请求(确保UTF-8编码) response = requests.post( url, data=json.dumps(draft_data, ensure_ascii=False).encode(“utf-8”), headers={“Content-Type”: “application/json”}, timeout=30 ) response.raise_for_status()# 抛出HTTP错误
result = response.json()
# 官方错误码映射(参考文档) error_map = { 40001: “access_token无效或过期”, 40003: “thumb_media_id无效(非永久素材)”, 45009: “文章内容过长(≤20000字)”, 47001: “content不是合法HTML(含不支持标签)” }
# 处理响应结果 if result.get(“errcode”) == 0: return { “media_id”: result[“media_id”], “message”: “草稿上传成功”, } else: err_code = result[“errcode”] return { “media_id”: “”, “message”: error_map.get(err_code, f”上传失败:{result[‘errmsg’]}”), }
except requests.exceptions.RequestException as e: return { “media_id”: “”, “message”: f”网络请求失败:{str(e)}”, } except json.JSONDecodeError: return { “media_id”: “”, “message”: “接口返回格式错误”, } except Exception as e: return { “media_id”: “”, “message”: f”处理失败:{str(e)}”, } |

这样我们核心的几个插件工具都搞定了。去工作流里面调用试一下。
总结一下
遇到写代码不要慌,AI 会帮你写的,你要学会的就是给 AI 提要求
做插件就是做基础功能,当你的基础功能足够丰富以后,你就可以搭建出任何工作流,进而可以实现任何想法最后以我 Java 老师的格言结尾,希望大厨老师身体康健,事事顺遂。
000-Coze入门