首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TNW-微信公众号各种消息交互

TNW-微信公众号各种消息交互

作者头像
Javen
发布于 2019-05-10 10:22:39
发布于 2019-05-10 10:22:39
77900
代码可运行
举报
文章被收录于专栏:酷玩时刻酷玩时刻
运行总次数:0
代码可运行

TNW 简介

TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持任何 Node.js 的服务端框架

测试号申请

测试时请自己的测试号

开启开发者模式

这里说的各种消息交互是指的 开发者模式下的消息交互 如果还没有开启开发者模式可以参考之前写文章 开启公众号开发者模式

简书

掘金

CSDN

开源中国

在 TNW 中实现微信公众号各种消息交互非常简单,步骤如下:

  1. 接收各种消息
  2. 调用 WeChat.handleMsg(...) 方法处理分发消息
  3. 实现 MsgAdapter 接口,实现业务逻辑以及各种消息回复

接收各种消息

开发者 URL 的 POST 方法下接收各种消息 具体实现代码如下

Express 示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 接收微信消息入口
app.post('/msg', function (req: any, res: any) {
    console.log('post...', req.query);
        // 支持多公众号
    let appId: string = req.query.appId;
    if (appId) {
        ApiConfigKit.setCurrentAppId(appId);
    }
        // 获取签名相关的参数用于消息解密(测试号以及明文模式无此参数)
    let msgSignature = req.query.msg_signature,
        timestamp = req.query.timestamp,
        nonce = req.query.nonce;

    //监听 data 事件 用于接收数据
    let buffer: Uint8Array[] = [];
    req.on('data', function (data: any) {
        buffer.push(data);
    });

    req.on('end', function () {
        let msgXml = Buffer.concat(buffer).toString('utf-8');
        // 处理消息并响应对应的回复
        // ....
    });
});

Nest 示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Post("/msg")
  PostMsg(@Req() req: Request, @Res() res: Response) {
    let that = this;
    console.log('post...', req.query);
        // 支持多公众号
    let appId: string = req.query.appId;
    if (appId) {
      ApiConfigKit.setCurrentAppId(appId);
    }
        // 获取签名相关的参数用于消息解密(测试号以及明文模式无此参数)
    let msgSignature = req.query.msg_signature,
      timestamp = req.query.timestamp,
      nonce = req.query.nonce;

    //监听 data 事件 用于接收数据
    let buffer: Uint8Array[] = [];
    req.on('data', function (data: any) {
      buffer.push(data);
    });

    req.on('end', function () {
      let msgXml = Buffer.concat(buffer).toString('utf-8');
      // 处理消息并响应对应的回复
      // ...
    });
  }

处理并分发消息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WeChat.handleMsg(msgAdapter: MsgAdapter, msgXml: string, msgSignature?: string, timestamp?: string, nonce?: string)

handleMsg 中包含了消息的解密、各种消息分发、消息加密、各种消息回复。这里就不贴源码了,感兴趣的可以看看源码,源码也有详细的注释。

Gitee-TNW-WeChat

GitHub-TNW-WeChat

其中 msgXmlmsgSignaturetimestampnonce 已在上面的 接收各种消息中 获得,就差 MsgAdapter 了。

MsgAdapter 介绍

MsgAdapter 接口中定义的方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export interface MsgAdapter {
    // 处理文本消息
    processInTextMsg(inTextMsg: InTextMsg): OutMsg;
    // 处理图片消息
    processInImageMsg(inImageMsg: InImageMsg): OutMsg;
    // 处理声音消息
    processInVoiceMsg(inVoiceMsg: InVoiceMsg): OutMsg;
    // 处理视频消息
    processInVideoMsg(inVideoMsg: InVideoMsg): OutMsg;
    // 处理小视频消息
    processInShortVideoMsg(inShortVideoMsg: InShortVideoMsg): OutMsg;
    // 处理地理位置消息
    processInLocationMsg(inLocationMsg: InLocationMsg): OutMsg;
    // 处理链接消息
    processInLinkMsg(inLinkMsg: InLinkMsg): OutMsg;
    // 处理语音识别结果
    processInSpeechRecognitionResults(inSpeechRecognitionResults: InSpeechRecognitionResults): OutMsg;
    // 处理未定义的消息(其他消息...小哥该扩展了)
    processIsNotDefinedMsg(inNotDefinedMsg: InNotDefinedMsg): OutMsg;

    // 处理关注、取消关注事件
    processInFollowEvent(inFollowEvent: InFollowEvent): OutMsg;
    // 处理扫码事件
    processInQrCodeEvent(inQrCodeEvent: InQrCodeEvent): OutMsg;
    // 处理地理位置事件
    processInLocationEvent(inLocationEvent: InLocationEvent): OutMsg;
    // 处理地理位置事件
    processInMenuEvent(inMenuEvent: InMenuEvent): OutMsg;
    // 处理模板消息事件
    processInTemplateMsgEvent(inTemplateMsgEvent: InTemplateMsgEvent): OutMsg;
    // 处理摇一摇周边事件
    processInShakearoundUserShakeEvent(inShakearoundUserShakeEvent: InShakearoundUserShakeEvent): OutMsg;
}

