该篇文章主要讲的是后台如何对小程序登录的用户进行通知。
ps:由于开发时间和写文章时间间隔过久,细节上的可能不是很详细,但是会把整体功能,以及代码实现贴上来。
通知效果:
解释: 简单的说就是用户登陆过小程序那便可以,将自己想要推送的内容发送到用户的微信当中,微信当中有一个叫服务通知的东西,推送的内容会在上面显示。
上面这种消息模板是在微信公众平台–>功能–>模板消息下面配置的,具体模板显示内容可以调整。
1. 推送必须的东西
首先呢这两个一个叫小程序Id一个叫小程序密钥这两个是可以在微信公众平台查到的。
接下来有三个url这个是发送推送消息必不可少的,第一个url是获取小程序全局唯一后台接口调用凭据;第二个接口是微信小程序推送接口,第三个接口是简单讲就是获取openId。然后微信开发者公众平台开发接口目录如下:微信公众平台开放接口
//获取access_token
private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
//推送url
private final static String PUSH_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=";
//根据code换取openId
//本接口应在后端服务器调用
private final static String CODE_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=";
以上这5个算是准备工作吧,然后接下来就是正式进入推送了。
2. 首先我们创建一个获取openId的工具类
根据官方文档和摸索一下,这个获取openId还是很简单的。
官方上的解释是: 登录凭证校验。通过 wx.login() 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。
也就是说上面说的第三个接口,通过把code传递到后台,然后通过后台调用第三个接口,便可以获取我们想得到接口,具体代码如下:
//获取小程序codeid换取openid
public static String getOpenId(String codeId) {
String url = CODE_URL + APP_ID + "&secret=" + SECRET + "&js_code=" + codeId + "&grant_type=authorization_code";
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer sb = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性 设置请求格式
//设置返回类型
conn.setRequestProperty("contentType", "text/plain");
//设置请求类型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//设置超时时间
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应 设置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
sb.append(line);
}
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
return jsonObject.get("openid").toString();
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
这样我们就换取用户的唯一标识 openId,具体上面的代码可以直接复用也比较简单就不多啰嗦了。
3. 接下来呢我们就要获取access_token(本接口应在后端服务器调用)
关于access_token的官方解释: 获取小程序全局唯一后台接口调用凭据(access_token)。调用各后台接口时都需使用 access_token,开发者需要进行妥善保存。
看官方的解释我们不难理解,access_token是调用微信后台接口比不可少的东西。注意事项官方也很明确的写出来了如下:
获取access_token工具类如下:
public static JSONObject getAccessToken() {
String url = ACCESS_TOKEN_URL + "appid=" + APP_ID + "&secret=" + SECRET;
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer sb = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性 设置请求格式
//设置返回类型
conn.setRequestProperty("contentType", "text/plain");
//设置请求类型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//设置超时时间
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应 设置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
sb.append(line);
}
// 将获得的String对象转为JSON格式
JSONObject jsonObject = JSONObject.parseObject(sb.toString());
return jsonObject;
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
解释已经很详细了,最后再说一些细节的操作先把工具类放出来。
4.推送工具类 (本接口应在后端服务器调用)
推送的具体实现具体的参数啊,还是查看官方文档再次不多赘述了。模板消息推送官方解释
代码如下:
/**
* 推送工具类
* @author 柚子
* @date 2018/12/25
* @param params 推送消息内容
* @param accessToken
* @return boolean
*/
public static boolean setPush(String params, String accessToken) {
boolean flag = false;
String url = PUSH_URL + accessToken;
OutputStream outputStream = null;
InputStreamReader inputStreamReader = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
HttpsURLConnection connection = null;
try {
// 创建URL对象
URL realUrl = new URL(url);
// 打开连接 获取连接对象
connection = (HttpsURLConnection) realUrl.openConnection();
// 设置请求编码
connection.addRequestProperty("encoding", "UTF-8");
// 设置允许输入
connection.setDoInput(true);
// 设置允许输出
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != params) {
outputStream = connection.getOutputStream();
// 注意编码格式
outputStream.write(params.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
inputStream = connection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "utf-8");
bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
JSONObject jsonObject = JSONObject.parseObject(buffer.toString());
int errorCode = jsonObject.getInteger("errcode");
String errorMessage = jsonObject.getString("errmsg");
if (errorCode == 0) {
flag = true;
} else {
logger.info("模板消息发送失败:" + errorCode + "," + errorMessage);
flag = false;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 依次关闭打开的输入流
try {
connection.disconnect();
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
// 依次关闭打开的输出流
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return flag;
}
请求数据的示例在官网当中是有的,json形式的数据也就是对应params参数,accessToken参数我们是通过传递进来的当然也可以写死。
5.最后的实现描述
关于推送的实现的描述:
代码如下所示:
/**
* 功能描述
*
* @param openId 小程序openId
* @param formId 小程序formId
* @param title 通知标题
* @param content 通知内容
* @return boolean
* @author youzi
* @date 2018/12/14
*/
private boolean pushNoticeUtil(String openId, String formId, String title,String content) {
logger.info("pushNoticeUtil方法开始");
//缓存access_token
if (redisUtils.get("access_token") == null || redisUtils.get("access_token").toString() == "") {
JSONObject jsonObject = getAccessToken();
if (jsonObject.get("expires_in") != null && jsonObject.get("expires_in").toString() != ""
&& Integer.parseInt(jsonObject.get("expires_in").toString()) == 7200) {
redisUtils.set("access_token", jsonObject.get("access_token"), 2 * 60 * 60L);
}
}
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("touser", openId);
// DINING_TEMPLATE 模板Id 微信公众平台添加模板时生成的ID
jsonObject1.put("template_id", DINING_TEMPLATE);
jsonObject1.put("form_id", formId);
JSONObject jsonObject2 = new JSONObject();
JSONObject jsonObject3 = new JSONObject();
jsonObject3.put("value", title);
jsonObject2.put("keyword1", jsonObject3);
jsonObject3 = new JSONObject();
jsonObject3.put("value", content);
jsonObject2.put("keyword2", jsonObject3);
jsonObject1.put("data", jsonObject2);
boolean pushResult = setPush(jsonObject1.toString(), redisUtils.get("access_token"));
logger.info("pushNoticeUtil方法结束:推送结果" + pushResult);
return pushResult;
}
疑问: formId是什么? 简单的将就是小程序发送请求传递的一个东西,作用是用户发送消息模板消息,具体的获取官方文档如下:获取formId
只是简单的解释一下可能不是很清楚,但是只要知道想要推送消息,那就必须要formId。
整体流程:
首先微信小程序登录,登录我们会获取到openId,将其和自己后台登录绑定到一起这样我们就可以保存下来openId用来推送,然后我们在小程序登录的时候模拟发送请求获取多个formId,将获取到的formId和openId保存到数据库表中,但是要注意formId是有时效性的如果时效了,推送也会推送不到用户。
然后我们便可以准备推送了,推送时我们可以先获取accessToken,将accessToken 放进redis里面设置过期时间,如果过期了我们重新获取,否则不需要重新获取,官方的建议也是如此。然后组装我们的推送数据,具体的组装数据需要根据模板确定,但是形式上是一样,然后调用推送此时便可以发现推送成功了。
最后: 如果还有疑问的话大家可以联系我,一起探讨一下qq704273004,谢谢。