解决微信公众号接入ChatGPT接口5秒限制的问题

1,416 阅读2分钟

解决微信公众号接入ChatGPT接口5秒限制的问题

相信通过上篇文章《使用Laf云平台,两步将ChatGPT接入微信公众号(含代码)》,已经有很多同学实现了公众号接入ChatGPT接口的操作,但是可能大家都会发现一个问题,就是当接口响应时间长的时候,微信公众号就会报错了,那是因为微信公众号对后台接口做了限制,一个接口超过5s没有响应就会重新发送,直到发送3次之后就会提示“该公众号暂时无法提供服务,请稍后再试”。官网文档如下:

公众号5秒限制

解决思路: 如果接口在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 } });
}

注意: 云函数修改后,发布才会生效!

案例:

使用案例