Commit 2213ef44 by 胡超

Merge remote-tracking branch 'remotes/origin/feature/2020323_1.9.17_rocketmq'

parents 3b4ec738 e76d5c7d
...@@ -328,6 +328,21 @@ ...@@ -328,6 +328,21 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId> <groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId> <artifactId>mapper-spring-boot-starter</artifactId>
</dependency> </dependency>
......
package cn.freemud.amp.config;
import cn.freemud.constant.RocketMQConst;
import com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter;
import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.AccessChannel;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
@Configuration
public class RocketMQConfig {
@Resource
private RocketMQProperties rocketMQProperties;
@Bean(name = "deliveryRocketMqTemplate", destroyMethod = "destroy")
public RocketMQTemplate rocketMQTemplate() {
DefaultMQProducer defaultMQProducer = createMQProducer(RocketMQConst.ORDER_THIRD_PUSH_PRODUCER_GROUP);
RocketMQTemplate rocketMQTemplate = new RocketMQTemplate();
rocketMQTemplate.setProducer(defaultMQProducer);
rocketMQTemplate.setMessageConverter(new MappingFastJsonMessageConverter());
rocketMQTemplate.setMessageQueueSelector(new SelectMessageQueueByHash()); // MessageQueueSelector, default SelectMessageQueueByHash
return rocketMQTemplate;
}
/**
* @return
*/
public DefaultMQProducer createMQProducer(String producerGroupName) {
RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer();
String nameServer = rocketMQProperties.getNameServer();
String groupName = StringUtils.isEmpty(producerGroupName) ? producerConfig.getGroup() : producerGroupName;
Assert.hasText(nameServer, "rocketmq.name-server must not be null");
Assert.hasText(groupName, "rocketmq.producer.group must not be null");
String accessChannel = rocketMQProperties.getAccessChannel();
String accessKey = rocketMQProperties.getProducer().getAccessKey();
String secretKey = rocketMQProperties.getProducer().getSecretKey();
DefaultMQProducer producer = null;
// 密码模式
if (!StringUtils.isEmpty(accessKey) && !StringUtils.isEmpty(secretKey)) {
producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(accessKey, secretKey))
, rocketMQProperties.getProducer().isEnableMsgTrace()
, rocketMQProperties.getProducer().getCustomizedTraceTopic());
producer.setVipChannelEnabled(false);
} else {
producer = new DefaultMQProducer(groupName
, rocketMQProperties.getProducer().isEnableMsgTrace()
, rocketMQProperties.getProducer().getCustomizedTraceTopic());
}
producer.setNamesrvAddr(nameServer);
if (!StringUtils.isEmpty(accessChannel)) {
producer.setAccessChannel(AccessChannel.valueOf(accessChannel));
}
producer.setSendMsgTimeout(producerConfig.getSendMessageTimeout());
producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed());
producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed());
producer.setMaxMessageSize(producerConfig.getMaxMessageSize());
producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyThreshold());
producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryNextServer());
producer.setPollNameServerInterval(rocketMQProperties.getPollNameServerInteval());
producer.setHeartbeatBrokerInterval(rocketMQProperties.getHeartbeatBrokerInterval());
producer.setPersistConsumerOffsetInterval(rocketMQProperties.getPersistConsumerOffsetInterval());
return producer;
}
}
package cn.freemud.amp.config;
import org.apache.rocketmq.common.MixAll;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* {@link org.apache.rocketmq.spring.autoconfigure.RocketMQProperties}
*/
@Primary
@Component
@ConfigurationProperties(prefix = "rocketmq")
public class RocketMQProperties {
/**
* The name server for rocketMQ, formats: `host:port;host:port`.
*/
private String nameServer;
/**
* Enum type for accesChannel, values: LOCAL, CLOUD
* {@link org.apache.rocketmq.client.AccessChannel}
*/
private String accessChannel;
/**
* 轮询nameServer间隔时间,默认30S
*/
private int pollNameServerInteval = 30 * 1000;
/**
* 向broker发送心跳间隔时间,默认30S
*/
private int heartbeatBrokerInterval = 30 * 1000;
/**
* 持久化Consumer进度间隔时间,默认5S
*/
private int persistConsumerOffsetInterval = 5 * 1000;
private Producer producer;
/**
* Configure enable listener or not.
* In some particular cases, if you don't want the the listener is enabled when container startup,
* the configuration pattern is like this :
* rocketmq.consumer.listeners.<group-name>.<topic-name>.enabled=<boolean value, true or false>
* <p>
* the listener is enabled by default.
*/
private Consumer consumer = new Consumer();
public String getNameServer() {
return nameServer;
}
public void setNameServer(String nameServer) {
this.nameServer = nameServer;
}
public String getAccessChannel() {
return accessChannel;
}
public void setAccessChannel(String accessChannel) {
this.accessChannel = accessChannel;
}
public int getPollNameServerInteval() {
return pollNameServerInteval;
}
public void setPollNameServerInteval(int pollNameServerInteval) {
this.pollNameServerInteval = pollNameServerInteval;
}
public int getHeartbeatBrokerInterval() {
return heartbeatBrokerInterval;
}
public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) {
this.heartbeatBrokerInterval = heartbeatBrokerInterval;
}
public int getPersistConsumerOffsetInterval() {
return persistConsumerOffsetInterval;
}
public void setPersistConsumerOffsetInterval(int persistConsumerOffsetInterval) {
this.persistConsumerOffsetInterval = persistConsumerOffsetInterval;
}
public RocketMQProperties.Producer getProducer() {
return producer;
}
public void setProducer(RocketMQProperties.Producer producer) {
this.producer = producer;
}
public static class Producer {
/**
* Group name of producer.
*/
private String group;
/**
* Millis of send message timeout.
*/
private int sendMessageTimeout = 3000;
/**
* Compress message body threshold, namely, message body larger than 4k will be compressed on default.
*/
private int compressMessageBodyThreshold = 1024 * 4;
/**
* Maximum number of retry to perform internally before claiming sending failure in synchronous mode.
* This may potentially cause message duplication which is up to application developers to resolve.
*/
private int retryTimesWhenSendFailed = 2;
/**
* <p> Maximum number of retry to perform internally before claiming sending failure in asynchronous mode. </p>
* This may potentially cause message duplication which is up to application developers to resolve.
*/
private int retryTimesWhenSendAsyncFailed = 2;
/**
* Indicate whether to retry another broker on sending failure internally.
*/
private boolean retryNextServer = false;
/**
* Maximum allowed message size in bytes.
*/
private int maxMessageSize = 1024 * 1024 * 4;
/**
* The property of "access-key".
*/
private String accessKey;
/**
* The property of "secret-key".
*/
private String secretKey;
/**
* Switch flag instance for message trace.
*/
private boolean enableMsgTrace = true;
/**
* The name value of message trace topic.If you don't config,you can use the default trace topic name.
*/
private String customizedTraceTopic = MixAll.RMQ_SYS_TRACE_TOPIC;
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public int getSendMessageTimeout() {
return sendMessageTimeout;
}
public void setSendMessageTimeout(int sendMessageTimeout) {
this.sendMessageTimeout = sendMessageTimeout;
}
public int getCompressMessageBodyThreshold() {
return compressMessageBodyThreshold;
}
public void setCompressMessageBodyThreshold(int compressMessageBodyThreshold) {
this.compressMessageBodyThreshold = compressMessageBodyThreshold;
}
public int getRetryTimesWhenSendFailed() {
return retryTimesWhenSendFailed;
}
public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {
this.retryTimesWhenSendFailed = retryTimesWhenSendFailed;
}
public int getRetryTimesWhenSendAsyncFailed() {
return retryTimesWhenSendAsyncFailed;
}
public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) {
this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;
}
public boolean isRetryNextServer() {
return retryNextServer;
}
public void setRetryNextServer(boolean retryNextServer) {
this.retryNextServer = retryNextServer;
}
public int getMaxMessageSize() {
return maxMessageSize;
}
public void setMaxMessageSize(int maxMessageSize) {
this.maxMessageSize = maxMessageSize;
}
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public boolean isEnableMsgTrace() {
return enableMsgTrace;
}
public void setEnableMsgTrace(boolean enableMsgTrace) {
this.enableMsgTrace = enableMsgTrace;
}
public String getCustomizedTraceTopic() {
return customizedTraceTopic;
}
public void setCustomizedTraceTopic(String customizedTraceTopic) {
this.customizedTraceTopic = customizedTraceTopic;
}
}
public Consumer getConsumer() {
return consumer;
}
public void setConsumer(Consumer consumer) {
this.consumer = consumer;
}
public static final class Consumer {
/**
* listener configuration container
* the pattern is like this:
* group1.topic1 = false
* group2.topic2 = true
* group3.topic3 = false
*/
private Map<String, Map<String, Boolean>> listeners = new HashMap<>();
public Map<String, Map<String, Boolean>> getListeners() {
return listeners;
}
public void setListeners(Map<String, Map<String, Boolean>> listeners) {
this.listeners = listeners;
}
}
}
\ No newline at end of file
package cn.freemud.amp.service; package cn.freemud.amp.service;
import cn.freemud.amp.config.PushOrderConfig; import cn.freemud.amp.config.PushOrderConfig;
import cn.freemud.amqp.Header;
import cn.freemud.amqp.MQAction;
import cn.freemud.amqp.MQMessage; import cn.freemud.amqp.MQMessage;
import cn.freemud.amqp.MQService; import cn.freemud.amqp.MQService;
import cn.freemud.constant.RocketMQConst;
import cn.freemud.entities.dto.delivery.CallbackUrlRequestDto;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.BooleanUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/** /**
* mq发送方 * mq发送方
*/ */
@Slf4j
@Service @Service
public class ProduceMQService { public class ProduceMQService {
@Autowired @Autowired
private MQService mqService; private MQService mqService;
@Resource
private RocketMQTemplate deliveryRocketMqTemplate;
@Value("${rocketmq.delivery.enable:false}")
private Boolean rocketMQDeliveryEnable;
/** /**
* 发送配送状态变更信息 * @param deliveryRequest
* @param body * @Description 发现配送信息到rabbitMQ
*/ */
public void sendOfDeliveryInfo(MQMessage body) { public void sendOfDeliveryInfo(CallbackUrlRequestDto deliveryRequest) {
mqService.convertAndSend(PushOrderConfig.EXCHANGE_NAME, PushOrderConfig.OPEN_PLATFORM_ORDER_DELIVERY_ROUTING_KEY, body); Header header = new Header(MQAction.UPDATE.getAction(), "delivery/callbackUrl", deliveryRequest.getOrderId(), "open-platform-order-delivery-queue");
MQMessage<CallbackUrlRequestDto> mqMessage = new MQMessage<>(header, deliveryRequest);
try {
mqService.convertAndSend(PushOrderConfig.EXCHANGE_NAME, PushOrderConfig.OPEN_PLATFORM_ORDER_DELIVERY_ROUTING_KEY, mqMessage);
} catch (Exception e) {
log.error("sendOfDeliveryInfo.error, message:{}, cause:{}", JSON.toJSONString(deliveryRequest), Throwables.getStackTraceAsString(e));
}
} }
/**
* @param deliveryRequest
* @Description 发送配送信息到rocketMq:
*/
public void sendRocketMqOfDeliveryInfo(CallbackUrlRequestDto deliveryRequest) {
if (BooleanUtils.isNotTrue(rocketMQDeliveryEnable)) {
return;
}
Header header = new Header(MQAction.UPDATE.getAction(), "delivery/callbackUrl", deliveryRequest.getOrderId(), RocketMQConst.ORDER_THIRD_PUSH_TOPIC);
MQMessage<CallbackUrlRequestDto> mqMessage = new MQMessage(header, deliveryRequest);
String destination = String.format("%s:%s", RocketMQConst.ORDER_THIRD_PUSH_TOPIC, RocketMQConst.OrderSubsidiaryTag.delivery);
Message message = MessageBuilder
.withPayload(mqMessage)
.setHeader("partnerId", deliveryRequest.getPartnerId())
.setHeader(MessageConst.PROPERTY_KEYS, deliveryRequest.getDeliveryId())
.build();
try {
SendResult sendResult = deliveryRocketMqTemplate.syncSendOrderly(destination, message, deliveryRequest.getOrderId());
log.info("sendDelivery of status:{}, message:{},", sendResult.toString(), JSON.toJSONString(message));
} catch (Exception e) {
log.error("sendDelivery.error, message:{}, cause:{}", JSON.toJSONString(message), Throwables.getStackTraceAsString(e));
}
}
} }
package cn.freemud.constant;
/**
* @Description RocketMQ服务配置
* @mark topic 、producerGroup、consumerGroup 最大长度32,格式为 ^[%|a-zA-Z0-9_-]
*/
public class RocketMQConst {
// 订单周边业务(配送、发票)推送开放平台topic
public static final String ORDER_THIRD_PUSH_TOPIC = "order_third_push_topic";
// 订单周边业务(配送、发票)推送开放平台生产者名称
public static final String ORDER_THIRD_PUSH_PRODUCER_GROUP = "order_third_push_producer";
public enum OrderSubsidiaryTag {
delivery, invoice;
}
}
package cn.freemud.controller.test; package cn.freemud.controller.test;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.entities.vo.CheckBeforeCreateOrderRequestVo;
import cn.freemud.monitorcenter.tools.HealthUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.log.ApiAnnotation; import com.freemud.application.sdk.api.log.ApiAnnotation;
import com.freemud.application.sdk.api.log.LogParams; import com.freemud.application.sdk.api.log.LogParams;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
...@@ -58,5 +53,4 @@ public class TestController { ...@@ -58,5 +53,4 @@ public class TestController {
return platformBaseResponse; return platformBaseResponse;
} }
} }
...@@ -64,6 +64,11 @@ public enum DeliveryStatus { ...@@ -64,6 +64,11 @@ public enum DeliveryStatus {
return null; return null;
} }
/**
* @Description: 校验配送单状态是否需要推送给开放平台
* @param status
* @return
*/
public static boolean checkDeliveryStatueForPlatform(int status) { public static boolean checkDeliveryStatueForPlatform(int status) {
DeliveryStatus deliveryStatus = DeliveryStatus.getDeliveryStatusByCode(status); DeliveryStatus deliveryStatus = DeliveryStatus.getDeliveryStatusByCode(status);
if (null == deliveryStatus) return false; if (null == deliveryStatus) return false;
......
package cn.freemud.service.delivery; package cn.freemud.service.delivery;
import cn.freemud.amp.service.ProduceMQService; import cn.freemud.amp.service.ProduceMQService;
import cn.freemud.amqp.Header;
import cn.freemud.amqp.MQAction;
import cn.freemud.amqp.MQMessage;
import cn.freemud.base.entity.BaseResponse; import cn.freemud.base.entity.BaseResponse;
import cn.freemud.entities.dto.delivery.CallbackUrlRequestDto; import cn.freemud.entities.dto.delivery.CallbackUrlRequestDto;
import cn.freemud.entities.dto.delivery.QueryDeliveryAmountRequestDto; import cn.freemud.entities.dto.delivery.QueryDeliveryAmountRequestDto;
...@@ -131,9 +128,8 @@ public class ThirdDeliveryServiceImpl implements ThirdDeliveryService { ...@@ -131,9 +128,8 @@ public class ThirdDeliveryServiceImpl implements ThirdDeliveryService {
// 订单配送状态变化时发送到MQ // 订单配送状态变化时发送到MQ
if (DeliveryStatus.checkDeliveryStatueForPlatform(deliveryStatus)) { if (DeliveryStatus.checkDeliveryStatueForPlatform(deliveryStatus)) {
Header header = new Header(MQAction.UPDATE.getAction(), "delivery/callbackUrl", request.getOrderId(), "open-platform-order-delivery-queue"); produceMQService.sendOfDeliveryInfo(request);
MQMessage<CallbackUrlRequestDto> message = new MQMessage<>(header, request); produceMQService.sendRocketMqOfDeliveryInfo(request);
produceMQService.sendOfDeliveryInfo(message);
} }
// else { // else {
// return ResponseUtil.error(ResponseResult.SYSTEM_ERROR.getCode(), "订单回调状态有误"); // return ResponseUtil.error(ResponseResult.SYSTEM_ERROR.getCode(), "订单回调状态有误");
......
...@@ -8,4 +8,4 @@ apollo.meta=http://212.129.229.203 ...@@ -8,4 +8,4 @@ apollo.meta=http://212.129.229.203
env=dev env=dev
apollo.cluster=default apollo.cluster=default
apollo.bootstrap.enabled=true apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=micro_progeram_commons,order_service apollo.bootstrap.namespaces=micro_progeram_commons,order_service
\ No newline at end of file
package cn.freemud.amp.service;
import cn.freemud.amqp.Header;
import cn.freemud.amqp.MQAction;
import cn.freemud.amqp.MQMessage;
import cn.freemud.entities.dto.delivery.CallbackUrlRequestDto;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Random;
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableDiscoveryClient
@EnableFeignClients
@EnableAutoConfiguration
@ActiveProfiles("dev")
@Slf4j
public class ProduceMQServiceTest {
@Autowired
private ProduceMQService produceMQService;
@Test
public void sendOfDeliveryInfo() {
CallbackUrlRequestDto callbackUrlRequestDto = buildCallbackUrlRequestDto();
produceMQService.sendOfDeliveryInfo(callbackUrlRequestDto);
}
@Test
public void send() {
CallbackUrlRequestDto callbackUrlRequestDto = buildCallbackUrlRequestDto();
produceMQService.sendRocketMqOfDeliveryInfo(callbackUrlRequestDto);
}
public MQMessage buildMQMessage() {
MQMessage body = new MQMessage();
Header header = new Header(MQAction.UPDATE.getAction(), "order-application-service", "orderId", "ORDER_DELIVERY");
body.setHeader(header);
CallbackUrlRequestDto callbackUrlRequestDto = buildCallbackUrlRequestDto();
Random random = new Random(System.currentTimeMillis());
callbackUrlRequestDto.setDeliveryStatus(random.nextInt(8) + 1);
body.setBody(callbackUrlRequestDto);
return body;
}
public CallbackUrlRequestDto buildCallbackUrlRequestDto() {
String json = "{\n" +
" \"channelCode\":\"MeiTuan\",\n" +
" \"channelDeliveryId\":\"1584868781086019780\",\n" +
" \"channelName\":\"美团\",\n" +
" \"deliveryId\":\"6913353047542579209b\",\n" +
" \"deliveryStatus\":2,\n" +
" \"orderId\":\"17283381807564801000006\",\n" +
" \"partnerId\":\"1864\",\n" +
" \"riderName\":\"宋**\",\n" +
" \"riderPhone\":\"1782****316\",\n" +
" \"storeId\":\"a785e270-0f67-4805-b3db-6e2604b87909\",\n" +
" \"updateTime\":\"2020-03-22 17:20:45\"\n" +
"}";
CallbackUrlRequestDto callbackUrlRequestDto = JSON.parseObject(json, CallbackUrlRequestDto.class);
return callbackUrlRequestDto;
}
}
...@@ -79,6 +79,7 @@ public class DefaultPromotionService implements IPromotionService { ...@@ -79,6 +79,7 @@ public class DefaultPromotionService implements IPromotionService {
shoppingCartGoodsDto.setOriginalTotalAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount()); shoppingCartGoodsDto.setOriginalTotalAmount(shoppingCartGoodsResponseVo.getOriginalTotalAmount());
shoppingCartGoodsDto.setTotalAmount(shoppingCartGoodsResponseVo.getTotalAmount()); shoppingCartGoodsDto.setTotalAmount(shoppingCartGoodsResponseVo.getTotalAmount());
shoppingCartGoodsDto.setTotalDiscountAmount(shoppingCartGoodsResponseVo.getTotalDiscountAmount()); shoppingCartGoodsDto.setTotalDiscountAmount(shoppingCartGoodsResponseVo.getTotalDiscountAmount());
// todo 包装费
shoppingCartGoodsDto.setPackageAmount(shoppingCartGoodsResponseVo.getNewPackAmount()); shoppingCartGoodsDto.setPackageAmount(shoppingCartGoodsResponseVo.getNewPackAmount());
List<CartGoods> cartGoodsList = shoppingCartGoodsResponseVo.getProducts(); List<CartGoods> cartGoodsList = shoppingCartGoodsResponseVo.getProducts();
List<ActivityCalculationDiscountResponseDto.CalculationDiscountResult.ApportionGoods> apportionGoodsList = List<ActivityCalculationDiscountResponseDto.CalculationDiscountResult.ApportionGoods> apportionGoodsList =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment