小程序实现设备消息订阅

news2024/9/23 1:29:38

小程序实现设备消息订阅

一、说明

先说明一下什么是小程序的消息订阅,其实就是在小程序进行某个消息的订阅,订阅以后就可以在微信收到推送的消息了。推送走的服务端,在服务端调用微信的推送接口,然后推送至指定的微信用户。

二、创建模版

消息订阅是有个消息模版概念的,一般分为以下三种:

1.一次性订阅
2.长期订阅
3.设备消息订阅

设备消息订阅也是长期订阅。
这里以其举例,设备消息订阅需要先创建硬件设备,先去小程序管理台进行操作,如下图:

在这里插入图片描述


添加了设备后,消息订阅那会有该设备相应的长期消息订阅。然后可以创建消息模版,可以看到每个消息有自己的模版ID,这个在之后会用到。具体如下图:
在这里插入图片描述

从消息模版列表点进去详情之后可以看到详细内容,这里的详细内容格式后面会用到,具体如下图:
在这里插入图片描述


三、代码实现

代码实现分为小程序和服务端两部分。

1.小程序

小程序主要就是通过消息模版id和设备modelId来进行订阅。代码如下:

Page({
	data: {
        settingData: [
            {
                'tempId': 'modelId',
                'title': '门锁安全告警',
                'content': '未订阅'
            },

            {
                'tempId': 'modelId',
                'title': '门锁撬动告警',
                'content': '未订阅'
            },
            {
                'tempId': 'modelId',
                'title': '门锁故障告警',
                'content': '未订阅'
            },
            {
                'tempId': 'modelId',
                'title': '开关门提醒',
                'content': '未订阅'
            },
            {
                'tempId': 'modelId',
                'title': '有人逗留提醒',
                'content': '未订阅'
            },
            {
                'tempId': 'modelId',
                'title': '门锁电量不足提醒',
                'content': '未订阅'
            },
        ]
        ],
    },

    // ================== 页面加载
    onLoad(options) {
        this.getSettings();
    },


    // ================== 页面显示
    onShow() {
        this.getSettings();
    },
    

    // ================== 渲染订阅列表
    getSettings() {
        let that = this;
        wx.getSetting({ withSubscriptions: true, success(res) {
            console.log(" 获取状态 = ",res);
            var settingDic = res.subscriptionsSetting.itemSettings;     // 设置的状态
            console.log('订阅数据为->' + JSON.stringify(settingDic))
            for (let key in settingDic) {

                for (let i = 0; i < that.data.settingData[0].length; i++) {
                    var object = that.data.settingData[0][i];
                    if (object['tempId'] == key) {
                        if (settingDic[key] == 'accept') {
                            that.data.settingData[0][i].content = '接收';
                        }
                         if (settingDic[key] == 'acceptWithForcePush') {
                            that.data.settingData[0][i].content = '接收并提醒';
                        } 
                         if (settingDic[key] == 'reject') {
                            that.data.settingData[0][i].content = '已订阅,不接收';
                        } 
                    }
                }
            }
            // 刷新数据
            that.setData({ settingData: that.data.settingData })
        }})
    },
    

	// ================== 订阅事件
    tableCellItemEvent(e) {
        console.log(" 点击事件 = ", e.detail.tempId, app.getUserId());
        console.log(" 点击内容 = ", e.detail.content);
        let that = this;

        // ================== 未订阅
        if (e.detail.content === '未订阅') {

            wx.showLoading({ title: '加载中···', mask: true });
            let dicA = { sn: app.getUserId(),
                         modelId: '设备modelId' }
            deviceAPI.getSnTicket(dicA, (snTicket) => {
                console.log(" 获取票据信息 = ",snTicket);
                wx.hideLoading();

                // 弹出订阅授权框
                let dic = { tmplIds: [e.detail.tempId + ''],
                             sn: app.getUserId() + '',
                             snTicket: snTicket + '',
                             modelId: "设备modelId",}

                             console.log('dic=>>>',dic);

                wx.requestSubscribeDeviceMessage({  tmplIds: [e.detail.tempId + ''],
                                                    sn: app.getUserId() + '',
                                                    snTicket: snTicket + '',
                                                    modelId: "设备modelId", success(res) {
                    // "允许" 回调
                    console.log('允许" 回调==>',res)
                    that.getSettings();
                },fail(res) {    
                    // "取消" 回调 
                    console.log(res)
                }})

            })
            return;
        }

        // ================== 不接收
        if (e.detail.content === '不接收' || e.detail.content === '已订阅,不接收') {
            this.setData({ 
                tipsBox:"tipsBox",
                tipsMsg:" 该消息已订阅,但是未打开提醒,如需打开,请前往'设置'->'通知管理'->'接收并提醒' "
            });
            return;
        }

        // ================== 接收
        if (e.detail.content === "接收") {
            this.setData({ 
                tipsBox:"tipsBox",
                tipsMsg:" 该消息已订阅,但是未打开提醒,如需打开,请前往'设置'->'通知管理'->'接收并提醒' "
            });
            return;
        }

        // ================== 接收并提醒
        if (e.detail.content === '接收并提醒') {
            this.setData({ 
                tipsBox:"tipsBox",
                tipsMsg:" 该消息已设置接收并提醒,确定更改吗"
            });
            return;
        }
    }
})

