/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: OrderServiceImpl
 * @Package cn.freemud.service.impl
 * @Description:
 * @author: liming.guo
 * @date: 2018/5/17 20:55
 * @version V1.0
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
package cn.freemud.service.impl;

import cn.freemud.adapter.*;
import cn.freemud.amqp.Header;
import cn.freemud.amqp.MQAction;
import cn.freemud.amqp.MQMessage;
import cn.freemud.amqp.MQService;
import cn.freemud.base.constant.Version;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.base.util.DateUtil;
import cn.freemud.constant.RedisKeyConstant;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.dto.PayAccessResponse;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.QueryOrdersResponseDto.DataBean.OrderBean;
import cn.freemud.entities.dto.order.CreateOrderOperateDto;
import cn.freemud.entities.dto.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.product.AttributeValue;
import cn.freemud.entities.dto.product.GroupDetail;
import cn.freemud.entities.dto.product.ProductAttributeGroup;
import cn.freemud.entities.dto.product.ProductGroup;
import cn.freemud.entities.dto.shoppingCart.NewShoppingCartClearDto;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.*;
import cn.freemud.service.thirdparty.*;
import cn.freemud.utils.LogUtil;
import cn.freemud.utils.ResponseUtil;
import cn.freemud.utils.ValidationCode;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.db.*;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.manager.*;
import com.freemud.api.assortment.datamanager.manager.cache.CacheOpenPlatformPartnerWxappConfigManager;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.api.assortment.datamanager.meal.MealCacheManager;
import com.freemud.application.sdk.api.constant.ResponseResultEnum;
import com.freemud.application.sdk.api.couponcenter.offline.response.CouponRedeemResponse;
import com.freemud.application.sdk.api.deliverycenter.service.DeliveryService;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.enums.AfterSalesType;
import com.freemud.application.sdk.api.ordercenter.enums.OrderClientType;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtInfoDto;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtendedReq;
import com.freemud.application.sdk.api.paymentcenter.client.request.CodePayRequest;
import com.freemud.application.sdk.api.paymentcenter.client.request.SVCCardAmountRequest;
import com.freemud.application.sdk.api.paymentcenter.client.response.CodePayResponse;
import com.freemud.application.sdk.api.paymentcenter.client.response.SVCCardAmountResponse;
import com.freemud.application.sdk.api.paymentcenter.client.service.PaymentNewService;
import com.freemud.application.sdk.api.storecenter.response.StoreResponse;
import com.freemud.application.sdk.api.storecenter.service.StoreCenterService;
import com.freemud.application.sdk.api.structure.service.MessageCenterClient;
import com.freemud.sdk.api.assortment.message.config.MessageOfficialRefundPushMqConfig;
import com.freemud.sdk.api.assortment.message.entity.MpTemplateMsg;
import com.freemud.sdk.api.assortment.message.entity.MpTemplateMsgDataValue;
import com.freemud.sdk.api.assortment.message.enums.MessageEventType;
import com.freemud.sdk.api.assortment.message.request.MessagePushOrderTemplateRequest;
import com.freemud.sdk.api.assortment.message.request.MessageTemplateRequest;
import com.freemud.sdk.api.assortment.message.service.IMessageTemplatePushService;
import cn.freemud.enums.CouponReqTypeEnum;
import cn.freemud.enums.MCCafeChannelEnum;
import com.freemud.sdk.api.assortment.order.enums.OldOrderStatus;
import com.freemud.sdk.api.assortment.order.enums.QueryOrderAccountType;
import cn.freemud.entities.dto.coupon.MCCafeConponRequest;
import cn.freemud.entities.dto.coupon.MCCafeCouponLockRequest;
import cn.freemud.entities.dto.coupon.MCCafeProductRedeemVo;
import cn.freemud.entities.dto.coupon.MCCafeTransactionVo;
import com.freemud.sdk.api.assortment.order.request.order.*;
import com.freemud.sdk.api.assortment.order.response.order.*;
import com.freemud.sdk.api.assortment.order.response.payment.OrderPayResponse;
import cn.freemud.service.mccafe.CouponClientService;
import cn.freemud.service.mccafe.MCCafeOrderCenterSdkService;
import com.freemud.sdk.api.assortment.order.service.OrderCenterSdkService;
import com.freemud.sdk.api.assortment.order.vo.ProductGroupVo;
import com.freemud.sdk.api.assortment.orderdistributor.entity.dto.PaymentMqMessageDto;
import com.freemud.sdk.api.assortment.orderdistributor.service.PaymentQueueService;
import com.freemud.sdk.api.assortment.payment.request.UnifiedOrderRequest;
import com.freemud.sdk.api.assortment.payment.response.UnifiedOrderResponse;
import com.freemud.sdk.api.assortment.payment.service.StandardPaymentService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MCCafeOrderServiceImpl implements MCCafeOrderService {

    private final Integer RESPONSE_SUCCESS_CODE = 100;

    private static Gson gson = new Gson();

    @Value("${saas.reverseNotifyiDcUrl}")
    private String reverseNotifyiDcUrl;
    @Value("${program.backorders_change_order_status_consumer_queue}")
    private String backOrdersChangeOrderStatusConsumerQueue;
    @Value("${program.backorders_notify_activity_exchange}")
    private String backOrdersNotifyActivityExchange;
    @Value("${mq.queue.cloud_print_queue}")
    private String cloudPrintQueue;
    @Value("${mq.cloud_print_exchange}")
    private String cloud_print_exchange;

    @Autowired
    private AssortmentCloudPrinterManager cloudPrinterManager;
    @Autowired
    private FMAssistantCloudPrintClient fmAssistantCloudPrintClient;
    @Autowired
    private MessageCenterClient messageNoticeClient;
    @Autowired
    private PromotionActivityClient promotionActivityClient;
    @Autowired
    private ShoppingCartClient shoppingCartClient;
    @Autowired
    private CustomerApplicationClient customerApplicationClient;
    @Autowired
    private ItemServiceImpl itemService;
    @Autowired
    private BuriedPointService buriedPointService;
    @Autowired
    private CouponActivityService couponActivityService;
    @Autowired
    private MessageNoticeAdapter messageNoticeAdapter;
    @Autowired
    private OrderAdapter orderAdapter;
    @Autowired
    private ActivityAdapter activityAdapter;
    @Autowired
    private CouponAdapter couponAdapter;
    @Autowired
    private MealCacheManager mealCacheManager;
    //聚合订单服务
    @Autowired
    private OrderCenterSdkService orderCenterSdkService;
    @Autowired
    private MCCafeOrderCenterSdkService mcCafeOrderCenterSdkService;
    @Autowired
    private StandardPaymentService standardPaymentService;
    //门店SDK
    @Autowired
    private StoreCenterService storeCenterService;
    @Autowired
    private DeliveryService deliveryService;
    @Autowired
    private MQService mqService;
    @Autowired
    @Qualifier("messageTemplatePushOrderService")
    private IMessageTemplatePushService<MessagePushOrderTemplateRequest> messageTemplatePushService;
    @Autowired
    private AssortmentOpenPlatformWxappManager openPlatformWxappManager;
    @Autowired
    private AssortmentOpenPlatformPartnerConfigManager openPlatformPartnerConfigManager;
    @Autowired
    private AssortmentCustomerInfoManager customerInfoManager;
    @Autowired
    private CheckMCCafeOrder checkMCCafeOrder;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private PaymentQueueService paymentQueueService;
    @Autowired
    private PaymentNewService paymentNewService;
    @Autowired
    private ActivityApplicationClient activityApplicationClient;
    @Autowired
    private AssortmentOpenPlatformWxappAuthorizerManager wxappAuthorizerManager;
    @Autowired
    private PaymentNewClient paymentNewClient;
    @Autowired
    private CacheOpenPlatformPartnerWxappConfigManager cacheOpenPlatformPartnerWxappConfigManager;
    @Autowired
    private OrderAdapterService orderAdapterService;
    @Autowired
    private AssortmentOpenPlatformPartnerManager assortmentOpenPlatformPartnerManager;
    @Autowired
    private CouponClientService couponClientService;

    @Override
    public BaseResponse createMCCafeOrder(CreateOrderVo createOrderVo) {
        String trackingNo = LogThreadLocal.getTrackingNo();
        // 查询用户信息、校验svc卡,余额购物车校验
        AssortmentCustomerInfoVo userLoginInfoDto = checkMCCafeOrder.checkOrderByMember(createOrderVo, trackingNo);
        // 查询门店信息 营业时间、营业状态，服务器当前时间在营业时间内
        StoreResponse.BizVO storeResponseDto = checkMCCafeOrder.checkOrderByStore(createOrderVo, trackingNo);
        // 查询购物车（内部校验券点餐方式，券是否可用） 校验当前订单类型的下单参数
        ShoppingCartGoodsDto shoppingCartGoodsDto = checkMCCafeOrder.getMCCafeShoppingCartGoodsDto(createOrderVo);
        // 查询小程序自提外卖配置信息 校验当前订单类型的下单参数 校验外卖是否满足起送条件
        Integer pushOrderTime = checkMCCafeOrder.checkOrderByOrderType(createOrderVo, userLoginInfoDto, storeResponseDto, shoppingCartGoodsDto, trackingNo);
        OrderExtInfoDto extInfo = getExtInfo(userLoginInfoDto, storeResponseDto, pushOrderTime, createOrderVo);
        //1.9.2套餐需求同步优化创建订单代码
        BaseResponse createOrderOperateDtoResponse = this.sdkCreateOrder(createOrderVo, storeResponseDto, shoppingCartGoodsDto, userLoginInfoDto);
        if(createOrderOperateDtoResponse == null || !ResponseResult.SUCCESS.getCode().equals(createOrderOperateDtoResponse.getCode()) || createOrderOperateDtoResponse.getResult() == null ) {
            return createOrderOperateDtoResponse;
        }
        CreateOrderOperateDto createOrderOperateDto = (CreateOrderOperateDto)createOrderOperateDtoResponse.getResult();
        //创建支付
        CreatePrepayRequestDto createPrepayRequestDto = orderAdapter.convertToCreatePrepayRequestDto(userLoginInfoDto, createOrderVo, createOrderOperateDto, extInfo);
        return this.createPrepayOrder(createPrepayRequestDto);
    }


    /**
     * 获取预支付成功，将信息放入死心队列，当支付成功没有回掉的时候处理
     *
     * @param partnerId
     * @param storeId
     * @param fmId
     * @param orderId
     */
    public void putDelMq(String partnerId, String storeId, String fmId, String orderId) {
        PaymentMqMessageDto dto = new PaymentMqMessageDto();
        try {
            dto.setFmId(fmId);
            dto.setOrderId(orderId);
            dto.setPartnerId(partnerId);
            dto.setStoreId(storeId);
            dto.setTrackingNo(LogThreadLocal.getTrackingNo());
            paymentQueueService.paymentCallback(dto);
        } catch (Exception e) {
            log.info("paymentQueueService.paymentCallback" + dto + " error" + e);
        }

    }

    @Override
    public String mcCafePaySuccessCallback(NewPaysuccessNoticeMessage newMessage) {
        PaysuccessNoticeMessage message = new PaysuccessNoticeMessage();
        message.setResult_code(StringUtils.isBlank(newMessage.getResultCode()) ? 0 : Integer.valueOf(newMessage.getResultCode()));
        message.setOut_trade_no(StringUtils.isBlank(newMessage.getTransactionCode()) ? "" : newMessage.getTransactionCode());
        message.setTrans_id(StringUtils.isBlank(newMessage.getTransId()) ? "" : newMessage.getTransId());
        message.setTotal_fee(newMessage.getTotalAmount() == null ? 0 : newMessage.getTotalAmount());
        message.setOpenid(StringUtils.isBlank(newMessage.getOpenId()) ? "" : newMessage.getOpenId());
        message.setPlatform_coupon(newMessage.getPlatformCoupon() == null ? 0 : newMessage.getPlatformCoupon());
        message.setMerchant_coupon(newMessage.getPlatformCoupon() == null ? 0 : newMessage.getPlatformCoupon());
        message.setPaid_no(newMessage.getThirdPartTradeNo());
        message.setEndTransId(newMessage.getEndTransId());
        message.setPlatformMchId(newMessage.getPlatformMchId());
        message.setTerminalId(newMessage.getAppId());
        message.setRuleId(newMessage.getRuleId());
        String res = orderAdapterService.mcCafePaySuccessCallback(message);
        JSONObject jsonObject = JSONObject.parseObject(res);
        if (jsonObject.containsKey("code")) {
            Integer code = (Integer) jsonObject.get("code");
            if (Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS_0, code) || Objects.equals(ResponseCodeConstant.RESPONSE_SUCCESS, code)) {
                //  新版支付成功的情况下code为100
                return newSendPaySuccessNoticeMessage();
            } else {
                return newSendPayFaileMessage();
            }
        }
        return newSendPayFaileMessage();
    }

    public QueryRelationOrderByIdResponseDto getQueryRelationOrderByIdResponseDto(String oid) {
        QueryRelatedOrderByCodeRequest baseQueryOrderRequest = new QueryRelatedOrderByCodeRequest();
        baseQueryOrderRequest.setOrderCode(oid);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryRelatedOrderByCodeResp queryOrderByIdResponse;
        queryOrderByIdResponse = orderCenterSdkService.queryRelatedOrderByCode(baseQueryOrderRequest);
        String string = JSONObject.toJSONString(queryOrderByIdResponse);
        JSONObject jsonObject = JSONObject.parseObject(string);
        QueryRelationOrderByIdResponseDto queryOrderByIdResponseDto = jsonObject.toJavaObject(QueryRelationOrderByIdResponseDto.class);
        String orderString = JSONObject.toJSONString(queryOrderByIdResponse.getOrderBeanList());
        queryOrderByIdResponseDto.setData(JSONArray.parseArray(orderString, OrderBean.class));
        return queryOrderByIdResponseDto;
    }

    public void backOrdersStatusChange(String oid, Integer orderStatus) {
        if (StringUtils.isEmpty(oid)) {
            return;
        }
        ApiLog.info("backOrdersStatusChange", oid, String.valueOf(orderStatus));
        OrderStatusChangeRequestDto requestDto = new OrderStatusChangeRequestDto();
        requestDto.setOid(oid);
        requestDto.setOrderStatus(orderStatus);

        try {
            Header header = new Header(MQAction.INSERT.getAction(), "backOrdersStatusChange", oid, backOrdersChangeOrderStatusConsumerQueue);
            MQMessage<OrderStatusChangeRequestDto> message = new MQMessage<>(header, requestDto);
            mqService.convertAndSend(backOrdersNotifyActivityExchange, backOrdersChangeOrderStatusConsumerQueue, message);
        } catch (Exception e) {
            LogUtil.error("ActivityReverse", JSON.toJSONString(requestDto), "", e);
        }
    }

    private QueryOrderByIdResponseDto getQueryOrderByIdResponseDto(String oid) {
        BaseQueryOrderRequest baseQueryOrderRequest = new BaseQueryOrderRequest();
        baseQueryOrderRequest.setOrderId(oid);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryOrderByIdResponse queryOrderByIdResponse = orderCenterSdkService.queryOrderById(baseQueryOrderRequest);
        String string = JSONObject.toJSONString(queryOrderByIdResponse);
        JSONObject jsonObject = JSONObject.parseObject(string);
        return jsonObject.toJavaObject(QueryOrderByIdResponseDto.class);
    }

    /**
     * 支付后通知确认返回信息
     */
    public String newSendPaySuccessNoticeMessage() {
        Map<String, Object> map = Maps.newTreeMap();
        map.put("code", 100);
        map.put("message", "success");
        return gson.toJson(map);
    }

    /**
     * 支付后通知失败返回信息
     */
    public String newSendPayFaileMessage() {
        Map<String, Object> map = Maps.newTreeMap();
        map.put("code", 500);
        map.put("message", "failed");
        return gson.toJson(map);
    }


    /**
     * 发送模板消息
     *
     * @param orderBean
     * @param messageEventType
     */
    private void sendMessage(OrderBean orderBean, MessageEventType messageEventType) {
        MessageTemplateRequest<MessagePushOrderTemplateRequest> messageTemplateRequest = null;
        try {
            messageTemplateRequest = messageNoticeAdapter.convent2MessageTemplateRequest(orderBean);
            messageTemplateRequest.setMessageEventType(messageEventType);
            this.messageTemplatePushService.sendTemplateMsg(messageTemplateRequest);
        } catch (Exception e) {
            LogUtil.error("sendTemplateMsg_error", JSONObject.toJSONString(orderBean), JSONObject.toJSONString(messageTemplateRequest), e);
        }
    }


    /**
     * 获取父子订单商品第三方商品编号
     *
     * @param
     * @return
     */
    private CreateFatherSonOrderRequest getProductCustomerCodeNew(CreateFatherSonOrderRequest fatherSonOrderRequest) {
        List<String> pids = new ArrayList<>();
        List<CreateFatherSonOrderRequest.OrderInfo> productOrderInfoList = fatherSonOrderRequest.getOrderInfoList().stream().filter(orderInfo -> orderInfo.getProducts() != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(productOrderInfoList)) {
            return fatherSonOrderRequest;
        }
        for (CreateOrderProductRequest productDto : productOrderInfoList.get(0).getProducts()) {
            pids.add(productDto.getProductId());
        }
        Map<String, GetProductsVo> products = itemService.getSpuProducts(pids, fatherSonOrderRequest.getPartnerId(), productOrderInfoList.get(0).getShopId(),fatherSonOrderRequest.getMenuType());
        if (products.isEmpty()) {
            return fatherSonOrderRequest;
        }
        for (CreateOrderProductRequest productDto : productOrderInfoList.get(0).getProducts()) {
            if (StringUtils.isNotEmpty(productDto.getSpecification()) && products.get(productDto.getSpecification()) != null) {
                productDto.setCustomerCode(products.get(productDto.getSpecification()).getCustomerCode());
                productDto.setProductCode(products.get(productDto.getSpecification()).getProductCode());
                productDto.setThirdProductSpecId(products.get(productDto.getSpecification()).getThirdProductSpecId());
                productDto.setThirdProductPropertyId(getThirdPropertyId(products.get(productDto.getSpecification()).getProductAttributeGroupList(),productDto.getAddInfo()));
            } else {
                productDto.setCustomerCode("");
                productDto.setProductCode("");
                LogUtil.error("getProducts_exception", JSONObject.toJSONString(pids), JSONObject.toJSONString(products));
            }
            //套餐子商品
            if(CollectionUtils.isNotEmpty(productDto.getComboProduct())){
                for (CreateOrderProductRequest comboProduct : productDto.getComboProduct()){
                    String comboSkuId = comboProduct.getSpecification();
                    if (products.get(comboSkuId) != null) {
                        comboProduct.setCustomerCode(products.get(comboSkuId).getCustomerCode());
                        comboProduct.setProductCode(products.get(comboSkuId).getProductCode());
                        comboProduct.setThirdProductSpecId(products.get(comboSkuId).getThirdProductSpecId());
                        comboProduct.setThirdProductPropertyId(getThirdPropertyId(products.get(comboSkuId).getProductAttributeGroupList(),comboProduct.getAddInfo()));
                    } else {
                        comboProduct.setCustomerCode("");
                        comboProduct.setProductCode("");
                        LogUtil.error("getProducts_exception", JSONObject.toJSONString(comboSkuId), JSONObject.toJSONString(products), null);
                    }
                }
            }
        }
        return fatherSonOrderRequest;
    }

    /**
     * 获取商品第三方商品编号
     *
     * @param createOrderDto
     * @return
     */
    private BaseCreateOrderRequest getProductCustomerCode(BaseCreateOrderRequest createOrderDto) {
        List<String> spuIds = new ArrayList<>();
        for (CreateOrderProductRequest productDto : createOrderDto.getProducts()) {
            spuIds.add(productDto.getProductId());
        }
        Map<String, GetProductsVo> products = itemService.getSpuProducts(spuIds, createOrderDto.getCompanyId(), createOrderDto.getShopId(),createOrderDto.getMenuType());
        if (products.isEmpty()) {
            return createOrderDto;
        }
        for (CreateOrderProductRequest productDto : createOrderDto.getProducts()) {
            String skuId = productDto.getSpecification();
            if (products.get(skuId) != null) {
                productDto.setCustomerCode(products.get(skuId).getCustomerCode());
                productDto.setProductCode(products.get(skuId).getProductCode());
                productDto.setThirdProductSpecId(products.get(productDto.getSpecification()).getThirdProductSpecId());
                productDto.setThirdProductPropertyId(getThirdPropertyId(products.get(productDto.getSpecification()).getProductAttributeGroupList(),productDto.getAddInfo()));

                // todo 商品组信息
                setProductGroupInfo(products.get(skuId).getProductGroupList(), productDto);
            } else {
                productDto.setCustomerCode("");
                productDto.setProductCode("");
                LogUtil.error("getProducts_exception", JSONObject.toJSONString(skuId), JSONObject.toJSONString(products), null);
            }
            //套餐子商品
            if(CollectionUtils.isNotEmpty(productDto.getComboProduct())){
                for (CreateOrderProductRequest comboProduct : productDto.getComboProduct()){
                    String comboSkuId = comboProduct.getSpecification();
                    System.out.println(comboSkuId);
                    if (products.get(comboSkuId) != null) {
                        comboProduct.setCustomerCode(products.get(comboSkuId).getCustomerCode());
                        comboProduct.setProductCode(products.get(comboSkuId).getProductCode());
                        comboProduct.setThirdProductSpecId(products.get(comboSkuId).getThirdProductSpecId());
                        comboProduct.setThirdProductPropertyId(getThirdPropertyId(products.get(comboSkuId).getProductAttributeGroupList(),comboProduct.getAddInfo()));
                        comboProduct.setStapleFood(products.get(comboSkuId).getStapleFood());
                        // todo 套餐商品的商品组信息
                        setProductGroupInfo(products.get(comboSkuId).getProductGroupList(), comboProduct);
                    } else {
                        comboProduct.setCustomerCode("");
                        comboProduct.setProductCode("");
                        LogUtil.error("getProducts_exception", JSONObject.toJSONString(skuId), JSONObject.toJSONString(products), null);
                    }
                }
            }
        }
        return createOrderDto;
    }

    /**
     * 设置商品组信息
     * @param productGroupList
     * @param product
     */
    private void setProductGroupInfo(List<ProductGroup> productGroupList, CreateOrderProductRequest product) {
        if (CollectionUtils.isEmpty(productGroupList)) return;

        List<ProductGroupVo> targetGroupList = Lists.newArrayList();
        for (ProductGroup productGroup : productGroupList) {
            for (GroupDetail groupDetail : productGroup.getGroupDetail()) {
                ProductGroupVo productGroupVo = ProductGroupVo.builder()
                        .groupId(groupDetail.getGroupId()).groupName(productGroup.getName())
                        .thirdGroupId(productGroup.getGroupCode()).build();
                if (!targetGroupList.contains(productGroupVo)) {
                    targetGroupList.add(productGroupVo);
                }
            }
        }
        product.setProductGroupList(targetGroupList);
    }

    private String getThirdPropertyId(List<ProductAttributeGroup> productAttributeGroups, String addInfo) {
        String thirdProductPropertyId = "";
        if(StringUtils.isBlank(addInfo) || CollectionUtils.isEmpty(productAttributeGroups) ){
            return thirdProductPropertyId;
        }
        JSONObject jsonObject = JSONObject.parseObject(addInfo);
        String attributeNames = (String)jsonObject.get("attributeNames");
        List<String> list = new ArrayList<>();
        String[] split = attributeNames.split("/");

        List<AttributeValue> attributeValues = new ArrayList<>();
        for (ProductAttributeGroup attributeGroup : productAttributeGroups){
            attributeValues.addAll(attributeGroup.getAttributeValues());
        }

        for (int i= 0;i<split.length;i++){
            for (AttributeValue attributeValue : attributeValues){
                if(attributeValue.getAttributeValue().equals(split[i])){
                    list.add(attributeValue.getCustomerCode());
                    break;
                }
            }
        }
        if (CollectionUtils.isNotEmpty(list)) {
            thirdProductPropertyId = StringUtils.join(list, ",");
        }
        return thirdProductPropertyId;
    }

    /**
     * 创建订单调用集成，不区分订单类型
     *
     * @return
     */
    public BaseResponse sdkCreateOrder(CreateOrderVo createOrderVo, StoreResponse.BizVO storeResponseDto, ShoppingCartGoodsDto shoppingCartGoodsDto,
                                                              AssortmentCustomerInfoVo userLoginInfoDto) {
        CreateOrderOperateDto response = new CreateOrderOperateDto();
        OrderExtendedReq orderExtendedReq = orderAdapter.saveStoreInfo(storeResponseDto);
        OrderClientType orderClient = OrderClientType.SAAS;
        String appId = userLoginInfoDto.getWxAppId();
        if(UserLoginChannelEnum.ALIPAY.getCode().equals(userLoginInfoDto.getChannel()) ){
            orderClient = OrderClientType.ALIPAY;
        } else if(UserLoginChannelEnum.APP.getCode().equals(userLoginInfoDto.getChannel())) {
            orderClient = OrderClientType.APP;
        }
        long totalAmount = 0;
        int cardAmount = 0;
        QueryOrdersResponse.DataBean.OrderBean fatherBeanListOne = new QueryOrdersResponse.DataBean.OrderBean();
        QueryOrdersResponse.DataBean.OrderBean productBeanListOne = new QueryOrdersResponse.DataBean.OrderBean();
        if (createOrderVo.getBuyMemberCard() != null && StringUtils.isNotEmpty(createOrderVo.getBuyMemberCard().getRuleId()) && StringUtils.isNotEmpty(createOrderVo.getBuyMemberCard().getPaidId())) {
            //父子订单
            int cardOriginalAmount = shoppingCartGoodsDto.getCardOriginalAmount() == null ? 0 : shoppingCartGoodsDto.getCardOriginalAmount();
            int cardDiscountAmount = shoppingCartGoodsDto.getCardDiscountAmount() == null ? 0 : shoppingCartGoodsDto.getCardDiscountAmount();
            cardAmount = cardOriginalAmount - cardDiscountAmount;
            CreateFatherSonOrderResponse createFatherSonOrderResponse = createFatherSonOrder(createOrderVo, storeResponseDto, shoppingCartGoodsDto, orderExtendedReq,appId);
            if (ObjectUtils.notEqual(Integer.valueOf(ResponseResult.SUCCESS.getCode()), createFatherSonOrderResponse.getErrcode())) {
                return ResponseUtil.error(createFatherSonOrderResponse.getErrcode().toString(), createFatherSonOrderResponse.getErrmsg());
            }
            List<QueryOrdersResponse.DataBean.OrderBean> orderBeanList = createFatherSonOrderResponse.getOrderBeanList();
            List<QueryOrdersResponse.DataBean.OrderBean> fatherBeanList = orderBeanList.stream().filter(orderBeanTemp -> orderBeanTemp.getIsParent()).collect(Collectors.toList());
            List<QueryOrdersResponse.DataBean.OrderBean> productBeanList = orderBeanList.stream().filter(orderBeanTemp -> 1 == orderBeanTemp.getBizType()).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(fatherBeanList)) fatherBeanListOne = fatherBeanList.get(0);
            if (CollectionUtils.isNotEmpty(productBeanList)) productBeanListOne = productBeanList.get(0);
            //订单总金额 商品+会员卡
            totalAmount = orderBeanList.stream().mapToLong(QueryOrdersResponse.DataBean.OrderBean::getAmount).count();
            fatherBeanList.get(0).setShopId(storeResponseDto.getStoreCode());
            fatherBeanList.get(0).setCompanyId(createOrderVo.getPartnerId());
        } else {
            //普通订单
            CreateOrderResponse createOrderFlowResponse = createOrder(createOrderVo, storeResponseDto, shoppingCartGoodsDto, orderExtendedReq, orderClient,appId);
            if (ObjectUtils.notEqual(Integer.valueOf(ResponseResult.SUCCESS.getCode()), createOrderFlowResponse.getErrcode())) {
                return ResponseUtil.error(createOrderFlowResponse.getErrcode().toString(), createOrderFlowResponse.getErrmsg());
            }
            fatherBeanListOne = createOrderFlowResponse.getData();
            productBeanListOne = createOrderFlowResponse.getData();
            totalAmount = createOrderFlowResponse.getData().getAmount();
        }
        response.setTotalAmount(totalAmount);
        response.setCardAmount(cardAmount);
        response.setFatherOrderBean(fatherBeanListOne);
        response.setProductOrderBean(productBeanListOne);
        return ResponseUtil.success(response);
    }

    /**
     * 创建预支付订单
     */
    public BaseResponse createPrepayOrder(CreatePrepayRequestDto createPrepayRequestDto) {

        CreateOrderResponseVo createOrderResponse;
        OrderPayResponse orderPayResponse = null;
        PaymentRequest paymentRequest = orderBodyConvertToPaymentBody(createPrepayRequestDto.getOpenId(), createPrepayRequestDto.getPartnerId(), createPrepayRequestDto.getWxAppId(), createPrepayRequestDto.getPayCode());
        long totalAmount = createPrepayRequestDto.getTotalAmount();
        String cardCode = createPrepayRequestDto.getCardCode();
        String transId = createPrepayRequestDto.getTransId();
        // 测试appId和openid，后面删除，改为实时获取
        paymentRequest.setWxAppId("wx21e254fdcc79dee8");
        paymentRequest.setOpenId("oR0VA5aRRaGpQxaLUPgQqcDHamg4");
        if (totalAmount < 0) {
            throw new ServiceException(ResponseResult.PAY_AMOUNT_ERROR);
        } else if (totalAmount > 0 && StringUtils.isBlank(cardCode)) {
            orderPayResponse = getPreOrderPay(createPrepayRequestDto.getFatherOrderBean(), paymentRequest, LogThreadLocal.getTrackingNo(), createPrepayRequestDto.getCardAmount(), transId);
        } else if (totalAmount > 0 && StringUtils.isNotBlank(cardCode)) {
            //svc卡支付
            orderPayResponse = svcPay(cardCode, createPrepayRequestDto.getFatherOrderBean(), paymentRequest, transId, LogThreadLocal.getTrackingNo());
        } else {
            // 0元订单如果不需要支付，自定义支付单号
            orderPayResponse = getOrderPayResponse(paymentRequest, createPrepayRequestDto.getFatherOrderBean());
        }
        if (orderPayResponse == null) {
            return failPreOrderPay(LogThreadLocal.getTrackingNo(), createPrepayRequestDto.getProductOrderBean(), cardCode, createPrepayRequestDto.getOrderClient());
        }
        createOrderResponse = orderAdapter.convent2CreateFatherSonOrderResponseVo(orderPayResponse, createPrepayRequestDto.getProductOrderBean());
        BaseResponse baseEditResponse = this.updateOrderInfo(orderPayResponse, createPrepayRequestDto.getOrderExtInfoDTO(), createPrepayRequestDto.getProductOrderBean(), LogThreadLocal.getTrackingNo());
        if (baseEditResponse != null) {
            return baseEditResponse;
        }
        if (totalAmount > 0 && StringUtils.isBlank(cardCode)) {
            createOrderResponse.setPaySuccess(false);
        } else {
            createOrderResponse.setPaySuccess(true);
        }
        // 推荐优惠插件用户下单数据上报
        //wechatPushProcessor.statusOrderCreate(userLoginInfoDto, createOrderResponse.getOid(), createOrderVo.getPartnerId());
        if (!createOrderResponse.getPaySuccess()) {
            return ResponseUtil.success(createOrderResponse);
        } else {
            //如果是商品券支付0元，调用回调接口
            PaysuccessNoticeMessage message = new PaysuccessNoticeMessage();
            message.setResult_code(100);
            message.setOut_trade_no(createOrderResponse.getFmId());
            message.setTrans_id(createOrderResponse.getOid());
            message.setTotal_fee(0);
            message.setOpenid(createPrepayRequestDto.getOpenId());
            message.setPlatform_coupon(0);
            message.setMerchant_coupon(0);
            orderAdapterService.paySuccessCallback(message);
            return ResponseUtil.success(createOrderResponse);
        }
    }

    /**
     * 创建普通订单
     */
    public CreateOrderResponse createOrder(CreateOrderVo createOrderVo, StoreResponse.BizVO storeResponseDto, ShoppingCartGoodsDto shoppingCartGoodsDto,
                                           OrderExtendedReq orderExtendedReq, OrderClientType orderClient,String appId) {
        BaseCreateOrderRequest baseCreateOrderRequest = orderAdapter.convent2CreateOrderDto(createOrderVo, shoppingCartGoodsDto, storeResponseDto);
        //查询第三方商品编号
        baseCreateOrderRequest = getProductCustomerCode(baseCreateOrderRequest);
        //保存门店渠道信息
        baseCreateOrderRequest.setOrderExtended(orderExtendedReq);
        baseCreateOrderRequest.setOrderClient(orderClient);
        baseCreateOrderRequest.setAppId(appId);
        CreateOrderRequest createOrderRequest = new CreateOrderRequest();
        baseCreateOrderRequest.setTrackingNo(LogThreadLocal.getTrackingNo());
        createOrderRequest.setBaseCreateOrderRequest(baseCreateOrderRequest);
        MqMessageRequest mqMessageRequest = new MqMessageRequest();
        mqMessageRequest.setBackOrdersNotifyActivityExchange(backOrdersNotifyActivityExchange);
        mqMessageRequest.setBackOrdersNotifyActivityQueue(backOrdersChangeOrderStatusConsumerQueue);
        createOrderRequest.setMqMessageRequest(mqMessageRequest);
        createOrderRequest.setTrackingNo(LogThreadLocal.getTrackingNo());
        return mcCafeOrderCenterSdkService.createMCCafeOrderFlow(createOrderRequest);
    }
    /**
     * 创建父子订单
     */
    public CreateFatherSonOrderResponse createFatherSonOrder(CreateOrderVo createOrderVo, StoreResponse.BizVO storeResponseDto,
                                                             ShoppingCartGoodsDto shoppingCartGoodsDto, OrderExtendedReq orderExtendedReq,
                                                             String appId) {
        CreateFatherSonOrderRequest createFatherSonOrderRequest = orderAdapter.convertFatherSonOrderRequest(createOrderVo, shoppingCartGoodsDto, orderExtendedReq,storeResponseDto,appId);
        //查询第三方商品编号
        createFatherSonOrderRequest = getProductCustomerCodeNew(createFatherSonOrderRequest);
        MqMessageRequest mqMessageRequest = new MqMessageRequest();
        mqMessageRequest.setBackOrdersNotifyActivityExchange(backOrdersNotifyActivityExchange);
        mqMessageRequest.setBackOrdersNotifyActivityQueue(backOrdersChangeOrderStatusConsumerQueue);
        createFatherSonOrderRequest.setMqMessageRequest(mqMessageRequest);
        return mcCafeOrderCenterSdkService.createMCCafeFatherSonOrder(createFatherSonOrderRequest);
    }

    private OrderPayResponse getOrderPayResponse(PaymentRequest paymentRequest, QueryOrdersResponse.DataBean.OrderBean orderBean) {
        OrderPayResponse orderPayResponse;
        String fmId = "SPAY" + ValidationCode.getRandomUuid();
        orderPayResponse = orderAdapter.getOrderPayResponse(orderBean.getCompanyId(), paymentRequest,
                orderBean.getOid(), fmId);
        return orderPayResponse;
    }

    private BaseResponse failPreOrderPay(String trackingNo, QueryOrdersResponse.DataBean.OrderBean orderBean, String cardCode, OrderClientType orderClient) {
        List<OrderClientType> notCancelOrderClientList = Lists.newArrayList(OrderClientType.APP);
        if(!notCancelOrderClientList.contains(orderClient)) {
            //失败冲正库存，冲正活动库存，取消订单
            CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                    AfterSalesType.SYSTEM_CANCEL, "获取预支付失败", trackingNo, null);
            orderCenterSdkService.orderCancel(cancelOrderRequest);
            // TODO: 2019/9/10 hubowen mq推送变更
            backOrdersStatusChange(orderBean.getOid(), orderBean.getStatus());
        }
        //svc 卡支付失败
        if (StringUtils.isNotBlank(cardCode)) {
            return ResponseUtil.error(ResponseResultEnum.PAY_BACKEND_CONFIG_ERROR.getCode(), ResponseResultEnum.PAY_BACKEND_CONFIG_ERROR.getMessage(), null);
        }
        return ResponseUtil.error(ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getCode(), ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getMessage(), null);
    }

    public OrderPayResponse getPreOrderPay(QueryOrdersResponse.DataBean.OrderBean orderBean, PaymentRequest paymentRequest, String trackingNo, Integer cardAmount, String transId) {
        try {
            UnifiedOrderRequest request = orderAdapter.convent2UnifiedOrderRequest(orderBean, paymentRequest, orderBean.getAmount(), cardAmount, transId);
            System.out.println(JSON.toJSONString(request));
            com.freemud.application.sdk.api.base.BaseResponse<UnifiedOrderResponse> responseBase = standardPaymentService.unifiedOrder(request, trackingNo);
            if (!ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode())) {
                log.error("支付SDK返回信息错误,trackingNo:{} request:{} response:{}", trackingNo, JSONObject.toJSONString(request), JSONObject.toJSONString(responseBase));
                return null;
            }
            putDelMq(request.getPartnerId(), request.getStoreId(), responseBase.getData().getFmId(), orderBean.getOid());
            OrderPayResponse orderPayResponse = orderAdapter.convent2OrderPayResponse(responseBase.getData());
            orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
            orderPayResponse.setOpenId(paymentRequest.getOpenId());
            orderPayResponse.setPartnerId(orderBean.getCompanyId());
            orderPayResponse.setOrderId(orderBean.getOid());
            return orderPayResponse;
        } catch (Exception e) {
            LogUtil.error("getPreOrderPay_error", JSONObject.toJSONString(orderBean), JSONObject.toJSONString(paymentRequest));
            //TODO 邮件告警
            return null;
        }
    }

    public OrderPayResponse svcPay(String cardCode, QueryOrdersResponse.DataBean.OrderBean orderBean, PaymentRequest paymentRequest, String transId, String trackingNo) {
        CodePayRequest request = new CodePayRequest();
        String partnerId = orderBean.getCompanyId();
        request.setBody(orderBean.getShopName());
        request.setBusinessDate(DateUtil.convert2String(new Date(), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
        request.setCode(cardCode);
        request.setPartnerId(partnerId);
        request.setStoreId(orderBean.getShopId());
        request.setAmount(orderBean.getAmount());
        request.setTransId(transId);
        request.setStationId("1");
        request.setOperatorId("1");
        request.setVer("2");
        SVCCardAmountRequest svcRequest = new SVCCardAmountRequest();
        svcRequest.setPartnerId(partnerId);
        svcRequest.setCardCodes(Arrays.asList(cardCode));
        //查询svc卡余额
        com.freemud.application.sdk.api.base.BaseResponse<SVCCardAmountResponse> svcCardAmountResponseBaseResponse = paymentNewService.querySVCCardAmount(svcRequest, trackingNo);
        if (svcCardAmountResponseBaseResponse == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(svcCardAmountResponseBaseResponse.getCode())
                || svcCardAmountResponseBaseResponse.getData().getData() == null || CollectionUtils.isEmpty(svcCardAmountResponseBaseResponse.getData().getData().getCardSimpleInfos())) {
            return null;
        }
        Integer amount = svcCardAmountResponseBaseResponse.getData().getData().getCardSimpleInfos().get(0).getAmount();
        Integer vamount = svcCardAmountResponseBaseResponse.getData().getData().getCardSimpleInfos().get(0).getVamount();
        if (amount + vamount < orderBean.getAmount()) {
            return null;
        }
        //svc卡支付
        com.freemud.application.sdk.api.base.BaseResponse<CodePayResponse> responseBase = paymentNewService.codePay(request, trackingNo);
        if (responseBase == null || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(responseBase.getCode()) || responseBase.getData().getData() == null) {
            return null;
        }
        OrderPayResponse orderPayResponse = new OrderPayResponse();
        CodePayResponse.CodePayDate codePayResponse = responseBase.getData().getData();
        orderPayResponse.setFmId(codePayResponse.getFmId());
        orderPayResponse.setPayTransId(codePayResponse.getPayTransId());
        orderPayResponse.setWxAppid(paymentRequest.getWxAppId());
        orderPayResponse.setOpenId(paymentRequest.getOpenId());
        orderPayResponse.setPartnerId(orderBean.getCompanyId());
        orderPayResponse.setOrderId(orderBean.getOid());
        return orderPayResponse;
    }

    private PaymentRequest orderBodyConvertToPaymentBody(String openId, String partnerId, String appId, String payCode) {
        //设置支付信息
        PaymentRequest paymentRequest = new PaymentRequest();
        paymentRequest.setOpenId(openId);
        paymentRequest.setWxAppId(appId);
        AssortmentOpenPlatformWxapp wxApp = openPlatformWxappManager.findByPartnerIdAndWxappId(partnerId, appId);
        AssortmentOpenPlatformPartner platformPartner = null;
        if (wxApp == null) {
            platformPartner = assortmentOpenPlatformPartnerManager.selectOpenPlatformPartner(partnerId);
        }
        paymentRequest.setPrincipalName(wxApp != null ? wxApp.getPrincipalName() : platformPartner != null ? platformPartner.getCompanyName() : "上海非码网络科技有限公司");
        paymentRequest.setReverseNotifyiDcUrl(reverseNotifyiDcUrl);
        paymentRequest.setPayCode(payCode);
        return paymentRequest;
    }

    private OrderExtInfoDto getExtInfo(AssortmentCustomerInfoVo userLoginInfoDto, StoreResponse.BizVO storeResponseDto,
                                      Integer pushOrderTime, CreateOrderVo createOrderVo) {

        Integer serviceTime = storeResponseDto.getServiceTime();
        String sessionId = createOrderVo.getSessionId();
        String version = createOrderVo.getVersion();
        CreateOrderVo.BuyMemberCard memberCard = createOrderVo.getBuyMemberCard();

        String deliveryHoursDayStart = "";
        String deliveryHoursDayEnd = "";
        if (StringUtils.isNotBlank(storeResponseDto.getDeliveryHoursDay())) {
            String[] days = storeResponseDto.getDeliveryHoursDay().split("-");
            if (days.length == 2) {
                deliveryHoursDayStart = DateUtil.convert2String(new Date(), DateUtil.FORMAT_yyyyMMdd_date) + " " + days[0] + ":00";
//                deliveryHoursDayEnd = DateUtil.convert2String(new Date(), DateUtil.FORMAT_yyyyMMdd_date) + " " + days[1] + ":00";
            }
        }

        OrderExtInfoDto orderExtInfoDto = new OrderExtInfoDto();
        orderExtInfoDto.setDeliveryHoursDayStart(deliveryHoursDayStart);
        orderExtInfoDto.setDeliveryHoursDayEnd(deliveryHoursDayEnd);
        orderExtInfoDto.setOpenid(userLoginInfoDto.getOpenId());
        orderExtInfoDto.setAppid(userLoginInfoDto.getWxAppId());
        orderExtInfoDto.setSessionId(sessionId);
        if (Objects.equals(serviceTime, null)) {
            serviceTime = 50;
        }
        orderExtInfoDto.setServiceTime(serviceTime);
        orderExtInfoDto.setPushOrderTime(pushOrderTime);
        orderExtInfoDto.setVersion(version);
        if (memberCard != null && memberCard.getRuleId() != null) {
            orderExtInfoDto.setRuleId(memberCard.getRuleId());
        }
        // 扩展字段中存储 sessionKey
        orderExtInfoDto.setSessionKey(createOrderVo.getSessionKey());
        orderExtInfoDto.setFormId(createOrderVo.getFormId());
        orderExtInfoDto.setFromAppId(userLoginInfoDto.getWxAppId());
        if (StringUtils.isNotBlank(createOrderVo.getScene())) {
            orderExtInfoDto.setScene(createOrderVo.getScene());
        }
        return orderExtInfoDto;
    }

    /**
     * 编辑订单，保持预支付信息
     */
    public BaseResponse updateOrderInfo(OrderPayResponse orderPayResponse, OrderExtInfoDto orderExtInfo
            , QueryOrdersResponse.DataBean.OrderBean orderBean, String trackingNo) {
        orderExtInfo.setOpenid(orderPayResponse.getOpenId());
        orderExtInfo.setFmId(orderPayResponse.getFmId());
        orderExtInfo.setAppid(orderPayResponse.getWxAppid());
        String prepayId = "";
        OrderPayResponse.PayOrderBean payOrder = orderPayResponse.getPayOrder();
        // StringUtils 依赖修改
        if (payOrder != null && !StringUtils.isEmpty(payOrder.getPackageX())) {
            String[] prepayIds = payOrder.getPackageX().split("=");
            prepayId = prepayIds.length > 1 ? prepayIds[1] : "";
        }
        //支付宝保存交易流水号发送支付宝模板消息
        if (payOrder != null && !StringUtils.isEmpty(payOrder.getAliPayOrder())) {
            prepayId = payOrder.getAliPayOrder();
        }
        orderExtInfo.setPrepayId(prepayId);

        OrderEditRequest orderEditRequest = new OrderEditRequest(orderPayResponse.getPayTransId(),
                JSONObject.toJSONString(orderExtInfo));
        orderEditRequest.setOrderId(orderBean.getOid());
        orderEditRequest.setTrackingNo(trackingNo);
        BaseOrderResponse baseOrderResponse = orderCenterSdkService.orderEdit(orderEditRequest);
        if (!ObjectUtils.equals(ResponseCodeConstant.RESPONSE_SUCCESS, baseOrderResponse.getErrcode())) {
            CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                    AfterSalesType.SYSTEM_CANCEL, "编辑订单支付信息失败", trackingNo, null);
            orderCenterSdkService.orderCancel(cancelOrderRequest);
            //如果编辑订单支付信息失败，冲正
            backOrdersStatusChange(orderBean.getOid(), orderBean.getStatus());
            return ResponseUtil.error(baseOrderResponse.getErrcode().toString(), baseOrderResponse.getErrmsg());

        }

        return null;
    }

    @Override
    public String paySuccessCallback(PaysuccessNoticeMessage message, ConfirmOrderDto confirmOrderDto, Map<String, QueryOrdersResponseDto.DataBean.OrderBean> orderBeans) {
        OrderBean orderBean = orderBeans.get(OrderBeanType.SAASORDER.getCode());
        String oid = StringUtils.isNotEmpty(orderBean.getParentCode()) && !"0".equals(orderBean.getParentCode()) ? orderBean.getParentCode() : orderBean.getOid();
        String partnerId = orderBean.getCompanyId();
        String userId = orderBean.getUserId();
        String storeId = orderBean.getShopId();
        orderBean.setPayVoucher(message.getOut_trade_no());
        //编辑订单信息，获取openid，用于退款
        String extInfo = orderBean.getExtInfo();
        OrderExtInfoDto orderExtInfoDto = null;
        String wxappid = "";
        String sessionId = "";
        String openid = "";
        String ruleId = "";
        String payCode = "";
        if (StringUtils.isNotBlank(extInfo)) {
            orderExtInfoDto = gson.fromJson(extInfo, OrderExtInfoDto.class);
            if (orderExtInfoDto != null && StringUtils.isNotBlank(orderExtInfoDto.getOpenid())) {
                openid = orderExtInfoDto.getOpenid();
                wxappid = orderExtInfoDto.getAppid();
                sessionId = orderExtInfoDto.getSessionId();
                ruleId = orderExtInfoDto.getRuleId();
            }
            if (orderExtInfoDto != null && StringUtils.isNotBlank(orderExtInfoDto.getPayCode())
                    && Arrays.asList(PayChannel.ALIPAY.getCode(), PayChannel.WXPAY.getCode()).contains(orderExtInfoDto.getPayCode())) {
                payCode = orderExtInfoDto.getPayCode();
            }
        }
        // 如果订单状态不是未支付，返回信息
        if (!PayStatus.NOT_PAY.getCode().equals(orderBean.getPayStatus()) || !OrderStatus.WAIT_PAY.getCode().equals(orderBean.getStatus())) {
            return sendPaySuccessNoticeMessage();
        }

        //核销优惠券
        MCCafeConponRequest mcCafeConponRequest = convertOrderBean2CouponLockRequest(orderBean);
        if(null != mcCafeConponRequest) {
            CouponRedeemResponse couponRedeemResponse = couponClientService.redeem(mcCafeConponRequest);
            //失败则取消订单并解锁优惠券
            if(!RESPONSE_SUCCESS_CODE.equals(couponRedeemResponse.getStatusCode())) {
                //异步冲正库存积分等
                CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                        AfterSalesType.SYSTEM_CANCEL, "支付核销优惠券失败", LogTreadLocal.getTrackingNo(), null);
                orderCenterSdkService.orderCancel(cancelOrderRequest);
                backOrdersStatusChange(orderBean.getOid(), orderBean.getStatus());
                throw new ServiceException(ResponseResult.COUPON_VERIFICATION_FAIL);
            }
        }

        //若该订单使用了优惠券，则移除卡包,移除失败也不退款
        couponActivityService.callbackNotify(orderBean);
        // 订单失败后 发消息重试 待实现
        String takeCode;
        String daySeq;
        PayAccessResponse payAccessResponse;
        ConfirmOrderRequest var1 = LightApplicationConvertToAssortmentSdkAdapter.confirmOrderDtoConvertToConfirmOrderRequest(confirmOrderDto, orderBeans.get(OrderBeanType.MERMBERORDER.getCode()));
        var1.setPartnerId(partnerId);
        var1.setStoreId(storeId);
        var1.setOrderType(orderBean.getType());
        var1.setProductOrderCode(orderBean.getOid());
        var1.setPayDate(DateUtil.convert2String(new Date(), "yyyy-MM-dd HH:mm:ss"));
        var1.setPayTransId(message.getOut_trade_no());
        var1.setOperator(orderBean.getUserName());
        var1.setEndTransId(message.getEndTransId());
        if (StringUtils.isNotBlank(payCode)) {
            var1.setPayChannel(payCode);
            var1.setPayChannelName(PayChannel.getByCode(payCode).getDesc());
        }
        if (orderBean.getGmtExpect() != null && orderBean.getGmtExpect() != 0) {
            var1.setExpectTime(DateUtil.convert2String(new Date(orderBean.getGmtExpect()), DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
        }
        // 订单支付成功
        com.freemud.sdk.api.assortment.order.response.order.PayAccessResponse payAccessRes = orderCenterSdkService.payAccess(var1);
        String string2 = JSONObject.toJSONString(payAccessRes);
        JSONObject jsonObject2 = JSONObject.parseObject(string2);
        payAccessResponse = jsonObject2.toJavaObject(PayAccessResponse.class);
        // 添加幂等处理，若订单是已支付成功状态，直接返回成功
        if (!RESPONSE_SUCCESS_CODE.equals(payAccessResponse.getErrcode())) {
            OrderBean saasOrder = getOrderBeanByOrderId(confirmOrderDto.getOrderId()).get(OrderBeanType.SAASORDER.getCode());
            if (saasOrder != null && (!PayStatus.NOT_PAY.getCode().equals(saasOrder.getPayStatus()) || !OrderStatus.WAIT_PAY.getCode().equals(saasOrder.getStatus()))) {
                return sendPaySuccessNoticeMessage();
            }
            LogUtil.error("paySuccessCallback_payAccess_faild", gson.toJson(confirmOrderDto), gson.toJson(payAccessResponse));
            //orderRefund(orderBean, "订单异常退款", openid, oid);
            return gson.toJson(message);
        }
        // TODO 订单序号替换取餐码显示
        takeCode = payAccessResponse.getData().getTakeCode();
        daySeq = payAccessResponse.getData().getDaySeq();


        //TODO 清空购物车
        NewShoppingCartClearDto newShoppingCartClearDto = new NewShoppingCartClearDto();
        newShoppingCartClearDto.setPartnerId(partnerId);
        newShoppingCartClearDto.setShopId(storeId);
        newShoppingCartClearDto.setUserId(userId);
        newShoppingCartClearDto.setAppId(wxappid);
        newShoppingCartClearDto.setSessionId(sessionId);
        newShoppingCartClearDto.setOperationType(1);
        shoppingCartClient.clearShoppingCart(newShoppingCartClearDto);
        if (StringUtils.isNotBlank(daySeq) && orderExtInfoDto != null && !OrderType.TAKE_OUT.getCode().equals(orderBean.getType())) {
            String storeAddress = StringUtils.isNotBlank(orderBean.getAddress()) ? orderBean.getAddress() : "";
            orderBean.setAddress(storeAddress);
            orderBean.setOtherCode(takeCode);
            //发送支付成功模板消息
            this.sendPaySuccessMessage(orderBean);
        }
        // 有云打印机 打印小票，杯贴
        try {
            List<AssortmentCloudPrinter> storePrinters = cloudPrinterManager.getStorePrinters(partnerId, storeId);
            if (null != storePrinters && storePrinters.size() > 0) {
                boolean printerStatus = false;
                for (AssortmentCloudPrinter cloudPrinter : storePrinters) {
                    if (null != cloudPrinter.getStatus() && cloudPrinter.getStatus() == 1) {
                        printerStatus = true;
                    }
                }
                //在线打印
                if (printerStatus) {
                    OrderPrintDto orderPrintDto = orderAdapter.convert2OrderPrintDto(orderBean);
                    orderPrintDto.setDaySeq(daySeq);
                    orderPrintDto.setOtherCode(takeCode);
                    asynchronousPrint(orderPrintDto);
                }
            }
        } catch (Exception e) {
            LogUtil.error("cloudPrint_error", null, null, e);
        }
        //TODO 埋点支付行为
        BuriedPointPaymentRequestDto requestDto = new BuriedPointPaymentRequestDto();
        requestDto.setStoreId(storeId);
        requestDto.setPartnerId(partnerId);
        requestDto.setWxAppId(wxappid);
        requestDto.setSessionId(sessionId);
        requestDto.setOpenId(orderExtInfoDto != null ? orderExtInfoDto.getOpenid() : "");
        buriedPointService.BuriedPointPayment(requestDto, orderBean);

        // 开通会员卡
        if (StringUtils.isNotBlank(ruleId)) {
            this.activateMemberCard(partnerId, ruleId, oid, userId);
        }
        //支付回掉成功标记
        redisCache.save(RedisKeyConstant.KGD_PAYMENT_CALLBACK_FMID + message.getOut_trade_no(), message.getOut_trade_no(), 10L, TimeUnit.MINUTES);
        return sendPaySuccessNoticeMessage();
    }

    private List<CreateOrderAccountRequest> convertOrderBean2Accounts(OrderBean orderBean) {
        List<CreateOrderAccountRequest> list = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(orderBean.getAccountList())) {
            orderBean.getAccountList().forEach(o -> {
                CreateOrderAccountRequest createOrderAccountDto = CreateOrderAccountRequest.builder()
                        .accountId(o.getAccountId())
                        .name(o.getName())
                        .price(o.getPrice())
                        .accountType(orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(o.getType())))
                        .sequence(o.getSequence())
                        .orderId(o.getOrderId())
                        .build();
                list.add(createOrderAccountDto);
            });
        }

        return list;
    }

    private MCCafeConponRequest convertOrderBean2CouponLockRequest(OrderBean orderBean) {
        if (null == orderBean || CollectionUtils.isEmpty(orderBean.getAccountList())) {
            return null;
        }
        Optional<OrderBean.AccountBean> accountRequest = orderBean.getAccountList().stream().filter(
                account -> orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.COUPON)
                        ||  orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.PRODUCT_COUPON)
                        ||  orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.DISCOUNT_COUPON)).findFirst();
        if (!accountRequest.isPresent() || accountRequest.get().getPrice() == 0) {
            return null;
        }
        OrderBean.AccountBean accountBean = accountRequest.get();
        List<MCCafeProductRedeemVo> products = new ArrayList<>();
        //商品券核销核销参数
        if (QueryOrderAccountType.PRODUCT_COUPON.equals(orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(accountBean.getType())))) {
            for (int i = 0; i < orderBean.getProductList().size(); i++) {
                OrderBean.ProductBean productBean = orderBean.getProductList().get(i);
                String pid = StringUtils.isNotBlank(productBean.getSpecification()) ? productBean.getSpecification() : productBean.getProductId();
                if (!org.springframework.util.CollectionUtils.isEmpty(orderBean.getProductList().get(i).getDiscountList())) {
                    List<OrderBean.ProductBean.ProductDiscount> discounts = orderBean.getProductList().get(i).getDiscountList().stream().
                            filter(productDiscount -> productDiscount.getDiscountId().equals(accountBean.getAccountId())).collect(Collectors.toList());
                    for (OrderBean.ProductBean.ProductDiscount productDiscount : discounts) {
                        if (productDiscount.getDiscountType() == null || productDiscount.getDiscountType() == 0) {
                            continue;
                        }
                        MCCafeProductRedeemVo mcCafeProductRedeemVo = new MCCafeProductRedeemVo();
                        mcCafeProductRedeemVo.setPid(pid);
                        mcCafeProductRedeemVo.setKeyProductCode(productBean.getCustomerCode());
                        mcCafeProductRedeemVo.setCustomer_code(productBean.getCustomerCode());
                        mcCafeProductRedeemVo.setConsume_num(productDiscount.getDiscountQty());
                        mcCafeProductRedeemVo.setSeq(i + 1);
                        products.add(mcCafeProductRedeemVo);
                    }
                }
            }
        }
        MCCafeConponRequest mcCafeConponRequest  = new MCCafeConponRequest();
        mcCafeConponRequest.setVer(Integer.valueOf(Version.VERSION_1));
        mcCafeConponRequest.setReqtype(CouponReqTypeEnum.REDEEM.getCode());
        mcCafeConponRequest.setPartnerId(Integer.parseInt(orderBean.getCompanyId()));
        mcCafeConponRequest.setStore_id(orderBean.getShopId());
        mcCafeConponRequest.setStation_id("-1");
        mcCafeConponRequest.setOperator_id("-1");
        // 订单号
        mcCafeConponRequest.setTrans_id(orderBean.getOid());
        mcCafeConponRequest.setChannel(OrderSourceType.ALIPAY.getCode().equals(orderBean.getSource())?
                MCCafeChannelEnum.MOCOFFEE_ZFB.getName():MCCafeChannelEnum.MOCOFFEE_WX.getName());
        List<MCCafeTransactionVo> transactions = new ArrayList<>();
        MCCafeTransactionVo mcCafeTransactionVo = new MCCafeTransactionVo();
        mcCafeTransactionVo.setCode(accountBean.getAccountId());
        mcCafeTransactionVo.setTotalAmount(-accountBean.getPrice());
        if (CollectionUtils.isNotEmpty(products)) {
            mcCafeTransactionVo.setProducts(products);
        }
        transactions.add(mcCafeTransactionVo);
        mcCafeConponRequest.setTransactions(transactions);
        mcCafeConponRequest.setSign("skip");

        mcCafeConponRequest.setAppFlag("kgd.N");
        mcCafeConponRequest.setBusiness_date(cn.freemud.base.util.DateUtil.convert2Str(new Date(), cn.freemud.base.util.DateUtil.FORMAT_yyyyMMdd));
        return mcCafeConponRequest;
    }

    private MCCafeCouponLockRequest convertOrderBean2CouponUnlockRequest(OrderBean orderBean) {
        if (null == orderBean || CollectionUtils.isEmpty(orderBean.getAccountList())) {
            return null;
        }
        Optional<OrderBean.AccountBean> accountRequest = orderBean.getAccountList().stream().filter(
                account -> orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.COUPON)
                        ||  orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.PRODUCT_COUPON)
                        ||  orderAdapter.getQueryOrderAccountType(orderAdapter.getOrderAccountType(account.getType())).equals(QueryOrderAccountType.DISCOUNT_COUPON)).findFirst();
        if (!accountRequest.isPresent() || accountRequest.get().getPrice() == 0) {
            return null;
        }
        OrderBean.AccountBean accountBean = accountRequest.get();
        MCCafeCouponLockRequest mcCafeCouponLockRequest = new MCCafeCouponLockRequest();
        mcCafeCouponLockRequest.setVer(Integer.valueOf(Version.VERSION_1));
        mcCafeCouponLockRequest.setReqType(CouponReqTypeEnum.UNLOCK.getCode());
        mcCafeCouponLockRequest.setPartnerId(orderBean.getCompanyId());
        mcCafeCouponLockRequest.setStoreId(orderBean.getShopId());
        // 订单号
        mcCafeCouponLockRequest.setTransId(orderBean.getOid());
        mcCafeCouponLockRequest.setCoupon(accountBean.getAccountId());
        mcCafeCouponLockRequest.setOfferId(accountBean.getAccountId());
        mcCafeCouponLockRequest.setNumber("1");
        mcCafeCouponLockRequest.setChannel(OrderSourceType.ALIPAY.getCode().equals(orderBean.getSource())?
                MCCafeChannelEnum.MOCOFFEE_ZFB.getName():MCCafeChannelEnum.MOCOFFEE_WX.getName());
        mcCafeCouponLockRequest.setOperatorId("-1");
        mcCafeCouponLockRequest.setStationId("-1");
        mcCafeCouponLockRequest.setSign("skip");

        return mcCafeCouponLockRequest;
    }

    /**
     * 支付后通知确认返回信息
     */
    public String sendPaySuccessNoticeMessage() {
        Map<String, Object> map = Maps.newTreeMap();
        map.put("code", 0);
        map.put("message", "success");
        return gson.toJson(map);
    }


    public Map<String, OrderBean> getOrderBeanByOrderId(String orderId) {
        // 订单查询：若结果集只有一个orderBean，则为普通订单，否则为会员卡订单（父子订单）
        Map<String, OrderBean> result = new HashMap<>();
        QueryRelationOrderByIdResponseDto queryOrderByIdResponseDto = getQueryRelationOrderByIdResponseDto(orderId);
        if (CollectionUtils.isEmpty(queryOrderByIdResponseDto.getData())) {
            return result;
        }
        if (1 == queryOrderByIdResponseDto.getData().size()) {
            result.put(OrderBeanType.SAASORDER.getCode(), queryOrderByIdResponseDto.getData().get(0));
        } else {
            List<OrderBean> saasOrderBeans = queryOrderByIdResponseDto.getData().stream().filter(order -> order.getBizType().equals(1)).collect(Collectors.toList());
            List<OrderBean> memberOrderBeans = queryOrderByIdResponseDto.getData().stream().filter(order -> order.getBizType().equals(3) && !order.isParent()).collect(Collectors.toList());
            List<OrderBean> fatherOrderBeans = queryOrderByIdResponseDto.getData().stream().filter(order -> order.getBizType().equals(2) && order.isParent()).collect(Collectors.toList());
            result.put(OrderBeanType.SAASORDER.getCode(), CollectionUtils.isNotEmpty(saasOrderBeans) ? saasOrderBeans.get(0) : null);
            result.put(OrderBeanType.MERMBERORDER.getCode(), CollectionUtils.isNotEmpty(memberOrderBeans) ? memberOrderBeans.get(0) : null);
            result.put(OrderBeanType.FATHERORDER.getCode(), CollectionUtils.isNotEmpty(fatherOrderBeans) ? fatherOrderBeans.get(0) : null);
        }
        return result;
    }


    /**
     * 发送支付成功模板消息
     *
     * @param orderBean
     */
    private void sendPaySuccessMessage(QueryOrdersResponseDto.DataBean.OrderBean orderBean) {
        Long gmtExpect = orderBean.getGmtExpect();
        if (gmtExpect != null) {
            // 预约下单
            this.sendMessage(orderBean, MessageEventType.PAYORDEREXPECT);
        } else {
            // 非预约下单
            this.sendMessage(orderBean, MessageEventType.PAYORDER);
        }
    }


    /**
     * 发MQ去打印
     *
     * @param request
     */
    public void asynchronousPrint(OrderPrintDto request) {
        LogUtil.debug("OrderPrintDto", JSONObject.toJSONString(request), null);
        Header header = new Header(MQAction.INSERT.getAction(), "asynchronous-print-api", request.getOid() + "", cloudPrintQueue);
        MQMessage<OrderPrintDto> message = new MQMessage<>(header, request);
        mqService.convertAndSend(cloud_print_exchange, cloudPrintQueue, message);
    }

    /**
     * 开通会员卡
     *
     * @param partnerId 商户号
     * @param ruleId    会员规则ID
     * @param oid       订单号
     * @param userId    用户ID
     */
    private void activateMemberCard(String partnerId, String ruleId, String oid, String userId) {
        PurchasePaidRequestDto purchasePaidRequestDto = new PurchasePaidRequestDto();
        purchasePaidRequestDto.setPartnerId(partnerId);
        purchasePaidRequestDto.setOperatorType(0);
        purchasePaidRequestDto.setRuleId(ruleId);
        purchasePaidRequestDto.setOrderId(oid);
        purchasePaidRequestDto.setMemberId(userId);
        // 尝试三次开通会员卡，中途成功则跳出
        int count = 3;
        for (int i = 1; i <= count; i++) {
            BaseResponse baseResponse = customerApplicationClient.purchasePaid(purchasePaidRequestDto);
            // 不以响应码为判断是否开通会员卡成功的标准
            if (baseResponse != null && "SUCCESS".equals(baseResponse.getResult())) {
                break;
            }
            // 尝试开通会员卡失败三次
            if (i >= count) {
                LogUtil.error("尝试开通会员卡失败" + count + "次", JSON.toJSONString(purchasePaidRequestDto), JSON.toJSONString(baseResponse));
            }
        }
    }

}
