ChatGPT接入微信公众号(手把手教学)

前言

本篇文章参考国内服务器 3 分钟将 ChatGPT 接入微信公众号(超详细)配置,纠正了一些过时的信息。

准备

一个微信公众号
一个能访问外网的梯子
一个ChatGPT账号

有了这些就可以配置了

注册免费服务器,并部署代码

前往Laf https://laf.run/ 注册一个账号,手机号注册即可。注意,别进到国外的了
file
点击新建项目
file
名称随便什么都可以,根据自己的喜好
file
创建好过后是这个样子,我们点击开发进入编程页面
file
进入后添加npm依赖
file
搜索chatgpt,添加第一个,保存并重启
file
然后新建一个函数
file
函数名字也随便取一个
file
然后将下列代码粘进去

// 引入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 = '******';

  // 验证消息是否合法,若不合法则返回错误信息
  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;
  }
}

代码中有四个需要讲的点

  • file
  • const token ****** 随意配置,一会要用
  • OPENAI_ACCESS_TOKEN, 这个就是聊天的token

怎么获取呢你
,需要先在浏览器中登录 ChatGPT 网页版,然后在浏览器中新建标签页访问这个 URL:https://chat.openai.com/api/auth/session 它会返回一个 JSON,里面包含了 accessToken 字段,将这个字段的值复制到代码中的OPENAI_ACCESS_TOKEN中即可。

最后点击发布即可一键部署

公众号配置

登录微信公众平台,点击设置与开发
file
点击「基本设置」,然后点击「服务器配置」,服务器配置那里点击修改配置:
file
这里的URL就是之前上文在laf发布旁边的网址
这里的Token就是之前上文在代码中的const token = ‘******’;
EncodingAESKey随机生成,提交后启用即可
file

现在你已经完成了所有必要的设置和配置,下面就可以直接进入微信公众号「我怀里的猫」后台与机器人进行交互啦!

我的公众号

效果

file

问题解答

在评论区遇到很多人token无效的,我这边提供几个解决方案供你们参考,我也遇到你们这种无效的情况,一种是换号多试几个号,一种是格式化一下,还有就是ChatGPTUnofficialProxyAPI 的使用文档中的另外几种取token的方式,我没有试过你们可以试一下.

还有就是看看日志为什么你的token失效或不生效
在这里插入图片描述

参考文档
https://juejin.cn/post/7221716906334994489
ChatGPTUnofficialProxyAPI 的使用文档
https://github.com/husanr/wechat_gpt_laf

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我怀里的猫

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值