日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微信订阅通知实战

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信订阅通知实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

一、微信訂閱通知是什么?

二、使用步驟

1.開通訂閱通知服務

2.獲取access_token

我們微信業務和內部業務項目是分離的,所以只在微信項目中實現接口供內部項目調用即可.具體的接口如下

接口完成后,在業務項目中調用接口即可.

總結




前言

截止至2021-11-2, 微信的訂閱通知還在灰度測試當中,傳說微信的模板消息即將下線,所以采用微信的訂閱通知來發送通知.??本文為實戰中的微信訂閱通知功能開發記錄, 目前已經在線上測試使用,僅供參考.



一、微信訂閱通知是什么?

模板消息被濫用, 很多用戶被騷擾, 微信為了管理,引入訂閱通知, 分為一次性訂閱,和長期訂閱兩種,一次性訂閱: 訂閱一次,能給用戶發送一條消息.? 長期訂閱: 訂閱一次, 目前來看無限次發送消息. 本文為長期訂閱案例, 一次性訂閱對于我們來說沒有價值.


二、使用步驟


1.開通訂閱通知服務

根據微信文檔開通即可, 需要提供公司的 <<資質授權文件>>,審核幾個小時一般就會有結果,通過后只能選取微信提供的模板,長期訂閱的模板很少,就幾個,不一定符合業務需求,只能湊合用.


2.獲取access_token

? ? ?必須操作!

  • yaml文件中添加 wechat:appId: wx005a........6ffappSecret: 18000b98b...........71b3e058
  • ? ? ?2.??AccessToken 類接收 "獲取access_token接口"

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

    ? ? ? 3.WeixinToken? 內存中保存access_token?

    /*** @Title: WeixinToken* @Description: 持有微信Access_token的對象* @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("系統獲取access_token出錯了!");}return token;}}

    5.開啟spring定時任務? 加入@EnableScheduling 注解

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

    6.定時任務獲取access_token (倆小時失效,必須倆小時之內更新access_token)

    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: 獲取微信access_token 定時任務* @date 2021-10-25 11:10*/ @Component public class AccessTokenTask {private Logger logger = LoggerFactory.getLogger(AccessTokenTask.class);@Autowiredprivate WeixinAccessTokenUtil weixinAccessTokenUtil;@Value("${wechat.appId}")private String appId;@Value("${wechat.appSecret}")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("獲取到的微信accessToken為" + token);} catch (Exception e) {logger.error("獲取微信adcessToken出錯,信息如下");e.printStackTrace();}}@Scheduled(initialDelay = 3000, fixedDelay = 1000 * 1000)public void testWeixinAccessT() {logger.info(WeixinToken.token);} }

    7.其中http發送用的是httpclient, 如果沒遺漏的話,就不需要其他依賴了.

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

    我們微信業務和內部業務項目是分離的,所以只在微信項目中實現接口供內部項目調用.具體的接口如下

    1.?WeixinMsg 接口用來接收業務相關數據

    @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.Controller中 , 其中R是自定義的返回結果實體,替換為你自己的返回結果Result即可!

    //發送微信訂閱消息@CrossOrigin(maxAge = 3600, origins = "*")@PostMapping("/subscribe/sendWeixinMsg")public R sendWeixinMsg(@RequestBody WeixinMsg weixinMsg) {Assert.isTrue(null != weixinMsg.getUserCode() && null != weixinMsg.getTemplateId() && null != weixinMsg.getMap(), "參數不正確");return weixinSendMsgService.send(weixinMsg);}

    3.接口

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

    4.service代碼,

    UserWechatMapper 和 其中String openId = userWechatMapper.queryOpenIdByUserCode(userCode);是我們有專門頁面,實現微信openId和業務之間Id的綁定.?可根據實際情況, 只要知道微信用戶的openId即可,具體獲取openId的功能,參考官方文檔!

    ImSmsWeixinMapper 和下方的private方法是業務代碼,記錄發送的日志,屏蔽或改成你自己的業務代碼即可.

    @Service("weixinSendMsgService") public class WeixinSendMsgServiceImpl implements WeixinSendMsgService {private Logger logger = LoggerFactory.getLogger(WeixinSendMsgServiceImpl.class);@Resourceprivate UserWechatMapper userWechatMapper;@Resourceprivate ImSmsWeixinMapper imSmsWeixinMapper;@Overridepublic 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("對用戶{}發送模板{}消息失敗,用戶未綁定無法獲取openId!", userCode, templateId);imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, "用戶未綁定,無法發送模板消息"));return R.fail("微信消息發送失敗,用戶未綁定");}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("對用戶{}發送模板{}消息成功!", userCode, templateId);} else {logger.error("對用戶{}發送模板{}消息異常!", userCode, templateId);logger.error("發送數據為:[{}]!", data);logger.error("錯誤碼:[{}]!", errcode);logger.error("錯誤信息:[{}]!", errmsg);imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, errmsg));return R.fail("微信消息發送失敗,錯誤碼" + errcode);}} catch (IOException e) {e.printStackTrace();logger.error("對用戶{}發送模板{}消息異常!", userCode, templateId);logger.error("發送數據為:[{}]!", data);imSmsWeixinMapper.insertSelective(getFailLog(now, userCode, openId, templateId, data, "程序發送出現了異常,請檢查" + 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. 一個問題:??開發過程中遇到? ? ?接口提示{"errcode":47001,"errmsg":"data.......}的問題, 檢查過json, 網上說單引號雙引號的問題,? ?我測試不是引號的問題,只要json格式正確即可.? 主要是發送的方式問題.? 開始的時候用的是UrlEncodeEntity這種方式發送的, 導致出現了47001問題, 上面代碼發送方式完全沒問題

    6. 我在官網上找了,沒找到可以提供測試的接口和方法, 只有線上測試了,? 發送一個圖文消息,? 在文章末尾插入訂閱消息插件 如圖

    ?7.用戶在文章中點擊訂閱通知,就能選擇相關訂閱, 訂閱后,再點擊訂閱就不再彈出訂閱框了.

    接口完成后,在業務項目中調用接口即可.

    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();}}}


    總結

    以上是生活随笔為你收集整理的微信订阅通知实战的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。