说明:

1.样式这里就不放了
2.这里主要就是渲染下订阅列表,然后点击时进行订阅,直接将settingData渲染就行。
3.其中deviceAPI.getSnTicket是服务端实现的一个获取票据的接口,会在下文讲到。

2、服务端

1.获取票据
public String getSnTicket(String appid, String sn, String modelId){
   Map<String,String> requestUrlParam = new HashMap<>();
   requestUrlParam.put("access_token", getAccessToken(appid));

   Map<String,Object> requestBodyParam = new HashMap<>();
   requestBodyParam.put("sn", sn);
   requestBodyParam.put("model_id", modelId);

   String requestUrl = "https://api.weixin.qq.com/wxa/getsnticket";

   log.info("get sn ticket -> <request={}>", JSON.toJSONString(requestBodyParam));
   JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, JSON.toJSONString(requestBodyParam)));
   log.info("get sn ticket -> <response={}>", jsonObject.toJSONString());
   return jsonObject.getString("sn_ticket");
}

说明:

1.这里appid是你的小程序的appid,注意在小程序调接口时加上,我的是放在全局,所以看不到。
2.sn和modelId是小程序传的参数
3.getAccessToken是获取接口调用凭证,在下面会讲到
4.返回值是获取的票据

2.接口调用凭证
/**
 * 接口调用凭证
 */
private String getAccessToken(String appid, String secret) {
   Map<String,String> requestUrlParam = new HashMap<>();
   requestUrlParam.put("appid", appId);  //开发者设置中的appId
   requestUrlParam.put("secret", secret); //开发者设置中的appSecret
   requestUrlParam.put("grant_type", "client_credential");    //默认参数

   log.info("get access token -> <request={}>", JSON.toJSONString(requestUrlParam));

   String requestUrl = "https://api.weixin.qq.com/cgi-bin/token";
   JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, null));
   log.info("get access token -> <response={}>", jsonObject.toJSONString());
   return jsonObject.getString("access_token");
}

说明:

1.这里appid是你的小程序的appid
2.secret是小程序的秘钥

3.推送消息
/**
 * 向用户发送设备消息
 */
public JSONObject hardwareDeviceSend(String appid, List<String> openIds, String templateId, String modelId){

	Map<String, Map<String, String>> data = new HashMap<>();
    Map<String, String> timeMap = new HashMap<>();
    timeMap.put("value", DateUtils.getDateFormat(System.currentTimeMillis()));
    data.put("time1", timeMap);
    Map<String, String> tipMap = new HashMap<>();
    tipMap.put("value", pushMessage);
    data.put("enum_string2", tipMap);
    
    String page = "/pages/home/home?params="+param;  // 消息订阅跳转地址(对应微信小程序相应页面)
        
    Map<String,Object> requestUrlParam = new HashMap<>();
    requestUrlParam.put("access_token", getAccessToken(appid));
    Map<String,Object> requestBodyParam = new HashMap<>();
    requestBodyParam.put("to_openid_list", openIds);
    requestBodyParam.put("template_id", templateId);
    requestBodyParam.put("sn", sn);
    requestBodyParam.put("model_id", modelId);

    requestBodyParam.put("data", data);
    requestBodyParam.put("page", page);
    
    // developer为开发版; trial为体验版: formal为正式版: 默认为正式版
    requestBodyParam.put("miniprogram_state", "formal");  // 微信小程序版本切换配置

    log.info("hardware device send -> <request={}>", JSON.toJSONString(requestBodyParam));

    String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/device/subscribe/send";
    JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam, JSON.toJSONString(requestBodyParam)));
    log.info("hardware device send -> <response={}>", jsonObject.toJSONString());
    return jsonObject;
}

