小程序订阅消息(用户通过弹窗订阅)开发指南 | 微信开放文档 (qq.com)
一. 在小程序后台申请模板获得模板ID
二.相关代码
2.1 编写相关实体类
2.1.1 详细内容类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataClaimVO {
private Map<String,String> thing4;
private Map<String,String> name2;
private Map<String,String> phone_number3;
private Map<String, LocalDate> time5;
}
2.1.2 通知订阅类
此处根据自己的实际业务书写,有多个模板就需要使用泛型
一个模板直接用final即可
@Data
public class WxInfoVO<T> {
/**
* 用户openid
*/
private String touser;
/**
* 模版id
*/
private String template_id;
/**
* 默认
*/
private static final String page = "pages/index/index";
/**
* "data": {
* "thing1": "身份证",
* "name2": "风清默",
* "phone_number4": "113132",
* "date3": "2024-4-25"
* },
*/
private T data;
/**
* 转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
*/
private static final String miniprogram_state = "developer";
private static final String lang = "zh_CN";
//category 0 :物品找回通知 通知失主 1:失物认领通知 通知发布(捡到的人)
public WxInfoVO(String touser, Boolean category, T dataVO) {
this.touser = touser;
this.template_id = (!category ? 模板1id : 模板2id);
this.data = dataVO;
}
}
2.1.3 小程序配置类
@Component
@ConfigurationProperties(prefix = "xunhang.wechat.wxinfo")
@Data
public class WeChatProperties {
private String appid; //小程序的appid
private String secret; //小程序的秘钥
private String mchid; //商户号
private String mchSerialNo; //商户API证书的证书序列号
private String privateKeyFilePath; //商户私钥文件
private String apiV3Key; //证书解密的密钥
private String weChatPayCertFilePath; //平台证书
private String notifyUrl; //支付成功的回调地址
private String refundNotifyUrl; //退款成功的回调地址
}
2.2 相关工具类
2.2.1 http请求类
public class HttpClientUtil {
static final int TIMEOUT_MSEC = 5 * 1000;
/**
* 发送GET方式请求
* @param url
* @param paramMap
* @return
*/
public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = "";
CloseableHttpResponse response = null;
try{
URIBuilder builder = new URIBuilder(url);
if(paramMap != null){
for (String key : paramMap.keySet()) {
builder.addParameter(key,paramMap.get(key));
}
}
URI uri = builder.build();
//创建GET请求
HttpGet httpGet = new HttpGet(uri);
//发送请求
response = httpClient.execute(httpGet);
//判断响应状态
if(response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(response.getEntity(),"UTF-8");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
response.close();
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (paramMap != null) {
List<NameValuePair> paramList = new ArrayList();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
httpPost.setConfig(builderRequestConfig());
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static<T> String doPostByJson(String url, T object) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
if (object != null) {
//构造json格式数据
// 将对象转换为JSON字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr= JSONUtil.toJsonStr(object);
StringEntity entity = new StringEntity(jsonStr,"utf-8");
//设置请求编码
entity.setContentEncoding("utf-8");
//设置数据类型
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
httpPost.setConfig(builderRequestConfig());
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
private static RequestConfig builderRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(TIMEOUT_MSEC)
.setConnectionRequestTimeout(TIMEOUT_MSEC)
.setSocketTimeout(TIMEOUT_MSEC).build();
}
}
2.2.2 微信功能类(核心)
这里我使用了 Redis 存储 accessToken
@Component
public class WxUtil {
@Autowired
private WeChatProperties weChatProperties;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void getAccessToken() {
String appid = weChatProperties.getAppid();
String secret = weChatProperties.getSecret();
String grant_type = "client_credential";
Map<String, String> map = new HashMap<String, String>();
map.put("appid", appid);
map.put("secret", secret);
map.put("grant_type", grant_type);
String json = HttpClientUtil.doGet(WX_ACCESS_TOKEN_URL, map);
JSONObject jsonObject = JSONObject.parseObject(json);
Integer errcode = jsonObject.getInteger("errcode");
if (errcode == null || errcode == 0) {
String accessToken = jsonObject.getString("access_token");
Integer expiresIn = jsonObject.getInteger("expires_in");
stringRedisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, expiresIn, TimeUnit.SECONDS);
} else {
throw new WxServiceException("调用accessToken失败");
}
}
public String sendSubscribeInfo(WxInfoVO wxInfoVO) throws InterruptedException, IOException {
String token = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
if (token == null) {
getAccessToken();
}
Integer t = 0;
while (token == null && t < 10) {
token = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
t++;
Thread.sleep(100);
}
if (token == null) {
throw new WxServiceException("获取不到accessToken");
}
String json = HttpClientUtil.doPostByJson(WX_SEND_SUBSCRIBE_URL + "?access_token=" + token,wxInfoVO);
return json;
}
}
2.3 相关依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--redis连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- hutoo-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.15</version>
</dependency>
<!--fastJSON-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.40</version>
</dependency>
三.执行
@SpringBootTest
public class WxinfoApplicationTests {
@Autowired
WxUtil wxUtil;
@Test
public void test() throws IOException, InterruptedException {
Map<String, String> thing1 = new HashMap<>();
thing1.put("value","身份证");
Map<String, String> name2 = new HashMap<>();
name2.put("value","风清默");
Map<String, String> phone_number4 = new HashMap<>();
phone_number4.put("value","1199293");
Map<String, LocalDateTime> date3 = new HashMap<>();
date3.put("value",LocalDateTime.now());
DatafoundVO dataVO = new DatafoundVO(thing1, name2, phone_number4,date3);
WxInfoVO wxInfoVO = new WxInfoVO(用户openid,false,dataVO);
// System.out.println(JSONUtil.toJsonStr(wxInfoVO));
System.out.println(wxUtil.sendSubscribeInfo(wxInfoVO));
}
}
成功