家政预约小程序10公众号集成

devtools/2024/10/15 5:46:34/

目录

  • 1 使用测试号
  • 3 工作流配置
  • 4 配置关注事件脚本
  • 5 注册开放平台
  • 6 获取公众号access_token
  • 6 实现关注业务逻辑
  • 总结

我们本次实战项目构建的相当于一个预约平台,既有家政企业,也有家政服务人员还有用户。不同的人员需要收到不同的消息,比如用户可以收到订单状态变更的消息,客服可以收到下单的消息,家政服务人员可以收到派单的消息。

如果是使用小程序订阅消息,存在的问题是订阅消息必须对方主动订阅才可以发,而且订阅一次才可以发一次。

对于用户可能问题不大,但是对于客服和家政人员就不太合适。因为他们接收消息是被动的,而且是接收多次消息。

对于这种需求,我们就需要和公众号集成来完成消息的接收。

1 使用测试号

登录到公众号后台,找到开发者工具,点击公众号测试号
在这里插入图片描述
用你自己的号扫码登录
在这里插入图片描述
登录之后,系统会给你初始化一个测试账号
在这里插入图片描述
这里的appID和appsecret在调用公众号接口的时候需要传入,下边的接口配置信息,主要是用来获取用户关注的事件,这里配置了微搭工作流的地址,我们接下来介绍一下工作流的配置

3 工作流配置

打开应用编辑器,切换到工作流视图,点击+号创建工作流
在这里插入图片描述
选择处理微信消息的通知模板
在这里插入图片描述
选择第一个节点,配置公众号的appid,token和secret我们选择随机生成
在这里插入图片描述
然后复制一下接收推送的URL,贴入到我们公众号的接口配置里,这样当用户在接收推送的时候就调用了微搭的工作流作为响应

4 配置关注事件脚本

在工作流里我们具体的关注事件响应是在js脚本里设置的,选中我们的js脚本节点,点击编辑
在这里插入图片描述
在这里插入图片描述
脚本的逻辑是先看表存不存在,不存在就创建一个,然后给用户返回一个欢迎信息

我们这里要修改一下,我们的表是事先创建好的,切换到数据源视图,找到我们的用户注册数据源,切换到基本信息,复制一下表信息
在这里插入图片描述
关注的时候需要写入正式表,点击立即发布
在这里插入图片描述
为了给用户发送消息,我们需要添加一列是公众号的openid
在这里插入图片描述
再添加一列公众号unionid
在这里插入图片描述
这里解释一下为什么要添加unionid,微信体系下如果公众号、小程序要进行关联的,需要用到unionid,前提是你的公众号和小程序都绑定到微信开放平台

5 注册开放平台

打开微信开发平台,按照提升进行注册
在这里插入图片描述
第二步登记主体信息
在这里插入图片描述
第三歩确认主体信息,注册成功后就可以将我们刚刚输入的邮箱和密码作为登录的用户名和密码了
在这里插入图片描述
登录之后先需要进行认证
在这里插入图片描述
在这里插入图片描述
认证通过之后,就需要将我们的公众号和小程序都绑定到开放平台
在这里插入图片描述
绑定之后我们的各个主体账号就统一到了开放平台下,这样就可以返回同一个unionid

6 获取公众号access_token

如果需要调用公众号接口的,先需要获取公众号的access_token,我们先创建一个数据源用来保存我们的access_token

在这里插入图片描述
先添加一列access_token类型选择文本
在这里插入图片描述
再添加一列expire_in类型选择数字
在这里插入图片描述
然后切换到工作流,新增一个工作流,选择空模板
在这里插入图片描述
第一个节点我们选择指定时间触发
在这里插入图片描述
选择重复周期为分钟,我们设置为每15分钟
在这里插入图片描述
然后拖入一个运行js脚本节点
在这里插入图片描述
将两个节点连接起来
在这里插入图片描述
在脚本里输入如下代码用来更新我们的token信息

