一个前端,爱跑步、爱吉他、爱做饭、爱生活、爱编程、爱南芳姑娘,爱我所爱。世间最温暖又无价的是阳光、空气与爱,愿它们能带你去更远的地方。

  • 文章
  • 心情
  • 照片墙
  • 留言板
  • 工具
  • 友链
  • biaoblog

    专注web开发技术分享

    微信公众号开放接口自定义收发消息

    技术 46 2025-03-02 19:58

    首先确认一点 被动回复消息是个人订阅号就可以实现的,不需要认证,详见下图

    文档地址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html


    第一步就是需要接入认证

    https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

    需要提前启动一个443或者80的服务

    我这里以koa为例子 主要只贴API部分,其它基础代码就不贴了, 代码如下

    router.get("/postPublicAccountMessage", async (ctx) => {
      // ctx.body = textBody;
      // Sha1签名计算
      const token = "xxxxxxxxxxxx"; // 这里填入你的token值
      function sha1(str) {
        return crypto.createHash("sha1").update(str).digest("hex");
      }
      const query = ctx.query;
      const { signature, timestamp, nonce, echostr, openid } = query;
    
      console.log("openid_", openid);
      // 步骤1: 对token, timestamp, nonce进行字典序排序
      const arr = [token, timestamp, nonce];
      arr.sort();
      // 步骤2: 拼接成一个字符串
      const concatenatedString = arr.join("");
    
      // 步骤3: 进行sha1签名计算
      const computedSignature = sha1(concatenatedString);
    
      // 步骤4: 验证signature
      if (computedSignature === signature) {
        ctx.body = echostr; // 如果签名匹配,返回echostr
      } else {
        ctx.body = { msg: "Signature verification failed" }; // 如果不匹配,返回错误
      }
    });
    

    记得需要下载一个 crypto的包

    npm install crypto
    


    然后可以在微信调试工具检验一下配置是否正确

    https://developers.weixin.qq.com/apiExplorer?type=messagePush


    AccessToken 的获取方式可以参考

    https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

    记得需要在服务端请求,不然会报错跨域,appid和secret 都可以在公众号后台找到 ,还要记得开启白名单请求,不然会获取失败

    axios
      .get(
        "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxx&secret=xxxxx"
      )
      .then((res) => {
        console.log("res__", res);
      });
    

    到这里差不多认证完成了,


    然后就可以把用户发送给公众号的内容对接到我们的服务器上了,我们也可以做相当于的自定义回复

    但是需要知道,微信官方有一个很煞笔的规定 必须要要在5秒内进行回复,不然就断开连接了


    第二步 接受和发送消息

    这里以明文方式进行接受和发送,这里以用户发送什么内容,就回复相同的内容,具体的可以自己定义,但是需要考虑上面的截图,需要在5秒内进行回复。。

    router.post("/postPublicAccountMessage", async (ctx) => {
      const txtMsg = function (toUser, fromUser, content) {
        var xmlContent = "<xml><ToUserName><![CDATA[" + toUser + "]]></ToUserName>";
        xmlContent += "<FromUserName><![CDATA[" + fromUser + "]]></FromUserName>";
        xmlContent += "<CreateTime>" + new Date().getTime() + "</CreateTime>";
        xmlContent += "<MsgType><![CDATA[text]]></MsgType>";
        xmlContent += "<Content><![CDATA[" + content + "]]></Content></xml>";
        return xmlContent;
      };
      const { req, res } = ctx;
      var buffer = [];
      req.on("data", function (data) {
        buffer.push(data);
      });
      //监听 end 事件 用于处理接收完成的数据
      let result = await new Promise((resolve, reject) => {
        req.on("end", function () {
          var msgXml = Buffer.concat(buffer).toString("utf-8");
          //解析xml
          parseString(
            msgXml,
            { explicitArray: false },
            async function (err, result) {
              if (!err) {
                result = result.xml;
                resolve(result);
              } else {
                //打印错误
                console.log(err);
              }
            }
          );
        });
      });
    
    
      const testBody = txtMsg(
        result.FromUserName,
        result.ToUserName,
        result.Content
      );
    
    
      ctx.status = 200;
      ctx.type = "application/xml";
      ctx.body = testBody;
    });
    

    回复消息的模板可以参考官方文档提供的

    https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html


    到这里就差不多了,如果接入有问题也可以留言或者联系咨询我。


    提供几个可参考的接入项目(node.js):

    https://github.com/SilenceHVK/wechatByNode

    https://github.com/Bill-Pang/node-wechat

    文章评论

    评论列表(0