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

目录

  • 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 ? "感谢您的关注" : "感谢您再次关注" };

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

根据状态转移图实现时序电路 (三段式状态机)

看图编程 * ** 代码 module seq_circuit(input C ,input clk ,input rst_n,output wire Y ); reg [1:0] current_stage ; reg [1:0] next_stage ; reg Y_reg; //输出//第一段 : 初始化当前状态和…

vmware esxi虚拟化数据迁移

1、启用esxi的ssh 登录esxi的web界面,选择主机-》操作——》服务——》启动ssh 2.xshell登录esxi 3、找到虚拟机所在目录 blog.csdnimg.cn/direct/d57372536a4145f2bcc1189d02cc7da8.png)#### 3在传输数据前需关闭防火墙服务 查看防火墙状态:esxcli …

vue3学习(六)

前言 接上一篇学习笔记,今天主要是抽空学习了vue的状态管理,这里学习的是vuex,版本4.1。学习还没有学习完,里面有大坑,难怪现在官网出的状态管理用Pinia。 一、vuex状态管理知识点 上面的方式没有写全,还有…

如何修改开源项目中发现的bug?

如何修改开源项目中发现的bug? 目录 如何修改开源项目中发现的bug?第一步:找到开源项目并建立分支第二步:克隆分支到本地仓库第三步:在本地对项目进行修改第四步:依次使用命令行进行操作注意:Gi…

OAK相机如何将 YOLOv9 模型转换成 blob 格式?

编辑:OAK中国 首发:oakchina.cn 喜欢的话,请多多👍⭐️✍ 内容可能会不定期更新,官网内容都是最新的,请查看首发地址链接。 Hello,大家好,这里是OAK中国,我是Ashely。 专…

逆天工具一键修复图片,视频去码。简直不要太好用!

今天,我要向您推荐一款功能强大的本地部署软件,它能够在您的计算机上一键修复图片和视频,去除令人不悦的码赛克(轻度马赛克)。这款软件是开源的,并在GitHub上公开可用,您可以免费下载并使用。 …

智能制造案例专题|与MongoDB一起解锁工业4.0转型与增长的无限潜力!

MongoDB 智能制造 数字化技术的洪流在各个产业链的主干和枝节涌现。在工业制造领域,能否通过数字化技术实现各生产要素、生产环节之间的紧密配合,高效规划、管理整个生产流程,是企业提升韧性、赢得竞争的关键。随着工业4.0的深入发展和智能…

Kafka自定义分区器编写教程

1.创建java类MyPartitioner并实现Partitioner接口 点击灯泡选择实现方法,导入需要实现的抽象方法 2.实现方法 3.自定义分区器的使用 在自定义生产者消息发送时,属性配置上加入自定义分区器 properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,&q…

stack和queue(1)

一、stack的简单介绍和使用 1.1 stack的介绍 1.stack是一种容器适配器,专门用在具有先进后出,后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入和弹出操作。 2.stack是作为容器适配器被实现的,容器适配器即是…

C++ 混合运算的类型转换

一 混合运算和隐式转换 257 整型2 浮点5 行吗?成吗?中不中? C 中允许相关的数据类型进行混合运算。 相关类型。 尽管在程序中的数据类型不同,但逻辑上进行这种运算是合理的相关类型在混合运算时会自动进行类型转换,再…

EXCEL数据透视图中的日期字段,怎样自动分出年、季度、月的功能?

在excel里,这个果然是有个设置的地方,修改后就好了。 点击文件选项卡,选项,在高级里,将图示选项的勾选给取消,然后再创建数据透视表或透视图,日期就不会自动组合了: 这个选项只对新…

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

近日,完成品牌升级的 Pencils Prtocol 结束了 Season 2 并无缝开启了 Season 3,在 Season 3 中,用户可以通过质押系列资产包括 $ETH、$USDT、$USDC、$STONE 、$wrsETH、$pufETH 等来获得可观收益,并获得包括 Scroll Marks、 Penci…

html+CSS部分基础运用9

项目1 参会注册表 1.设计参会注册表页面,效果如图9-1所示。 图9-1 参会注册表页面 项目2 设计《大学生暑期社会实践调查问卷》 1.设计“大学生暑期社会实践调查问卷”页面,如图9-2所示。 图9-2 大学生暑期社会调查表页面 2.调查表前导语的…

C/C++中互斥量(锁)的实现原理探究

互斥量的实现原理探究 文章目录 互斥量的实现原理探究互斥量的概念何为原子性操作原理探究 互斥量的概念 ​ 互斥量(mutex)是一种同步原语,用于保护多个线程同时访问共享数据。互斥量提供独占的、非递归的所有权语义:一个线程从成…

LeetCode374猜数字大小

题目描述 我们正在玩猜数字游戏。猜数字游戏的规则如下:我会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。如果你猜错了,我会告诉你,我选出的数字比你猜测的数字大了还是小了。你可以通过调用一个预先定义好的接口 int guess(int n…

代码随想录算法训练营第四十四天 | 01背包问题 二维、 01背包问题 一维、416. 分割等和子集

01背包问题 二维 代码随想录 视频讲解:带你学透0-1背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili 1.dp数组定义 dp[i][j] 下标为[0,i]之间的物品&…

2024盘古石初赛(服务器部分)

赛后总结 这次初赛就有20道服务器部分赛题,做的情况一般,错了5道题这样,主要原因就是出在第二个网站服务器没有重构起来 今天来复现一下 这次的服务器部分我直接用仿真仿起来就开找了 第一台IM前期配置 先把网配置好,然后ssh…

搭载算能 BM1684 芯片,面向AI推理计算加速卡

搭载算能 BM1684 芯片,是面向AI推理的算力卡。可集成于服务器、工控机中,高效适配市场上所有AI算法,实现视频结构化、人脸识别、行为分析、状态监测等应用,为智慧城市、智慧交通、智慧能源、智慧金融、智慧电信、智慧工业等领域进…

Django Celery技术详解

文章目录 简介安装和配置创建并调度任务启动Celery Worker在视图中调用异步任务拓展功能 简介 Django Celery 是一个为Django应用程序提供异步任务处理能力的强大工具。它通过与消息代理(如RabbitMQ、Redis)集成,可以轻松地处理需要长时间运…

QT5:调用qt键盘组件实现文本框输入

目录 一、环境与目标 二、Qt VirtualKeyboard 1.勾选Qt VirtualKeyboard 2.ui设计流程 3.注意事项及问题点 三、参考代码 参考博客 一、环境与目标 qt版本:5.12.7 windows 11 下的 Qt Designer (已搭建) 目标:创建一个窗…