const cloudbase = require('@cloudbase/node-sdk')
const fetch = require('node-fetch');
const app = cloudbase.init({env: cloudbase.SYMBOL_CURRENT_ENV
})
// 1. 获取数据库引用
const db = app.database()
// 获取access_token的函数
async function getAccessToken(appId, appSecret) {const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${appSecret}`;try {const response = await fetch(url);const data = await response.json();if (data && data.access_token) {return data.access_token;} else {console.error('获取access_token失败:', data);return null;}} catch (error) {console.error('获取access_token出错:', error);return null;}
}// 查找存储access_token的文档的函数
async function findAccessTokenDoc() {console.log("-----------ssss-----------------")try {const tokenDocs = await db.collection('lcap-data-3ThdFDXPo-gzhtoken_uwynyav').get()console.log("----------------------------", tokenDocs)if (tokenDocs.data && tokenDocs.data.length > 0) {return tokenDocs.data[0];} else {return null;}} catch (error) {console.error('查找access_token文档出错:', error);return null;}
}// 写入云开发数据库中的access_token的函数
async function addAccessTokenToDatabase(accessToken, expiresIn) {try {const res = await db.collection('lcap-data-3ThdFDXPo-gzhtoken_uwynyav').add({access_token: accessToken,expire_in: expiresIn,createdAt: new Date().getTime(), // 存储为毫秒值createBy: "",updateBy: "",_openid: "",updatedAt: new Date().getTime(), // 存储为毫秒值});console.log('access_token写入成功,文档ID:', res);return res} catch (error) {console.error('access_token写入失败:', error);return null}
}// 更新云开发数据库中的access_token的函数
async function updateAccessTokenInDatabase(docId, accessToken, expiresIn) {try {const res = await db.collection('lcap-data-3ThdFDXPo-gzhtoken_uwynyav').doc(docId).update({access_token: accessToken,expire_in: expiresIn,updatedAt: new Date().getTime(), // 存储为毫秒值});console.log('access_token更新成功');return res} catch (error) {console.error('access_token更新失败:', error);return null}
}const appId = '';
const appSecret = '';
let res = null
const tokenDoc = await findAccessTokenDoc();
if (tokenDoc) {const docId = tokenDoc._id;const accessToken = await getAccessToken(appId, appSecret);if (accessToken) {res = await updateAccessTokenInDatabase(docId, accessToken, 7200);}
} else {const accessToken = await getAccessToken(appId, appSecret);console.log("accessToken", accessToken)if (accessToken) {res = await addAccessTokenToDatabase(accessToken, 7200);}
}return {res
}

代码的逻辑是,如果还没有写入token,那么就调用新增接口写入,如果已经写入了,就调用更新接口做更新操作

在工作流中,我们调用第三方接口的需要用到node-fetch包,其次如果我们想操作数据库的需要引入数据库的sdk

6 实现关注业务逻辑

相关配置都准备好之后,我们就可以写关注的逻辑了。我们的想法是如果用户关注,我们先获取到用户的openid,然后根据openid调用用户信息接口获取unionid,将获得的信息写入到数据源中,完成一个注册,代码如下:

const cloudbase = require("@cloudbase/node-sdk");
const fetch = require('node-fetch');
const app = cloudbase.init({env: cloudbase.SYMBOL_CURRENT_ENV // 这里可以修改为其他环境
});
const db = app.database();
const tokenDocs = await db.collection('lcap-data-3ThdFDXPo-gzhtoken_uwynyav').get()
console.log("tokenDocs",tokenDocs)
const access_token = tokenDocs.data[0].access_token; 
console.log("access_token",access_token)
const openid =""// wxTrigger.output.FromUserName; 
const response = await fetch(`https://api.weixin.qq.com/cgi-bin/user/info?access_token=${access_token}&openid=${openid}&lang=zh_CN`); console.log("response",response)const data = await response.json();console.log("data",data) const unionid = data?.unionid
const users = await db.collection("lcap-data-3Rr9TzWzJ-yhgl_2rtx1m9");const { total } = await users.where({ gzhopenid: openid }).count();
console.log("total",total)
const isNewUser = total === 0;
console.log("isNewUser",isNewUser)
if (isNewUser) {await users.add({ gzhopenid: data.openid ,gzhunionid:unionid});
}return `${isNewUser ? "感谢您的关注" : "感谢您再次关注" };

总结

本篇我们介绍了如何和公众号集成,将公众号的信息和小程序的信息关联是必备的功能,后续章节中我们介绍一下小程序注册用户时如何和公众号进行关联


http://www.ppmy.cn/devtools/44908.html

相关文章

Kubernetes 之 ReplicaSet

Kubernetes 之 ReplicaSet ReplicaSet 定义 ReplicaSet 是 Kubernetes 中的一种副本控制器,其主要作用是控制其管理的 Pod 的预设副本数量。它会持续监听这些 Pod 的运行状态,在Pod发生故障时执行重启策略,当 Pod 数量减少时会重新启动新的…

牛客NC236 最大差值【simple 动态规划 Java/Go/PHP】

题目 题目链接: https://www.nowcoder.com/practice/a01abbdc52ba4d5f8777fb5dae91b204 思路 不难看出该题可以使用动态规划的方式解题。 在循环数组的过程中,记录截止到当前位置-1的最小值, 然后用当前的值去计算最大的差值。Java代码 im…

16:00面试,16:08就出来了,问的问题有点变态。。。

从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到8月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…

【Unity2D 2022:Particle System】添加粒子特效

一、创建粒子系统游戏物体 1. 创建粒子系统游戏物体Smog Effect 2. 给粒子特效添加精灵贴图 (1)启用Texture Sheet Animation(纹理表动画) (2)点击加号添加一个纹理,并将两张厌恶图片导入到纹理…

Python | R | MATLAB群体消息和遗传病筛选多元统计模型

🎯要点 🎯概率分布结构模型:有向无环图模型结构、部分有向无环图、动态贝叶斯网络、结构方程模型、广义噪声或模型、连接树、聚类图、因子图、马尔可夫链 | 🎯多类分类模型:朴素贝叶斯分类器、求和朴素贝叶斯分类器、…

Rust语言实现的去中心化AI网络节点

一、概述 去中心化和人工智能(AI)是两个极具潜力的发展方向。Gaia项目正是将这两者结合起来,创造了一个去中心化的AI网络节点。本文将深入探讨Gaia项目的技术细节,通过丰富的示例和详细描述,帮助读者全面理解并掌握该…

gulp入门1-安装

Gulp 是一个流行的自动化构建工具,主要用于前端开发中的任务自动化,如文件压缩、代码合并、代码校验等。以下是一个 Gulp 的入门教程,帮助你快速上手: 1. 安装 Node.js 和 npm 首先,你需要在你的计算机上安装 Node.j…

js-hasOwnProperty与in

hasOwnProperty与in都是被用于检查对象属性。但他们的检查范围不通。 hasOwnProperty方法仅检查自身属性,而不考虑原型链上的属性。如果检查的属性是来自原型链的,那么返回false。 in运算符则检查自身以及它的原型链上是否存在该属性。如果属性存在自身或…