Ver código fonte

第三方服务调用异常处理优化

woody 1 ano atrás
pai
commit
e974f4364d

+ 11 - 9
framework-email/src/main/java/com/chelvc/framework/email/DefaultEmailHandler.java

@@ -81,33 +81,35 @@ public class DefaultEmailHandler implements EmailHandler {
     }
 
     @Override
-    public void send(@NonNull Body body) {
-        this.send(body, EMPTY_ATTACHMENT_ARRAY);
+    public boolean send(@NonNull Body body) {
+        return this.send(body, EMPTY_ATTACHMENT_ARRAY);
     }
 
     @Override
-    public void send(@NonNull Body body, @NonNull File... attachments) {
-        this.send(body, EmailUtils.file2mixed(attachments));
+    public boolean send(@NonNull Body body, @NonNull File... attachments) {
+        return this.send(body, EmailUtils.file2mixed(attachments));
     }
 
     @Override
-    public void send(@NonNull Body body, @NonNull MimeBodyPart... attachments) {
+    public boolean send(@NonNull Body body, @NonNull MimeBodyPart... attachments) {
         Message message = this.body2message(body, attachments);
         Transport transport = null;
         try {
             transport = this.session.getTransport();
             transport.connect();
             transport.sendMessage(message, message.getAllRecipients());
-        } catch (MessagingException e) {
-            throw new RuntimeException(e);
+        } catch (Exception e) {
+            log.warn("Email send failed: {}", e.getMessage(), e);
+            return false;
         } finally {
             if (transport != null) {
                 try {
                     transport.close();
-                } catch (MessagingException e) {
-                    log.warn("Close email transport failed: {}", e.getMessage());
+                } catch (Exception e) {
+                    log.warn("Close email transport failed: {}", e.getMessage(), e);
                 }
             }
         }
+        return true;
     }
 }

+ 6 - 3
framework-email/src/main/java/com/chelvc/framework/email/EmailHandler.java

@@ -14,22 +14,25 @@ public interface EmailHandler {
      * 发送邮件
      *
      * @param body 邮件消息体对象
+     * @return true/false
      */
-    void send(Body body);
+    boolean send(Body body);
 
     /**
      * 发送邮件
      *
      * @param body        邮件消息体对象
      * @param attachments 邮件附件数组
+     * @return true/false
      */
-    void send(Body body, File... attachments);
+    boolean send(Body body, File... attachments);
 
     /**
      * 发送邮件
      *
      * @param body        邮件消息体对象
      * @param attachments 邮件附件数组
+     * @return true/false
      */
-    void send(Body body, MimeBodyPart... attachments);
+    boolean send(Body body, MimeBodyPart... attachments);
 }

+ 73 - 90
framework-jpush/src/main/java/com/chelvc/framework/jpush/DefaultJPushHandler.java

@@ -13,7 +13,6 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
 import javax.crypto.Cipher;
@@ -85,14 +84,16 @@ public class DefaultJPushHandler implements JPushHandler {
      * 获取历史消息地址
      */
     private static final String GET_HISTORY_MESSAGE_URL = "https://report.im.jpush.cn/v2/users/%s/messages?cursor=%s";
+
     private final RestTemplate restTemplate;
     private final JPushProperties properties;
-    @Value("${spring.profiles.active}")
-    private String env;
     private PrivateKey privateKey;
     private JPushClient pushClient;
     private JMessageClient messageClient;
 
+    @Value("${spring.profiles.active}")
+    private String env;
+
     @PostConstruct
     public void initialize() throws GeneralSecurityException {
         // 初始化登录认证配置
@@ -185,7 +186,13 @@ public class DefaultJPushHandler implements JPushHandler {
         headers.add("Authorization", ServiceHelper.getBasicAuthorization(appkey, secret));
         headers.setContentType(MediaType.APPLICATION_JSON);
         HttpEntity<?> entity = new HttpEntity<>(headers);
-        ChatMessage message = this.restTemplate.exchange(url, HttpMethod.GET, entity, ChatMessage.class).getBody();
+        ChatMessage message;
+        try {
+            message = this.restTemplate.exchange(url, HttpMethod.GET, entity, ChatMessage.class).getBody();
+        } catch (Exception e) {
+            log.warn("JPush get chat message failed: {}", e.getMessage(), e);
+            return null;
+        }
         if (debug) {
             log.debug("JPush response: {}", message);
         }
@@ -207,14 +214,21 @@ public class DefaultJPushHandler implements JPushHandler {
         headers.add("Authorization", authorization);
         headers.setContentType(MediaType.APPLICATION_JSON);
         HttpEntity<?> entity = new HttpEntity<>(parameters, headers);
-        JPushMobile response =
-                this.restTemplate.exchange(TOKEN2MOBILE_URL, HttpMethod.POST, entity, JPushMobile.class).getBody();
+        JPushMobile response;
+        try {
+            response = this.restTemplate.exchange(
+                    TOKEN2MOBILE_URL, HttpMethod.POST, entity, JPushMobile.class
+            ).getBody();
+        } catch (Exception e) {
+            log.warn("JPush get mobile failed: {}", e.getMessage(), e);
+            return null;
+        }
         if (debug) {
             log.debug("JPush response: {}", response);
         }
-        Objects.requireNonNull(response, "Invalid jpush server response");
-        if (response.getCode() == null || response.getCode() != 8000) {
-            throw new RuntimeException(String.format("[%d] %s", response.getCode(), response.getContent()));
+        if (response == null || response.getCode() == null || response.getCode() != 8000) {
+            log.warn("JPush get mobile failed: {}", response);
+            return null;
         }
 
         // 解码手机号
@@ -228,62 +242,39 @@ public class DefaultJPushHandler implements JPushHandler {
     }
 
     @Override
-    public void register(@NonNull RegisterInfo... registrations) {
-        if (registrations.length > 0) {
-            boolean debug = log.isDebugEnabled();
-            if (debug) {
-                log.debug("JPush request: {}", Arrays.toString(registrations));
-            }
-            String result;
-            try {
-                result = this.getMessageClient().registerUsers(registrations);
-            } catch (APIConnectionException e) {
-                throw new RuntimeException(e);
-            } catch (APIRequestException e) {
-                throw new RuntimeException(e.getErrorMessage(), e);
-            }
-            if (debug) {
-                log.debug("JPush response: {}", result);
-            }
+    public boolean register(@NonNull RegisterInfo... registrations) {
+        if (registrations.length == 0) {
+            return false;
         }
-    }
-
-    @Override
-    public void register(@NonNull Collection<RegisterInfo> registrations) {
-        if (!registrations.isEmpty()) {
-            this.register(registrations.toArray(new RegisterInfo[0]));
-        }
-    }
-
-    @Override
-    public List<String> getPushIdentities(int count) {
         boolean debug = log.isDebugEnabled();
         if (debug) {
-            log.debug("JPush request: {}", count);
+            log.debug("JPush request: {}", Arrays.toString(registrations));
         }
-        List<String> identities;
+        String result;
         try {
-            identities = this.getPushClient().getCidList(count, "push").cidlist;
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+            result = this.getMessageClient().registerUsers(registrations);
+        } catch (Exception e) {
+            int code;
+            if (e instanceof APIRequestException
+                    && ((code = ((APIRequestException) e).getErrorCode()) == 1011 || code == 899001)) {
+                return true;
+            }
+            log.warn("JPush register failed: {}", e.getMessage(), e);
+            return false;
         }
         if (debug) {
-            log.debug("JPush response: {}", identities);
+            log.debug("JPush response: {}", result);
         }
-        return identities;
+        return true;
     }
 
     @Override
-    public long push(@NonNull PushPayload payload) {
-        return this.push(payload, e -> {
-            throw new RuntimeException(e.getErrorMessage(), e);
-        });
+    public boolean register(@NonNull Collection<RegisterInfo> registrations) {
+        return !registrations.isEmpty() && this.register(registrations.toArray(new RegisterInfo[0]));
     }
 
     @Override
-    public long push(@NonNull PushPayload payload, @NonNull Consumer<APIRequestException> failure) {
+    public long push(@NonNull PushPayload payload) {
         // 针对生产环境IOS推送,需要设置apnsProduction为true
         if (this.isProduction()) {
             payload.resetOptionsApnsProduction(true);
@@ -292,23 +283,22 @@ public class DefaultJPushHandler implements JPushHandler {
         if (debug) {
             log.debug("JPush request: {}", payload);
         }
-        JPushClient client = this.getPushClient();
+        PushResult result;
         try {
-            PushResult result = client.sendPush(payload);
-            if (debug) {
-                log.debug("JPush response: {}", result);
-            }
-            if (result != null && result.statusCode == 0) {
-                return result.msg_id;
-            }
-            Integer code = result == null || result.error == null ? null : result.error.getCode();
-            String message = result == null || result.error == null ? null : result.error.getMessage();
-            throw new RuntimeException(String.format("[%d] %s", code, message));
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            failure.accept(e);
+            result = this.getPushClient().sendPush(payload);
+        } catch (Exception e) {
+            log.warn("JPush push failed: {}", e.getMessage(), e);
+            return 0;
+        }
+        if (debug) {
+            log.debug("JPush response: {}", result);
+        }
+        if (result != null && result.statusCode == 0) {
+            return result.msg_id;
         }
+        Integer code = result == null || result.error == null ? null : result.error.getCode();
+        String message = result == null || result.error == null ? null : result.error.getMessage();
+        log.warn("JPush push failed: [{}] {}", code, message);
         return 0;
     }
 
@@ -379,13 +369,11 @@ public class DefaultJPushHandler implements JPushHandler {
 
         // 批量推送消息
         BatchPushResult result;
-        JPushClient client = this.getPushClient();
         try {
-            result = client.batchSendPushByAlias(payloads);
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+            result = this.getPushClient().batchSendPushByAlias(payloads);
+        } catch (Exception e) {
+            log.warn("JPush push failed: {}", e.getMessage(), e);
+            return null;
         }
         if (debug) {
             log.debug("JPush response: {}", JacksonContextHolder.serialize(result));
@@ -408,13 +396,11 @@ public class DefaultJPushHandler implements JPushHandler {
             return Collections.emptyList();
         }
         ReceivedsResult result;
-        JPushClient client = this.getPushClient();
         try {
-            result = client.getReceivedsDetail(ids);
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+            result = this.getPushClient().getReceivedsDetail(ids);
+        } catch (Exception e) {
+            log.warn("JPush get deliveries failed: {}", e.getMessage(), e);
+            return Collections.emptyList();
         }
         if (debug) {
             log.debug("JPush response: {}", JacksonContextHolder.serialize(result));
@@ -449,10 +435,9 @@ public class DefaultJPushHandler implements JPushHandler {
         UserInfoResult user;
         try {
             user = this.getMessageClient().getUserInfo(username);
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+        } catch (Exception e) {
+            log.warn("JPush get user info failed: {}", e.getMessage(), e);
+            return null;
         }
         if (debug) {
             log.debug("JPush response: {}", user);
@@ -469,10 +454,9 @@ public class DefaultJPushHandler implements JPushHandler {
         UserStateResult state;
         try {
             state = this.getMessageClient().getUserState(username);
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+        } catch (Exception e) {
+            log.warn("JPush get user state failed: {}", e.getMessage(), e);
+            return null;
         }
         if (debug) {
             log.debug("JPush response: {}", state);
@@ -492,10 +476,9 @@ public class DefaultJPushHandler implements JPushHandler {
         UserStateListResult[] states;
         try {
             states = this.getMessageClient().getUsersState(usernames);
-        } catch (APIConnectionException e) {
-            throw new RuntimeException(e);
-        } catch (APIRequestException e) {
-            throw new RuntimeException(e.getErrorMessage(), e);
+        } catch (Exception e) {
+            log.warn("JPush get user state failed: {}", e.getMessage(), e);
+            return new UserStateListResult[0];
         }
         if (debug) {
             log.debug("JPush response: {}", Arrays.toString(states));

+ 4 - 21
framework-jpush/src/main/java/com/chelvc/framework/jpush/JPushHandler.java

@@ -3,9 +3,7 @@ package com.chelvc.framework.jpush;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Consumer;
 
-import cn.jiguang.common.resp.APIRequestException;
 import cn.jmessage.api.common.model.RegisterInfo;
 import cn.jmessage.api.user.UserInfoResult;
 import cn.jmessage.api.user.UserStateListResult;
@@ -37,23 +35,17 @@ public interface JPushHandler {
      * 账号注册
      *
      * @param registrations 注册信息数组
+     * @return true/false
      */
-    void register(RegisterInfo... registrations);
+    boolean register(RegisterInfo... registrations);
 
     /**
      * 账号注册
      *
      * @param registrations 注册信息集合
+     * @return true/false
      */
-    void register(Collection<RegisterInfo> registrations);
-
-    /**
-     * 获取推送标识列表
-     *
-     * @param count 标识数量
-     * @return 标识列表
-     */
-    List<String> getPushIdentities(int count);
+    boolean register(Collection<RegisterInfo> registrations);
 
     /**
      * 推送消息
@@ -63,15 +55,6 @@ public interface JPushHandler {
      */
     long push(PushPayload payload);
 
-    /**
-     * 推送消息
-     *
-     * @param payload 消息体
-     * @param failure 推送失败异常处理方法
-     * @return 消息ID
-     */
-    long push(PushPayload payload, Consumer<APIRequestException> failure);
-
     /**
      * 推送消息
      *

+ 10 - 6
framework-location/src/main/java/com/chelvc/framework/location/support/JuheMobileHandler.java

@@ -2,7 +2,6 @@ package com.chelvc.framework.location.support;
 
 import java.time.Duration;
 import java.util.Date;
-import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -53,13 +52,18 @@ public class JuheMobileHandler implements MobileHandler {
         if (debug) {
             log.debug("Juhe location request: {}", url);
         }
-        JuheLocationResponse response = restTemplate.getForObject(url, JuheLocationResponse.class);
-        Objects.requireNonNull(response, "Invalid juhe server response");
+        JuheLocationResponse response;
+        try {
+            response = this.restTemplate.getForObject(url, JuheLocationResponse.class);
+        } catch (Exception e) {
+            log.warn("Juhe locate failed: {}", e.getMessage(), e);
+            return null;
+        }
         if (debug) {
-            log.debug("Juhe location response: {}", response);
+            log.debug("Juhe locate response: {}", response);
         }
-        if (response.getStatus() == null || response.getStatus() != 0) {
-            log.error("Juhe location response exception: [{}] {}", response.getStatus(), response.getMessage());
+        if (response == null || response.getStatus() == null || response.getStatus() != 0) {
+            log.warn("Juhe locate failed: {}", response);
             return null;
         }
         String province = ObjectUtils.ifNull(response.getResult(), JuheLocationResponse.Location::getProvince);

+ 11 - 5
framework-location/src/main/java/com/chelvc/framework/location/support/TencentLocationHandler.java

@@ -56,17 +56,23 @@ public class TencentLocationHandler implements LocationHandler {
         if (debug) {
             log.debug("Tencent location request: {}", url);
         }
-        TencentLocationResponse response = this.restTemplate.getForObject(url, TencentLocationResponse.class);
-        Objects.requireNonNull(response, "Invalid tencent server response");
+        TencentLocationResponse response;
+        try {
+            response = this.restTemplate.getForObject(url, TencentLocationResponse.class);
+        } catch (Exception e) {
+            log.warn("Tencent locate failed: {}", e.getMessage(), e);
+            return null;
+        }
         if (debug) {
-            log.debug("Tencent location response: {}", response);
+            log.debug("Tencent locate response: {}", response);
         }
-        if (response.getStatus() == null || response.getStatus() != 0) {
-            log.error("Tencent location response exception: [{}] {}", response.getStatus(), response.getMessage());
+        if (response == null || response.getStatus() == null || response.getStatus() != 0) {
+            log.warn("Tencent locate failed: {}", response);
             return null;
         }
         TencentLocationResponse.Location location = response.getResult().getLocation();
         if (!Region.isRegion(location.getAdcode())) {
+            log.warn("Tencent locate adcode invalid: {}", location.getAdcode());
             return null;
         }
 

+ 2 - 1
framework-sms/src/main/java/com/chelvc/framework/sms/NormalSmsHandler.java

@@ -12,6 +12,7 @@ public interface NormalSmsHandler {
      *
      * @param content 短信内容
      * @param mobiles 手机号数组
+     * @return true/false
      */
-    void send(String content, String... mobiles);
+    boolean send(String content, String... mobiles);
 }

+ 6 - 3
framework-sms/src/main/java/com/chelvc/framework/sms/TemplateSmsHandler.java

@@ -20,8 +20,9 @@ public interface TemplateSmsHandler {
      * @param mobile     手机号
      * @param template   模板标识
      * @param parameters 模版参数
+     * @return true/false
      */
-    void send(String mobile, String template, String... parameters);
+    boolean send(String mobile, String template, String... parameters);
 
     /**
      * 发送短信
@@ -29,8 +30,9 @@ public interface TemplateSmsHandler {
      * @param mobile     手机号
      * @param template   模板标识
      * @param parameters 模版参数
+     * @return true/false
      */
-    void send(String mobile, String template, Map<String, ?> parameters);
+    boolean send(String mobile, String template, Map<String, ?> parameters);
 
     /**
      * 发送短信验证码
@@ -38,6 +40,7 @@ public interface TemplateSmsHandler {
      * @param mobile   手机号
      * @param template 模版标识
      * @param code     验证码
+     * @return true/false
      */
-    void sendCaptcha(String mobile, String template, String code);
+    boolean sendCaptcha(String mobile, String template, String code);
 }

+ 10 - 9
framework-sms/src/main/java/com/chelvc/framework/sms/support/AliyunSmsHandler.java

@@ -34,12 +34,12 @@ public class AliyunSmsHandler implements TemplateSmsHandler {
     private final AliyunSmsProperties properties;
 
     @Override
-    public void send(String mobile, String template, String... parameters) {
+    public boolean send(String mobile, String template, String... parameters) {
         throw new UnsupportedOperationException("Not support method");
     }
 
     @Override
-    public void send(@NonNull String mobile, @NonNull String template, @NonNull Map<String, ?> parameters) {
+    public boolean send(@NonNull String mobile, @NonNull String template, @NonNull Map<String, ?> parameters) {
         String param = JacksonContextHolder.serialize(parameters);
         boolean debug = log.isDebugEnabled();
         if (debug) {
@@ -50,24 +50,25 @@ public class AliyunSmsHandler implements TemplateSmsHandler {
         SendSmsResponse response;
         try {
             response = this.client.sendSms(request);
-        } catch (RuntimeException e) {
-            throw e;
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            log.warn("Aliyun sms send failed: {}", e.getMessage(), e);
+            return false;
         }
         if (debug) {
             log.debug("Aliyun sms response: {}", JacksonContextHolder.serialize(response));
         }
-        SendSmsResponseBody body = Objects.requireNonNull(response.getBody(), "Invalid aliyun sms response");
+        SendSmsResponseBody body = response.getBody();
         if (Objects.equals(body.getCode(), "isv.BUSINESS_LIMIT_CONTROL")) {
             throw new ResourceUnavailableException(SMS_SEND_FREQUENTLY, body.getMessage());
         } else if (!Objects.equals(body.getCode(), "OK")) {
-            throw new ResourceUnavailableException(body.getMessage());
+            log.warn("Aliyun sms send failed: [{}] {}", body.getCode(), body.getMessage());
+            return false;
         }
+        return true;
     }
 
     @Override
-    public void sendCaptcha(@NonNull String mobile, @NonNull String template, @NonNull String code) {
-        this.send(mobile, template, ImmutableMap.of("code", code));
+    public boolean sendCaptcha(@NonNull String mobile, @NonNull String template, @NonNull String code) {
+        return this.send(mobile, template, ImmutableMap.of("code", code));
     }
 }

+ 10 - 12
framework-sms/src/main/java/com/chelvc/framework/sms/support/TencentTemplateSmsHandler.java

@@ -1,9 +1,7 @@
 package com.chelvc.framework.sms.support;
 
-import java.io.IOException;
 import java.util.Arrays;
 import java.util.Map;
-import java.util.Objects;
 
 import com.chelvc.framework.base.context.JacksonContextHolder;
 import com.chelvc.framework.base.exception.ResourceUnavailableException;
@@ -11,11 +9,9 @@ import com.chelvc.framework.sms.TemplateSmsHandler;
 import com.chelvc.framework.sms.config.TencentSmsProperties;
 import com.github.qcloudsms.SmsSingleSender;
 import com.github.qcloudsms.SmsSingleSenderResult;
-import com.github.qcloudsms.httpclient.HTTPException;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.json.JSONException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.stereotype.Component;
@@ -35,7 +31,7 @@ public class TencentTemplateSmsHandler implements TemplateSmsHandler {
     private final TencentSmsProperties properties;
 
     @Override
-    public void send(@NonNull String mobile, @NonNull String template, @NonNull String... parameters) {
+    public boolean send(@NonNull String mobile, @NonNull String template, @NonNull String... parameters) {
         boolean debug = log.isDebugEnabled();
         if (debug) {
             log.debug("Tencent sms request: {}, {}", mobile, Arrays.toString(parameters));
@@ -44,27 +40,29 @@ public class TencentTemplateSmsHandler implements TemplateSmsHandler {
         try {
             result = this.sender.sendWithParam(this.properties.getRegion(), mobile, Integer.parseInt(template),
                     parameters, this.properties.getSignature(), null, null);
-        } catch (HTTPException | JSONException | IOException e) {
-            throw new RuntimeException(e);
+        } catch (Exception e) {
+            log.warn("Tencent sms send failed: {}", e.getMessage(), e);
+            return false;
         }
         if (debug) {
             log.debug("Tencent sms response: {}", JacksonContextHolder.serialize(result));
         }
-        Objects.requireNonNull(result, "Invalid tencent sms response");
         if (result.result == 1023) {
             throw new ResourceUnavailableException(SMS_SEND_FREQUENTLY, result.errMsg);
         } else if (result.result != 0) {
-            throw new ResourceUnavailableException(result.errMsg);
+            log.warn("Tencent sms send failed: [{}] {}", result.result, result.errMsg);
+            return false;
         }
+        return true;
     }
 
     @Override
-    public void send(String mobile, String template, Map<String, ?> parameters) {
+    public boolean send(String mobile, String template, Map<String, ?> parameters) {
         throw new UnsupportedOperationException("Not support method");
     }
 
     @Override
-    public void sendCaptcha(@NonNull String mobile, @NonNull String template, @NonNull String code) {
-        this.send(mobile, template, code);
+    public boolean sendCaptcha(@NonNull String mobile, @NonNull String template, @NonNull String code) {
+        return this.send(mobile, template, code);
     }
 }

+ 19 - 13
framework-wechat/src/main/java/com/chelvc/framework/wechat/DefaultWechatPublicHandler.java

@@ -242,18 +242,24 @@ public class DefaultWechatPublicHandler implements WechatPublicHandler {
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_JSON);
         HttpEntity<?> entity = new HttpEntity<>(body, headers);
-        WechatPublicMessage response = WechatUtils.execute(
-                () -> this.restTemplate.exchange(url, HttpMethod.POST, entity, WechatPublicMessage.class).getBody(),
-                (status, message) -> {
-                    // 如果访问令牌过期或无效则更新访问令牌后重试
-                    if (status == 40001 || status == 42001) {
-                        return WechatUtils.execute(() -> this.restTemplate.exchange(
-                                String.format(SEND_TEMPLATE_MESSAGE_URL, this.refreshAccessToken()),
-                                HttpMethod.POST, entity, WechatPublicMessage.class
-                        ).getBody());
-                    }
-                    throw new RuntimeException(String.format("[%d] %s", status, message));
-                });
-        return response.getId();
+        WechatPublicMessage response;
+        try {
+            response = this.restTemplate.exchange(url, HttpMethod.POST, entity, WechatPublicMessage.class).getBody();
+            if (response != null && (response.getErrcode() == 40001 || response.getErrcode() == 42001)) {
+                // 如果是令牌过期则刷新令牌后重试
+                url = String.format(SEND_TEMPLATE_MESSAGE_URL, this.refreshAccessToken());
+                response = this.restTemplate.exchange(
+                        url, HttpMethod.POST, entity, WechatPublicMessage.class
+                ).getBody();
+            }
+        } catch (Exception e) {
+            log.warn("Wechat public push failed: {}", e.getMessage(), e);
+            return 0;
+        }
+        if (response != null && response.getErrcode() == 0) {
+            return response.getId();
+        }
+        log.warn("Wechat public push failed: {}", response);
+        return 0;
     }
 }