微信小程序通过公众号(服务号)推送通知或提醒步骤及代码(一,获取推送前所需信息)

您所在的位置:网站首页 手机qq消息推送设置在哪里设置 微信小程序通过公众号(服务号)推送通知或提醒步骤及代码(一,获取推送前所需信息)

微信小程序通过公众号(服务号)推送通知或提醒步骤及代码(一,获取推送前所需信息)

2023-08-13 01:23| 来源: 网络整理| 查看: 265

提前准备:微信小程序,微信公众号(服务号),微信开放平台 微信小程序不用说啦,肯定要有的。 微信公众号(服务号)是需要有企业资质才可以申请的,个人无法申请,认证费300RMB 微信开放平台申请,这个需要企业资质,认证费用300RMB

开发前关系绑定: 在公众号后台绑定小程序,原因:公众号绑定了小程序可以再直接跳转到小程序中,位置再公众号后台左侧菜单栏 -> 小程序 -> 小程序管理中。一个公众号可以绑定多个小程序。在这里插入图片描述 把小程序和公众号都绑定到微信开放平台,原因:为了获取unionid,unionid是什么?简单来说,就是开放平台用于区分是否是同一用户的标识,你把多个小程序,公众号,第三方平台等都绑定到开放平台上,取到的unionid都是一样的,这样就可以知道多个不同程序之间的用户是否是同一用户。 我们这里获取unionid就是为了知道使用我们小程序的销售和关注了公众号的销售是不是同一个销售,从而给该销售发送提醒通知,我们在小程序端获取销售的openId和unionid,在公众号端通过关注也获取销售的openId和unionid,其中openId是不同的,unionid是相同的。我们就可以通过小程序的unionid找到公众号的openid。通过openId就知道给谁发送通知。(openId就是小程序或公众号的唯一标识) 在这里插入图片描述

公众号白名单配置和服务器配置

白名单配置: 在公众号后台进行配置,开发 -> 基本配置 -> IP白名单。把部署的服务器IP配置进来就可以 在公众号后台进行配置

服务器配置: 在公众号后台进行配置,开发 -> 基本配置 -> 服务器配置 官方文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html 在这里插入图片描述 URL: 用户微信服务器调用进行验证和发送信息使用。 Token: 可以随便写,但是要和代码中一致,才可以验证过去 验证服务器配置接口: 要先把接口写好放到服务器中,服务器配置才可以成功。

//这个token要与公众平台服务器配置填写的token一致 private final static String TOKEN = "xxxxxx"; //该接口就是在公众号后台配置的服务器URL @GetMapping("/mp/serverCheck") public void doGet(HttpServletRequest request, HttpServletResponse response) throws AesException, IOException { // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 String signature = request.getParameter("signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echostr = request.getParameter("echostr"); log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr); if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { throw new IllegalArgumentException("请求参数非法,请核实!"); } // 将token、timestamp、nonce三个参数进行字典序排序 2)将三个参数字符串拼接成一个字符串进行sha1加密 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信 String signatureCheck = getSHA1(TOKEN, timestamp, nonce); log.info("\n加密后的signatureCheck = {}", signatureCheck); if (signatureCheck.equals(signature)) { log.info("\n接入成功"); PrintWriter out = response.getWriter(); //原样返回echostr参数 out.print(echostr); out.flush(); out.close(); } else { throw new AesException(AesException.ValidateSignatureError); } }

SHA1加密方法