说明:

1.data中的参数根据消息模版列表中的详细内容格式来组装
2.page是你微信收到推送后点击时跳转的页面
3.appId是小程序的appid
4.openIds是要推送的为i想你用户的openId列表,可以一次性推送多个
5.templateId是消息模版的templateId
6.modelId是设备的modelId
7.sendPost是http工具请求方法,这个自己实现。jsonObject是推送的结果。

四、总结

总结一下设备消息推送的总流程,大概分为以下五步:

1.设备接入
2.获取模版ID
3.获取设备票据
4.发起订阅
5.发送设备消息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2041939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

xlua热补丁

print("*********第一个热补丁***********")--直接写好代码 运行 是会报错的 --我们必须做4个非常重要的操作 --1.加特性 --2.加宏 第一次开发热补丁需要加 --3.生成代码 --4.hotfix 注入 --注入时可能报错 提示你要引入Tools--热补丁的缺点&#xff1a;只要我们修改…

无人值守变电站视频监控统一接入系统方案

目录 一、背景介绍 1、无人值守变电站 2、特点 二、需求分析 1、基本需求 2、需求分析 三、目标和网络 1、设计目标 2、系统网络建设目标 四、系统组成 1、总体架构图 2、前端采集层 &#xff08;1&#xff09;摄像头 &#xff08;2&#xff09;传感器 &#xf…

Qt——多线程

一、QThread类 如果要设计多线程程序&#xff0c;一般是从QThread继承定义一个线程类&#xff0c;并重新定义QThread的虚函数 run() &#xff0c;在函数 run() 里处理线程的事件循环。 应用程序的线程称为主线程&#xff0c;创建的其他线程称为工作线程。主线程的 start() 函数…

猫头虎 分享已解决Bug || Failed to start docker.service: Unit not found. 解决方案

猫头虎 分享已解决Bug || Failed to start docker.service: Unit not found. 解决方案 今天猫头虎带您解决一个在运维工作中常见的问题&#xff1a; Failed to start docker.service: Unit not found.。这是一个困扰了许多运维小伙伴的问题&#xff0c;尤其是在部署Docker时&a…

安全测试担心效果不好?这3个安全测试工具你用了吗?

其实在信息科技发展的初期&#xff0c;很多互联网公司就有意识到保护软件产品安全的重要性。但时至今日&#xff0c;我们还是经常能看到某某app软件泄露用户隐私信息&#xff0c;或遭受黑客攻击导致一些损失&#xff0c;其中不乏有一定市场地位的大厂。此类信息安全问题屡见不鲜…

元素设置了sticky粘性布局后,关于滚动后怎么样让这个元素自动添加阴影,我用自定义指令实现

前言 在写h5或者pc站的时候&#xff0c;顶部总会固定一些东西。然后我们会设置顶部的容器为粘性布局固定在顶部。但滚动之后会很僵硬。例如下面这样&#xff1a; 我们看看element的表格的效果&#xff1a; 再来看看最后我们实现的效果&#xff1a; 其实网上也有纯css实现…

简单创建代理工厂

简单创建代理工厂 一般对于JDBC来说&#xff0c;无非就是连接数据库、查询数据库、封装实体、返回实体&#xff0c;如果要设计一个ORM框架的话也就是要考虑怎么把用户自定义的数据库操作接口、XML中的SQL语句、数据库三者给联系起来&#xff0c;其实最适合的操作就是代理&…

2766:最大子矩阵

网址如下&#xff1a; OpenJudge - 2766:最大子矩阵 用dp来做就行了 代码如下&#xff08;MLE&#xff09;&#xff1a; #include<cstdio>const int maxn 101; int dp[maxn][maxn][maxn][maxn]; int martix[maxn][maxn]; int N, ans;int main(void) {scanf("%d&q…

jackson 轻松搞定接口数据脱敏

一、简介 实际的业务开发过程中&#xff0c;我们经常需要对用户的隐私数据进行脱敏处理&#xff0c;所谓脱敏处理其实就是将数据进行混淆隐藏&#xff0c;例如下图&#xff0c;将用户的手机号、地址等数据信息&#xff0c;采用*进行隐藏&#xff0c;以免泄露个人隐私信息。 如…

