位置: IT常识 - 正文

SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)(springboot整合ssm)

编辑:rootadmin
SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)

目录

概述

公众号给关注用户推送自定义消息

一、申请公众号模板消息

二、获取安装“web开发者工具”

三、微信网页授权说明

四、微信网页授权 - 流程时序图

五、HTTPClient 实现微信公众号消息推送与发布(四步走)

六、通过weixin-java-mp SDK实现微信公众号消息推送与发布(七步走)

七、抽取与封装


概述

推荐整理分享SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)(springboot整合ssm),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:springboot整合sentinel,springboot整合ssm,springboot整合canal,springboot整合canal,springboot整合consul,springboot整合jedis,springboot整合jedis,springboot整合canal,内容如对您有帮助,希望把文章链接给更多的朋友!

本篇文章主要基于Java+Spring Boot+Spring Cloud的应用中接入微信公众号,调用微信的JavaSDK > weixin-java-mp进行应用消息推送,实现业务数据推送到指定的微信用户客户端。通过本篇博客,将快速上手,从0到1构建起消息推送与发布。

公众号给关注用户推送自定义消息一、申请公众号模板消息

1、开通微信公众号平台的“模板消息”栏

提交申请:

添加功能插件>功能详情>申请开通模板接口> 填写业务服务目标所属的行业,申请理由,

如果是新申请的消息模板,需要注意规范,否则会被封号的可能!!!

等待审核通过就可以使用了!

“模板消息”开通审核通过后,在微信公众号平台>左边栏>广告与服务>就可以看到模板消息栏了,

接着,就可以添加用于业务系统推送公众号的模板消息内容了,

如下图: 

 添加完成后,就可以在,模板消息>我的模板,中进行查看了,如下图:

关于推送的模板消息内容,用两种定义方式: 1、用公众号模板库已经存在的,也就是别人之前申请过的, 2、如果在模板消息库中检索不到符合当下业务系统需求的消息模板内容,则可以自定义,在模板库中选择“帮助我们完善模板库” 如下图:

 添加自定义的微信公众号模板的内容的注意事项: 1、添加模版前,需要先仔细阅读《模版消息申请添加前必读指引》。请勿违反运营规则,否则可能被停用模版消息接口甚至封号的可能; 2、贡献新模版需要等待“7-15”天审核期,且内容可能被审核人员修改。每月只可申请新建3个新模版; 3、审核通过后,模版将放入模版库以供他人使用,会被官方共享出去,也就是这里的消息模板,没有私有这一说,之前博主的客户提需求,说必须要私有的,不能共享,因为这不是自己能控制的,遂进行了多轮沟通后最终才说服了客户;

二、获取安装“web开发者工具”

《web开发者工具稳定版下载》

微信web开发者工具,安装完成后,打开应用程序,选择“公众号网页项目”, 如下图;

为公众号绑定开发者:

如果出现 “ 该微信用户未开启“公众号安全助手”的消息接收功能,请先开启后再绑定 ”

参考:

《该微信用户未开启“公众号安全助手”的消息接收功能,请先开启后再绑定》

邀请绑定,

设置完成后,再次邀请绑定即可完成绑定了,如下图:

绑定成功后,再打开,微信公众号平台>设置与开发>开发者工具>选择“web开发者工具”>如下图(web开发者工具最多可绑定50人), 如下图:

三、微信网页授权说明

1、微信开发网页授权五步走

第一步:用户同意授权,获取code 在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(已认证服务号,默认拥有 scope 参数中的snsapi_base和snsapi_userinfo 权限),引导关注者打开如下页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有 scope 参数对应的授权作用域权限。

注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问,跳转回调redirect_uri,应当使用 https 链接来确保授权 code 的安全性。

参考链接(请在微信客户端中打开此链接体验):

scope为snsapi_base:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

scope为snsapi_userinfo:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

用户同意授权后

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。

code说明:

code作为换取access_token的票据,每次用户授权带上的 code 将不一样,code只能使用一次,5分钟未被使用自动过期。

请求参数说明:

回调错误码说明:

第二步:通过 code 换取网页授权access_token

首先请注意,这里通过 code 换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

注意:由于公众号的 secret 和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。

请求方法

获取 code 后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

请求参数说明:

  

