1. 最近项目有个需求要把小程序和公众号关联到一起,发布商品,下单的时候的时候给用户推送消息
  2. 小程序要跟微信公众号(服务号认证300块,订阅号不行)绑定到一起,要先绑定到微信开放平台(需要认证300块)
  3. 绑定完成后小程序登录就可以获取unionid了,关于怎么获取unionid网上有很多教程,这里的unionid需要在微信开放平台绑定后才能看到。
  4. 关联公众号,根据unionid来查询,这里我是先获取小程序的unionid然后存入数据库,再新建一个表,存放公众号的unionid和公众号的openid
  5. 获取公众号的unionidopenid,微信公众号里面有个设置与开发-基本配置 -服务器配置把他开启,这个里面的token是自己自定义的需要和后端一致不然不能提交保存


        @GetMapping(value = "/verify_wx_token")public String verifyWXToken(HttpServletRequest request) throws AesException {String msgSignature = request.getParameter("signature");String msgTimestamp = request.getParameter("timestamp");String msgNonce = request.getParameter("nonce");String echostr = request.getParameter("echostr");//下面这个方法里面有自定义的token 需要和服务器配置定义的一致if (WXPublicUtils.verifyUrl(msgSignature, msgTimestamp, msgNonce)) {return echostr;}return null;}

工具类

public class WXPublicUtils {/*** 验证Token* @param msgSignature 签名串,对应URL参数的signature* @param timeStamp 时间戳,对应URL参数的timestamp* @param nonce 随机串,对应URL参数的nonce** @return 是否为安全签名* @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息*/public static boolean verifyUrl(String msgSignature, String timeStamp, String nonce)throws AesException {// 这里的 WXPublicConstants.TOKEN 填写你自己设置的Token就可以了String signature = SHA1.getSHA1("你服务器配置中自定义的token", timeStamp, nonce);if (!signature.equals(msgSignature)) {throw new AesException(AesException.VALIDATE_SIGNATURE_ERROR);}return true;}
import java.security.MessageDigest;
import java.util.Arrays;public class 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 < 3; i++) {sb.append(array[i]);}String str = sb.toString();// SHA1签名生成MessageDigest md = MessageDigest.getInstance("SHA-1");md.update(str.getBytes());byte[] digest = md.digest();StringBuffer hexstr = new StringBuffer();String shaHex = "";for (int i = 0; i < digest.length; i++) {shaHex = Integer.toHexString(digest[i] & 0xFF);if (shaHex.length() < 2) {hexstr.append(0);}hexstr.append(shaHex);}return hexstr.toString();} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.COMPUTE_SIGNATURE_ERROR);}}}
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class XmlUtil {/*** xml转map*/public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {HashMap<String, String> map = new HashMap<String, String>();SAXReader reader = new SAXReader();InputStream ins = request.getInputStream();Document doc = reader.read(ins);Element root = doc.getRootElement();@SuppressWarnings("unchecked")List<Element> list = (List<Element>) root.elements();for (Element e : list) {map.put(e.getName(), e.getText());}ins.close();return map;}public static WechatNotifyRequestVO fromXML(String xml, Class clazz, Class... childClazz) {XStream xmlStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));XStream.setupDefaultSecurity(xmlStream);xmlStream.processAnnotations(new Class[]{clazz});xmlStream.processAnnotations(childClazz);xmlStream.allowTypes(new Class[]{clazz});xmlStream.allowTypes(childClazz);xmlStream.ignoreUnknownElements();Object result = xmlStream.fromXML(xml);return (WechatNotifyRequestVO) result;}/*** 对象组装成xml** @param object 要转换的对象* @return xml文档*/public static String toXML(Object object) {//转换成XMLXStream xmlStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_")));XStream.setupDefaultSecurity(xmlStream);xmlStream.processAnnotations(new Class[]{object.getClass()});xmlStream.allowTypes(new Class[]{object.getClass()});return xmlStream.toXML(object);}}
import com.thoughtworks.xstream.annotations.XStreamAlias;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import lombok.experimental.Accessors;/*** 详情见微信官方文档* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html*/@Accessors(chain = true)@XStreamAlias(value = "xml")public class WechatNotifyRequestVO {@ApiModelProperty("开发者微信号")@XStreamAlias(value = "ToUserName")private String toUserName;public String getToUserName() {return toUserName;}public void setToUserName(String toUserName) {this.toUserName = toUserName;}public String getFromUserName() {return fromUserName;}public void setFromUserName(String fromUserName) {this.fromUserName = fromUserName;}public Integer getCreateTime() {return createTime;}public void setCreateTime(Integer createTime) {this.createTime = createTime;}public String getMessageType() {return messageType;}public void setMessageType(String messageType) {this.messageType = messageType;}public String getEvent() {return event;}public void setEvent(String event) {this.event = event;}@ApiModelProperty("发送方帐号(一个OpenID)")@XStreamAlias(value = "FromUserName")private String fromUserName;@ApiModelProperty("消息创建时间 (整型)")@XStreamAlias(value = "CreateTime")private Integer createTime;@ApiModelProperty("消息类型,event")@XStreamAlias(value = "MsgType")private String messageType;@ApiModelProperty("事件类型,subscribe(订阅)、unsubscribe(取消订阅)")@XStreamAlias(value = "Event")private String event;}
  1. 配置好后,后端需要监控你的关注或取消关注的事件,我们这边关注后就能获取公众号用户这边的信息,然后去查询unionidopenid,这样就能根据小程序的unionid来查询公众号的openid,这个代码里面的访问名和公众号服务配置的名字是一样的,写在同一个controller下面,只不过一个是GET(验证服务器)一个是POST(监控公众号关注事件
private  final  static Logger logger = LoggerFactory.getLogger(WeixinMsgController. class);//关注或取消公众号事件@PostMapping(value = "/verify_wx_token", produces = "text/plain;charset=utf-8")public Object notify(HttpServletRequest req, HttpServletResponse resp) {try {req.setCharacterEncoding("UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}resp.setCharacterEncoding("UTF-8");String message = "success";try {//把微信返回的xml信息转义成mapMap<String, String> map = null;try {map = XmlUtil.xmlToMap(req);} catch (IOException e) {e.printStackTrace();}System.out.println("微信接收到的消息为:"+map.toString());String fromUserName = map.get("FromUserName");//消息来源用户标识 openidString toUserName = map.get("ToUserName");//消息目的用户标识 公众号idString msgType = map.get("MsgType");//消息类型(event或者text)System.out.println("用户openId:"+fromUserName);System.out.println("公众号:"+toUserName);System.out.println("消息类型为:"+msgType);String eventType = map.get("Event");//事件类型System.out.println(eventType);String unionid = getUnionid(fromUserName);if(eventType.equals("subscribe")){//关注了System.out.println(unionid);LitemallUnionid unionids=litemallUserService.findByun(unionid);if(unionids==null){//查询公众号表是否存在过这个用户,没有就新增litemallUserService.addun(fromUserName,unionid);}else{System.out.println("已存在该用户");//更新公众号表的关注状态litemallUserService.updtype1(fromUserName);}}else if(eventType.equals("unsubscribe")){//没关注 更新状态litemallUserService.updtype0(fromUserName);}} catch (DocumentException e) {e.printStackTrace();}System.out.println("关注微信公众号自动回复的消息内容为:"+message);return message;}/**这边返回出去的是 公众号的unionid**/public static String getUnionid(String openId) {String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";String url = requestUrl.replace("OPENID", openId).replace("ACCESS_TOKEN", "你自己的公众号token");JSONObject obj = WeiXinUtil.HttpGet(url);
//        String nickName = (String)obj.get("nickname");String unionid = (String)obj.get("unionid");return unionid;}
  1. 这样的话我们小程序的unionid和公众号的unionid就都拿到了,然后就可以根据小程序那边登录后拿到的unionid去查询公众号表里面的openid了,之后发送推送信息,因为我这里是在小程序中订阅商家然后发布商品后发送消息给用户,所以需要循环获取openid

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Component
public class WechatMsgs {@Autowiredprivate LitemallUserService userService;@Autowiredprivate LitemallGroupService litemallGroupService;public void Send(Integer userId,String name,String retailPrice,String starttime,String endtime) {// 接口地址String sendMsgApi = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+ "你公众号的token";//跟据用户id查询订阅过的商家有几个,商家id对应用户表里面的id,//我这边是子查询所以直接把公众号的用户给查出来了, 然后循环List<LitemallUnionid> unionids=litemallGroupService.cxunionid(userId);LitemallUser user=userService.findById(userId);//循环公众号列表for(LitemallUnionid u:unionids){//openIdString toUser =""+u.getOpenid()+"";//消息模板IDString template_id = "wYhlJQXV4Zr2-lmf7gOMYXhDlWB_wilklbnSq7E2cys";//整体参数mapMap<String, Object> paramMap = new HashMap<String, Object>();Map<String, Object> xcx = new HashMap<String, Object>();//消息主题显示相关mapMap<String, Object> dataMap = new HashMap<String, Object>();//根据自己的模板定义内容和颜色dataMap.put("first",new DataEntity("您订阅的"+user.getNickname()+"社群发布了新商品","#173177"));dataMap.put("Pingou_ProductName",new DataEntity(name,"#0f0f0f"));dataMap.put("Weixin_ID",new DataEntity(user.getNickname(),"#173177"));dataMap.put("Remark",new DataEntity("点击查看详情进入主页","#F78934"));paramMap.put("touser", toUser);paramMap.put("template_id", template_id);paramMap.put("data", dataMap);
//            xcx.put("appid","小程序的appid"); 这个是跳转
//            xcx.put("pagepath","pages/index/index");
//            paramMap.put("miniprogram",xcx);//需要实现跳转网页的,可以添加下面一行代码实现跳转// paramMap.put("url","http://xxxxxx.html");System.out.println(doGetPost(sendMsgApi,"POST",paramMap));}}/*** 调用接口 post* @param apiPath*/public static String doGetPost(String apiPath, String type, Map<String, Object> paramMap){OutputStreamWriter out = null;InputStream is = null;String result = null;try{URL url = new URL(apiPath);// 创建连接HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setDoOutput(true);connection.setDoInput(true);connection.setUseCaches(false);connection.setInstanceFollowRedirects(true);connection.setRequestMethod(type) ; // 设置请求方式connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式connection.connect();if(type.equals("POST")){out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码out.append(JSON.toJSONString(paramMap));out.flush();out.close();}// 读取响应is = connection.getInputStream();int length = (int) connection.getContentLength();// 获取长度if (length != -1) {byte[] data = new byte[length];byte[] temp = new byte[512];int readLen = 0;int destPos = 0;while ((readLen = is.read(temp)) > 0) {System.arraycopy(temp, 0, data, destPos, readLen);destPos += readLen;}result = new String(data, "UTF-8"); // utf-8编码}} catch (IOException e) {e.printStackTrace();} finally {try {is.close();} catch (IOException e) {e.printStackTrace();}}return  result;}
  1. 小程序发布商品成功后公众号收到消息

总结

  1. 小程序和公众号绑定到同一个开放平台下;
  2. 如果是新的公众号没有任何用户关注的话,可以直接在后端监控关注事件然后去数据库对比;如果是已经有公众号用户了,就需要先拉取一遍公众号的用户存入数据库然后再进行比对;
  3. 公众号服务器配置需要是80端口或者443端口才能提交,token也要和后端对应,否则会 提示参数错误之类的;
  4. 小程序和公众号的关联都是通过unionid来联系的,这里一个用户表一个公众号表,小程序用户登录后得到unionid,然后存入数据库,公众号用户关注后获取unionid和openid,之后根据小程序的unionid去查询公众号的unionid得到openid之后就可以直接推送消息啦。

小程序关联公众号推送公众号消息相关推荐

  1. 小程序消息主动推送php,微信小程序有几种推送消息的方式

    微信小程序有5种推送消息的方式,分别为:1.小票机订单提醒,实现对商家的消息提醒:2.短信提醒:3.模板消息,各种动态可及时掌握:4.公众号订单提醒:5.消息主动推送,商家主动出击.推销自己的最好手段 ...

  2. 微信小程序云开发定时推送订阅消息

    微信小程序云开发定时推送订阅消息 1.找到自己想要的模板 (1)点击订阅消息 (2)点击公共模板库,然后找到想要选用的模板,点击选用. (3)在我的模板里面,复制模板id. 如果找不到想要用的模板,可 ...

  3. 微信公众号推送多图文消息,直接跳转至外部链接(wxJava)

    文章目录 前言 一.解决思路 1.公众号后台设置 2.客服消息 3.google & baidu 寻找答案 4.关注后自动推送(正解) 总结 前言 需求:用户关注公众号后,如何在微信推送的多图 ...

  4. uniapp如何使用微信小程序的订阅信息推送消息给用户?

    1.首先获取小程序用户登录openId // 获取openidasync opid() {let self = thiswx.login({success(res) {if (res.code) { ...

  5. 关于微信小程序uniapp版的推送消息

    1.按钮触发推送消息 <button type="primary" size="mini" @tap="pushMesage"> ...

  6. 教你设置微信小程序的服务通知推送!搜狗文章

    场景碎碎念:嗨喽,小伙伴闷,今天的学习到咯.通过咱们快一个月的学习,已经把平台的组件学习的差不多了,当然咱闷这个功能组件是在不停更新.不断完善的.今天咱们来学下"模板消息"推送功能 ...

  7. 尝试开发微信公众号消息推送功能并且和小程序关联

    之前写了几篇关于微信小程序的开发实践,总的来说没啥难度,感兴趣的请移步:使用Mpvue配合Weui开发面试题题库微信小程序,并且发布到正式环境,这一次我们来尝试开发一下微信公众号,那么公众号和小程序到 ...

  8. 微信小程序消息从公众号推送

    2020.06.05更新 新的一年认证续费只需要续费公众号. 小程序可以自动关联认证. 一定要记得!!!!!!! ------------------------------------------- ...

  9. 微信小程序向公众号推送消息超详细教程

    官方教程 官方教程 开通一下服务号公众号 超级管理员登录服务号公众号后台 登录地址 开通模板消息 申请一个模板消息,获取模板ID 注意此处的参数,后续接口需要使用 绑定公众号与小程序 官方教程 1.登 ...

最新文章

  1. Google发布Zipkin与Stackdriver Trace的集成功能
  2. 嵌入式成长轨迹11 【嵌入式环境及基础】【Linux shell深入】【深入讨论】
  3. 多协程爬取中大微博内容(以及转发数,点赞数,评论数)
  4. leetcode 7 Reverse Integer
  5. 开源与自由 | 商业自由:从边缘到核心贡献
  6. Dynamics 365执行操作报SQL Server已超时,更改这个超时设置的方法
  7. F. 张胖胖玩多米诺骨牌 (南阳理工oj—21新生第二场招新赛)
  8. 智能一代云平台(三十四):后端架构一些总结
  9. PreparedStatement 不定参数处理
  10. matlab卡住了 打不开,win7系统matlab打不开无法运行的解决方法
  11. 成功安装ubuntu一些东西
  12. kindle看pdf的文档字体调小了
  13. RAID技术详解与总结
  14. 李理:详解卷积神经网络
  15. 实至名归,凯联资本荣获融资中国第十一届资本年会多项荣誉
  16. Matlab 计算显色指数(Ra,R1-R15)、CCT、duv、Lux、XYZ三刺激值、CIE1931x、CIE1931y
  17. 页面报错405了怎么办
  18. 挫败感可以有,但还是加油吧
  19. ScrollView文字竖直滚动
  20. python关键词对联_对联数据

热门文章

  1. php ppt转视频教程,狸窝ppt转换器软件新手使用教程 ppt转换成视频格式
  2. mac外接键盘右击键映射之karabiner
  3. Monster Tower (堆 二分
  4. CSS3实现针线缝合效果
  5. 微信小程序----折叠面板(MUI折叠面板)
  6. webupload大文件上传的坑
  7. 读取解压h5文件为图片
  8. matlab常微分方程数值求解
  9. 三种技术实现PC1、PC2与PC3都通,而PC1与PC2不通
  10. simditor 上传图片php,simditor富文本编辑器最新最简单的使用方法