shikeyin
2024-01-11 65da8373531677b1c37a98f53eaa30c892f35e5a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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<Variable> 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);
    }
 
}