前言
本篇文章参考国内服务器 3 分钟将 ChatGPT 接入微信公众号(超详细)配置,纠正了一些过时的信息。
准备
一个微信公众号
一个能访问外网的梯子
一个ChatGPT账号
有了这些就可以配置了
注册免费服务器,并部署代码
前往Laf https://laf.run/ 注册一个账号,手机号注册即可。注意,别进到国外的了
点击新建项目
名称随便什么都可以,根据自己的喜好
创建好过后是这个样子,我们点击开发进入编程页面
进入后添加npm依赖
搜索chatgpt,添加第一个,保存并重启
然后新建一个函数
函数名字也随便取一个
然后将下列代码粘进去
// 引入crypto和cloud模块
import * as crypto from 'crypto';
import cloud from '@lafjs/cloud';
const OPENAI_ACCESS_TOKEN = "这个token我们稍后讲,怎么拿"
const WAIT_MESSAGE = `处理中 ... \n\n请稍等3秒后发送【1】查看回复`
const NO_MESSAGE = `暂无内容,请稍后回复【1】再试`
const CLEAR_MESSAGE = `✅ 记忆已清除`
const HELP_MESSAGE = `ChatGPT 指令使用指南
| 关键字 | 功能 |
| 1 | 上一次问题的回复 |
| 11 | 清除上下文 |
| 111 | 获取更多帮助 |
`
// 不支持的消息类型
const UNSUPPORTED_MESSAGE_TYPES = {
image: '暂不支持图片消息',
voice: '暂不支持语音消息',
video: '暂不支持视频消息',
music: '暂不支持音乐消息',
news: '暂不支持图文消息',
}
// 定义休眠函数
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
// 创建数据库连接并获取Message集合
const db = cloud.database();
const Message = db.collection('messages')
// 处理接收到的微信公众号消息
export async function main(event) {
const { signature, timestamp, nonce, echostr } = event.query;
const token = '123456';
// 验证消息是否合法,若不合法则返回错误信息
if (!verifySignature(signature, timestamp, nonce, token)) {
return 'Invalid signature';
}
// 如果是首次验证,则返回 echostr 给微信服务器
if (echostr) {
return echostr;
}
// 处理文本回复消息
async function replyText(message) {
const { question, sessionId } = message;
console.log("replyText 执行了")
// 检查是否是重试操作,如果是重试操作,返回上一次的回复
if (question === '1') {
const lastMessage = await Message.where({
sessionId
}).orderBy("createdAt", "desc").get();
if (lastMessage.data[0]) {
return `${lastMessage.data[0].question}\n------------\n${lastMessage.data[0].answer}`;
}
return NO_MESSAGE;
}
// 获取上下文 id
const res = await Message.where({
sessionId
}).orderBy("createdAt", "desc").getOne();
const parentId = res?.data?.parentMessageId
const conId = res?.data?.conversationId
// 发送指令
if (question.startsWith('11')) {
return await processCommandText(message);
}
// 获取 OpenAI 回复内容
const { error, answer, parentMessageId, conversationId } = await getOpenAIReply(question, parentId, conId);
if (error) {
console.error(`sessionId: ${sessionId}; question: ${question}; error: ${error}`);
return error;
}
// 将消息保存到数据库中
const token = question.length + answer.length;
const result = await Message.add({ token, answer, parentMessageId, conversationId, ...message });
console.debug(`[save message] result: ${result}`);
return answer;
}
// 获取 OpenAI API 的回复
async function getOpenAIReply(question, parentId, conId) {
console.log("getOpenAIReply 执行了")
// 引入 ChatGPTUnofficialProxyAPI 模块
const { ChatGPTUnofficialProxyAPI } = await import('chatgpt')
// 创建 ChatGPTUnofficialProxyAPI 实例
const api = new ChatGPTUnofficialProxyAPI({
accessToken: OPENAI_ACCESS_TOKEN,
apiReverseProxyUrl: "https://ai.fakeopen.com/api/conversation"
})
try {
// 如果有上下文 id,就带上
let res;
if (parentId && conId) {
res = await api.sendMessage(question, { conversationId: conId, parentMessageId: parentId })
} else {
res = await api.sendMessage(question)
}
// 返回 OpenAI 回复的内容及上下文 id
return { answer: res.text.replace("\n\n", ""), parentMessageId: res.parentMessageId, conversationId: res.conversationId }
} catch (e) {
console.log(e)
return {
error: "问题太难了 出错了. (uДu〃).",
}
}
}
// 校验微信服务器发送的消息是否合法
function verifySignature(signature, timestamp, nonce, token) {
const arr = [token, timestamp, nonce].sort();
const str = arr.join('');
const sha1 = crypto.createHash('sha1');
sha1.update(str);
return sha1.digest('hex') === signature;
}
// 返回组装 xml
function toXML(payload, content) {
const timestamp = Date.now();
const { tousername: fromUserName, fromusername: toUserName } = payload;
return `
<xml>
<ToUserName><![CDATA[${toUserName}]]></ToUserName>
<FromUserName><![CDATA[${fromUserName}]]></FromUserName>
<CreateTime>${timestamp}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${content}]]></Content>
</xml>
`
}
async function processCommandText({ sessionId, question }) {
// 清理历史会话
if (question === '11') {
const res = await Message.where({ sessionId }).remove({ multi: true })
return CLEAR_MESSAGE;
} else {
return HELP_MESSAGE;
}
}
代码中有四个需要讲的点
- const token 123456 随意配置,一会要用
- OPENAI_ACCESS_TOKEN, 这个就是聊天的token
怎么获取呢你
,需要先在浏览器中登录 ChatGPT 网页版,然后在浏览器中新建标签页访问这个 URL:https://chat.openai.com/api/auth/session 它会返回一个 JSON,里面包含了 accessToken 字段,将这个字段的值复制到代码中的OPENAI_ACCESS_TOKEN中即可。
- apiReverseProxyUrl
这个URL可能变化,原文就变了 现在用的是"https://ai.fakeopen.com/api/conversation" 还能用,如果以后用不了了请参考ChatGPTUnofficialProxyAPI 的使用文档
最后点击发布即可一键部署
公众号配置
登录微信公众平台,点击设置与开发
点击「基本设置」,然后点击「服务器配置」,服务器配置那里点击修改配置:
这里的URL就是之前上文在laf发布旁边的网址
这里的Token就是之前上文在代码中的const token = ‘123456’;
EncodingAESKey随机生成,提交后启用即可
现在你已经完成了所有必要的设置和配置,下面就可以直接进入微信公众号「我怀里的猫」后台与机器人进行交互啦!
效果
参考文档
https://juejin.cn/post/7221716906334994489
ChatGPTUnofficialProxyAPI 的使用文档
https://github.com/husanr/wechat_gpt_laf
本文由博客一文多发平台 OpenWrite 发布!