回调参数说明:

回调错误码说明:

 

更多返回码说明请参看:

【全局返回码说明】

第三步:刷新access_token(可选项)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。

请求方法

获取第二步的refresh_token后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

请求参数说明:

回调参数说明:

回调错误码说明:参看第二步回调错误码说明!

SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(手把手从0到1)(springboot整合ssm)

第四步:拉取用户信息(scope 为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和 openid 拉取用户信息了。

请求方法

http:GET(请使用 https 协议):

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

关于scope授权作用域:

/** * oauth2网页授权的scope. */ public static class OAuth2Scope { /** * 不弹出授权页面,直接跳转,只能获取用户openid. */ public static final String SNSAPI_BASE = "snsapi_base"; /** * 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息. */ public static final String SNSAPI_USERINFO = "snsapi_userinfo"; /** * 手动授权,可获取成员的详细信息,包含手机、邮箱。只适用于企业微信或企业号. */ public static final String SNSAPI_PRIVATEINFO = "snsapi_privateinfo"; }

请求参数说明:

回调参数说明:

回调错误码说明:参看第二步回调错误码说明!

第五步:检验授权凭证(access_token)是否有效(可选项)

请求方法

http:GET(请使用 https 协议):

https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

请求参数说明:

回调参数说明:

两个参数(errcode、errmsg)

回调错误码说明:参看第二步回调错误码说明!

2、其它说明

一、关于网页授权回调域名的说明 1、在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头。

2、授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com 无法进行OAuth2.0鉴权。 3、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可。

二、关于网页授权的两种 scope 的区别说明 1、以snsapi_base为 scope 发起的网页授权,是用来获取进入页面的用户的 openid 的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)。

2、以snsapi_userinfo为 scope 发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户 OpenID 来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

三、关于网页授权access_token和普通access_token的区别 1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息。

2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。

四、微信网页授权 - 流程时序图

五、HTTPClient 实现微信公众号消息推送与发布(四步走)

第一步:获取微信公众号CODE

