微信小程序订阅消息开发指南(java)
微信小程序订阅消息开发指南(java)
第一步 准备阶段
1、你得有一个小程序,并且认证了,个人的也行
2、开通订阅消息
小程序后台
->功能
->订阅消息
3、公共模板库选择一个模板
选择的时候,选择你需要的字段,因为字段有限制
4、我的模板点击详情
详情内容,模板 id 都是需要提供个服务端开发人员的
第二步 编码阶段
小程序端
小程序消息订阅,需要用户确认
1、首先小程序授权登陆获取 code
官网示例:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html
wx.login({ success (res) { if (res.code) { //发起网络请求 wx.request({ url: 'https://example.com/onLogin', data: { code: res.code } }) } else { console.log('登录失败!' + res.errMsg) } } }) // 结果 {errMsg: "login:ok", code: "0a3kK4Ga10Gk3F0oBAHa1mGyRl3kK4Gd"}
uni-App 示例:https://uniapp.dcloud.net.cn/api/plugins/login.html#login
uni.login({ provider: 'weixin', //使用微信登录 success: function (loginRes) { console.log(loginRes) } }); // 结果 {errMsg: "login:ok", code: "0a3kK4Ga10Gk3F0oBAHa1mGyRl3kK4Gd"}
2、将 code
传给服务端 获取用户唯一标识 openId
3、通过代码起小程序消息订阅界面、用户点击确定ok,小程序工作结束
tmplIds
填写模板 id 即可,最多三个
wx.requestSubscribeMessage({ tmplIds: [''], success (res) { console.log(res) } })
4、注意事项:
避免重复拉起用户订阅通知,可以通过微信提供的
getSetting
判断用户是否订阅了,如果没有就拉起。注意下面是用
uniapp
写的,方法前缀是uni
如果你小程序代码记得修改wx
以及提示组件到此小程序工作结束
getSetting() { uni.getSetting({ withSubscriptions: true, // 获取用户订阅状态 success(res) { // false 表示用户未订阅改消息 if (!res.subscriptionsSetting.mainSwitch) { this.subscribeMessage(); } else { uni.showToast({ title: '已订阅', icon: 'none' }) } } }) }, subscribeMessage() { uni.requestSubscribeMessage({ tmplIds: ['模板id'], success(res) { if (res.errMsg === 'requestSubscribeMessage:ok') { uni.showToast({ title: '订阅成功', icon: 'none' }) } } }) }
服务端
微信小程序的
appid
和secret
小程序后台
->开发
->开发管理
->开发设置
->开发者 ID
注意事项:
http
请求这里使用 apache 的工具类,你也可以使用别的- 微信消息模板字段
thing
字段有长度限制20,超过会失败 - 以下演示代码,生产环境还需进行优化
1、通过 code 获取用户 open id 官网文档
public String getOpenId(String code) throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); params.put("appid", Constants.APPLET_APP_ID); params.put("secret", Constants.APPLET_SECRET); params.put("js_code", code); params.put("grant_type", "authorization_code"); String url = handleParams("https://api.weixin.qq.com/sns/jscode2session", params); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); } public static void main(String[] args) throws IOException { HttpUtils httpUtils = new HttpUtils(); String token = httpUtils.getToken(); System.out.println(token); }
响应结果:
{"access_token":"67_u22CQaWq22222222Q4griDE6kiT5hwg7jVxedn8J9te17Az1oWGGxPgB22222229Y4Wm6h_Yzci7-FSDjeH8YG6DsCOYrQXJCWsPXhT6nWbKIWCXfABACID","expires_in":7200}
2、通过 appid
和 secret
获取 token 超时 7200 秒 可 redis 缓存 官方文档
public String getToken() throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); params.put("appid", Constants.APPLET_APP_ID); params.put("secret", Constants.APPLET_SECRET); params.put("grant_type", "client_credential"); String url = handleParams("https://api.weixin.qq.com/cgi-bin/token", params); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); }
3、指定用户推送消息结束 官方文档
public String pushMsg(String token) throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); // 处理微信推送数据结构 JSONObject mapData = new JSONObject(); Map<String, Object> map1 = new HashMap<>(); map1.put("value", "任务名称"); mapData.put("thing2", map1); Map<String, Object> map2 = new HashMap<>(); map2.put("value", "2022-04-03 10:00:00"); mapData.put("time3", map2); Map<String, Object> map3 = new HashMap<>(); map3.put("value", "描述信息"); mapData.put("thing4", map3); Map<String, Object> map4 = new HashMap<>(); map4.put("value", "备注信息"); mapData.put("thing10", map4); Map<String, Object> map5 = new HashMap<>(); map5.put("value", "任务来源"); mapData.put("thing11", map5); params.put("template_id", "templateId");// 模板 id params.put("touser", "openId"); // open id params.put("data", mapData); // 数据 params.put("page", "page"); // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转 params.put("miniprogram_state", "trial"); //developer为开发版;trial为体验版;formal为正式版;默认为正式版 params.put("lang", "zh_CN"); // HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token); httpPost.addHeader("ContentTyp", "application/json"); // 参数转 JSON 格式 String json = objToStr(params); StringEntity stringEntity = new StringEntity(json, CharSetType.UTF8.getType()); stringEntity.setContentEncoding(CharSetType.UTF8.getType()); httpPost.setEntity(stringEntity); CloseableHttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); }
4、完整代码
import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.chenlijia1111.utils.core.enums.CharSetType; import org.apache.http.HttpEntity; 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.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.jeecg.modules.video.utitls.Constants; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; /** * @description: * @author: Mr.Fang * @create: 2023-04-03 17:06 **/ public class HttpUtils { /** * description: 获取token,返回结果为 JSON 自行转 map * create by: Mr.Fang * * @return: java.lang.String * @date: 2023/4/3 17:46 */ public String getToken() throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); params.put("appid", Constants.APPLET_APP_ID); params.put("secret", Constants.APPLET_SECRET); params.put("grant_type", "client_credential"); String url = handleParams("https://api.weixin.qq.com/cgi-bin/token", params); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); } /** * description: 获取 open id,返回结果为 JSON 自行转 map * create by: Mr.Fang * * @param: [code] * @return: java.lang.String * @date: 2023/4/3 17:46 */ public String getOpenId(String code) throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); params.put("appid", Constants.APPLET_APP_ID); params.put("secret", Constants.APPLET_SECRET); params.put("js_code", code); params.put("grant_type", "authorization_code"); String url = handleParams("https://api.weixin.qq.com/sns/jscode2session", params); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); } /** * description: 消息推送 返回结果为 JSON 自行转 map;token 调用 getToken获取 * create by: Mr.Fang * * @param: [token] * @return: java.lang.String * @date: 2023/4/3 17:46 */ public String pushMsg(String token) throws IOException { CloseableHttpClient httpClient = HttpClientBuilder.create().build(); Map<String, Object> params = new HashMap<>(); // 处理微信推送数据结构 JSONObject mapData = new JSONObject(); Map<String, Object> map1 = new HashMap<>(); map1.put("value", "任务名称"); mapData.put("thing2", map1); Map<String, Object> map2 = new HashMap<>(); map2.put("value", "2023-04-03 12:00:00"); mapData.put("time3", map2); Map<String, Object> map3 = new HashMap<>(); map3.put("value", "描述信息"); mapData.put("thing4", map3); Map<String, Object> map4 = new HashMap<>(); map4.put("value", "备注系信息"); mapData.put("thing10", map4); Map<String, Object> map5 = new HashMap<>(); map5.put("value", "抖音"); mapData.put("thing11", map5); params.put("template_id", "templateId");// 模板 id params.put("touser", "openId"); // open id params.put("data", mapData); // 数据 params.put("page", "page"); // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转 params.put("miniprogram_state", "trial"); //developer为开发版;trial为体验版;formal为正式版;默认为正式版 params.put("lang", "zh_CN"); // HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token); httpPost.addHeader("ContentTyp", "application/json"); // 参数转 JSON 格式 String json = objToStr(params); StringEntity stringEntity = new StringEntity(json, CharSetType.UTF8.getType()); stringEntity.setContentEncoding(CharSetType.UTF8.getType()); httpPost.setEntity(stringEntity); CloseableHttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); // 响应结果 return EntityUtils.toString(entity, CharSetType.UTF8.getType()); } /** * description: 对象转 字符串 * create by: Mr.Fang * * @param: [obj] * @return: java.lang.String * @date: 2023/4/3 17:45 */ public static String objToStr(Object obj) { ObjectMapper objectMapper = new ObjectMapper(); if (Objects.nonNull(obj)) { try { String jsonStr = objectMapper.writeValueAsString(obj); return jsonStr; } catch (JsonProcessingException var2) { var2.printStackTrace(); } } return null; } /** * description: map 转 URL 地址拼接 * create by: Mr.Fang * * @param: [url, params] * @return: java.lang.String * @date: 2023/4/3 17:45 */ public String handleParams(String url, Map<String, Object> params) { if (params.size() != 0) { Set<Map.Entry<String, Object>> entries = params.entrySet(); String paramsString = entries.stream().map((e) -> { try { StringBuilder sb = new StringBuilder(); sb.append(URLEncoder.encode(e.getKey(), CharSetType.UTF8.getType())); sb.append("="); if (Objects.nonNull(e.getValue())) { sb.append(URLEncoder.encode(e.getValue().toString(), CharSetType.UTF8.getType())); } return sb.toString(); } catch (UnsupportedEncodingException var2) { var2.printStackTrace(); return null; } }).collect(Collectors.joining("&")); return url + "?" + paramsString; } return url; } }
哇!又赚了一天人民币
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库