InXxxxMsg 统一继承自 InMsgInXxxxEvent 统一继承自 EventInMsgEventInMsg 又继承自 InMsg ,所以在任何的 inXxxxx 中都很容易获取到 toUserName(开发者微信号即appId)fromUserName(发送方帐号openId)TNW 支持多公众,后面会使用到此 appId 来实现不同公众号回复不同的消息

响应对应的回复

代码实现比较简单就不过多介绍了,请看源码

提醒:回复消息时可以对不同的公众号做特殊的处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export class MsgController implements MsgAdapter {

    processInTextMsg(inTextMsg: InTextMsg): OutMsg {
        let outMsg: any;
        let content: string = "IJPay 让支付触手可及 \n\nhttps://gitee.com/javen205/IJPay";
        if ("极速开发微信公众号" == inTextMsg.getContent) {
            // 多公众号支持 分别给不同的公众号发送不同的消息
            if (ApiConfigKit.getApiConfig.getAppId == 'wx614c453e0d1dcd12') {
                content = "极速开发微信公众号 \n\nhttps://github.com/javen205/weixin_guide"
                outMsg = new OutTextMsg(inTextMsg);
                outMsg.setContent(content);
            } else {
                content = "极速开发微信公众号 \n\nhttps://github.com/javen205/TNW"
                outMsg = new OutTextMsg(inTextMsg);
                outMsg.setContent(content);
            }

        } else if ("聚合支付" == inTextMsg.getContent) {
            // 最新规则:开发者只能回复1条图文消息;其余场景最多可回复8条图文消息
            outMsg = new OutNewsMsg(inTextMsg);
            outMsg.addArticle("聚合支付了解下", "IJPay 让支付触手可及",
                "https://gitee.com/javen205/IJPay/raw/master/assets/img/IJPay-t.png", "https://gitee.com/javen205/IJPay")
            outMsg.addArticle("jfinal-weixin", "极速开发微信公众号",
                "https://gitee.com/javen205/IJPay/raw/master/assets/img/IJPay-t.png", "https://gitee.com/JFinal/jfinal-weixin")
        } else {
            // outMsg = new OutTextMsg(inTextMsg);
            // outMsg.setContent(content);
            // 转发给多客服PC客户端
            outMsg = new OutCustomMsg(inTextMsg);
            console.log("转发给多客服PC客户端");

        }
        return outMsg;
    }

    processInImageMsg(inImageMsg: InImageMsg): OutMsg {
        let outMsg = new OutImageMsg(inImageMsg);
        outMsg.setMediaId = inImageMsg.getMediaId;
        return outMsg;
    }
    processInVoiceMsg(inVoiceMsg: InVoiceMsg): OutMsg {
        let outMsg = new OutVoiceMsg(inVoiceMsg);
        outMsg.setMediaId = inVoiceMsg.getMediaId;
        return outMsg;
    }
    processInVideoMsg(inVideoMsg: InVideoMsg): OutMsg {
        let outMsg = new OutVideoMsg(inVideoMsg);
        outMsg.setMediaId = inVideoMsg.getMediaId;
        outMsg.setDescription = "IJPay 让支付触手可及";
        outMsg.setTitle = "视频消息";
        return outMsg;
    }
    processInShortVideoMsg(inShortVideoMsg: InShortVideoMsg): OutMsg {
        let outMsg = new OutVideoMsg(inShortVideoMsg);
        outMsg.setMediaId = inShortVideoMsg.getMediaId;
        outMsg.setDescription = "TypeScript + Node.js 开发微信公众号";
        outMsg.setTitle = "短视频消息";
        return outMsg;
    }
    processInLocationMsg(inLocationMsg: InLocationMsg): OutMsg {
        return this.renderOutTextMsg(inLocationMsg,
            "位置消息... \n\nX:" + inLocationMsg.getLocation_X + " Y:" + inLocationMsg.getLocation_Y + "\n\n" + inLocationMsg.getLabel);
    }
    processInLinkMsg(inLinkMsg: InLinkMsg): OutMsg {
        let text = new OutTextMsg(inLinkMsg);
        text.setContent("链接频消息..." + inLinkMsg.getUrl);
        return text;
    }
    processInSpeechRecognitionResults(inSpeechRecognitionResults: InSpeechRecognitionResults): OutMsg {
        let text = new OutTextMsg(inSpeechRecognitionResults);
        text.setContent("语音识别消息..." + inSpeechRecognitionResults.getRecognition);
        return text;
    }

    processInFollowEvent(inFollowEvent: InFollowEvent): OutMsg {

        if (InFollowEvent.EVENT_INFOLLOW_SUBSCRIBE == inFollowEvent.getEvent) {
            return this.renderOutTextMsg(inFollowEvent,
                "感谢你的关注 么么哒 \n\n交流群:114196246");
        }
        else if (InFollowEvent.EVENT_INFOLLOW_UNSUBSCRIBE == inFollowEvent.getEvent) {
            console.error("取消关注:" + inFollowEvent.getFromUserName);
            return this.renderOutTextMsg(inFollowEvent);
        } else {
            return this.renderOutTextMsg(inFollowEvent);
        }
    }

    processInQrCodeEvent(inQrCodeEvent: InQrCodeEvent): OutMsg {
        if (InQrCodeEvent.EVENT_INQRCODE_SUBSCRIBE == inQrCodeEvent.getEvent) {
            console.debug("扫码未关注:" + inQrCodeEvent.getFromUserName);
            return this.renderOutTextMsg(inQrCodeEvent,
                "感谢您的关注,二维码内容:" + inQrCodeEvent.getEventKey);
        }
        else if (InQrCodeEvent.EVENT_INQRCODE_SCAN == inQrCodeEvent.getEvent) {
            console.debug("扫码已关注:" + inQrCodeEvent.getFromUserName);
            return this.renderOutTextMsg(inQrCodeEvent);
        } else {
            return this.renderOutTextMsg(inQrCodeEvent);
        }
    }
    processInLocationEvent(inLocationEvent: InLocationEvent): OutMsg {
        console.debug("发送地理位置事件:" + inLocationEvent.getFromUserName);

        return this.renderOutTextMsg(inLocationEvent,
            "地理位置是:" + inLocationEvent.getLatitude);
    }
    processInMenuEvent(inMenuEvent: InMenuEvent): OutMsg {
        console.debug("菜单事件:" + inMenuEvent.getFromUserName);

        return this.renderOutTextMsg(inMenuEvent,
            "菜单事件内容是:" + inMenuEvent.getEventKey);
    }
    processInTemplateMsgEvent(inTemplateMsgEvent: InTemplateMsgEvent): OutMsg {
        console.debug("模板消息事件:" + inTemplateMsgEvent.getFromUserName + " " + inTemplateMsgEvent.getStatus);
        return this.renderOutTextMsg(inTemplateMsgEvent,
            "消息发送状态:" + inTemplateMsgEvent.getStatus);
    }

    processInShakearoundUserShakeEvent(inShakearoundUserShakeEvent: InShakearoundUserShakeEvent): OutMsg {
        console.debug("摇一摇事件:" + inShakearoundUserShakeEvent.getFromUserName + " " + inShakearoundUserShakeEvent.getUuid);
        return this.renderOutTextMsg(inShakearoundUserShakeEvent,
            "uuid:" + inShakearoundUserShakeEvent.getUuid);
    }

    processIsNotDefinedMsg(inNotDefinedMsg: InNotDefinedMsg): OutMsg {
        return this.renderOutTextMsg(inNotDefinedMsg,
            "未知消息");
    }

    renderOutTextMsg(inMsg: InMsg, content?: string): OutTextMsg {
        let outMsg = new OutTextMsg(inMsg);
        outMsg.setContent(content ? content : " ");
        return outMsg;
    }
}

