Wechat subscription notification practice

preface 1, What is wechat subscription notification? 2, Use steps 1. Subscribe to notification service 2. Get access_tok...
1. Subscribe to notification service
2. Get access_token
Our wechat business and internal business projects are separated, so we only implement interfaces in wechat projects for internal projects to call. The specific interfaces are as follows
After the interface is completed, the interface can be invoked in the business project.

preface

1, What is wechat subscription notification?

2, Use steps

1. Subscribe to notification service

2. Get access_token

Our wechat business and internal business projects are separated, so we can only implement the interface in the wechat project for internal project calls. The specific interface is as follows

After the interface is completed, the interface can be invoked in the business project.

summary


preface

As of November 2, 2021, the subscription notice of wechat is still under gray scale test. It is said that the template message of wechat will be offline soon, so the subscription notice of wechat is used to send the notice    This article is the development record of wechat subscription notification function in practice. At present, it has been tested online for reference only


1, What is wechat subscription notification?

Template messages are abused and many users are harassed. In order to manage, wechat introduces subscription notifications, which are divided into one-time subscription and long-term subscription. One-time subscription: one subscription can send a message to users   Long term subscription: Subscribe once. At present, send messages indefinitely. This article is a case of long-term subscription. One-time subscription is of no value to us


2, Use steps


1. Subscribe to notification service

According to the wechat document, the company's < < Qualification Authorization Document > > needs to be provided. Generally, there will be results after a few hours of review. After passing, only the templates provided by wechat can be selected. There are few long-term subscription templates, which do not necessarily meet the business needs and can only be used together


2. Get access_token

      Must operate!

  1. Add to yaml file
    wechat: appId: wx005a........6ff appSecret: 18000b98b...........71b3e058

      two    AccessToken class receives "get access_token interface"

@Data public class AccessToken { private String accessToken; private Long expiresIn; }

      3.WeixinToken   Save access in memory_ token  

/** * @Title: WeixinToken * @Description: Hold wechat Access_token object * @date 2021-10-25 11:09 */ public class WeixinToken { public static String token; }

        4.WeixinAccessTokenUtil Access_token

