微信小程序订阅消息(java后端实现)开发


Posted in Javascript onJune 01, 2020

订阅消息说明

订阅消息是微信近期新出的一个能力,用来代替原有的模板消息(原有的模板消息即将下线)

订阅消息的功能较模板消息有所提升,"7天"的限制取消,同时有"一次性"和"永久"订阅.(功能上是这样说的,但是实际开发时发现"永久"订阅还是对小程序的服务类目有要求的,客户的小程序只支持"一次性"订阅)

官方通道:
小程序前端:点击进入
小程序服务端:点击进入

开发思路

用户在小程序内触发按钮或进行支付操作时前端调用订阅消息授权框,默认一次授权只能发送一次订阅消息
如果用户勾选"下次自动授权",下次将不再弹出授权框->点击按钮直接拥有一次发送订阅消息的机会,此处不需要模板消息的"formId",较之前更简单
经过测试,如果在小程序上多次点击触发授权的按钮,发送订阅消息的机会可以累加!!!
(如,1分钟内点击了10次按钮,后面将拥有10次发送订阅消息的机会,什么时候发都可以)

代码实现(仅java后端)

实体类部分

1.TemplateParam.java

public class TemplateParam { 

private String key; 
private String value; 

public TemplateParam(String key,String value){ 
 this.key=key; 
 this.value=value; 
} 
public String getValue() { 
 return value; 
} 
public void setValue(String value) { 
 this.value = value; 
}
public String getKey() {
 return key;
}
public void setKey(String key) {
 this.key = key;
} 
 
}

2.Template.java

import java.util.List;

public class Template { 
 
private String touser; 
private String template_id; 
private String page;
private List<TemplateParam> templateParamList; 


public String getTouser() {
 return touser;
}

public void setTouser(String touser) {
 this.touser = touser;
}

public String getTemplate_id() {
 return template_id;
}

public void setTemplate_id(String template_id) {
 this.template_id = template_id;
}

public String getPage() {
 return page;
}

public void setPage(String page) {
 this.page = page;
}



public String toJSON() { 
 StringBuffer buffer = new StringBuffer(); 
 buffer.append("{"); 
 buffer.append(String.format("\"touser\":\"%s\"", this.touser)).append(","); 
 buffer.append(String.format("\"template_id\":\"%s\"", this.template_id)).append(","); 
 buffer.append(String.format("\"page\":\"%s\"", this.page)).append(","); 
 buffer.append("\"data\":{"); 
 TemplateParam param = null; 
 for (int i = 0; i < this.templateParamList.size(); i++) { 
   param = templateParamList.get(i); 
  // 判断是否追加逗号 
  if (i < this.templateParamList.size() - 1){ 
   buffer.append(String.format("\"%s\": {\"value\":\"%s\"},", param.getKey(), param.getValue())); 
  }else{ 
   buffer.append(String.format("\"%s\": {\"value\":\"%s\"}", param.getKey(), param.getValue())); 
  } 
 } 
 buffer.append("}"); 
 buffer.append("}"); 
 return buffer.toString(); 
 } 

public List<TemplateParam> getTemplateParamList() { 
 return templateParamList; 
} 

public void setTemplateParamList(List<TemplateParam> templateParamList) { 
 this.templateParamList = templateParamList; 
} 
}

工具类部分

1.CommonUtil.java

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.ConnectException; 
import java.net.HttpURLConnection; 
import java.net.URL; 

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSocketFactory; 
import javax.net.ssl.TrustManager; 

import net.sf.json.JSONObject; 

