|  | @@ -0,0 +1,296 @@
 | 
	
		
			
				|  |  | +package com.fs.erp.http;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import cn.hutool.core.bean.BeanUtil;
 | 
	
		
			
				|  |  | +import cn.hutool.core.map.MapUtil;
 | 
	
		
			
				|  |  | +import cn.hutool.http.HttpRequest;
 | 
	
		
			
				|  |  | +import cn.hutool.http.HttpResponse;
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.JSON;
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.PropertyNamingStrategy;
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.TypeReference;
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.serializer.SerializeConfig;
 | 
	
		
			
				|  |  | +import com.fs.erp.dto.*;
 | 
	
		
			
				|  |  | +import com.fs.erp.service.impl.JstTokenService;
 | 
	
		
			
				|  |  | +import com.fs.erp.utils.SignUtil;
 | 
	
		
			
				|  |  | +import com.fs.ybPay.dto.RefundOrderDTO;
 | 
	
		
			
				|  |  | +import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  | +import org.apache.commons.lang.ObjectUtils;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Value;
 | 
	
		
			
				|  |  | +import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.util.Arrays;
 | 
	
		
			
				|  |  | +import java.util.Collections;
 | 
	
		
			
				|  |  | +import java.util.HashMap;
 | 
	
		
			
				|  |  | +import java.util.Map;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@Slf4j
 | 
	
		
			
				|  |  | +@Service
 | 
	
		
			
				|  |  | +public class JstErpHttpServiceImpl implements JstErpHttpService {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static final String BASE_URL = "https://openapi.jushuitan.com/";
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取access_token、refresh_token url
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final String GET_INIT_TOKEN_URL = BASE_URL + "openWeb/auth/getInitToken";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 更新access_token、refresh_token url
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private static final String REFRESH_TOKEN_URL = BASE_URL + "openWeb/auth/refreshToken";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Value("${jst.app_key:''}")
 | 
	
		
			
				|  |  | +    private String appKey;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Value("${jst.app_secret:''}")
 | 
	
		
			
				|  |  | +    private String appSecret;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private JstTokenService jstTokenService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public GetInitTokenResponseDTO getInitToken(GetInitTokenRequestDTO dto) {
 | 
	
		
			
				|  |  | +        // 将DTO转换为表单参数
 | 
	
		
			
				|  |  | +        Map<String, Object> formParams = BeanUtil.beanToMap(dto);
 | 
	
		
			
				|  |  | +        log.info("请求初始化token - URL: {}, 参数: {}", GET_INIT_TOKEN_URL, JSON.toJSONString(formParams));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeFormPost(GET_INIT_TOKEN_URL, formParams);
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<GetInitTokenResponseDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public GetInitTokenResponseDTO refreshToken(RefreshTokenRequestDTO dto) {
 | 
	
		
			
				|  |  | +        log.info("刷新token - URL: {}, 请求体: {}", REFRESH_TOKEN_URL, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +        Map<String, Object> formParams = BeanUtil.beanToMap(dto);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeFormPost(REFRESH_TOKEN_URL, formParams);
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<GetInitTokenResponseDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public ProductUploadResultDTO uploadGoods(GoodsInfoDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/jushuitan/itemsku/upload";
 | 
	
		
			
				|  |  | +        log.info("上传商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, dto);
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<ProductUploadResultDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public ProductResponseDTO queryGoods(ProductQueryRequestDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/sku/query";
 | 
	
		
			
				|  |  | +        log.info("查询商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, dto);
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<ProductResponseDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public ErpOrderResponseDTO upload(ShopOrderDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "open/jushuitan/orders/upload";
 | 
	
		
			
				|  |  | +        log.info("上传订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, Arrays.asList(dto));
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<ErpOrderResponseDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public OrderQueryResponseDTO query(OrderQueryRequestDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/orders/single/query";
 | 
	
		
			
				|  |  | +        log.info("查询订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, dto);
 | 
	
		
			
				|  |  | +        return parseResponse(response, new TypeReference<CommonResponse<OrderQueryResponseDTO>>() {});
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public CommonResponse cancel(OrderCancelRequestDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/jushuitan/orderbyoid/cancel";
 | 
	
		
			
				|  |  | +        log.info("取消订单 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, dto);
 | 
	
		
			
				|  |  | +        // 这里直接返回CommonResponse类型
 | 
	
		
			
				|  |  | +        return parseCommonResponse(response);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public CommonResponse<AfterSaleResponseDTO> aftersaleUpload(RefundOrderDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/aftersale/upload";
 | 
	
		
			
				|  |  | +        log.info("售后上传 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, Collections.singletonList(dto));
 | 
	
		
			
				|  |  | +        // 这里直接返回CommonResponse类型
 | 
	
		
			
				|  |  | +        return parseCommonResponse(response);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public CommonResponse<AssetProcessResultDTO> aftersaleConfirm(AfterSaleConfirmRequestDTO dto) {
 | 
	
		
			
				|  |  | +        String url = BASE_URL + "/open/webapi/aftersaleapi/open/confirm";
 | 
	
		
			
				|  |  | +        log.info("售后单确认 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = executeJsonPost(url, dto);
 | 
	
		
			
				|  |  | +        // 这里直接返回CommonResponse类型
 | 
	
		
			
				|  |  | +        return parseCommonResponse(response);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 执行JSON格式的POST请求
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param url 请求URL
 | 
	
		
			
				|  |  | +     * @param dto 请求对象
 | 
	
		
			
				|  |  | +     * @param needToken 是否需要添加access_token(认证相关请求不需要)
 | 
	
		
			
				|  |  | +     * @return HttpResponse响应
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private HttpResponse executeJsonPost(String url, Object dto, boolean needToken) {
 | 
	
		
			
				|  |  | +        SerializeConfig serializeConfig = new SerializeConfig();
 | 
	
		
			
				|  |  | +        serializeConfig.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
 | 
	
		
			
				|  |  | +        String jsonBody = JSON.toJSONString(dto, serializeConfig);
 | 
	
		
			
				|  |  | +        Map<String, Object> map = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 只有在需要token的请求中才添加access_token
 | 
	
		
			
				|  |  | +        if (needToken) {
 | 
	
		
			
				|  |  | +            String accessToken = jstTokenService.getAccessToken();
 | 
	
		
			
				|  |  | +            map.put("access_token", accessToken);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        map.put("app_key", appKey);
 | 
	
		
			
				|  |  | +        map.put("timestamp", System.currentTimeMillis() / 1000);
 | 
	
		
			
				|  |  | +        map.put("version", "2");
 | 
	
		
			
				|  |  | +        map.put("charset", "utf-8");
 | 
	
		
			
				|  |  | +        map.put("biz", jsonBody);
 | 
	
		
			
				|  |  | +        map.put("sign", SignUtil.getSignNew(appSecret, map));
 | 
	
		
			
				|  |  | +        Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
 | 
	
		
			
				|  |  | +                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +        log.debug("发送JSON请求 - URL: {}, Headers: {}, Body: {}", url, headers, JSON.toJSONString(map));
 | 
	
		
			
				|  |  | +        HttpResponse response = HttpRequest.post(url)
 | 
	
		
			
				|  |  | +                .headerMap(headers, true)
 | 
	
		
			
				|  |  | +                .form(map)
 | 
	
		
			
				|  |  | +                .execute();
 | 
	
		
			
				|  |  | +        logResponse(response);
 | 
	
		
			
				|  |  | +        return response;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 执行JSON格式的POST请求
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param url 请求URL
 | 
	
		
			
				|  |  | +     * @param dto 请求对象
 | 
	
		
			
				|  |  | +     * @return HttpResponse响应
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private HttpResponse executeJsonPost(String url, Object dto) {
 | 
	
		
			
				|  |  | +        SerializeConfig serializeConfig = new SerializeConfig();
 | 
	
		
			
				|  |  | +        serializeConfig.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        String jsonBody = JSON.toJSONString(dto, serializeConfig);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Map<String,Object> map = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        String accessToken = jstTokenService.getAccessToken();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        map.put("access_token",accessToken);
 | 
	
		
			
				|  |  | +        map.put("app_key",appKey);
 | 
	
		
			
				|  |  | +        map.put("timestamp",System.currentTimeMillis()/1000);
 | 
	
		
			
				|  |  | +        map.put("version","2");
 | 
	
		
			
				|  |  | +        map.put("charset","utf-8");
 | 
	
		
			
				|  |  | +        map.put("biz", jsonBody);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        map.put("sign",SignUtil.getSignNew(appSecret, map));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
 | 
	
		
			
				|  |  | +                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        log.debug("发送JSON请求 - URL: {}, Headers: {}, Body: {}", url, headers, JSON.toJSONString(map));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = HttpRequest.post(url)
 | 
	
		
			
				|  |  | +                .headerMap(headers, true)
 | 
	
		
			
				|  |  | +                .form(map)
 | 
	
		
			
				|  |  | +                .execute();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        logResponse(response);
 | 
	
		
			
				|  |  | +        return response;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 执行表单格式的POST请求
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param url 请求URL
 | 
	
		
			
				|  |  | +     * @param formParams 表单参数
 | 
	
		
			
				|  |  | +     * @return HttpResponse响应
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private HttpResponse executeFormPost(String url, Map<String, Object> formParams) {
 | 
	
		
			
				|  |  | +        Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
 | 
	
		
			
				|  |  | +                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
 | 
	
		
			
				|  |  | +                .build();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        log.debug("发送表单请求 - URL: {}, Headers: {}, Form: {}", url, headers, formParams);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        HttpResponse response = HttpRequest.post(url)
 | 
	
		
			
				|  |  | +                .headerMap(headers, true)
 | 
	
		
			
				|  |  | +                .form(formParams)
 | 
	
		
			
				|  |  | +                .execute();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        logResponse(response);
 | 
	
		
			
				|  |  | +        return response;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 记录HTTP响应日志
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param response HTTP响应
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private void logResponse(HttpResponse response) {
 | 
	
		
			
				|  |  | +        log.debug("收到响应 - Status: {}, Headers: {}", response.getStatus(), response.headers());
 | 
	
		
			
				|  |  | +        log.debug("响应体: {}", response.body());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 解析带有泛型的HTTP响应
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param response HTTP响应
 | 
	
		
			
				|  |  | +     * @param typeReference 响应类型引用
 | 
	
		
			
				|  |  | +     * @param <T> 期望的响应数据类型
 | 
	
		
			
				|  |  | +     * @return 解析后的数据
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private <T> T parseResponse(HttpResponse response, TypeReference<CommonResponse<T>> typeReference) {
 | 
	
		
			
				|  |  | +        String body = response.body();
 | 
	
		
			
				|  |  | +        log.debug("解析响应体: {}", body);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        CommonResponse<T> commonResponse = JSON.parseObject(body, typeReference);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//        if (ObjectUtils.notEqual(commonResponse.getCode(), 0)) {
 | 
	
		
			
				|  |  | +        if (!Integer.valueOf(0).equals(commonResponse.getCode())) {
 | 
	
		
			
				|  |  | +            log.error("API请求失败 - 错误码: {}, 错误信息: {}", commonResponse.getCode(), commonResponse.getMsg());
 | 
	
		
			
				|  |  | +            throw new RuntimeException("请求接口失败!原因:" + commonResponse.getMsg());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        T result = commonResponse.getData();
 | 
	
		
			
				|  |  | +        log.info("API请求成功 - 结果: {}", JSON.toJSONString(result));
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 解析普通CommonResponse响应(无泛型)
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param response HTTP响应
 | 
	
		
			
				|  |  | +     * @return CommonResponse对象
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private CommonResponse parseCommonResponse(HttpResponse response) {
 | 
	
		
			
				|  |  | +        String body = response.body();
 | 
	
		
			
				|  |  | +        log.debug("解析响应体: {}", body);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        CommonResponse commonResponse = JSON.parseObject(body, CommonResponse.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (ObjectUtils.notEqual(commonResponse.getCode(), 0)) {
 | 
	
		
			
				|  |  | +            log.error("API请求失败 - 错误码: {}, 错误信息: {}", commonResponse.getCode(), commonResponse.getMsg());
 | 
	
		
			
				|  |  | +            throw new RuntimeException("请求接口失败!原因:" + commonResponse.getMsg());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        log.info("API请求成功 - 结果: {}", JSON.toJSONString(commonResponse));
 | 
	
		
			
				|  |  | +        return commonResponse;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |