package com.iplatform.base; import com.fasterxml.jackson.databind.node.ObjectNode; import com.iplatform.base.util.NotificationUtils; import com.iplatform.base.util.RestTemplateUtils; import com.iplatform.core.BeanContextAware; import com.iplatform.model.vo.NotificationTemplateVo; import com.iplatform.model.vo.WeChatAccessTokenVo; import com.walker.infrastructure.arguments.Variable; import com.walker.infrastructure.utils.StringUtils; import com.walker.push.Notification; import org.springframework.web.client.RestTemplate; import java.text.MessageFormat; import java.util.List; public abstract class WechatBaseController extends PlatformAdapterController{ // public void setRestTemplate(RestTemplate restTemplate) { // this.restTemplate = restTemplate; // } // private RestTemplate restTemplate; /** * 平台统一根据模板,发送提醒通知。 * @param mark 通知标识,如:发货、订单等,从:sf_notification 表查询 * @param variableList 业务数据,key,value * @param userId 用户ID * @date 2023-08-25 */ protected void pushNotificationWithTemplate(String mark, List variableList, long userId){ if(StringUtils.isEmpty(mark)){ throw new IllegalArgumentException("必须输入通知模板标记:mark"); } if(StringUtils.isEmptyList(variableList)){ throw new IllegalArgumentException("必须输入推送消息业务数据:variableList"); } NotificationTemplateVo templateVo = this.getNotificationTemplateCache().get(mark); if(templateVo == null){ logger.error("通知模板缓存不存在,mark={}", mark); return; } // 1:存在微信公众号推送方式 if(templateVo.getWechat()){ String openId = this.getUser(userId).getWx_open_id(); if(StringUtils.isEmpty(openId)){ logger.error("用户openId为空,无法发送微信公众号通知, userId={}", userId); return; } String accessToken = this.acquirePublicAccessToken(); if(StringUtils.isEmpty(accessToken)){ logger.error("推送公众号消息失败,accessToken获取为空,mark={}, userId={}", mark, userId); return; } Notification notification = NotificationUtils.acquireWechatNotification(accessToken , templateVo.getWechatTempId(), openId, variableList); this.getPushManager().push(notification, null); } // 2:存在短信推送 if(templateVo.getSms()){ String userPhone = this.getUser(userId).getPhonenumber(); if(StringUtils.isEmpty(userPhone)){ logger.error("用户手机号为空,无法发送短信通知, userId={}", userId); return; } Notification smsNotification = NotificationUtils.acquireSmsNotification(templateVo.getSmsTempId(), userPhone, variableList, "短信通知"); this.getPushManager().push(smsNotification, null); } // 3:存在微信小程序推送方式 if(templateVo.getRoutine()){ throw new UnsupportedOperationException("未实现微信小程序消息通知"); } } /** * 获取微信小程序(access_token),并设置缓存。 * @return * @date 2023-09-16 */ protected String acquireMiniAccessToken(){ String appId = this.getArgumentVariable(WechatConstants.WECHAT_MINI_APPID).getStringValue(); if(StringUtils.isEmpty(appId)){ throw new PlatformRuntimeException("请先配置微信参数:小程序appid"); } String miniAccessToken = this.getWechatCache().getMiniAccessToken(); if(StringUtils.isNotEmpty(miniAccessToken)){ logger.debug("缓存中已有'access_token':{}", miniAccessToken); return miniAccessToken; } String secret = this.getArgumentVariable(WechatConstants.WECHAT_MINI_APPSECRET).getStringValue(); if (StringUtils.isEmpty(secret)) { throw new PlatformRuntimeException("微信小程序secret未设置"); } // String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); // logger.debug("url = {}", url); // ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); // if(objectNode == null){ // throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); // } // logger.debug(objectNode.toString()); ObjectNode objectNode = this.acquireAccessTokenNode(appId, secret); WeChatAccessTokenVo accessTokenVo = null; try { // if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { // if (objectNode.has("errmsg")) { // // 保存到微信异常表 //// wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); // throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); // } // } this.checkStatusError(objectNode); accessTokenVo = new WeChatAccessTokenVo(); accessTokenVo.setAccessToken(objectNode.get("access_token").asText()); accessTokenVo.setExpiresIn(objectNode.get("expires_in").asInt()); // accessTokenVo = JsonUtils.jsonStringToObject(result, WeChatAccessTokenVo.class); this.getWechatCache().putMiniAccessToken(accessTokenVo.getAccessToken(), accessTokenVo.getExpiresIn().longValue() - 1800L); logger.info("调用一次微信远程接口获取'mini_accessToken',并缓存:{}", accessTokenVo.getAccessToken()); return accessTokenVo.getAccessToken(); } catch (Exception e) { throw new RuntimeException("json字符串转对象错误:" + objectNode, e); } } /** * 获取微信公众号(普通)access_token * @return * @date 2023-08-23 */ protected String acquirePublicAccessToken( // String appId, String type ){ String appId = this.getArgumentVariable(WechatConstants.WECHAT_PUBLIC_APPID).getStringValue(); if(StringUtils.isEmpty(appId)){ throw new PlatformRuntimeException("请先配置微信参数:公众号appid"); } String publicAccessToken = this.getWechatCache().getPublicAccessToken(); if(StringUtils.isNotEmpty(publicAccessToken)){ logger.debug("缓存中已有'access_token':{}", publicAccessToken); return publicAccessToken; } String secret = this.getArgumentVariable(WechatConstants.WECHAT_PUBLIC_APPSECRET).getStringValue(); if (StringUtils.isEmpty(secret)) { throw new PlatformRuntimeException("微信公众号secret未设置"); } // String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); // logger.debug("url = {}", url); // ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); // if(objectNode == null){ // throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); // } // logger.debug(objectNode.toString()); ObjectNode objectNode = this.acquireAccessTokenNode(appId, secret); WeChatAccessTokenVo accessTokenVo = null; try { // if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { // if (objectNode.has("errmsg")) { // // 保存到微信异常表 //// wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); // throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); // } // } this.checkStatusError(objectNode); accessTokenVo = new WeChatAccessTokenVo(); accessTokenVo.setAccessToken(objectNode.get("access_token").asText()); accessTokenVo.setExpiresIn(objectNode.get("expires_in").asInt()); // accessTokenVo = JsonUtils.jsonStringToObject(result, WeChatAccessTokenVo.class); this.getWechatCache().putPublicAccessToken(accessTokenVo.getAccessToken(), accessTokenVo.getExpiresIn().longValue() - 1800L); logger.info("调用一次微信远程接口获取'public_accessToken',并缓存:{}", accessTokenVo.getAccessToken()); return accessTokenVo.getAccessToken(); } catch (Exception e) { throw new RuntimeException("json字符串转对象错误:" + objectNode, e); } } private ObjectNode acquireAccessTokenNode(String appId, String secret){ String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); logger.debug("url = {}", url); ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); if(objectNode == null){ throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); } logger.debug(objectNode.toString()); return objectNode; } private void checkStatusError(ObjectNode objectNode){ // ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(result); if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { if (objectNode.has("errmsg")) { // 保存到微信异常表 // wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); } else { throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode")); } } } /** * 返回微信基础配置缓存对象。 * @return * @date 2023-08-23 */ protected WechatCacheProvider getWechatCache(){ return BeanContextAware.getBeanByType(WechatCacheProvider.class); } }