public class CommonUtil { 
 
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) { 
  
 JSONObject jsonObject = null; 
 StringBuffer buffer = new StringBuffer(); 
 try { 
  // 创建SSLContext对象,并使用我们指定的信任管理器初始化 
  TrustManager[] tm = { new MyX509TrustManager() }; 
  SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); 
  sslContext.init(null, tm, new java.security.SecureRandom()); 
  // 从上述SSLContext对象中得到SSLSocketFactory对象 
  SSLSocketFactory ssf = sslContext.getSocketFactory(); 

  URL url = new URL(requestUrl); 
  HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); 
  httpUrlConn.setSSLSocketFactory(ssf); 

  httpUrlConn.setDoOutput(true); 
  httpUrlConn.setDoInput(true); 
  httpUrlConn.setUseCaches(false); 
  // 设置请求方式(GET/POST) 
  httpUrlConn.setRequestMethod(requestMethod); 

  if ("GET".equalsIgnoreCase(requestMethod)) { 
    httpUrlConn.connect(); 
  } 
    

  // 当有数据需要提交时 
  if (null != outputStr) { 
   OutputStream outputStream = httpUrlConn.getOutputStream(); 
   // 注意编码格式,防止中文乱码 
   outputStream.write(outputStr.getBytes("UTF-8")); 
   outputStream.close(); 
  } 

  // 将返回的输入流转换成字符串 
  InputStream inputStream = httpUrlConn.getInputStream(); 
  InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); 
  BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

  String str = null; 
  while ((str = bufferedReader.readLine()) != null) { 
   buffer.append(str); 
  } 
  bufferedReader.close(); 
  inputStreamReader.close(); 
  // 释放资源 
  inputStream.close(); 
  inputStream = null; 
  httpUrlConn.disconnect(); 
  jsonObject = JSONObject.fromObject(buffer.toString()); 
 } catch (ConnectException ce) { 
  ce.printStackTrace(); 
 } catch (Exception e) { 
  e.printStackTrace(); 
 } 
 return jsonObject; 
} 
 
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) { 
  
  
 StringBuffer buffer = new StringBuffer(); 
 try { 
  

  URL url = new URL(requestUrl); 
  HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); 
   

  httpUrlConn.setDoOutput(true); 
  httpUrlConn.setDoInput(true); 
  httpUrlConn.setUseCaches(false); 
  // 设置请求方式(GET/POST) 
  httpUrlConn.setRequestMethod(requestMethod); 

  if ("GET".equalsIgnoreCase(requestMethod)) { 
    httpUrlConn.connect(); 
  } 
    

  // 当有数据需要提交时 
  if (null != outputStr) { 
   OutputStream outputStream = httpUrlConn.getOutputStream(); 
   // 注意编码格式,防止中文乱码 
   outputStream.write(outputStr.getBytes("UTF-8")); 
   outputStream.close(); 
  } 

  // 将返回的输入流转换成字符串 
  InputStream inputStream = httpUrlConn.getInputStream(); 
  InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); 
  BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

  String str = null; 
  while ((str = bufferedReader.readLine()) != null) { 
   buffer.append(str); 
  } 
  bufferedReader.close(); 
  inputStreamReader.close(); 
  // 释放资源 
  inputStream.close(); 
  inputStream = null; 
  httpUrlConn.disconnect(); 
  //jsonObject = JSONObject.fromObject(buffer.toString()); 
 } catch (ConnectException ce) { 
  ce.printStackTrace(); 
 } catch (Exception e) { 
  e.printStackTrace(); 
 } 
 return buffer.toString(); 
} 
public static String urlEncodeUTF8(String source){ 
 String result = source; 
 try { 
  result = java.net.URLEncoder.encode(source,"utf-8"); 
 } catch (UnsupportedEncodingException e) { 
  e.printStackTrace(); 
 } 
 return result; 
} 
 
public static String httpsRequestForStr(String requestUrl, String requestMethod, String outputStr) { 
  
 String result=""; 
 StringBuffer buffer = new StringBuffer(); 
 try { 
  // 创建SSLContext对象,并使用我们指定的信任管理器初始化 
  TrustManager[] tm = { new MyX509TrustManager() }; 
  SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); 
  sslContext.init(null, tm, new java.security.SecureRandom()); 
  // 从上述SSLContext对象中得到SSLSocketFactory对象 
  SSLSocketFactory ssf = sslContext.getSocketFactory(); 

  URL url = new URL(requestUrl); 
  HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); 
  httpUrlConn.setSSLSocketFactory(ssf); 

  httpUrlConn.setDoOutput(true); 
  httpUrlConn.setDoInput(true); 
  httpUrlConn.setUseCaches(false); 
  // 设置请求方式(GET/POST) 
  httpUrlConn.setRequestMethod(requestMethod); 

  if ("GET".equalsIgnoreCase(requestMethod)) { 
    httpUrlConn.connect(); 
  } 
    

  // 当有数据需要提交时 
  if (null != outputStr) { 
   OutputStream outputStream = httpUrlConn.getOutputStream(); 
   // 注意编码格式,防止中文乱码 
   outputStream.write(outputStr.getBytes("UTF-8")); 
   outputStream.close(); 
  } 

  // 将返回的输入流转换成字符串 
  InputStream inputStream = httpUrlConn.getInputStream(); 
  InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); 
  BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

  String str = null; 
  while ((str = bufferedReader.readLine()) != null) { 
   buffer.append(str); 
  } 
  bufferedReader.close(); 
  inputStreamReader.close(); 
  // 释放资源 
  inputStream.close(); 
  inputStream = null; 
  httpUrlConn.disconnect(); 
  result=buffer.toString(); 
 } catch (ConnectException ce) { 
  ce.printStackTrace(); 
 } catch (Exception e) { 
  e.printStackTrace(); 
 } 
 return result; 
} 
 
}

