Browse Source

开放接口 订单状态通知

叶君翔 3 years ago
parent
commit
811e1544e9

+ 7 - 3
lb-app/src/main/java/com/ydd/app/callback/controller/KFDeliveryCallback.java

@@ -2,6 +2,7 @@ package com.ydd.app.callback.controller;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ydd.api.DeliveryCallbackApi;
 import com.ydd.app.service.ApiDeliveryBindService;
 import com.ydd.app.service.ApiDeliveryService;
@@ -54,9 +55,12 @@ public class KFDeliveryCallback {
         CallBackOrderVo vo = new CallBackOrderVo();
         vo.setLbClient(DeliveryTypeEnums.KUAI_FU.getName());
         vo.setParams(jsonParam);
-        ResObject<KfCallbackOrderVo> callbackRes =(ResObject<KfCallbackOrderVo>) callback.doOrder(vo);
-        if (callbackRes.getCode() == 0) {
-            KfCallbackOrderVo orderVo = callbackRes.getData();
+
+        Object result = callback.doOrder(vo);
+        ObjectMapper objectMapper = new ObjectMapper();
+        ResObject callbackRes = objectMapper.convertValue(result, ResObject.class);
+        if (callbackRes.getCode() == 0 && callbackRes.getData() != null) {
+            KfCallbackOrderVo orderVo = objectMapper.convertValue(callbackRes.getData(), KfCallbackOrderVo.class);
             ApiCallBackContent content = new ApiCallBackContent(new ApiCallBackKF(orderVo));
             OrderDelivery orderDelivery = iOrderDeliveryService.getOne(new QueryWrapper<OrderDelivery>().eq("child_order_sn",orderVo.getOrderId()));
             CallBackOrderDto dto = content.createCallBack();

+ 30 - 26
lb-app/src/main/java/com/ydd/app/consumer/DelayStatusNotifyListener.java

@@ -7,6 +7,7 @@ import com.alibaba.fastjson.parser.Feature;
 import com.ydd.app.vo.OrderStatusNotifyVo;
 import com.ydd.app.vo.StoreStatusNotifyVo;
 import com.ydd.common.constant.RabbitConstant;
+import com.ydd.common.constant.RedisKeyConstant;
 import com.ydd.common.core.redis.RedisCache;
 import com.ydd.common.enums.ResponseResultCodeEnum;
 import com.ydd.common.utils.http.HttpUtils;
@@ -24,11 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Set;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 @Slf4j
@@ -40,19 +37,26 @@ public class DelayStatusNotifyListener {
 
     private final RedisCache redisCache;
 
-    @RabbitListener(queues = RabbitConstant.QUEUE_DELAY_OPEN_STATUS_NOTIFY)
+    @RabbitListener(queues = RabbitConstant.QUEUE_DELAY_OPEN_STORE_STATUS_NOTIFY)
     @RabbitHandler
-    public void statusNotifyDelayListener(Object msg) {
-        log.info("收到延迟推送状态的消息:{}", msg);
+    public void statusNotifyDelayListener(StoreStatusNotifyVo storeStatusNotifyVo) {
+        log.info("收到门店推送状态的消息:{}", storeStatusNotifyVo);
         try {
             // 门店状态通知
-            if (msg instanceof StoreStatusNotifyVo) {
-                this.doStoreStatusNotify((StoreStatusNotifyVo) msg);
-            }
+            this.doStoreStatusNotify(storeStatusNotifyVo);
+        } catch (Exception e) {
+            log.error("状态推送异常", e);
+        }
+
+    }
+
+    @RabbitListener(queues = RabbitConstant.QUEUE_DELAY_OPEN_ORDER_STATUS_NOTIFY)
+    @RabbitHandler
+    public void orderStatusNotifyDelayListener(OrderStatusNotifyVo orderStatusNotifyVo) {
+        log.info("收到订单推送状态的消息:{}", orderStatusNotifyVo);
+        try {
             // 订单状态通知
-            if (msg instanceof OrderStatusNotifyVo) {
-                this.doOrderStatusNotify((OrderStatusNotifyVo) msg);
-            }
+            this.doOrderStatusNotify(orderStatusNotifyVo);
         } catch (Exception e) {
             log.error("状态推送异常", e);
         }
@@ -61,8 +65,8 @@ public class DelayStatusNotifyListener {
 
     private void doStoreStatusNotify(StoreStatusNotifyVo notifyVo) {
         Integer notifyCount = notifyVo.getNotifyCount();
-        log.info("第 {} 次推送门店状态通知, 通知内容: {}", notifyCount, JSONObject.toJSONString(notifyVo));
-        String key = notifyVo.getShopCode() + "-" + notifyVo.getStatus();
+        log.info("第 {} 次推送门店: {} 状态通知, 通知内容: {}", notifyCount, notifyVo.getShopCode(), JSONObject.toJSONString(notifyVo));
+        String key = RedisKeyConstant.STORE_STATUS_NOTIFY + notifyVo.getShopCode() + "-" + notifyVo.getStatus();
         // 若缓存在, 说明已经通知过并收到成功响应
         if (redisCache.hasKey(key)) {
             return;
@@ -88,12 +92,12 @@ public class DelayStatusNotifyListener {
         notifyVo.setSign(sign);
         String storeStatusNotifyVoStr = JSONObject.toJSONString(notifyVo);
         try {
-            storeStatusNotifyVoStr = URLEncoder.encode(storeStatusNotifyVoStr,"utf-8");
             log.info("门店状态同步请求参数: {}", storeStatusNotifyVoStr);
-            String resp = HttpUtils.sendPost(appInfo.getStoreStatusNotifyUrl(), storeStatusNotifyVoStr);
-            log.info("门店状态同步返回结果: {}", resp);
+            Map<String, String> header = new HashMap<>();
+            String result = HttpUtils.post(appInfo.getStoreStatusNotifyUrl(), header, storeStatusNotifyVoStr, "utf-8");
+            log.info("门店状态同步返回结果: {}", result);
             // 收到成功响应后存入缓存, 后续不再推送
-            if (ResponseResultCodeEnum.SUCCESS.getMessage().equals(resp)) {
+            if (ResponseResultCodeEnum.SUCCESS.getMessage().equals(result)) {
                 redisCache.setCacheObject(key, "SUCCESS", 24, TimeUnit.HOURS);
             } else {
                 if (notifyCount == AppConstant.NOTIFY_INTERVAL_DURATION.size()) {
@@ -109,8 +113,8 @@ public class DelayStatusNotifyListener {
 
     private void doOrderStatusNotify(OrderStatusNotifyVo notifyVo) {
         Integer notifyCount = notifyVo.getNotifyCount();
-        log.info("第 {} 次推送订单状态通知, 通知内容: {}", notifyCount, JSONObject.toJSONString(notifyVo));
-        String key = notifyVo.getOrderSn() + "-" + notifyVo.getStatus();
+        log.info("第 {} 次推送订单: {} 状态通知, 通知内容: {}", notifyCount, notifyVo.getOrderSn(), JSONObject.toJSONString(notifyVo));
+        String key = RedisKeyConstant.ORDER_STATUS_NOTIFY + notifyVo.getOrderSn() + "-" + notifyVo.getStatus();
         // 若缓存在, 说明已经通知过并收到成功响应
         if (redisCache.hasKey(key)) {
             return;
@@ -136,12 +140,12 @@ public class DelayStatusNotifyListener {
         notifyVo.setSign(sign);
         String orderStatusNotifyVoStr = JSONObject.toJSONString(notifyVo);
         try {
-            orderStatusNotifyVoStr = URLEncoder.encode(orderStatusNotifyVoStr,"utf-8");
             log.info("订单状态同步请求参数: {}", orderStatusNotifyVoStr);
-            String resp = HttpUtils.sendPost(appInfo.getOrderStatusNotifyUrl(), orderStatusNotifyVoStr);
-            log.info("订单状态同步返回结果: {}", resp);
+            Map<String, String> header = new HashMap<>();
+            String result = HttpUtils.post(appInfo.getOrderStatusNotifyUrl(), header, orderStatusNotifyVoStr, "utf-8");
+            log.info("订单状态同步返回结果: {}", result);
             // 收到成功响应后存入缓存, 后续不再推送
-            if (ResponseResultCodeEnum.SUCCESS.getMessage().equals(resp)) {
+            if (ResponseResultCodeEnum.SUCCESS.getMessage().equals(result)) {
                 redisCache.setCacheObject(key, "SUCCESS", 24, TimeUnit.HOURS);
             } else {
                 if (notifyCount == AppConstant.NOTIFY_INTERVAL_DURATION.size()) {

+ 5 - 1
lb-app/src/main/java/com/ydd/app/dto/BaseDto.java

@@ -2,12 +2,16 @@ package com.ydd.app.dto;
 
 import lombok.Data;
 
+import java.io.Serializable;
+
 /**
  * @author wangtao
  * @date 2022/4/7
  */
 @Data
-public class BaseDto {
+public class BaseDto implements Serializable {
+
+    private static final long serialVersionUID = 230827872539339255L;
 
     private String appId;
     private String sign;

+ 2 - 2
lb-app/src/main/java/com/ydd/app/service/impl/ApiShopServiceImpl.java

@@ -642,7 +642,7 @@ public class ApiShopServiceImpl implements ApiShopService {
             Merchant merchant = iMerchantService.getById(shop.getMerchantId());
             if (merchant != null && merchant.getAppId() != null) {
                 StoreStatusNotifyVo notifyVo = StoreStatusNotifyVo.builder()
-                        .shopCode(sd.getShopNo())
+                        .shopCode(shop.getCode())
                         .deliveryId(DeliveryTypeEnums.FENG_NIAO.getType())
                         .status(sd.getBindStatus())
                         .failMsg(sd.getAuthMsg())
@@ -684,7 +684,7 @@ public class ApiShopServiceImpl implements ApiShopService {
             Merchant merchant = iMerchantService.getById(shop.getMerchantId());
             if (merchant != null && merchant.getAppId() != null) {
                 StoreStatusNotifyVo notifyVo = StoreStatusNotifyVo.builder()
-                        .shopCode(sd.getShopNo())
+                        .shopCode(shop.getCode())
                         .deliveryId(DeliveryTypeEnums.FENG_NIAO.getType())
                         .status(sd.getBindStatus())
                         .failMsg(sd.getAuthMsg())

+ 179 - 0
lb-common/src/main/java/com/ydd/common/utils/http/HttpUtils.java

@@ -9,13 +9,39 @@ import java.net.ConnectException;
 import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import com.ydd.common.constant.Constants;
@@ -29,6 +55,61 @@ public class HttpUtils
 {
     private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
 
+    private static final String CHARSET = "utf-8";
+
+    private final static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).setConnectionRequestTimeout(60000).build();
+    private static PoolingHttpClientConnectionManager manager;
+    private static SSLContext sslcontext;
+
+    static {
+        sslcontext = createIgnoreVerifySSL();
+        // 设置协议http和https对应的处理socket链接工厂的对象
+        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
+                .register("http", PlainConnectionSocketFactory.INSTANCE)
+                .register("https", new SSLConnectionSocketFactory(sslcontext))
+                .build();
+        manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+        manager.setMaxTotal(800);// 连接池最大并发连接数
+        manager.setDefaultMaxPerRoute(400);// 单路由最大并发数
+    }
+
+    /**
+     * 绕过验证
+     *
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws KeyManagementException
+     */
+    public static SSLContext createIgnoreVerifySSL() {
+        SSLContext sc = null;
+        try {
+            sc = SSLContext.getInstance("TLS");
+            // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
+            X509TrustManager trustManager = new X509TrustManager() {
+                @Override
+                public void checkClientTrusted(
+                        java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
+                        String paramString) throws CertificateException {
+                }
+
+                @Override
+                public void checkServerTrusted(
+                        java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
+                        String paramString) throws CertificateException {
+                }
+
+                @Override
+                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+            };
+            sc.init(null, new TrustManager[]{trustManager}, null);
+        } catch (Exception e) {
+            log.error(ExceptionUtils.getFullStackTrace(e));
+        }
+        return sc;
+    }
+
     /**
      * 向指定 URL 发送GET方法的请求
      *
@@ -232,6 +313,104 @@ public class HttpUtils
         return result.toString();
     }
 
+    /**
+     * HTTP POST 请求
+     *
+     * @param url               请求url
+     * @param headers           请求头
+     * @param requestBodyString 表单字符串
+     * @param charset           编码
+     * @return
+     */
+    public static String post(String url, Map<String, String> headers, String requestBodyString, String charset) throws IOException {
+        if (charset == null || charset.trim().isEmpty()) {
+            charset = CHARSET;
+        }
+        CloseableHttpClient httpClient = getHttpclient();
+        CloseableHttpResponse response = null;
+        HttpEntity entity = null;
+        try {
+            HttpPost httpPost = new HttpPost(url);
+            handleHeader(headers).forEach(header -> httpPost.addHeader(header));
+            StringEntity reqBodyParams = new StringEntity(requestBodyString, charset);
+            reqBodyParams.setContentType("application/json");
+            httpPost.setEntity(reqBodyParams);
+            response = httpClient.execute(httpPost);
+            entity = response.getEntity();
+            if (response.getStatusLine().getStatusCode() == 200) {
+                return EntityUtils.toString(entity, charset);
+            }
+        } catch (IOException e) {
+            log.error("post请求异常,请求地址:" + url + ", 异常信息:" + JSON.toJSONString(e));
+            throw e;
+        } finally {
+            closeALL(entity, response, httpClient);
+        }
+        return null;
+    }
+
+    private static CloseableHttpClient getHttpclient() {
+        CloseableHttpClient httpclient = HttpClients.custom()
+                .setDefaultRequestConfig(requestConfig)
+                .setConnectionManager(manager)
+                .setRetryHandler(new DefaultHttpRequestRetryHandler())
+                .setConnectionManagerShared(true)
+                .build();
+        return httpclient;
+    }
+
+    /**
+     * 处理请求头
+     * Header只支持ASCII,如果使用中文需要编码
+     *
+     * @param headers map请求头
+     * @return header集合
+     */
+    private static List<Header> handleHeader(Map<String, String> headers) {
+        List<Header> headerArray = new ArrayList<>();
+        if (headers != null && !headers.isEmpty()) {
+            for (Map.Entry<String, String> entry : headers.entrySet()) {
+                Header header = new BasicHeader(entry.getKey(), entry.getValue());
+                headerArray.add(header);
+            }
+        } else {
+            Header header = new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36");
+            headerArray.add(header);
+        }
+        return headerArray;
+    }
+
+    /**
+     * 关闭所有连接
+     *
+     * @param entity
+     * @param response
+     * @param httpclient
+     */
+    private static void closeALL(HttpEntity entity, CloseableHttpResponse response, CloseableHttpClient httpclient) {
+        if (entity != null) {
+            try {
+                EntityUtils.consume(entity);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        if (response != null) {
+            try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        if (httpclient != null) {
+            try {
+                httpclient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
     private static class TrustAnyTrustManager implements X509TrustManager
     {
         @Override

+ 7 - 4
lb-feginclient/src/main/java/com/ydd/api/DeliveryCallbackApi.java

@@ -2,13 +2,16 @@ package com.ydd.api;
 
 
 import com.alibaba.fastjson.JSONObject;
-import com.ydd.third.common.dto.AptCallbackOrderVo;
 import com.ydd.third.common.dto.FengniaoV3Token;
 import com.ydd.third.common.vo.ResObject;
-import com.ydd.third.common.vo.callback.*;
+import com.ydd.third.common.vo.callback.CallBackOrderVo;
+import com.ydd.third.common.vo.callback.FengniaoV3CallbackStoreVo;
+import com.ydd.third.common.vo.callback.ShansongTokenVo;
 import com.ydd.third.common.vo.waimai.meituan.MeituanToken;
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
 
 import java.util.Map;
 
@@ -16,7 +19,7 @@ import java.util.Map;
 public interface DeliveryCallbackApi {
 
     @PostMapping(value = "/callBack/doOrder")
-    Object doOrder(@RequestBody CallBackOrderVo CallBackOrderVo);
+    <T> T doOrder(@RequestBody CallBackOrderVo CallBackOrderVo);
 
     @PostMapping(value = "/callback/fengniaoToken")
     ResObject<FengniaoV3Token> doToken(@RequestParam("code") String code, @RequestParam("merchantId") String merchantId);

+ 15 - 0
lb-feginclient/src/main/java/com/ydd/config/CustomizedConfiguration.java

@@ -0,0 +1,15 @@
+package com.ydd.config;
+
+import feign.codec.Decoder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CustomizedConfiguration {
+
+    @Bean
+    public Decoder feignDecoder() {
+        return new GenericsFeignResultDecoder();
+    }
+
+}

+ 35 - 0
lb-feginclient/src/main/java/com/ydd/config/GenericsFeignResultDecoder.java

@@ -0,0 +1,35 @@
+package com.ydd.config;
+
+import com.alibaba.fastjson.JSON;
+import feign.FeignException;
+import feign.Response;
+import feign.Util;
+import feign.codec.DecodeException;
+import feign.codec.Decoder;
+import lombok.extern.slf4j.Slf4j;
+import sun.reflect.generics.reflectiveObjects.TypeVariableImpl;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * @author 叶君翔
+ * @date 2022/04/19 15:44
+ */
+@Slf4j
+public class GenericsFeignResultDecoder implements Decoder {
+
+    @Override
+    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
+        if (response.body() == null) {
+            throw new DecodeException(response.status(), "no data response", response.request());
+        }
+        Class returnType = ((Method)((TypeVariableImpl)type).getGenericDeclaration()).getReturnType();
+        String bodyStr = Util.toString(response.body().asReader(Util.UTF_8));
+        log.info("bodyStr==================={}", bodyStr);
+        //对结果进行转换
+        return JSON.parseObject(bodyStr,returnType);
+    }
+
+}

+ 2 - 0
lb-module/src/main/java/com/ydd/module/constants/AppConstant.java

@@ -35,4 +35,6 @@ public interface AppConstant {
      */
     List<Integer> NOTIFY_INTERVAL_DURATION = Arrays.asList(0, 10, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200);
 
+//    List<Integer> NOTIFY_INTERVAL_DURATION = Arrays.asList(0, 10, 30, 60);
+
 }

+ 2 - 0
lb-third/lb-third-common/src/main/java/com/ydd/third/common/vo/callback/KfCallbackOrderVo.java

@@ -9,6 +9,8 @@ import java.util.List;
 
 @Data
 public class KfCallbackOrderVo extends BaseResponse {
+
+    private static final long serialVersionUID = 4085909012796689477L;
     /**
      * 响应错误信息
      */