DDR爱好者之家 Design By 杰米

订阅消息说明

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

订阅消息的功能较模板消息有所提升,"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"
 + 小程序的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"; 
  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.通过该功能的开发,发现小程序的通知类功能监管更加严格,必须用户授权才可以发订阅消息,同时用户可以更方便的取消订阅,所以建议开发者慎用此功能

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。