/** * Description:[获取公众号CODE] * * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatCode") @ApiOperation(value = "/getWeChatCode", notes = "获取公众号CODE") public void getWeChatCode(HttpServletResponse response) { try { // 构建公众号消息体 String weChatGetCodeUrl = String.format(this.WE_CHAT_CODE_URL, this.WE_CHAT_APP_ID, this.WE_CHAT_CALL_BACK_DOMAIN_URL, WxConsts.OAuth2Scope.SNSAPI_BASE); log.info("we_chat_get_code_url:" + weChatGetCodeUrl); response.sendRedirect(weChatGetCodeUrl); } catch (Exception e) { log.info("异常信息:{}", e); } }

 请求回调获取的用户授权CODE,如下图:

第二部:根据Code获取用户OpenId

/** * Description:[根据Code获取用户OpenId] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatOpenId") @ApiOperation(value = "/getWeChatOpenId", notes = "根据Code获取用户OpenId") public JSONResult getWeChatOpenId(@RequestParam String code, @RequestParam String state) { try { log.info("we_chat_code: " + code); String weChatDomain = String.format(this.WE_CHAT_AUTHORIZATION_URL, this.WE_CHAT_APP_ID, this.WE_CHAT_SECRET, code); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> responseEntity = restTemplate.getForEntity(weChatDomain, String.class); String openid = JSONObject.parseObject(responseEntity.getBody()).getString("openid"); String access_token = JSONObject.parseObject(responseEntity.getBody()).getString("access_token"); // 用户的OpenId,用户的微信授权Access_Token log.info("we_chat_open_id: " + openid); log.info("we_chat_access_token: " + access_token); return JSONResult.success(openid); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

 获取的openid如下图:

第三步:根据Code获取用户Access_Token(可选)

/** * Description:[根据Code获取用户Access_Token] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getUserAccessToken") @ApiOperation(value = "/getUserAccessToken", notes = "根据Code获取用户Access_Token") public JSONResult getUserAccessToken(@RequestParam String code, @RequestParam String state) { try { String weChatDomain = String.format(this.WE_CHAT_AUTHORIZATION_URL, this.WE_CHAT_APP_ID, this.WE_CHAT_SECRET, code); log.info("we_chat_authorization_url:{}" + weChatDomain); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> responseEntity = restTemplate.getForEntity(weChatDomain, String.class); String accessToken = JSONObject.parseObject(responseEntity.getBody()).getString("access_token"); log.info("we_chat_access_token: " + accessToken); return JSONResult.success(accessToken); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第四步:获取微信公众号的Access_Token

/** * Description:[获取微信公众号的Access_Token] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatAccessToken") @ApiOperation(value = "/getWeChatAccessToken", notes = "微信公众号的Access_Token") public JSONResult getWeChatAccessToken() { try { // 微信公众号官方获取AccessToken RestTemplate restTemplate = new RestTemplate(); String requestParams = String.format(this.WE_CHAT_ACCESS_TOKEN_URL, this.WE_CHAT_APP_ID, this.WE_CHAT_SECRET); ResponseEntity<String> responseEntity = restTemplate.getForEntity(requestParams, String.class); String accessToken = JSONObject.parseObject(responseEntity.getBody()).getString("access_token"); log.info("we_chat_access_token: " + accessToken); return JSONResult.success(accessToken); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第五步:微信公众号指定用户消息推送与发布

/** * Description:[公众号指定用户消息推送] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/sendWeChatRecharge") @ApiOperation(value = "/sendWeChatRecharge", notes = "公众号指定用户消息推送") public JSONResult sendWeChatRecharge() { // 1、构建公众号消息体 WeChatRechargeTemplateParamsDTO weChatRechargeTemplateParamsDTO = WeChatRechargeTemplateParamsDTO.builder() .first("尊敬用户您好,你的缴费结果如下:") .keyword1("HuaZai") .keyword2("10010110010001") .keyword3(BigDecimal.valueOf(2000)) .keyword4(BigDecimal.valueOf(10000182.92)) .keyword5(DateUtil.getDateTime()) .remark("缴费成功,祝您生活愉快!") .touser("**********") .customerNumber("549527") .build(); // 2、组装消息数据 Map<String, WeChatMsgDTO> weChatMsgMap = new HashMap<>(); weChatMsgMap.put("first", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getFirst())); weChatMsgMap.put("keyword1", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getKeyword1())); weChatMsgMap.put("keyword2", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getKeyword2())); weChatMsgMap.put("keyword3", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getKeyword3().toString())); weChatMsgMap.put("keyword4", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getKeyword4().toString())); weChatMsgMap.put("keyword5", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getKeyword5())); weChatMsgMap.put("remark", new WeChatMsgDTO(weChatRechargeTemplateParamsDTO.getRemark())); String customerCallUrl = String.format(this.WE_CHAT_CUSTOMER_CALL_URL, weChatRechargeTemplateParamsDTO.getCustomerNumber()); //3、构建模板消息体 WeChatTemplateParamsDTO weChatTemplateParamsDTO = WeChatTemplateParamsDTO.builder() .touser(weChatRechargeTemplateParamsDTO.getTouser()) .template_id(this.WE_CHAT_TEMPLATE_ID) .url(customerCallUrl) .topcolor(this.WE_CHAT_TOP_COLOR) .data(weChatMsgMap) .build(); // 4、微信公众号消息推送与发布 RestTemplate restTemplate = new RestTemplate(); String resultUrl = String.format(this.WE_CHAT_REQUEST_URL, this.WE_CHAT_ACCESS_TOKEN); ResponseEntity<String> responseEntity = restTemplate.postForEntity(resultUrl, weChatTemplateParamsDTO, String.class); if (!OK.equals(responseEntity.getStatusCode())) { log.error("公众号消息推送失败!", responseEntity.getBody()); } return JSONResult.success(); }

消息推送,返回code为0,即表示消息已成功推送(否则失败,需要code码和上面的错误信息说明进行对比,针对性问题处理),如下图:

再打开微信公众号,就可以看到推送的消息了,如下图:

 

常量说明:

// 微信公众号的 app_id String WE_CHAT_APP_ID = "**********"; // 微信公众号的 secret String WE_CHAT_SECRET = "**********"; // 微信公众号的 access_token String WE_CHAT_ACCESS_TOKEN = "**********"; // 微信公众号code获取地址 String WE_CHAT_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=STATE#wechat_redirect"; // 回调地址,获取open_id String WE_CHAT_CALL_BACK_DOMAIN_URL = "https://***.***.***.***/***/***/getWeChatOpenId"; // 微信公众号的token获取地址 String WE_CHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; // 微信公众号消息推送地址 String WE_CHAT_REQUEST_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s"; // 微信公众号推送消息模板id String WE_CHAT_TEMPLATE_ID = "**********"; // 微信公众号的消息回调地址(这儿可根据业务需求自定义动作,可选) String WE_CHAT_CUSTOMER_CALL_URL = "https://***.***.***.***/***/***/accountInfo?keyword=%s"; // 微信公众号的主题颜色 String WE_CHAT_TOP_COLOR = "#A349A4"; // 微信公众号微信用户授权地址 String WE_CHAT_AUTHORIZATION_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";六、通过weixin-java-mp SDK实现微信公众号消息推送与发布(七步走)

