Przeglądaj źródła

feat: 推送订单到erp

xdd 3 dni temu
rodzic
commit
e9518c1650

+ 10 - 1
fs-admin/src/test/java/com/fs/store/controller/FsStorePaymentControllerTest.java

@@ -20,6 +20,7 @@ import com.fs.store.mapper.FsStoreDeliversMapper;
 import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.mapper.FsStorePaymentMapper;
 import com.fs.store.service.IFsCouponScheduleService;
+import com.fs.store.service.IFsStoreOrderService;
 import com.fs.store.service.IFsStorePaymentService;
 import com.fs.store.service.channel.YbPaymentHandler;
 import com.fs.store.service.channel.param.PayProcessContext;
@@ -46,6 +47,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.test.context.junit4.SpringRunner;
 
 import java.math.BigDecimal;
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.*;
@@ -87,6 +89,13 @@ public class FsStorePaymentControllerTest {
     @Autowired
     private JstErpHttpService httpService;
 
+    @Autowired
+    private IFsStoreOrderService fsStoreOrderService;
+
+    @Test
+    public void pushErp() throws ParseException {
+        fsStoreOrderService.createOmsOrder(1332678L);
+    }
     @Test
     public void initJstToken() {
         GetInitTokenRequestDTO requestDTO = new GetInitTokenRequestDTO();
@@ -96,7 +105,7 @@ public class FsStorePaymentControllerTest {
         requestDTO.setCode("zzzzzz");
         requestDTO.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
 
-        requestDTO.setSign(SignUtil.getSign("1d112cb9d21d41e187ff824b5852f4cf",requestDTO));
+        requestDTO.setSign(SignUtil.getSignNew("1d112cb9d21d41e187ff824b5852f4cf",requestDTO));
 
         log.info("请求参数: {}", JSON.toJSONString(requestDTO));
         GetInitTokenResponseDTO initToken = httpService.getInitToken(requestDTO);

+ 2 - 0
fs-service-system/src/main/java/com/fs/erp/domain/ErpOrder.java

@@ -30,5 +30,7 @@ public class ErpOrder {
     String receiver_address;
     String deal_datetime;
 
+    String buyer_account;
+
     List<ErpOrderPayment> payments;
 }

+ 3 - 3
fs-service-system/src/main/java/com/fs/erp/dto/GetInitTokenResponseDTO.java

@@ -22,17 +22,17 @@ public class GetInitTokenResponseDTO implements Serializable {
     /**
      * 访问令牌
      */
-    private String accessToken;
+    private String access_token;
 
     /**
      * access_token访问过期时间(单位:秒)
      */
-    private Integer expiresIn;
+    private Integer expires_in;
 
     /**
      * 更新令牌
      */
-    private String refreshToken;
+    private String refresh_token;
 
     /**
      * 权限范围(固定值:all)

+ 62 - 0
fs-service-system/src/main/java/com/fs/erp/dto/RefreshTokenRequestDTO.java

@@ -0,0 +1,62 @@
+package com.fs.erp.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import java.io.Serializable;
+
+/**
+ * 刷新令牌请求DTO
+ *
+ * @author xdd
+ * @version 1.0
+ * @since 2025-02-27
+ */
+@Data
+@Accessors(chain = true)
+public class RefreshTokenRequestDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 开发者应用Key
+     * 示例值: 0ecde8631431a5ed6b3e7368afbabdadss
+     */
+    private String app_key;
+
+    /**
+     * 当前请求的时间戳(单位:秒)
+     * 示例值: 1577771730
+     */
+    private String timestamp;
+
+    /**
+     * 授权类型
+     * 固定值: refresh_token
+     */
+    private String grant_type = "refresh_token";
+
+    /**
+     * 交互数据的编码
+     * 固定值: utf-8
+     */
+    private String charset = "utf-8";
+
+    /**
+     * 更新令牌
+     * 示例值: eb1964a9d142423a9f0de88b97bb38fc
+     */
+    private String refresh_token;
+
+    /**
+     * 授权范围
+     * 固定值: all
+     */
+    private String scope = "all";
+
+    /**
+     * 请求的数字签名
+     * 通过所有请求参数通过摘要生成,保证请求参数没有被篡改
+     * 示例值: 0ecde8631431a5ed6b3e7368afbabdaoas
+     */
+    private String sign;
+}

+ 1 - 1
fs-service-system/src/main/java/com/fs/erp/http/JstErpHttpService.java

@@ -24,7 +24,7 @@ public interface JstErpHttpService {
      * @param dto 请求参数
      * @return GetInitTokenResponseDTO
      */
-    GetInitTokenResponseDTO refreshToken(GetInitTokenRequestDTO dto);
+    GetInitTokenResponseDTO refreshToken(RefreshTokenRequestDTO dto);
 
     /**
      * 普通商品资料上传

+ 46 - 8
fs-service-system/src/main/java/com/fs/erp/http/JstErpHttpServiceImpl.java

@@ -5,12 +5,20 @@ 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.JSONObject;
+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 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.HashMap;
 import java.util.Map;
 
@@ -29,18 +37,28 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
      */
     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);
+        HttpResponse response = executeJsonPost(GET_INIT_TOKEN_URL, formParams);
         return parseResponse(response, new TypeReference<CommonResponse<GetInitTokenResponseDTO>>() {});
     }
 
     @Override
-    public GetInitTokenResponseDTO refreshToken(GetInitTokenRequestDTO dto) {
+    public GetInitTokenResponseDTO refreshToken(RefreshTokenRequestDTO dto) {
         log.info("刷新token - URL: {}, 请求体: {}", REFRESH_TOKEN_URL, JSON.toJSONString(dto));
 
         HttpResponse response = executeJsonPost(REFRESH_TOKEN_URL, dto);
@@ -67,10 +85,10 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
 
     @Override
     public ErpOrderResponseDTO upload(ShopOrderDTO dto) {
-        String url = BASE_URL + "/open/jushuitan/orders/upload";
+        String url = BASE_URL + "open/jushuitan/orders/upload";
         log.info("上传订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));
 
-        HttpResponse response = executeJsonPost(url, dto);
+        HttpResponse response = executeJsonPost(url, Arrays.asList(dto));
         return parseResponse(response, new TypeReference<CommonResponse<ErpOrderResponseDTO>>() {});
     }
 
@@ -101,22 +119,42 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
      * @return HttpResponse响应
      */
     private HttpResponse executeJsonPost(String url, Object dto) {
-        String jsonBody = JSON.toJSONString(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/json;charset=UTF-8")
+                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                 .build();
 
-        log.debug("发送JSON请求 - URL: {}, Headers: {}, Body: {}", url, headers, jsonBody);
+
+        log.debug("发送JSON请求 - URL: {}, Headers: {}, Body: {}", url, headers, JSON.toJSONString(map));
 
         HttpResponse response = HttpRequest.post(url)
                 .headerMap(headers, true)
-                .body(jsonBody)
+                .form(map)
                 .execute();
 
         logResponse(response);
         return response;
     }
 
+
     /**
      * 执行表单格式的POST请求
      *

+ 29 - 8
fs-service-system/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -5,8 +5,13 @@ import com.fs.erp.domain.*;
 import com.fs.erp.dto.*;
 import com.fs.erp.http.JstErpHttpService;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.erp.utils.SignUtil;
+import com.fs.store.service.IFsStoreOrderService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.text.SimpleDateFormat;
@@ -17,21 +22,27 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Service
+@Primary
 public class JSTErpOrderServiceImpl implements IErpOrderService {
     @Autowired
     private JstErpHttpService jstErpHttpService;
+
+    @Autowired
+    private IFsStoreOrderService fsStoreOrderService;
+
     @Override
     public ErpOrderResponse addOrder(ErpOrder order) {
         ErpOrderPayment erpOrderPayment = order.getPayments().get(0);
 
         ShopOrderDTO shopOrderDTO = new ShopOrderDTO();
+
         shopOrderDTO.setShopId(Long.valueOf(order.getShop_code()));
         shopOrderDTO.setSoId(order.getPlatform_code());
         shopOrderDTO.setOrderDate(order.getDeal_datetime());
         // 待发货
         shopOrderDTO.setShopStatus(OrderStatusEnum.WAIT_SELLER_SEND_GOODS.name());
         // 买家账号
-        shopOrderDTO.setShopBuyerId(order.getReceiver_phone());
+        shopOrderDTO.setShopBuyerId(order.getBuyer_account());
         // 收货人省份
         shopOrderDTO.setReceiverState(order.getReceiver_province());
         // 收货人城市
@@ -43,11 +54,13 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         // 收货人详细地址
         shopOrderDTO.setReceiverName(order.getReceiver_name());
         // 收货人电话
-        shopOrderDTO.setReceiverPhone(order.getReceiver_phone());
+        shopOrderDTO.setReceiverPhone(order.getReceiver_mobile());
         // 支付金额
         shopOrderDTO.setPayAmount(erpOrderPayment.getPayment());
         // 运费
-        shopOrderDTO.setFreight(order.getPost_fee());
+        if(ObjectUtils.isEmpty(order.getPost_fee())) {
+            shopOrderDTO.setFreight(Double.valueOf("0.00"));
+        }
         // 备注
         shopOrderDTO.setRemark(order.getBuyer_memo());
         // 买家留言
@@ -60,12 +73,15 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         List<OrderItemDTO> itemDTOList = new ArrayList<>();
         for (ErpOrderItem detail : details) {
             OrderItemDTO orderItemDTO = new OrderItemDTO();
-            orderItemDTO.setSkuId(detail.getItem_code());
-            orderItemDTO.setShopSkuId(detail.getSku_code());
+            orderItemDTO.setSkuId("105220");
+            orderItemDTO.setShopSkuId(detail.getItem_code());
+            orderItemDTO.setName(detail.getItem_code());
             orderItemDTO.setAmount(Double.valueOf(detail.getPrice()));
-            orderItemDTO.setBasePrice(Double.valueOf(detail.getOrigin_price()));
+            if(detail.getOrigin_price() != null) {
+                orderItemDTO.setBasePrice(Double.valueOf(detail.getOrigin_price()));
+            }
             orderItemDTO.setQty(detail.getQty());
-            orderItemDTO.setOuterOiId(detail.getItem_code());
+            orderItemDTO.setOuterOiId(order.getPlatform_code());
             itemDTOList.add(orderItemDTO);
         }
         shopOrderDTO.setItems(itemDTOList);
@@ -76,7 +92,7 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         paymentDTO.setOuterPayId(order.getPlatform_code());
         paymentDTO.setPayDate(order.getDeal_datetime());
         paymentDTO.setPayment("微信");
-        paymentDTO.setBuyerAccount(order.getReceiver_phone());
+        paymentDTO.setBuyerAccount(order.getBuyer_account());
         paymentDTO.setSellerAccount("平台销售");
         shopOrderDTO.setPay(paymentDTO);
 
@@ -87,6 +103,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return erpOrderResponse;
     }
 
+
+
     @Override
     public ErpOrderResponse refundOrder(ErpRefundOrder order) {
         return null;
@@ -103,6 +121,8 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
         requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
 
+
+
         // 2. 调用ERP服务查询订单
         OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
 
@@ -233,6 +253,7 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         requestDTO.setOIds(Collections.singletonList(Integer.valueOf(param.getTid())));
         requestDTO.setCancelType("用户退款");
         requestDTO.setRemark("用户退款");
+
         jstErpHttpService.cancel(requestDTO);
 
         BaseResponse baseResponse = new BaseResponse();

+ 196 - 0
fs-service-system/src/main/java/com/fs/erp/service/impl/JstTokenService.java

@@ -0,0 +1,196 @@
+package com.fs.erp.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+import com.fs.erp.dto.GetInitTokenRequestDTO;
+import com.fs.erp.dto.GetInitTokenResponseDTO;
+import com.fs.erp.dto.RefreshTokenRequestDTO;
+import com.fs.erp.http.JstErpHttpService;
+import com.fs.erp.utils.SignUtil;
+import org.apache.http.protocol.HttpService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class JstTokenService {
+    private static final Logger log = LoggerFactory.getLogger(JstTokenService.class);
+
+    private static final String JST_TOKEN_KEY = "jst:access_token";
+    private static final String JST_REFRESH_TOKEN_KEY = "jst:refresh_token";
+    private static final String JST_TOKEN_EXPIRE_KEY = "jst:token_expire";
+
+    @Value("${jst.app_key}")
+    private String appKey;
+
+    @Value("${jst.app_secret}")
+    private String appSecret;
+
+    @Value("${jst.authorization_code}")
+    private String authorizationCode;
+
+    @Autowired
+    private JstErpHttpService httpService;
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    /**
+     * 获取访问令牌,如果缓存中存在有效令牌则直接返回,否则重新获取
+     * @return 有效的访问令牌
+     */
+    public String getAccessToken() {
+        String accessToken = redisTemplate.opsForValue().get(JST_TOKEN_KEY);
+
+        if (accessToken != null && !accessToken.isEmpty()) {
+            log.debug("从缓存中获取到有效的access_token");
+            return accessToken;
+        }
+
+        log.info("缓存中没有有效的access_token,重新获取");
+        return refreshAccessToken();
+    }
+
+    /**
+     * 强制刷新访问令牌
+     * @return 新的访问令牌
+     */
+    public String refreshAccessToken() {
+        // 检查是否有刷新令牌
+        String refreshToken = redisTemplate.opsForValue().get(JST_REFRESH_TOKEN_KEY);
+
+        if (refreshToken != null && !refreshToken.isEmpty()) {
+            log.info("使用refresh_token刷新令牌");
+            try {
+                return refreshTokenWithApi(refreshToken);
+            } catch (Exception e) {
+                log.error("使用refresh_token刷新失败,尝试重新初始化", e);
+            }
+        }
+
+        // 如果没有刷新令牌或刷新失败,则重新初始化
+        return initToken();
+    }
+
+    /**
+     * 初始化令牌
+     * @return 新的访问令牌
+     */
+    private String initToken() {
+        GetInitTokenRequestDTO requestDTO = new GetInitTokenRequestDTO();
+        requestDTO.setApp_key(appKey);
+        requestDTO.setGrant_type("authorization_code");
+        requestDTO.setCharset("utf-8");
+        requestDTO.setCode(authorizationCode);
+        requestDTO.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
+
+        // 计算签名
+        requestDTO.setSign(SignUtil.getSignNew(appSecret, requestDTO));
+
+        log.info("初始化token请求参数: {}", JSON.toJSONString(requestDTO));
+
+        GetInitTokenResponseDTO response = httpService.getInitToken(requestDTO);
+        if (response == null || response.getAccess_token() == null) {
+            throw new RuntimeException("初始化token失败: " + (response != null ? JSON.toJSONString(response) : "响应为空"));
+        }
+
+        // 缓存token信息
+        storeTokenInfo(response);
+
+        log.info("初始化token成功,token将在{}秒后过期", response.getExpires_in());
+        return response.getAccess_token();
+    }
+
+    /**
+     * 使用刷新令牌API刷新令牌
+     * @param refreshToken 刷新令牌
+     * @return 新的访问令牌
+     */
+    private String refreshTokenWithApi(String refreshToken) {
+        RefreshTokenRequestDTO requestDTO = new RefreshTokenRequestDTO();
+        requestDTO.setApp_key(appKey);
+        requestDTO.setGrant_type("refresh_token");
+        requestDTO.setCharset("utf-8");
+        requestDTO.setRefresh_token(refreshToken);
+        requestDTO.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
+
+        // 计算签名
+        requestDTO.setSign(SignUtil.getSignNew(appSecret, requestDTO));
+
+        log.info("刷新token请求参数: {}", JSON.toJSONString(requestDTO));
+
+        GetInitTokenResponseDTO response = httpService.refreshToken(requestDTO);
+        if (response == null || response.getAccess_token() == null) {
+            throw new RuntimeException("刷新token失败: " + (response != null ? JSON.toJSONString(response) : "响应为空"));
+        }
+
+        // 缓存token信息
+        storeTokenInfo(response);
+
+        log.info("刷新token成功,token将在{}秒后过期", response.getExpires_in());
+        return response.getAccess_token();
+    }
+
+    /**
+     * 将令牌信息存储到Redis
+     * @param tokenInfo 令牌信息
+     */
+    private void storeTokenInfo(GetInitTokenResponseDTO tokenInfo) {
+        // 默认30天过期时间,转换为秒
+        long expiresIn = tokenInfo.getExpires_in() != null ?
+                          Long.parseLong(String.valueOf(tokenInfo.getExpires_in())) : 30 * 24 * 60 * 60;
+
+        // 存储令牌,设置比官方少一天的过期时间,以确保安全
+        redisTemplate.opsForValue().set(JST_TOKEN_KEY, tokenInfo.getAccess_token(), expiresIn - 86400, TimeUnit.SECONDS);
+
+        // 存储刷新令牌,有效期与访问令牌相同
+        if (tokenInfo.getRefresh_token() != null) {
+            redisTemplate.opsForValue().set(JST_REFRESH_TOKEN_KEY, tokenInfo.getRefresh_token(), expiresIn, TimeUnit.SECONDS);
+        }
+
+        // 存储过期时间戳
+        long expireAt = System.currentTimeMillis() + (expiresIn * 1000);
+        redisTemplate.opsForValue().set(JST_TOKEN_EXPIRE_KEY, String.valueOf(expireAt), expiresIn, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 定时任务,每20天刷新一次令牌
+     * 根据文档说明,刷新token必须在有效期小于15天时进行,所以这里设置20天刷新一次
+     */
+    @Scheduled(fixedRate = 20 * 24 * 60 * 60 * 1000)
+    public void scheduleTokenRefresh() {
+        log.info("定时任务:刷新聚水潭API令牌");
+        try {
+            refreshAccessToken();
+        } catch (Exception e) {
+            log.error("定时刷新令牌失败", e);
+        }
+    }
+
+    /**
+     * 启动时初始化令牌
+     */
+    @PostConstruct
+    public void init() {
+        try {
+            // 检查Redis中是否已有有效token
+            String accessToken = redisTemplate.opsForValue().get(JST_TOKEN_KEY);
+            if (accessToken == null || accessToken.isEmpty()) {
+                log.info("系统启动,初始化聚水潭API令牌");
+                initToken();
+            } else {
+                log.info("系统启动,发现缓存中已有有效的聚水潭API令牌");
+            }
+        } catch (Exception e) {
+            log.error("初始化聚水潭API令牌失败", e);
+        }
+    }
+}

+ 63 - 22
fs-service-system/src/main/java/com/fs/erp/utils/SignUtil.java

@@ -6,36 +6,36 @@ import lombok.extern.slf4j.Slf4j;
 
 import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
 
 @Slf4j
 public class SignUtil {
     private SignUtil() {}
 
-    public static String getSign(String app_secret, Object bean) {
+    /**
+     * 获取签名 - 支持Map<String, Object>类型参数
+     *
+     * @param app_secret 密钥
+     * @param params 参数Map,支持Object类型值
+     * @return 签名字符串
+     */
+    public static String getSignNew(String app_secret, Map<String, Object> params) {
         try {
-            Map<String, Object> stringObjectMap = BeanUtil.beanToMap(bean);
-            return getSign(app_secret,stringObjectMap);
-        } catch (Exception e) {
+            String sortedStr = getSortedParamStrNew(params);
+            String paraStr = app_secret + sortedStr;
+
+            log.info("paraStr: {}",paraStr);
+            return createSign(paraStr);
+        } catch (UnsupportedEncodingException e) {
             log.warn("getSign UnsupportedEncodingException ", e);
         }
 
         return StringUtils.EMPTY;
     }
 
-    public static String getSign(String app_secret, Map<String, Object> params) {
+    public static String getSignNew(String app_secret, Object obj) {
         try {
-            Map<String, String> paramMap = new HashMap<>();
-            for (Map.Entry<String, Object> entry : params.entrySet()) {
-                if (entry.getValue() != null) {
-                    paramMap.put(entry.getKey(), entry.getValue().toString());
-                }
-            }
-
-            String sortedStr = getSortedParamStr(paramMap);
+            String sortedStr = getSortedParamStrNew(BeanUtil.beanToMap(obj));
             String paraStr = app_secret + sortedStr;
 
             return createSign(paraStr);
@@ -47,12 +47,12 @@ public class SignUtil {
     }
 
     /**
-     * 构造自然排序请求参数
+     * 构造自然排序请求参数 - 支持Map<String, Object>类型参数
      *
-     * @param params 请求
-     * @return 字符串
+     * @param params 请求参数
+     * @return 排序后的字符串
      */
-    private static String getSortedParamStr(Map<String, String> params) throws UnsupportedEncodingException {
+    private static String getSortedParamStrNew(Map<String, Object> params) throws UnsupportedEncodingException {
         Set<String> sortedParams = new TreeSet<>(params.keySet());
 
         StringBuilder strB = new StringBuilder();
@@ -62,7 +62,10 @@ public class SignUtil {
                 continue;
             }
 
-            String value = params.get(key);
+            Object valueObj = params.get(key);
+
+            // 处理Object类型值,转换为字符串
+            String value = valueObj != null ? valueObj.toString() : null;
 
             if (StringUtils.isNotEmpty(value)) {
                 strB.append(key).append(value);
@@ -103,4 +106,42 @@ public class SignUtil {
             return null;
         }
     }
+
+    /**
+     * 原有方法保留,保持向后兼容
+     */
+    public static String getSign(String app_secret, Map<String, String> params) {
+        try {
+            String sortedStr = getSortedParamStr(params);
+            String paraStr = app_secret + sortedStr;
+
+            return createSign(paraStr);
+        } catch (UnsupportedEncodingException e) {
+            log.warn("getSign UnsupportedEncodingException ", e);
+        }
+
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 原有方法保留,保持向后兼容
+     */
+    private static String getSortedParamStr(Map<String, String> params) throws UnsupportedEncodingException {
+        Set<String> sortedParams = new TreeSet<>(params.keySet());
+
+        StringBuilder strB = new StringBuilder();
+        // 排除sign和空值参数
+        for (String key : sortedParams) {
+            if ("sign".equalsIgnoreCase(key)) {
+                continue;
+            }
+
+            String value = params.get(key);
+
+            if (StringUtils.isNotEmpty(value)) {
+                strB.append(key).append(value);
+            }
+        }
+        return strB.toString();
+    }
 }

+ 8 - 6
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -1885,18 +1885,20 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             return;
         }
         ErpOrder erpOrder=new ErpOrder();
+        erpOrder.setBuyer_account(String.valueOf(order.getUserId()));
         if (order.getCompanyId()!=null){
             erpOrder.setVip_code(order.getUserId().toString()+order.getCompanyId().toString());
         }else {
             erpOrder.setVip_code(order.getUserId().toString());
         }
         erpOrder.setPlatform_code(order.getOrderCode());
-        if(order.getStoreHouseCode().equals("YDSP001")){
-            erpOrder.setShop_code("RunDayWuHan");
-        }
-        else{
-            erpOrder.setShop_code(sysConfig.getErpShopCode());
-        }
+        erpOrder.setShop_code("18461733");
+//        if(order.getStoreHouseCode().equals("YDSP001")){
+//            erpOrder.setShop_code("RunDayWuHan");
+//        }
+//        else{
+//            erpOrder.setShop_code(sysConfig.getErpShopCode());
+//        }
         erpOrder.setSeller_memo(order.getMark());
         List<ErpOrderPayment> payments=new ArrayList<>();
         ErpOrderPayment payment=new ErpOrderPayment();