@Component public class WeixinAccessTokenUtil { private Logger logger = LoggerFactory.getLogger(WeixinAccessTokenUtil.class); public AccessToken getToken(String appid, String appSecrect) { AccessToken token = new AccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/token" + "?grant_type=client_credential&appid=" + appid+ "&secret=" + appSecrect; HttpClient httpClient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet(url); ResponseHandler<String> responseHandler = new BasicResponseHandler(); try { String response = httpClient.execute(httpGet,responseHandler); JsonObject returnData = new JsonParser().parse(response).getAsJsonObject(); if(returnData != null){ token.setAccessToken(returnData.get("access_token").getAsString()); token.setExpiresIn(returnData.get("expires_in").getAsLong()); } } catch (IOException e) { token = null; e.printStackTrace(); logger.error("System acquisition access_token Something went wrong!"); } return token; } }

5. Start the spring scheduled task   Add @ enableshcheduling annotation

@SpringBootApplication @ServletComponentScan @EnableScheduling public class WeixinApplication { public static void main(String[] args) { SpringApplication.run(WeixinApplication.class, args); } }

6. Obtain access for scheduled tasks_ Token (invalid within two hours, and the access_token must be updated within two hours)

package com.qqrw.wx.service.impl; import com.qqrw.wx.entity.WeixinToken; import com.qqrw.wx.util.WeixinAccessTokenUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * @Title: AccessTokenTask * @Description: Get wechat access_token timed task * @date 2021-10-25 11:10 */ @Component public class AccessTokenTask { private Logger logger = LoggerFactory.getLogger(AccessTokenTask.class); @Autowired private WeixinAccessTokenUtil weixinAccessTokenUtil; @Value("$") private String appId; @Value("$") private String appSecret; @Scheduled(initialDelay = 1000, fixedDelay = 7000 * 1000) public void getWeixinAccessToken() { try { String token = weixinAccessTokenUtil.getToken(appId, appSecret).getAccessToken(); WeixinToken.token = token; logger.info("Wechat obtained accessToken by" + token); } catch (Exception e) { logger.error("Get wechat adcessToken Error, the information is as follows"); e.printStackTrace(); } } @Scheduled(initialDelay = 3000, fixedDelay = 1000 * 1000) public void testWeixinAccessT() { logger.info(WeixinToken.token); } }

7. http is sent with httpclient. If there is no omission, there is no need for other dependencies

<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>$</version> </dependency>

Our wechat business and internal business projects are separated, so we only implement interfaces in wechat projects for internal projects to call. The specific interfaces are as follows

one   The WeixinMsg interface is used to receive service related data

@Data public class WeixinMsg { private String userCode; private String templateId; private Map<String,Object> map; public String getUserCode() { return userCode; } public void setUserCode(String userCode) { this.userCode = userCode; } public String getTemplateId() { return templateId; } public void setTemplateId(String templateId) { this.templateId = templateId; } public Map<String, Object> getMap() { return map; } public void setMap(Map<String, Object> map) { this.map = map; } }

2. In the controller, where R is a user-defined return Result entity, replace it with your own return Result!

//Send wechat subscription message @CrossOrigin(maxAge = 3600, origins = "*") @PostMapping("/subscribe/sendWeixinMsg") public R sendWeixinMsg(@RequestBody WeixinMsg weixinMsg) { Assert.isTrue(null != weixinMsg.getUserCode() && null != weixinMsg.getTemplateId() && null != weixinMsg.getMap(), "parameter is incorrect"); return weixinSendMsgService.send(weixinMsg); }

3. Interface

public interface WeixinSendMsgService { R send(WeixinMsg weixinMsg); }

4.service code,

UserWechatMapper and where String openId = userWechatMapper.queryOpenIdByUserCode(userCode); Yes, we have a special page to realize the binding between wechat openId and business Id   According to the actual situation, just know the openId of wechat users. For specific functions of openId, please refer to the official documents!

ImSmsWeixinMapper and the private method below are business codes. Record the sending log, mask or change it to your own business code

@Service("weixinSendMsgService") public class WeixinSendMsgServiceImpl implements WeixinSendMsgService { private Logger logger = LoggerFactory.getLogger(WeixinSendMsgServiceImpl.class); @Resource private UserWechatMapper userWechatMapper; @Resource private ImSmsWeixinMapper imSmsWeixinMapper; @Override public R send(WeixinMsg weixinMsg) { System.out.println(weixinMsg); Date now = new Date(); String userCode = weixinMsg.getUserCode(); String openId = userWechatMapper.queryOpenIdByUserCode(userCode); String templateId = weixinMsg.getTemplateId(); Map<String, Object> map = weixinMsg.getMap(); Map<String, Map<String, Object>> data = new HashMap<>(); if (StringUtils.isBlank(openId)) { logger.info("For users{}Send template{}Message failed,The user is not bound and cannot be obtained openId!", userCode, templateId); imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, "User not bound,Unable to send template message")); return R.fail("Wechat message sending failed,User not bound"); } for (Map.Entry<String, Object> entry : map.entrySet()) { HashMap<String, Object> one = new HashMap<>(); one.put("value", entry.getValue()); data.put(entry.getKey(), one); } System.out.println(openId); System.out.println(data); String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token=" + WeixinToken.token; try { HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Content-Type", "application/json"); String charSet = "UTF-8"; Map<String, Object> params = new HashMap<>(); params.put("access_token", WeixinToken.token); params.put("touser", openId); params.put("template_id", templateId); params.put("data", data); StringEntity entity = new StringEntity(JsonUtils.toJson(params), charSet); httpPost.setEntity(entity); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String response = httpClient.execute(httpPost, responseHandler); JsonObject returnData = new JsonParser().parse(response).getAsJsonObject(); int errcode = returnData.get("errcode").getAsInt(); String errmsg = returnData.get("errmsg").getAsString(); if ("ok".equals(errmsg)) { imSmsWeixinMapper.insertSelective(getSuccessLog(now, userCode, openId, templateId, data)); logger.info("For users{}Send template{}Message succeeded!", userCode, templateId); } else { logger.error("For users{}Send template{}Message exception!", userCode, templateId); logger.error("Send data as:[{}]!", data); logger.error("Error code:[{}]!", errcode); logger.error("error message:[{}]!", errmsg); imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, errmsg)); return R.fail("Wechat message sending failed,Error code" + errcode); } } catch (IOException e) { e.printStackTrace(); logger.error("For users{}Send template{}Message exception!", userCode, templateId); logger.error("Send data as:[{}]!", data); imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, "The program sent an exception,Please check" + e.getMessage())); } return R.ok(); } private ImSmsWeixin getSuccessLog(Date now, String userCode, String openId, String templateId, Map<String, Map<String, Object>> data) { ImSmsWeixin imSmsWeixin = genLog(now, userCode, openId, templateId, data); imSmsWeixin.setState(1); return imSmsWeixin; } private ImSmsWeixin getFailLog(Date now, String userCode, String openId, String templateId, Map<String, Map<String, Object>> data, String errorMsg) { ImSmsWeixin imSmsWeixin = genLog(now, userCode, openId, templateId, data); imSmsWeixin.setState(2); imSmsWeixin.setErrorMsg(errorMsg); return imSmsWeixin; } private ImSmsWeixin genLog(Date now, String userCode, String openId, String templateId, Map<String, Map<String, Object>> data) { ImSmsWeixin imSmsWeixin = new ImSmsWeixin(); imSmsWeixin.setUserCode(userCode); imSmsWeixin.setOpenId(openId); imSmsWeixin.setTemplateId(templateId); imSmsWeixin.setData(JsonUtils.toJson(data)); imSmsWeixin.setSendTime(now); return imSmsWeixin; } }

5. One question:    Encountered during development       The interface prompts {"errcode":47001,"errmsg":"data....}. I checked json and said single quotation marks and double quotation marks on the Internet,     My test is not about quotes, as long as the json format is correct   It's mainly about the way of sending   At the beginning, it was sent in the way of UrlEncodeEntity, resulting in 47001 problem. The above code sending method is completely OK

6. I found it on the official website, but I couldn't find the interface and method that can provide testing. I only had online testing,   Send a text message,   Insert the subscription message plug-in at the end of the article, as shown in the figure

  7. Click the subscription notice in the article to select the relevant subscription. After subscribing, click the subscription again to stop the subscription box from popping up

After the interface is completed, the interface can be invoked in the business project.

public class WeixinMsgUtil { private static HttpClient httpClient = new DefaultHttpClient(); public static void sendWeixinSms(String userCode, String templateId, Map data) { HashMap<String, Object> params = new HashMap<>(); params.put("userCode",userCode); params.put("templateId",templateId); params.put("map",data); String url = "http://123.456.12.12:8080/api/subscribe/sendWeixinMsg"; HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Content-Type", "application/json"); String charSet = "UTF-8"; StringEntity entity = new StringEntity(JsonUtil.toJson(params), charSet); httpPost.setEntity(entity); ResponseHandler<String> responseHandler = new BasicResponseHandler(); try { httpClient.execute(httpPost, responseHandler); } catch (IOException e) { e.printStackTrace(); } } }

1 November 2021, 20:55 | Views: 9854

Add new comment

For adding a comment, please log in
or create account

0 comments