开源推荐

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.04.28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
微信公众号开发之如何实现消息交互
总所周知Jfinal 开发中配置非常简单只要在web.xml中添加如下代码就可以将所有的请求交由Jfianl处理
Javen
2018/08/21
1.5K0
微信公众号开发之如何实现消息交互
TNW-公众号发送模板消息
TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持 http 模块扩展、支持任何 Node.js 的服务端框架(Express、NestJS、Egg、Koa 等)
Javen
2019/07/09
8420
TNW-开启公众号开发者模式
TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持 http 模块扩展、支持任何 Node.js 的服务端框架(Express、NestJS 等)
Javen
2019/04/25
5220
微信公众号开发之现金红包
在使用现金红包之前,请前往开通现金红包功能。操作路径:【登录微信支付商户平台——>产品中心——>现金红包——>开通】。
Javen
2018/08/21
4.1K0
微信公众号开发之现金红包
独立开发微信公众号服务的一次复盘
上篇文章主要分享了异步编程的一些经验。主要包括回调函数,发布订阅,Promise,async await以及yield关键字。
terrence386
2022/07/14
4730
独立开发微信公众号服务的一次复盘
SpringBoot开发微信公众号
在讲微信公众号开发之前,先来大概了解一下微信公众号。微信公众号大体上可以分为服务号和订阅号,订阅号和服务号的区别如下:
Java旅途
2020/09/14
3K0
微信公众号支付
公众号支付发生在微信内部,微信提供了专门的API,为了更加完善的作为生成环境使用,请遵循以下步骤
收心
2022/01/19
6.2K0
公众号开发:获取用户消息和回复消息
最近在看微信公众号的开发文档,觉得很有意思,可以自定义开发一些功能,比如有人关注了公众号之后,你可以做出稍微复杂点的回复(简单的回复在公众号后台配置就好啦);比如关注者发送了「学习」消息,你可以给他推送一些文章,发送「天气」的消息,你可以回复当前的天气状况;还可以进行素材的管理,用户的管理等等。
Java技术编程
2020/06/10
6K0
公众号开发:获取用户消息和回复消息
微信公众号开放接口自定义收发消息
文档地址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Explanation_of_interface_privileges.html
biaoblog.cn 个人博客
2025/05/21
2050
微信公众号推送如何写代码
写微信公众号推送的代码需要用到微信公众平台提供的开发者文档和API接口。以下是一个示例代码,包含了获取用户信息和回复文本消息:
hide
2023/12/12
3650
微信公众号推送如何写代码
手把手教你如何微信公众号开发「建议收藏」
最近的话,发现微信开发其实也有很多挺有意思的地方,比如最近很火的一款游戏“跳一跳”,也让我如此着迷。。但是,今天我所要讲的并不是对于小程序的开发,而是要说一下,关于微信开发的另外一个内容,那就是微信公众号。。
全栈程序员站长
2022/09/25
3.6K0
手把手教你如何微信公众号开发「建议收藏」
微信公众号开发者模式介绍及接入
编辑模式和开发模式是互斥的关系,也就是说,当我们使用开发模式时,编辑模式下的操作就会失效。反之,使用编辑模式时,开发模式下的操作就会失效,所以只能使用其中一个模式进行公众号的开发。
端碗吹水
2020/09/23
1.5K0
微信公众号开发者模式介绍及接入
TNW-授权获取用户信息
TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持任何 Node.js 的服务端框架(Express、Nest、egg 等)
Javen
2019/07/30
1.4K0
巧用 Serverless,轻松搭建微信公众号的智能后台服务
一般来说,想给微信公众号增加更多的功能,需要有一台服务器,来进行公众号后台服务的搭建。那么在 Serverless 架构下,是否有更简便的方法来实现这么一个公众号后台呢?我们试试? 初步搭建 一、Serverless 原生开发 首先要有一个微信公众号! 接下来,我们要为我们的函数计算服务申请固定 IP: 点击白名单之后,我们可以填写表单,完成固定公网出口 IP 的申请。 接下来进行代码开发。 将函数绑定到公众号后台,并按照文档在函数中完成一个基本的鉴定功能: def checkSignature(
腾讯云serverless团队
2020/05/22
3.8K0
微信公众号开发基本流程
背景: 过年前后做了个微信公众号项目,已经过去一段时间了,抽空回忆总结下基本流程吧,不然很快估计自己就忘了。。
全栈程序员站长
2022/09/06
4.2K0
微信公众号开发基本流程
Java微信公众平台开发(三)--接收消息的分类及实体的创建
前面一篇有说道应用服务器和腾讯服务器是通过消息进行通讯的,并简单介绍了微信端post的消息类型,这里我们将建立消息实体以方便我们后面的使用!
用户2417870
2019/09/18
1.1K0
Java微信公众平台开发(三)--接收消息的分类及实体的创建
微信公众号推送消息笔记
根据业务需要,开发一个微信公众号的相关开发,根据相关开发和整理总结了一下相关的流程和需要,进行一些整理和总结分享给大家,最近都在加班和忙碌,博客已经很久未更新了,打气精神,再接再厉,申请、认证公众号的一系列流程就不在这里赘述了,主要进行的是技术的分享,要达到的效果如下图:
stark张宇
2024/07/23
3780
手把手教你开发微信公众号后台
松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里-->Spring Boot+Vue+微人事视频教程
江南一点雨
2020/08/21
3.1K0
手把手教你开发微信公众号后台
微信支付之企业付款
付款之前需要充值: 在调用API接口付款或通过微信支付商户平台网页功能操作付款之前需要登录微信支付商户平台,通过网页充值功能充值(商户平台-交易中心)
Javen
2018/08/21
3.3K0
微信支付之企业付款
springboot整合IJpay实现微信支付
它聚合了各种支付,封装了微信支付、QQ支付、支付宝支付、京东支付、银联支付、PayPal支付等常用的支付方式以及各种常用的接口。不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里,同时在gitee中也是高 Stars 的开源项目。
Blue_007
2023/10/21
2.2K3
springboot整合IJpay实现微信支付
相关推荐
微信公众号开发之如何实现消息交互
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档