Java后台+微信小程序实现推送 “服务通知” 您所在的位置:网站首页 微信怎样显示小程序客服消息提醒 Java后台+微信小程序实现推送 “服务通知”

Java后台+微信小程序实现推送 “服务通知”

#Java后台+微信小程序实现推送 “服务通知”| 来源: 网络整理| 查看: 265

微信小程序+java后台实现,小程序推送“服务通知”给用户

成功步骤:

1.注册微信小程序app,然后登陆微信公众平台开通“消息推送”,配置url、token等参数 2.平台——模板消息——我的模板 申请模板,获取模板id、配置的字段名 3.在外网80/443的接口中放一个可以验证签名的接口(详情见下文)。 4.Java后台写发送消息的工具类 5.小程序写一个可以获取formId、openid的页面 6.用真机调试中获取到的参数在java工具类中main方法测试发送通知。成功!

0、登录微信公众平台,开启小程序“消息推送”功能

https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN

开发——开发设置——消息推送 在这里插入图片描述 注意:URL填写的是:要在外网能访问的接口(需要80或者443端口才行),该接口需要包括能够验证签名的方法,具体方法如下:

只需要把下面接口中的WECHAT_TOKEN :改成 消息推送的"Token(令牌)"值 一样即可。

import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * 微信授权 */ @Controller @Slf4j @RequestMapping("api/wx") public class APIWxController{ // 与接口配置信息中的Token要一致 private static String WECHAT_TOKEN = "WECHAT_TOKEN"; @RequestMapping("/checkToken") public void get(HttpServletRequest request, HttpServletResponse response) throws Exception { log.info("========checkToken Controller========= "); boolean isGet = request.getMethod().toLowerCase().equals("get"); PrintWriter print; if (isGet) { // 微信加密签名 String signature = request.getParameter("signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echostr = request.getParameter("echostr"); // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (signature != null && checkSignature(signature, timestamp, nonce)) { try { print = response.getWriter(); print.write(echostr); print.flush(); log.info("========checkToken success ========= "); } catch (IOException e) { e.printStackTrace(); } }else{ log.error("========checkToken failed========= "); } }else { log.error("========checkToken failed:Only support Get Method ========="); } } /** * 验证签名 * * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkSignature(String signature, String timestamp, String nonce) { String[] arr = new String[] { WECHAT_TOKEN, timestamp, nonce }; // 将token、timestamp、nonce三个参数进行字典序排序 // Arrays.sort(arr); sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 将字节数组转换为十六进制字符串 * * @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; } public static void sort(String a[]) { for (int i = 0; i if (a[j].compareTo(a[i]) //字段值例如:keyword1:订单类型,keyword2:下单金额,keyword3:配送地址,keyword4:取件地址,keyword5备注 private String value;//依次排下去 // private String color;//字段颜色(微信官方已废弃,设置没有效果) }

WxMssVo .java

import lombok.Data; import java.util.Map; /* * 小程序推送所需数据 * */ @Data public class WxMssVo { private String touser;//用户openid private String template_id;//模版id private String page = "pages/index/index";//默认跳到小程序首页 private String form_id;//收集到的用户formid // private String emphasis_keyword = "keyword1.DATA";//放大那个推送字段 private Map data;//推送文字 } 2、java后台创建发送消息推送类

WeChatService.java 该类包括以下主要方法: 1、推送通知的主要方法类: /** * * @param access_token app的token * @param openid 用户openid * @param formId 表单ID * @param templateId 模板ID * @param keywords {与模板字段一一对应} * @return / public String pushOneUser(String access_token,String openid, String formId,String templateId,String[] keywords) 2、获取app的access_token 方法 / * 获取access_token * appid和appsecret到小程序后台获取,当然也可以让小程序开发人员给你传过来 * */ public String getAccess_token()

import com.alibaba.fastjson.JSONObject; import com.weixin.demo.entity.TemplateDataVo; import com.weixin.demo.entity.WxMssVo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; @Slf4j @Service public class WeChatService { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } @Autowired private RestTemplate restTemplate; /** * * @param access_token app的token * @param openid 用户openid * @param formId 表单ID * @param templateId 模板ID * @param keywords {与模板字段一一对应} * @return */ public String pushOneUser(String access_token,String openid, String formId,String templateId,String[] keywords) { //如果access_token为空则从新获取 if(StringUtils.isEmpty(access_token)){ access_token = getAccess_token(); } String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send" + "?access_token=" + access_token; //拼接推送的模版 WxMssVo wxMssVo = new WxMssVo(); wxMssVo.setTouser(openid);//用户openid wxMssVo.setForm_id(formId);//formId wxMssVo.setTemplate_id(templateId);//模版id Map m = new HashMap(); //封装数据 if(keywords.length>0){ for(int i=1;i log.error("keywords长度为空"); return null; } if(restTemplate==null){ restTemplate = new RestTemplate(); } ResponseEntity responseEntity = restTemplate.postForEntity(url, wxMssVo, String.class); log.error("小程序推送结果={}", responseEntity.getBody()); return responseEntity.getBody(); } /* * 获取access_token * appid和appsecret到小程序后台获取,当然也可以让小程序开发人员给你传过来 * */ public String getAccess_token() { //获取access_token String appid = "wxb1abfc1724c5ee8b"; String appsecret = "c88a5dd3c3af8228a389d778fce3e32b"; String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appid=" + appid + "&secret=" + appsecret; if(restTemplate==null){ restTemplate = new RestTemplate(); } String json = restTemplate.getForObject(url, String.class); JSONObject myJson = JSONObject.parseObject(json); return myJson.get("access_token").toString(); } public static void main(String[] args) { System.out.println(new WeChatService().getAccess_token()); WeChatService weChatUtil = new WeChatService(); String values[] ={"Jack方","2019-5-8 10:10:10","xxx有限公司","JAVA开发","xx区xx广场xx号","请带好入职材料"}; weChatUtil.pushOneUser(weChatUtil.getAccess_token() ,"o_fh25E0IufW7NIpezUReODfVH68","ec76b8b81cd04cf6b464bb0adf309d3b","zv0IsYDpJxgKWLHGUy8FEv0ajtJqkfhWTsFWiM7zzSU" ,values); } } 3、微信小程序(小程序申请什么的就自己去操作吧)

我们在本地的小程序开发工具构建一个这样的页面来测试下: 为什么是这样的页面?主要是为了方便获取openid、formId 在这里插入图片描述

index.wxml 只有 元素中 加上report-submit=“true” 才能获取得到formId,formId有效期为7天,一个formId只能发送一次通知,发完就不能再用了,formId是发送推送信息的必要条件。

获取用户唯一标识openid openid:{{openid}} session_key:{{session_key}} formId:{{formId}} 发送模板消息 errcode:{{errcode}} errmsg:{{errmsg}} 获取列表

index.js 将index.js中的下面几个参数换成你的即可 const APP_ID = 'APP_ID ';//输入小程序appid const APP_SECRET = 'APP_SECRET ';//输入小程序app_secret

//index.js //获取应用实例 const app = getApp() const APP_ID = 'APP_ID ';//输入小程序appid const APP_SECRET = 'APP_SECRET ';//输入小程序app_secret var OPEN_ID = ''//储存获取到openid var SESSION_KEY = ''//储存获取到session_k var FORM_ID = ''//储存获取到的formId Page({ data: { motto: 'Hello World', userInfo: {}, hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') }, //事件处理函数 bindViewTap: function () { wx.navigateTo({ url: '../list/list' }) }, onLoad: function () { if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } else if (this.data.canIUse) { // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { // 在没有 open-type=getUserInfo 版本的兼容处理 wx.getUserInfo({ success: res => { app.globalData.userInfo = res.userInfo this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) } }, getUserInfo: function (e) { console.log(e) app.globalData.userInfo = e.detail.userInfo this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) }, getOpenIdTap: function (e) { var that = this; FORM_ID = e.detail.formId;//获取到formId console.log("formId1:"+FORM_ID) that.setData({ formId: FORM_ID }) wx.login({ success: function (res) { wx.request({ //获取openid接口 url: 'https://api.weixin.qq.com/sns/jscode2session', data: { appid: APP_ID, secret: APP_SECRET, js_code: res.code, grant_type: 'authorization_code' }, method: 'GET', success: function (res) { OPEN_ID = res.data.openid;//获取到的openid SESSION_KEY = res.data.session_key;//获取到session_key console.log("openid:" + OPEN_ID) console.log("session_key:" + SESSION_KEY) that.setData({ openid: OPEN_ID, session_key: SESSION_KEY }) } }) } }) }, testSubmit: function (e) { var that = this; wx.request({ url: 'http://127.0.0.1:80/pushMsg', method: 'POST', data: { access_token:null, openid:OPEN_ID, formid:FORM_ID }, success: function (res) { that.setData({ errcode: res.data.errcode, errmsg: res.data.errmsg }) console.log(res) }, fail: function (err) { console.log('request fail ', err); }, complete: function (res) { console.log("request completed!"); } }) } }) 运行小程序,点击获取openid、formId

如果出现如下图所示:formId is a mock one。 说明需要我们用真机测试才能获取formId 在这里插入图片描述 点击“真机调试”,用手机扫描二维码 在这里插入图片描述 拿到我们需要的openId、formId 在这里插入图片描述

回到java后台WeChatService.java

用main方法测试一下。推送成功! 在这里插入图片描述 看下手机端展示: 在这里插入图片描述 在这里插入图片描述

为什么不直接在 小程序中直接发送“模板消息”? 答:主要是因为真机测试时,手机不能调用本地的接口,所以不好测试,我们用真机测试获取formId,在放在java后台,模拟调用接口测试 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有