/** * 用SHA1算法验证Token * * @param token 票据 * @param timestamp 时间戳 * @param nonce 随机字符串 * @return 安全签名 * @throws AesException */ public static String getSHA1(String token, String timestamp, String nonce) throws AesException { try { String[] array = new String[]{token, timestamp, nonce}; StringBuffer sb = new StringBuffer(); // 字符串排序 Arrays.sort(array); for (int i = 0; i shaHex = Integer.toHexString(digest[i] & 0xFF); if (shaHex.length() e.printStackTrace(); throw new AesException(AesException.ComputeSignatureError); } }

获取公众号用户的openId 和 unionId

我这里就不写获取小程序的openId 和 unionId和用户信息了,获取小程序的代码有点杂,是以前写的,不会的可以上网找一下如何获取,如果不绑定开放平台时获取不到unionId的,可以看一下官方文档https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html

下面是获取公众号的openId和unionId代码:根据关注的用户进行获取 这个接口就是服务器配置的URL,上面验证的时候也使用过一次,不过验证时get请求,这次是post请求。 Controller层

@Autowired private WeChatMPService weChatMPService; @ApiOperation(value = "处理微信服务器发来的消息", notes = "处理微信服务器发来的消息") @PostMapping("/mp/serverCheck") public String doPost(HttpServletRequest request, HttpServletResponse response) { // 调用核心服务类接收处理请求 return weChatMPService.processRequest(request); }

Service接口层

String processRequest(HttpServletRequest request, String projectId);

ServiceImpl实现类

import com.minapp.management.config.WeChatContant; import com.minapp.management.service.TdSysMpStaffLoginService; import com.minapp.management.service.WeChatMPService; import com.minapp.management.utils.WeChatUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * @ClassName: WeChatServiceImpl * @Description: 可以结合官网的api看是什么意思 ↓ 消息管理 -> 接受事件推送 * https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html * @Authror: XQD * @Date: 2021/1/4 15:42 */ @Slf4j @Service public class WeChatMPServiceImpl implements WeChatMPService { @Resource private TdSysMpStaffLoginService mpStaffLoginService; @Override public String processRequest(HttpServletRequest request) { // xml格式的消息数据 String respXml = null; // 默认返回的文本消息内容 String respContent; try { // 调用parseXml方法解析请求消息 Map requestMap = WeChatUtil.parseXml(request); // 消息类型 String msgType = requestMap.get(WeChatContant.MsgType); log.info("\n消息类型:{}", msgType); String mes = null; // 文本消息 if (msgType.equals("text")) { respContent = "您发送的是文本消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 图片消息 else if (msgType.equals("image")) { respContent = "您发送的是图片消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 语音消息 else if (msgType.equals("voice")) { respContent = "您发送的是语音消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 视频消息 else if (msgType.equals("video")) { respContent = "您发送的是视频消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 地理位置消息 else if (msgType.equals("location")) { respContent = "您发送的是地理位置消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 链接消息 else if (msgType.equals("link")) { respContent = "您发送的是链接消息!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 事件推送 else if (msgType.equals("event")) { // 事件类型 String eventType = requestMap.get("Event"); log.info("\n事件类型为:{}", eventType); // 关注 if (eventType.equals("subscribe")) { mpStaffLoginService.subscribeMPUserInfo(requestMap.get(WeChatContant.FromUserName)); respContent = "谢谢您的关注!"; respXml = WeChatUtil.sendTextMsg(requestMap, respContent); } // 取消关注 else if (eventType.equals("unsubscribe")) { mpStaffLoginService.unsubscribeMPUserInfo(requestMap.get(WeChatContant.FromUserName)); // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复 } // 扫描带参数二维码 else if (eventType.equals("SCAN")) { // TODO 处理扫描带参数二维码事件 } // 上报地理位置 else if (eventType.equals("LOCATION")) { // TODO 处理上报地理位置事件 } // 自定义菜单 else if (eventType.equals("CLICK")) { // TODO 处理菜单点击事件 } } mes = mes == null ? "不知道你在干嘛" : mes; if (respXml == null) { respXml = WeChatUtil.sendTextMsg(requestMap, mes); } log.info("\n"+respXml); return respXml; } catch (Exception e) { e.printStackTrace(); } return ""; } }

WeChatUtil工具类

package com.minapp.management.utils; import com.minapp.management.config.WeChatContant; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; /** * @ClassName: WeChatUtil * @Description: 请求校验工具类 * @Authror: XQD * @Date: 2021/1/4 15:35 */ public class WeChatUtil { /** * 将字节数组转换为十六进制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } private static void sort(String a[]) { for (int i = 0; i if (a[j].compareTo(a[i]) "unchecked"}) public static Map parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map map = new HashMap(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList){ map.put(e.getName(), e.getText()); } // 释放资源 inputStream.close(); inputStream = null; return map; } public static String mapToXML(Map map) { StringBuffer sb = new StringBuffer(); sb.append(""); mapToXML2(map, sb); sb.append(""); try { return sb.toString(); } catch (Exception e) { } return null; } private static void mapToXML2(Map map, StringBuffer sb) { Set set = map.keySet(); for (Iterator it = set.iterator(); it.hasNext();) { String key = (String) it.next(); Object value = map.get(key); if (null == value){ value = ""; } if (value.getClass().getName().equals("java.util.ArrayList")) { ArrayList list = (ArrayList) map.get(key); sb.append(""); for (int i = 0; i if (value instanceof HashMap) { sb.append(""); mapToXML2((HashMap) value, sb); sb.append(""); } else { sb.append(""); } } } } /** * 回复文本消息 * @param requestMap * @param content * @return */ public static String sendTextMsg(Map requestMap,String content){ Map map=new HashMap(); map.put("ToUserName", requestMap.get(WeChatContant.FromUserName)); map.put("FromUserName", requestMap.get(WeChatContant.ToUserName)); map.put("MsgType", WeChatContant.RESP_MESSAGE_TYPE_TEXT); map.put("CreateTime", System.currentTimeMillis()); map.put("Content", content); return mapToXML(map); } }

在这里插入图片描述

在用户关注了,会触发关注事件,微信服务器通过接口给你发送上面的一段xml信息,里面包括了openId和一些其他信息,解析出来后,可以通过openId 和access_token (access_token获取方法在我推送服务通知的博客里面) 获取到用户的昵称,头像,unionId 等等一些信息,把这些信息存入数据库中就可以。代码如下 service接口

import com.alibaba.fastjson.JSONObject; import com.minapp.management.entity.TdSysMpStaffLogin; import com.baomidou.mybatisplus.extension.service.IService; /** *

* 服务类 *

* * @author XQD * @since 2021-01-04 */ public interface TdSysMpStaffLoginService extends IService { // 关注公众号事件调用的接口 public void subscribeMPUserInfo(String openId); // 取消关注公众号事件调用的接口 public void unsubscribeMPUserInfo(String openId); // 发送模板信息接口 boolean sendTemplateMsg(String staffIds, String messageType, JSONObject param); }

ServiceImpl实现类

@Resource private ObjectMapper objectMapper; /** * @Description: 订阅的公众号用户信息存入数据库 * @Param: [projectId, openId] * @return: void * @Author: XQD * @Date:2021/1/4 17:45 */ @Override public void subscribeMPUserInfo(String openId) { String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+getAccessToken()+"&openid="+openId+"&lang=zh_CN"; String mpUserInfo = HttpClientUtil.get(url); Map map = null; try { map = objectMapper.readValue(mpUserInfo, Map.class); } catch (IOException e) { log.error("公众号异常通知-获取用户信息转化异常", e); } TdSysMpStaffLogin mpStaffLogin = new TdSysMpStaffLogin(); mpStaffLogin.setId(GeneratorIDUtil.generatorId()) .setOpenId(openId) .setProjectId(projectId) .setNickName((String) map.get("nickname")) .setHeadImageUrl((String) map.get("headimgurl")) .setSex((Integer) map.get("sex")) .setSubscribe((Integer) map.get("subscribe")) .setUnionId((String) map.get("unionid")) .setCountry((String) map.get("country")) .setProvince((String) map.get("province")) .setCity((String) map.get("city")) .setSubscribeScene((String) map.get("subscribe_scene")); UpdateWrapper mpStaffLoginUpdateWrapper = new UpdateWrapper(); mpStaffLoginUpdateWrapper.set("subscribe",1) .eq("open_id",openId); //数据库操作 if (mpStaffLoginService.saveOrUpdate(mpStaffLogin, mpStaffLoginUpdateWrapper)){ log.info("\n关注的用户信息添加成功 openId = {}", openId); }else { log.info("\n关注的用户信息添加失败 openId = {}", openId); } } /** * @Description: 取消订阅用户 * @Param: [projectId, openId] * @return: void * @Author: XQD * @Date:2021/1/4 17:45 */ @Override public void unsubscribeMPUserInfo(String openId) { // 数据库操作,就是把关注的状态改一下 UpdateWrapper mpStaffLoginUpdateWrapper = new UpdateWrapper(); mpStaffLoginUpdateWrapper.set("subscribe",0) .eq("open_id",openId); if (mpStaffLoginService.update(mpStaffLoginUpdateWrapper)){ log.info("\n取消关注的用户操作成功 openId = {}", openId); }else { log.info("\n取消关注的用户操作失败 openId = {}", openId); } }

HttpClientUtil类就是用来调用外部接口的,就不贴出来了,



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3