2.HttpUtil.java

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpUtil {

private static final CloseableHttpClient httpclient = HttpClients.createDefault();

/**
 * 发送HttpGet请求
 * @param url
 * @return
 */
public static String sendGet(String url) {

 HttpGet httpget = new HttpGet(url);
 CloseableHttpResponse response = null;
 try {
  response = httpclient.execute(httpget);
 } catch (IOException e1) {
  e1.printStackTrace();
 }
 String result = null;
 try {
  HttpEntity entity = response.getEntity();
  if (entity != null) {
   result = EntityUtils.toString(entity);
  }
 } catch (Exception e) {
  e.printStackTrace();
 } finally {
  try {
   response.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 return result;
}

/**
 * 发送HttpPost请求,参数为map
 * @param url
 * @param map
 * @return
 */
public static String sendPost(String url, Map<String, String> map) {
 List<NameValuePair> formparams = new ArrayList<NameValuePair>();
 for (Map.Entry<String, String> entry : map.entrySet()) {
  formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
 }
 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
 HttpPost httppost = new HttpPost(url);
 httppost.setEntity(entity);
 CloseableHttpResponse response = null;
 try {
  response = httpclient.execute(httppost);
 } catch (IOException e) {
  e.printStackTrace();
 }
 HttpEntity entity1 = response.getEntity();
 String result = null;
 try {
  result = EntityUtils.toString(entity1);
 } catch (Exception e) {
  e.printStackTrace();
 }
 return result;
}

/**
 * 发送不带参数的HttpPost请求
 * @param url
 * @return
 */
public static String sendPost(String url) {
 HttpPost httppost = new HttpPost(url);
 CloseableHttpResponse response = null;
 try {
  response = httpclient.execute(httppost);
 } catch (IOException e) {
  e.printStackTrace();
 }
 HttpEntity entity = response.getEntity();
 String result = null;
 try {
  result = EntityUtils.toString(entity);
 } catch (Exception e) {
  e.printStackTrace();
 }
 return result;
}
 
}

jar包:

1.fastjson-1.2.44.jar

控制层代码:

1.获取ACCESS_TOKEN

String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
 + 小程序的appid
 + "&secret="
 + 小程序的Secret
 String result = HttpUtil.sendGet(url);
 JSONObject object=JSON.parseObject(result);
 String Access_Token = object.getString("access_token");

2.发送订阅消息

Template template=new Template(); 
 template.setTemplate_id("填写小程序申请的订阅消息id"); 
 template.setTouser("用户的openid");
 template.setPage("pages/index/index");
 List<TemplateParam> paras=new ArrayList<TemplateParam>(); 
 paras.add(new TemplateParam("character_string2","000001")); 
 paras.add(new TemplateParam("amount1","888.88")); 
 paras.add(new TemplateParam("date3","2015年01月05日")); 
 paras.add(new TemplateParam("thing4","请进入小程序查1看")); 
 template.setTemplateParamList(paras); 
  String requestUrl="https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN"; 
  requestUrl=requestUrl.replace("ACCESS_TOKEN", Access_Token);  
  
  System.out.println(template.toJSON());
  net.sf.json.JSONObject jsonResult=CommonUtil.httpsRequest(requestUrl, "POST", template.toJSON()); 
  if(jsonResult!=null){ 
  System.out.println(jsonResult);
   int errorCode=jsonResult.getInt("errcode"); 
   String errorMessage=jsonResult.getString("errmsg"); 
   if(errorCode==0){ 
    System.out.println("Send Success");
   }else{ 
    System.out.println("订阅消息发送失败:"+errorCode+","+errorMessage); 
   } 
  }

总结

1.本文阅读对象为初学者,所有各种工具类.jar包都粘出来了,直接复制即可使用
2.通过该功能的开发,发现小程序的通知类功能监管更加严格,必须用户授权才可以发订阅消息,同时用户可以更方便的取消订阅,所以建议开发者慎用此功能

到此这篇关于微信小程序订阅消息(java后端实现)开发的文章就介绍到这了,更多相关小程序订阅消息内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
工作中常用到的JS表单验证代码(包括例子)
Nov 11 Javascript
Jquery实现弹出层分享微博插件具备动画效果
Apr 03 Javascript
纯文字版返回顶端的js代码
Aug 01 Javascript
JS实现距离上次刷新已过多少秒示例
May 23 Javascript
js实现ArrayList功能附实例代码
Oct 29 Javascript
bootstrap table表格使用方法详解
Apr 26 Javascript
给Easyui-Datebox设置隐藏或者不可用的解决方法
May 26 Javascript
详解Angular6学习笔记之主从组件
Sep 05 Javascript
javascript中如何判断类型汇总
May 14 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
Aug 23 Javascript
微信小程序实现上拉加载功能
Nov 20 Javascript
JavaScript 浏览器对象模型BOM原理与常见用法实例分析
Dec 16 Javascript
微信小程序开发(三):返回上一级页面并刷新操作示例【页面栈】
Jun 01 #Javascript
微信小程序开发(二):页面跳转并传参操作示例
Jun 01 #Javascript
5个你不知道的JavaScript字符串处理库(小结)
Jun 01 #Javascript
基于Vue sessionStorage实现保留搜索框搜索内容
Jun 01 #Javascript
微信小程序开发(一):服务器获取数据列表渲染操作示例
Jun 01 #Javascript
JavaScript forEach中return失效问题解决方案
Jun 01 #Javascript
原生JS封装拖动验证滑块的实现代码示例
Jun 01 #Javascript
You might like
PHP+FLASH实现上传文件进度条相关文件 下载
2007/07/21 PHP
完美实现GIF动画缩略图的php代码
2011/01/02 PHP
php源码分析之DZX1.5随机数函数random用法
2015/06/17 PHP
PHP随机获取未被微信屏蔽的域名(微信域名检测)
2017/03/19 PHP
jQuery 性能优化指南 (1)
2009/05/21 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
jquery ajax传递中文参数乱码问题及解决方法说明
2014/02/07 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
了不起的node.js读书笔记之node.js中的特性
2014/12/22 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
2016/01/21 Javascript
jQuery 获取多选框的值及多选框中文的函数
2016/05/16 Javascript
js实现当鼠标移到表格上时显示这一格全部内容的代码
2016/06/12 Javascript
微信小程序 SocketIO 实例讲解
2016/10/13 Javascript
vue按需加载组件webpack require.ensure的方法
2017/12/13 Javascript
Vue实现带进度条的文件拖动上传功能
2018/02/23 Javascript
Vue+element-ui 实现表格的分页功能示例
2018/08/18 Javascript
JavaScript函数、闭包、原型、面向对象学习笔记
2018/09/06 Javascript
原生JavaScript实现随机点名表
2021/01/14 Javascript
Python实例分享:快速查找出被挂马的文件
2014/06/08 Python
Python处理RSS、ATOM模块FEEDPARSER介绍
2015/02/18 Python
Python的Flask框架中Flask-Admin库的简单入门指引
2015/04/07 Python
python:pandas合并csv文件的方法(图书数据集成)
2018/04/12 Python
python3解析库BeautifulSoup4的安装配置与基本用法
2018/06/26 Python
详解PANDAS 数据合并与重塑(join/merge篇)
2019/07/09 Python
Python 利用flask搭建一个共享服务器的步骤
2020/12/05 Python
皮肤科医师岗位职责
2013/12/04 职场文书
高三语文教学反思
2014/01/15 职场文书
运动会入场解说词300字
2014/01/25 职场文书
学生会竞选演讲稿学习部
2014/08/25 职场文书
2015毕业生实习工作总结
2014/12/12 职场文书
还款承诺书范本
2015/01/20 职场文书
学生会生活部工作总结2015
2015/03/31 职场文书
计划生育工作总结2015
2015/04/03 职场文书
详解MySQL InnoDB存储引擎的内存管理
2021/04/08 MySQL
golang 比较浮点数的大小方式
2021/05/02 Golang
Python实现视频中添加音频工具详解
2021/12/06 Python