C++_基本语法笔记_模板

函数模板 基本使用 思想是Java里的泛型&#xff08;不确定用什么类型的数据&#xff09; 这里template这一句&#xff0c;意思是声明T是泛型&#xff0c;后面写用到泛型T的函数。 建议都用template<class T> 应用场景&#xff1a;不同数据类型的交换函数 两种使用方法…

猫咪泪痕消除术!希喂主食罐开启补水大作战!

我家小猫之前的泪痕真的不是一般的严重&#xff0c;每天都能看到它眼角挂着两条明显的褐色痕迹&#xff0c;我每天早晚都得小心翼翼地帮它擦拭&#xff0c;但效果总是微乎其微&#xff0c;眼眶边总是留下那么一圈顽固的黑色痕迹&#xff0c;我真是既忧心又无奈。 后来&#xff…

2024【十大品牌网】发布|车载WiFi十大品牌排行榜

自驾游无法随时随地联网?货车司机流量不够用&#xff1f;网约车线上抢单网速不好&#xff1f;来看看最新发布的车载WiFi十大品牌排行榜&#xff0c;帮你解决网速慢、流量不够用的问题&#xff01; 1.格行 格行作为有15年历史的老牌物联网企业&#xff0c;在产品质量和服务上…

沃可趣助力乐园工会:员工活动的数字化创新与实践

企业组织员工活动难处多多 预算不足都算轻的&#xff0c;时间协调也颇有难度&#xff0c;活动内容设计更是既要激发员工兴趣&#xff0c;又要符合企业文化&#xff0c;这让原本专注于OA服务和福利平台开发的公司纷纷退缩。 因此&#xff0c;当群硕决定在沃可趣上增加活动管理…

渲染优化策略,如何在有限资源下实现最佳视觉效果

在数字内容创作领域&#xff0c;渲染是一个至关重要的环节&#xff0c;它决定了最终图像或动画的视觉质量。然而&#xff0c;高质量的渲染往往伴随着高计算资源需求&#xff0c;如何在有限资源下实现最佳的视觉效果&#xff0c;成为了创作者们不断探索的课题。 一、优化3D模型…

青颖飞帆(青书)大模型算法工程师面试题6道|含解析

问题1、Decoder-Only和Encoder-Decoder模型相比有什么优势&#xff1f;在训练和推理效率上有什么区别&#xff1f;**** Decoder-Only模型&#xff1a;结构较为简洁&#xff0c;通常只由一个解码器组成。模型参数较少&#xff0c;相比于Encoder-Decoder模型在训练和推理上可能更…

UE5学习笔记9-创建一个小窗口提示人物是否和武器重叠

一、目标 创建一个UsrWidget去显示如果人物和武器重叠显示窗口&#xff0c;如果人物和武器不重叠将窗口隐藏 二、创建窗口并显示 1.创建一个窗口蓝图类&#xff0c;命名为PickUpWidget&#xff0c;这个蓝图类不需要C类&#xff0c;在对应文件夹中单机右键选择用户界面的控件蓝…

torch分布式训练DataParallel和DistributedDataParallel

Pytorch 分布式训练主要有两种方式&#xff1a; torch.nn.DataParallel > 简称 DP torch.nn.parallel.DistributedDataParallel > 简称DDP 其中 DP 只用于单机多卡&#xff0c;DDP 可以用于单机多卡也可用于多机多卡&#xff0c;后者现在也是Pytorch训练的主流用法&…

维基知识库系统Wiki.js本地Linux环境部署并配置公网地址远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

所生成项目的处理器架构“MSIL”与引用“***”的处理器架构“x86”不匹配。

在c#工程里新建了一个类库&#xff0c;编译的场合出现以下警告&#xff1a;C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2401,5): warning MSB3270: 所生成项目的处理器架构“MSIL”与引用“…

单链表leetcode刷题/下(C语言版)

目录 题目1&#xff1a;返回倒数第k个结点 题目2&#xff1a;回文链表 题目3&#xff1a;相交链表 题目1&#xff1a;返回倒数第k个结点 如图&#xff0c;该题使用到了快慢指针的思想。先定义两个指针&#xff0c;同时指向链表的首元结点&#xff0c;然后让fast指针向前先走…