第一步:pom.xml新增依赖

<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>4.3.0</version> </dependency>

第二步:配置WxMpService

配置me.chanjar.weixin.mp.api.WxMpService,可以通过@Component组件注入交由Spring进行管理,或者直接在启动类@SpringBootApplication中@Bean注入,

注入的内容如下:

@Bean public WxMpService wxMpService() { WxMpMapConfigImpl wxMpMapConfig = new WxMpMapConfigImpl(); wxMpMapConfig.setAppId(Constant.WE_CHAT_APP_ID); wxMpMapConfig.setSecret(Constant.WE_CHAT_SECRET); val wxMpService = new WxMpServiceImpl(); wxMpService.setWxMpConfigStorage(wxMpMapConfig); return wxMpService; }

 第三步:获取微信公众号CODE

@Autowired private WxMpService wxMpService; /** * Description:[获取公众号CODE] * * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatCode") @ApiOperation(value = "/getWeChatCode", notes = "获取公众号CODE") public RedirectView getWeChatCode() { try { // 构造网页授权url String authorizationUrl = wxMpService.getOAuth2Service().buildAuthorizationUrl(this.WE_CHAT_CALL_BACK_DOMAIN_URL, WxConsts.OAuth2Scope.SNSAPI_BASE, null); log.info("we_chat_get_code_url:" + authorizationUrl); return new RedirectView(authorizationUrl); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第四步:根据Code获取用户OpenId

/** * Description:[根据Code获取用户OpenId] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatOpenId") @ApiOperation(value = "/getWeChatOpenId", notes = "根据Code获取用户OpenId") public JSONResult getWeChatOpenId(@RequestParam String code, @RequestParam String state) { try { log.info("we_chat_code: " + code); // 通过微信回调过来的code获得access token,其中也包含用户的openid等信息 WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code); String openid = wxOAuth2AccessToken.getOpenId(); String access_token = wxOAuth2AccessToken.getAccessToken(); // 用户的OpenId,用户的微信授权Access_Token log.info("we_chat_open_id: " + openid); log.info("we_chat_access_token: " + access_token); return JSONResult.success(openid); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第五步:根据Code获取用户Access_Token(可选)

/** * Description:[根据Code获取用户Access_Token] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getUserAccessToken") @ApiOperation(value = "/getUserAccessToken", notes = "根据Code获取用户Access_Token") public JSONResult getUserAccessToken(@RequestParam String code, @RequestParam String state) { try { // 根据Code获取用户Access_Token WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code); String accessToken = wxOAuth2AccessToken.getAccessToken(); log.info("we_chat_user_access_token: " + accessToken); return JSONResult.success(accessToken); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第六步:获取微信公众号的Access_Token  

/** * Description:[获取微信公众号的Access_Token] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/getWeChatAccessToken") @ApiOperation(value = "/getWeChatAccessToken", notes = "微信公众号的Access_Token") public JSONResult getWeChatAccessToken() { try { // 微信公众号官方获取AccessToken String accessToken = wxMpService.getAccessToken(); log.info("we_chat_access_token: " + accessToken); return JSONResult.success(accessToken); } catch (Exception e) { log.info("异常信息:{}", e); } return null; }

第七步:微信公众号指定用户消息推送与发布

/** * Description:[公众号指定用户消息推送] * * @return JSONResult * @date 2019-05-19 * @author huazai */ @GetMapping("/sendWeChatRecharge") @ApiOperation(value = "/sendWeChatRecharge", notes = "公众号指定用户消息推送") public JSONResult sendWeChatRecharge() { try { // 1、构建公众号消息体 WeChatRechargeTemplateParamsDTO weChatRechargeTemplateParamsDTO = WeChatRechargeTemplateParamsDTO.builder() .first("尊敬用户您好,你的缴费结果如下:") .keyword1("HuaZai") .keyword2("10010110010001") .keyword3(BigDecimal.valueOf(2000)) .keyword4(BigDecimal.valueOf(10000182.92)) .keyword5(DateUtil.getDateTime()) .remark("缴费成功,祝您生活愉快!") .touser("**********") .customerNumber("549527") .build(); // 2、组装消息数据 List<WxMpTemplateData> wxMpTemplateDataList = new ArrayList<>(); wxMpTemplateDataList.add(new WxMpTemplateData("first", weChatRechargeTemplateParamsDTO.getFirst(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("keyword1", weChatRechargeTemplateParamsDTO.getKeyword1(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("keyword2", weChatRechargeTemplateParamsDTO.getKeyword2(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("keyword3", weChatRechargeTemplateParamsDTO.getKeyword3().toString(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("keyword4", weChatRechargeTemplateParamsDTO.getKeyword4().toString(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("keyword5", weChatRechargeTemplateParamsDTO.getKeyword5(), this.WE_CHAT_TOP_COLOR)); wxMpTemplateDataList.add(new WxMpTemplateData("remark", weChatRechargeTemplateParamsDTO.getRemark(), this.WE_CHAT_TOP_COLOR)); String customerCallUrl = String.format(this.WE_CHAT_CUSTOMER_CALL_URL, weChatRechargeTemplateParamsDTO.getCustomerNumber()); //3、构建模板消息体 WxMpTemplateMessage wxMpTemplateMessage = WxMpTemplateMessage.builder() .toUser(weChatRechargeTemplateParamsDTO.getTouser()) .templateId(this.WE_CHAT_TEMPLATE_ID) .url(customerCallUrl) .data(wxMpTemplateDataList) .build(); // 4、微信公众号消息推送与发布 String msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(wxMpTemplateMessage); log.error("公众号模板消息推送与发布结果:{}", msgId); } catch (Exception e) { log.info("异常信息:{}", e); } return JSONResult.success(); }七、抽取与封装

这儿的封装需要更具自身业务的不同,封装的深度也不同,需要自由抽取封装,但万变不离其宗,

1、简单工厂-普通模式

建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

如下图:

2、简单工厂-多方法模式

对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

如下图:

3、简单工厂-多静态方法模式

将多工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

4、工厂方法模式

简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?

解决这个问题就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

5、抽象工厂模式

工厂方法模式:

一个抽象产品类,可以派生出多个具体产品类;一个抽象工厂类,可以派生出多个具体工厂类; 每个具体工厂类只能创建一个具体产品类的实例;

抽象工厂模式:

多个抽象产品类,每个抽象产品类可以派生出多个具体产品类;一个抽象工厂类,可以派生出多个具体工厂类;每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品;

区别:

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个;工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个;工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随;抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承;

对于Java应用程序来说,能见到的大部分抽象工厂模式都是这样的:里面是一堆工厂方法,每个工厂方法返回某种类型的对象。 例如:工厂可以生产鼠标和键盘。那么抽象工厂的实现类(它的某个具体子类)的对象都可以生产鼠标和键盘,但可能工厂 A 生产的是先科的键盘和鼠标,工厂 B 是Microsoft的。这样 A 和 B 就是工厂,对应于抽象工厂;每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从先科如丝滑般的切换到Microsoft。但是用了抽象工厂模式,要想切换工厂 C 的雷蛇,就可以同时替换鼠标和键盘一套。如果产品有几十个,当然用抽象工厂模式一次替换全部最方便快捷(工厂会替换相应的工厂方法)

所以抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线!!!

微信公众号开发注意两点: 1、公众号开发获取调用auoth2授权接口获取,Token_assecc授权时,需要授权IP, 参考: 《errcode“:40164,“errmsg“:“invalid ip ...微信公众号开发调用失败的解决办法》 2、在发布时,由于是基于Web页面开发的,需要授权域名的绑定验证, 参考: 《微信公众号开发redirect_uri 参数错误 的解决办法,Oauth2授权重定向域名参数错误解决办法》

3、SpringBoot整合调用微信模板方法实现微信公众号消息通知推送

《 HTTPClient 实现微信公众号消息推送与发布(四步走) 》

4、SpringBoot整合调用微信模板方法实现微信公众号消息通知推送

《 通过weixin-java-mp SDK实现微信公众号消息推送与发布(七步走) 》

参考:

【公众号模板消息接口文档】

【微信网页开发-Web开发者工具下载】

【微信开发包】更多内容查看WIKI,MP_OAuth2网页授权

【模板消息接口文档】

【MP_OAuth2网页授权】

 好了,关于 SpringBoot整合调用微信模板方法实现微信公众号消息通知推送,Java实现微信公众号给关注用户推送自定义消息通知(从0到1)  就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。  歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。

作       者:华    仔联系作者:who.seek.me@java98k.vip来        源:CSDN (Chinese Software Developer Network)原        文:https://blog.csdn.net/Hello_World_QWP/article/details/125871196版权
本文链接地址:https://www.jiuchutong.com/zhishi/296185.html 转载请保留说明!

上一篇:养老院管理系统(Java+Web+MySQL)(养老院管理系统er图)

下一篇:【AI绘画】我以Midjourney为主学习AI绘画效果咋样?(以我为主题画一幅画)

  • 抖音怎么关闭小额免密支付(抖音怎么关闭小额付款)

    抖音怎么关闭小额免密支付(抖音怎么关闭小额付款)

  • b站怎么一起看一个视频(b站怎么一起看电影)

    b站怎么一起看一个视频(b站怎么一起看电影)

  • 滴滴的预付款是什么意思(滴滴预付款什么时候到账)

    滴滴的预付款是什么意思(滴滴预付款什么时候到账)

  • 虚拟机繁忙关不掉(虚拟机关不了显示繁忙)

    虚拟机繁忙关不掉(虚拟机关不了显示繁忙)

  • 平板激活出错怎么恢复(平板激活出错怎么解决)

    平板激活出错怎么恢复(平板激活出错怎么解决)

  • Volte通话是什么意思(volte通话功能有什么用)

    Volte通话是什么意思(volte通话功能有什么用)

  • 闲鱼分账冻结什么意思(闲鱼交易账期冻结,分账冻结什么意思)

    闲鱼分账冻结什么意思(闲鱼交易账期冻结,分账冻结什么意思)

  • 华为lld一al00是啥型号(华为lld-al00是什么型号多少钱)

    华为lld一al00是啥型号(华为lld-al00是什么型号多少钱)

  • 亚马逊alexa国内能用吗(亚马逊asia)

    亚马逊alexa国内能用吗(亚马逊asia)

  • 电脑更新系统会不会丢失文件(电脑更新系统会怎么样)

    电脑更新系统会不会丢失文件(电脑更新系统会怎么样)

  • 华为nova3怎么开微信美颜(华为nova3怎么开悬浮窗回复信息)

    华为nova3怎么开微信美颜(华为nova3怎么开悬浮窗回复信息)

  • 页面设置对话框中有哪四个标签(页面设置对话框中的标签有)

    页面设置对话框中有哪四个标签(页面设置对话框中的标签有)

  • 小米手机自动静音是怎么回事(小米手机自动静音怎么解除)

    小米手机自动静音是怎么回事(小米手机自动静音怎么解除)

  • 荣耀20 荣耀20pro 区别(荣耀20 荣耀20pro 手机壳)

    荣耀20 荣耀20pro 区别(荣耀20 荣耀20pro 手机壳)

  • 亚马逊店铺怎么注册(亚马逊店铺怎么关闭月租)

    亚马逊店铺怎么注册(亚马逊店铺怎么关闭月租)

  • 手机通知铃声怎么关闭(手机通知铃声怎么删除)

    手机通知铃声怎么关闭(手机通知铃声怎么删除)

  • tpguest是什么wifi

    tpguest是什么wifi

  • vivonex3和iqoopro的区别

    vivonex3和iqoopro的区别

  • 小米bn45电池是小米几(小米bm45电池价格)

    小米bn45电池是小米几(小米bm45电池价格)

  • 华为yal一al00是什么型号(华为yal-al00)

    华为yal一al00是什么型号(华为yal-al00)

  • 手机为什么定不到位置(手机为什么定不了高铁票)

    手机为什么定不到位置(手机为什么定不了高铁票)

  • 华为手机更改锁屏时间(华为手机更改锁屏密码忘记原密码)

    华为手机更改锁屏时间(华为手机更改锁屏密码忘记原密码)

  • 苹果耳机二代什么时候出(苹果耳机二代什么型号)

    苹果耳机二代什么时候出(苹果耳机二代什么型号)

  • 苹果怎么下载不了网易云音乐(苹果怎么下载不用输入id密码)

    苹果怎么下载不了网易云音乐(苹果怎么下载不用输入id密码)

  • 手机保存网页图片找不到(手机保存网页图片失败是什么原因)

    手机保存网页图片找不到(手机保存网页图片失败是什么原因)

  • 华为mate20pro双卡双待吗(华为mate20Pro双卡一个4G一个2G)

    华为mate20pro双卡双待吗(华为mate20Pro双卡一个4G一个2G)

  • 公司车保险费用高么
  • 个人所得税劳务报酬范围
  • 怎样在网上申报营业执照年检
  • 小规模纳税人出售使用过固定资产
  • 代收款需要开票吗
  • 不得抵扣的进项税额转出会计分录
  • 房屋租赁个人所得税缴纳标准是多少
  • 厂房怎么计提折旧费
  • 小规模企业没有进项发票怎么办
  • 公司办公室收到上级主管部门的一份
  • 无形资产土地的入账价值包括哪些
  • 企业外购消费品会计分录
  • 本期增加发生额是指
  • 企业利息收入的税率是多少
  • 注册资本没有缴足前贷款利息
  • 大中小微企业划分标准2023年
  • 为什么预计负债是递延所得税资产
  • 外包劳务费用如何计算
  • 医疗服务免税发票怎么开
  • 员工租赁宿舍开几个点发票
  • 建筑工地伙食费会计分录
  • 建设单位管理费费率
  • Windows10如何修复引导
  • 如何设置鼠标移过超链接
  • win7系统网络一直转圈,什么都打不开
  • win10商店下载错误怎么回事
  • 苹果发布macOS13.6
  • 若依框架介绍
  • srv.exe病毒
  • dwm.exe是啥
  • yii2框架中文手册
  • 增值税留抵抵欠流程
  • fall 瀑布
  • php示例代码
  • 搜索人工制造
  • 如何做架构规划图
  • 超参数有哪些调优方法
  • springcloud阿里巴巴
  • tsop封装
  • opengl 帧率
  • wordpress文章发布不显示作者
  • php安装插件
  • 织梦是啥
  • 补发以前年度工资
  • 垃圾处理费申报怎么填
  • 增值税税控维护费
  • 当月收入未开票怎么入账
  • 职工福利费的比例
  • 持有至到期投资减值准备
  • 公司怎么样能开发票
  • 商贸公司库存商品进销存报表怎么做
  • 小规模申请专票,税率是多少?
  • 在建工程明细科目怎么设置
  • 固定资产盘点基本情况
  • ubuntu笔记软件
  • centos怎么配置yum
  • mac怎么打开访达功能
  • linux系统ll
  • c:windowssys:em32mtgyu.dll 内存分配访问无效的解决办法
  • win7 windows安全
  • win7电脑ip地址怎么查
  • grep的结果 再次查找
  • js数组常用的方法及用法
  • android模块开发
  • perl脚本foreach
  • opengl源码在哪里
  • opengl transform
  • unity android build support
  • shell 循环 for
  • jQuery插件ajaxFileUpload使用实例解析
  • js点击
  • unity ugui组件
  • document对象的常用方法
  • jquery ajax结合thinkphp的getjson实现跨域的方法
  • 税务总局副局长饶
  • 广东税务社保缴费查询
  • 出口退税范围的货物
  • 财税库银是什么费用
  • 山东省梁山县属于什么市?
  • 48岁了还有必要上环吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设