解决微信公众号接入ChatGPT接口5秒限制的问题
相信通过上篇文章《使用Laf云平台,两步将ChatGPT接入微信公众号(含代码)》,已经有很多同学实现了公众号接入ChatGPT接口的操作,但是可能大家都会发现一个问题,就是当接口响应时间长的时候,微信公众号就会报错了,那是因为微信公众号对后台接口做了限制,一个接口超过5s没有响应就会重新发送,直到发送3次之后就会提示“该公众号暂时无法提供服务,请稍后再试”。官网文档如下:
解决思路: 如果接口在5秒之内没有返回,我们先返回给用户友好等待提示,然后把接口返回存储在数据库中,等到用户下一次发送请求时把数据库中的数据拿出返回给用户。
1. 在Laf云平台新建一个集合(云数据库)
在集合选项这里,点击加号新建一个集合
输入集合名称,点击确定
2. 优化云函数代码
// 引入必要的库
import * as crypto from 'crypto';
import cloud from '@lafjs/cloud';
// 创建数据库连接
const db = cloud.database();
// 校验微信服务器发送的消息是否合法
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;
}
// 处理接收到的消息
export async function main(event, context) {
const { signature, timestamp, nonce, echostr } = event.query;
const token = 'hello123';
const { ChatGPTAPI } = await import('chatgpt')
const api = new ChatGPTAPI({ apiKey: "YOUR API-KEY" })
// 验证消息是否合法,若不合法则返回错误信息
if (!verifySignature(signature, timestamp, nonce, token)) {
return 'Invalid signature';
}
// 如果是首次验证,则返回 echostr 给微信服务器
if (echostr) {
return echostr;
}
// 处理接收到的消息
const { fromusername, tousername, content } = event.body.xml;
// 查询数据库中是否有上一次的聊天记录
const chatData = await db.collection('chat').get();
const lastMessage = chatData.data[chatData.data.length - 1];
// 如果用户发送的是“继续”,则返回上一次的聊天记录
if (content[0] === '继续' && lastMessage) {
//清空数据库
await db.collection('chat').where({}).remove();
return `
<xml>
<ToUserName><![CDATA[${fromusername}]]></ToUserName>
<FromUserName><![CDATA[${tousername}]]></FromUserName>
<CreateTime>${Date.now()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${lastMessage.data.message}]]></Content>
</xml>
`;
}
// 调用 ChatGPT API 进行聊天
const startTime = Date.now();
// 如果响应时间大于等于 5s,则返回提示信息给用户
if(startTime - (timestamp+"000") > 5000) {
return `
<xml>
<ToUserName><![CDATA[${fromusername}]]></ToUserName>
<FromUserName><![CDATA[${tousername}]]></FromUserName>
<CreateTime>${Date.now()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${"返回内容过长,请稍后回复继续以获取最新结果!"}]]></Content>
</xml>
`;
}
const response = await api.sendMessage(content[0]);
const endTime = Date.now();
// 如果响应时间小于 5s,则直接返回结果给用户
if (endTime - startTime < 5000) {
return `
<xml>
<ToUserName><![CDATA[${fromusername}]]></ToUserName>
<FromUserName><![CDATA[${tousername}]]></FromUserName>
<CreateTime>${Date.now()}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${response.text}]]></Content>
</xml>
`;
}
// 如果响应时间大于等于 5s,将结果存入数据库
await db.collection('chat').add({ data: { message: response.text } });
}
注意: 云函数修改后,发布才会生效!