package cn.freemud.service.impl;

import cn.freemud.adapter.BigDataAdapter;
import cn.freemud.adapter.MessageNoticeAdapter;
import cn.freemud.adapter.UserAdapter;
import cn.freemud.base.constant.Version;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.util.MD5Util;
import cn.freemud.constant.ApplicationConstant;
import cn.freemud.constant.RedisKeyConstant;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.constant.UserInfoKeyConstant;
import cn.freemud.entities.db.OpenPlatformPartnerMerchant;
import cn.freemud.entities.db.OpenPlatformWxapp;
import cn.freemud.entities.db.Partner;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.user.UserInfoDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.manager.OpenPlatformPartnerMerchantManager;
import cn.freemud.manager.OpenPlatformWxappManager;
import cn.freemud.manager.OpenPlatformWxappPluginBindManager;
import cn.freemud.manager.PartnerManager;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.UserService;
import cn.freemud.service.thirdparty.*;
import cn.freemud.utils.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author liming.guo
 * @date 2018/05/11
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private final static String RESPONSE_SUCCESS_CODE = "100";

    private final static String NOT_REGISTER = "1004";

    private static Gson gson = new Gson();

    private final static String COUPON_PLUGINS = "wx8e98654a3e2f42f7";
    @Value("${image.partnerId}")
    private String imagePartnerId;

    @Autowired
    private PartnerManager partnerManager;
    @Autowired
    private CustomerClient customerClient;
    @Autowired
    private StoreClient storeClient;
    @Autowired
    private ShortMessageClient shortMessageClient;
    @Autowired
    private WeChatClient weChatClient;
    @Autowired
    private OpenPlatformClient openPlatformClient;
    @Autowired
    private MessageNoticeClient messageNoticeClient;
    @Autowired
    private MessageNoticeAdapter messageNoticeAdapter;
    @Autowired
    private UserAdapter userAdapter;
    @Autowired
    private StoreServiceImpl storeService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private OpenPlatformWxappPluginBindManager openPlatformWxappPluginBindManager;
    @Autowired
    private OpenPlatformPartnerMerchantManager openPlatformPartnerMerchantManager;
    @Autowired
    private OpenPlatformWxappManager openPlatformWxappManager;
    @Autowired
    private BigDataAdapter bigDataAdapter;
    @Autowired
    private BigDataFeiginClient bigDataFeiginClient;

    @Override
    public BaseResponse<UserLoginVo> getSessionId(GetUserLoginSessionIdVo requestUserLoginVo) {
        LogUtil.info("getSessionId_request_start", gson.toJson(requestUserLoginVo), null);
        String partnerId = requestUserLoginVo.getPartnerId();
        String appid = requestUserLoginVo.getAppId();
        // 用户登录凭证,可换取openid 和 session_key
        String code = requestUserLoginVo.getCode();
        GetWxappUserInfoDto getWxappUserInfoDto = new GetWxappUserInfoDto(code, appid);
        LogUtil.info("getSessionId request", gson.toJson(getWxappUserInfoDto), null);
        GetWxappUserInfoResponseDto getWxappUserInfoResponseDto = openPlatformClient.getOpenPlatformUserInfo(getWxappUserInfoDto);
        LogUtil.info("getSessionId request_end", gson.toJson(getWxappUserInfoDto), gson.toJson(getWxappUserInfoResponseDto));
        if (!RESPONSE_SUCCESS_CODE.equals(getWxappUserInfoResponseDto.getCode()) || getWxappUserInfoResponseDto.getResult() == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "获取用户信息失败");
        }
        GetWxappUserInfoResponseDto.ResultBean resultBean = getWxappUserInfoResponseDto.getResult();
        String openid = resultBean.getOpenid();
        String sessionKey = resultBean.getSession_key();
        if (StringUtils.isBlank(openid) || StringUtils.isBlank(sessionKey)) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "获取用户信息失败");
        }
        UserLoginVo responseUserLoginVo = this.getUserLoginInfo(openid, sessionKey, appid, partnerId, requestUserLoginVo);

        // 添加插件map
        List<WxappPluginVo> openPlatformWxappPluginBinds = openPlatformWxappPluginBindManager.queryByWxAppid(requestUserLoginVo.getAppId());
        Map<String, Boolean> plugins = new HashMap<>();
        Map<String, Object> pluginsParam = new HashMap<>();
        openPlatformWxappPluginBinds.forEach(bind -> {
            //查询插件是否可用
            boolean enabled = Objects.equals(bind.getAuditStatus(), PluginAuditStatusEnum.PASS.getCode())
                    && Objects.equals(bind.getOperateStatus(), YesOrNoEnum.YES.getCode());
            plugins.put(bind.getNickname(), enabled);
            if(bind.getPluginAppid().equals(COUPON_PLUGINS) && enabled){
                JSONObject param = new JSONObject();
                param.put("openid",openid);
                param.put("act_id",bind.getWechatActId());
                pluginsParam.put(bind.getNickname(),param);
            }
        });
        responseUserLoginVo.setPlugins(plugins);
        responseUserLoginVo.setPluginsParam(pluginsParam);
        LogUtil.info("getSessionId_response_end", null, gson.toJson(responseUserLoginVo));
        responseUserLoginVo.setOpenId(openid);
        OpenPlatformWxapp wxApp = openPlatformWxappManager.findByWxappId(appid);
        if (wxApp != null) {
            String mchId = wxApp.getMchId();
            List<OpenPlatformPartnerMerchant> list = openPlatformPartnerMerchantManager.selectMerchantListByPartnerId(partnerId);
            Set<String> mchIds = list.stream().map(OpenPlatformPartnerMerchant::getMchId).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(mchIds) && mchIds.contains(mchId)) {
                responseUserLoginVo.setSubMchId(mchId);
            }
        }
        return ResponseUtil.success(responseUserLoginVo);
    }

    /**
     * 获取用户信息
     *
     * @param requestUserLoginVo
     * @return
     */
    @Override
    public BaseResponse<UserLoginVo> getUserInfo(GetUserLoginSessionIdVo requestUserLoginVo) {
        LogUtil.info("getSessionId_request_start", gson.toJson(requestUserLoginVo), null);
        String partnerId = requestUserLoginVo.getPartnerId();
        String appid = requestUserLoginVo.getAppId();
        // 用户登录凭证,可换取openid 和 session_key
        String code = requestUserLoginVo.getCode();
        GetWxappUserInfoDto getWxappUserInfoDto = new GetWxappUserInfoDto(code, appid);
        LogUtil.info("getSessionId request", gson.toJson(getWxappUserInfoDto), null);
        GetWxappUserInfoResponseDto getWxappUserInfoResponseDto = openPlatformClient.getOpenPlatformUserInfo(getWxappUserInfoDto);
        LogUtil.info("getSessionId request_end", gson.toJson(getWxappUserInfoDto), gson.toJson(getWxappUserInfoResponseDto));
        if (!RESPONSE_SUCCESS_CODE.equals(getWxappUserInfoResponseDto.getCode()) || getWxappUserInfoResponseDto.getResult() == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "获取用户信息失败");
        }
        GetWxappUserInfoResponseDto.ResultBean resultBean = getWxappUserInfoResponseDto.getResult();
        String openid = resultBean.getOpenid();
        String sessionKey = resultBean.getSession_key();
        if (StringUtils.isBlank(openid) || StringUtils.isBlank(sessionKey)) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "获取用户信息失败");
        }
        UserLoginVo responseUserLoginVo = this.getUserLoginInfoNew(openid, sessionKey, appid, partnerId, requestUserLoginVo);

        String trackingId = TrackingIdUtil.getTrackingId();
        //埋点
        ThreadPoolUtil.getPoolExecutorForNull(ApplicationConstant.BURYINGPOINT).execute(() -> {
            if (StringUtils.isBlank(requestUserLoginVo.getCts()) || StringUtils.isBlank(requestUserLoginVo.getDevBrand()) || StringUtils.isBlank(requestUserLoginVo.getDevModel()) || StringUtils.isBlank(requestUserLoginVo.getChannel())) {
                return;
            }
            BuryingPointBigDto buryingPointBigDto = null;
            try {
                buryingPointBigDto = bigDataAdapter.convert2BuryingPoint(appid, partnerId, requestUserLoginVo, getWxappUserInfoDto, resultBean, responseUserLoginVo);
                LogUtil.info(trackingId, "登录埋点数据", JSON.toJSONString(bigDataFeiginClient.syncLoginData(buryingPointBigDto)), null);
            } catch (Exception e) {
                LogUtil.error(trackingId, "埋点发送异常", JSON.toJSONString(buryingPointBigDto), null, e);
            }
        });

        // 添加插件map
        List<WxappPluginVo> openPlatformWxappPluginBinds = openPlatformWxappPluginBindManager.queryByWxAppid(requestUserLoginVo.getAppId());
        Map<String, Boolean> plugins = new HashMap<>();
        Map<String, Object> pluginsParam = new HashMap<>();
        openPlatformWxappPluginBinds.forEach(bind -> {
            //查询插件是否可用
            boolean enabled = Objects.equals(bind.getAuditStatus(), PluginAuditStatusEnum.PASS.getCode())
                    && Objects.equals(bind.getOperateStatus(), YesOrNoEnum.YES.getCode());
            plugins.put(bind.getNickname(), enabled);
            if(bind.getPluginAppid().equals(COUPON_PLUGINS) && enabled){
                JSONObject param = new JSONObject();
                param.put("openid",openid);
                param.put("act_id",bind.getWechatActId());
                pluginsParam.put(bind.getNickname(),param);
            }
        });
        responseUserLoginVo.setPlugins(plugins);
        responseUserLoginVo.setPluginsParam(pluginsParam);
        LogUtil.info("getSessionId_response_end", null, gson.toJson(responseUserLoginVo));
        responseUserLoginVo.setOpenId(openid);
        OpenPlatformWxapp wxApp = openPlatformWxappManager.findByWxappId(appid);
        if (wxApp != null) {
            String mchId = wxApp.getMchId();
            List<OpenPlatformPartnerMerchant> list = openPlatformPartnerMerchantManager.selectMerchantListByPartnerId(partnerId);
            Set<String> mchIds = list.stream().map(OpenPlatformPartnerMerchant::getMchId).collect(Collectors.toSet());
            if (CollectionUtils.isNotEmpty(mchIds) && mchIds.contains(mchId)) {
                responseUserLoginVo.setSubMchId(mchId);
            }
        }
        return ResponseUtil.success(responseUserLoginVo);
    }

    @Override
    public BaseResponse<OpenUserInfoVo> getOpenSessionid(GetUserLoginSessionIdVo getUserLoginSessionIdVo) {
        OpenUserInfoVo openUserInfoVo = OpenUserInfoVo.builder()
                .sessionId("22312312312")
                .openId("oqlGZ5YNm-17iSyFG6rrEe5yR27A")
                .mobile("15170070311")
                .nickName("张三")
                .unionId("17iSyFG6rrEe5yR271")
                .build();
        return ResponseUtil.success(openUserInfoVo);
    }

    @Override
    public BaseResponse updateNickName(UpdateNickNameVo updateNickNameVo) {
        return ResponseUtil.success();
    }

    @Override
    public BaseResponse getOpenUserInfo(GetOpenUserInfoVo getOpenUserInfoVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(getOpenUserInfoVo.getSessionId());
        if (userInfoMap == null || userInfoMap.size() == 0) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        OpenUserInfoVo openUserInfoVo = OpenUserInfoVo.builder()
                .sessionId(getOpenUserInfoVo.getSessionId())
                .openId("oqlGZ5YNm-17iSyFG6rrEe5yR27A")
                .mobile("15170070311")
                .nickName("张三")
                .unionId("17iSyFG6rrEe5yR271")
                .build();
        return ResponseUtil.success(openUserInfoVo);
    }


    @Override
    public BaseResponse getPhoneNumber(GetPhoneNumberVo phoneNumberVo) {
        BaseResponse baseResponse = checkPhoneNumberVo(phoneNumberVo);
        if (baseResponse != null) {
            return baseResponse;
        }
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(phoneNumberVo.getSessionId());
        //校验用户是否注册
        String openid = (String) userInfoMap.get(UserInfoKeyConstant.OPEN_ID);
        String partnerId = (String) userInfoMap.get(UserInfoKeyConstant.PARTNER_ID);
        String mobile = (String) userInfoMap.get(UserInfoKeyConstant.MOBILE);
        if (StringUtils.isNotBlank(mobile)) {
            UserLoginVo userLoginVo = userAdapter.getUserLoginVo(phoneNumberVo.getSessionId(), mobile, 1);
            return ResponseUtil.success(userLoginVo);
        }
        String sessionKey = (String) userInfoMap.get(UserInfoKeyConstant.SESSION_KEY);
        //解密用户信息，获取手机号
        mobile = getPhoneNumber(sessionKey, phoneNumberVo.getEncryptedData(), phoneNumberVo.getIv());
        if (StringUtils.isBlank(mobile)) {
            return new BaseResponse(Version.VERSION_1, ResponseResult.USER_GETPHONE_ERROR.getCode(), "获取用户手机号失败");
        }
        log.info("getPhoneNumber mobile  :{}", mobile);
        MemberInfoDto memberInfoDto = getUserInfo(openid, partnerId, mobile);
        if (memberInfoDto == null) {
            return ResponseUtil.error(ResponseResult.USER_GETPHONE_ERROR);
        }
        userInfoMap.put(UserInfoKeyConstant.MOBILE, mobile == null ? "" : mobile);
        this.saveUserInfoMap(RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + phoneNumberVo.getSessionId(), userInfoMap);
        UserLoginVo userLoginVo = userAdapter.getUserLoginVo(phoneNumberVo.getSessionId(), mobile, 1);
        return ResponseUtil.success(userLoginVo);
    }

    @Override
    public BaseResponse sendSmsCode(SendSmsCodeVo sendSmsCodeVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(sendSmsCodeVo.getSessionId());
        if (userInfoMap == null) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        //校验用户是否注册
        String partnerId = (String) userInfoMap.get(UserInfoKeyConstant.PARTNER_ID);
        String mobile = sendSmsCodeVo.getMobile();
        String key = RedisKeyConstant.SAAS_VERIFICATION_CODE_KEY_PREFIX + mobile;
        //查询配置信息
        Partner partner = partnerManager.selectByPartnerId(partnerId);
        if (partner == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "商家未开通小程序");
        }
        //发送短信接口参数
        JSONObject jsonObject = new JSONObject();
        //随机生成六位数字
        String code = ValidationCode.getRandomNumber(6);
        jsonObject.put("code", code);
        jsonObject.put("minute", "2");
        String encode;
        try {
            encode = URLEncoder.encode(jsonObject.toJSONString(), "UTF-8");
        } catch (Exception e) {
            log.error("sendSmsCode sendPostRequest is error ! ", e);
            return null;
        }
        SendShortMessageCodeDto sendShortMessageCodeDto = new SendShortMessageCodeDto();
        sendShortMessageCodeDto.setMobile(mobile);
        sendShortMessageCodeDto.setSmstype(1);
        sendShortMessageCodeDto.setContent(encode);
        sendShortMessageCodeDto.setValidcode(code);
        sendShortMessageCodeDto.setSmschannel("1001");
        sendShortMessageCodeDto.setTemplatecode("SMS_60345418");

        SendSmsCodeResponseDto sendSmsCodeResponseDto = shortMessageClient.sendSmsCode(partner.getMsappId(),
                sendShortMessageCodeDto);
        if (!sendSmsCodeResponseDto.getIssuccess()) {
            log.error("sendSmsCode sendSmsCode is error ,sendSmsCodeResponseDto:{}", sendShortMessageCodeDto);
            return ResponseUtil.error(ResponseResult.SMSCODE_SEND_ERROR);
        }
        redisCache.save(key, code, 120L, TimeUnit.SECONDS);
        return ResponseUtil.success();
    }

    @Override
    public BaseResponse registerByMobile(RegisterByMobileVo registerByMobileVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(registerByMobileVo.getSessionId());
        if (userInfoMap == null || userInfoMap.size() == 0) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        String sessionId = registerByMobileVo.getSessionId();
        String smsCode = registerByMobileVo.getSmsCode();
        String mobile = registerByMobileVo.getMobile();
        String key = RedisKeyConstant.SAAS_VERIFICATION_CODE_KEY_PREFIX + mobile;
        if (redisCache.getValue(key) == null || !smsCode.equals(redisCache.getValue(key))) {
            return ResponseUtil.error(ResponseResult.SMSCODE_ERROR);
        }
        redisCache.delete(key);
        String openid = (String) userInfoMap.get(UserInfoKeyConstant.OPEN_ID);
        String partnerId = (String) userInfoMap.get(UserInfoKeyConstant.PARTNER_ID);
        MemberInfoDto memberInfoDto = getUserInfo(openid, partnerId, mobile);
        if (StringUtils.isBlank(memberInfoDto.getMemberId())) {
            return ResponseUtil.error(ResponseResult.USER_REGISTER_ERROR);
        }
        userInfoMap.put(UserInfoKeyConstant.MOBILE, mobile == null ? "" : mobile);
        this.saveUserInfoMap(RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId, userInfoMap);
        UserLoginVo userLoginVo = userAdapter.getUserLoginVo(sessionId, mobile, 1);
        return ResponseUtil.success(userLoginVo);
    }

    /**
     * 用户修改手机号
     */
    @Override
    public BaseResponse editMobile(EditMobileVo editMobileVo) {
        BaseResponse baseResponse = checkRequestEditMobile(editMobileVo);
        if (baseResponse != null) {
            return baseResponse;
        }
        //sessionId验证
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(editMobileVo.getSessionId());
        if (null == userInfoMap) {
            return ResponseUtil.error(ResponseResult.SESSION_INVAILD.getCode(), "用户登陆信息已过期，请重新登陆");
        }
        String openid = (String) userInfoMap.get(UserInfoKeyConstant.OPEN_ID);
        String partnerId = (String) userInfoMap.get(UserInfoKeyConstant.PARTNER_ID);
        //获取用户注册信息
        MemberInfoDto memberInfoDto = getUserInfo(openid, partnerId, editMobileVo.getMobile());
        if (memberInfoDto == null) {
            return ResponseUtil.error(ResponseResult.USER_EDIT_MOBILE_ERROR);
        }
        return ResponseUtil.success();
    }

    @Override
    public BaseResponse getDeliveryAddress(QueryDeliveryAddressVo queryDeliveryAddressVo) {
        LogUtil.info("getDeliveryAddress start", gson.toJson(queryDeliveryAddressVo), null);
        checkUserLogin(queryDeliveryAddressVo.getSessionId());
        UserLoginInfoDto userLoginInfoDto = getUserLoginInfoBySessionId(queryDeliveryAddressVo.getSessionId());
        String storeId = queryDeliveryAddressVo.getShopId();
        if (queryDeliveryAddressVo.getPageNo() == null) {
            queryDeliveryAddressVo.setPageNo(1);
        }
        if (queryDeliveryAddressVo.getPageSize() == null) {
            queryDeliveryAddressVo.setPageSize(10);
        }
        if (StringUtils.isBlank(queryDeliveryAddressVo.getLatitude())) {
            queryDeliveryAddressVo.setLatitude("0");
        }
        if (StringUtils.isBlank(queryDeliveryAddressVo.getLongitude())) {
            queryDeliveryAddressVo.setLongitude("0");
        }
        //TODO 如果shopId为空，查询用户收货地址列表
        StoreDeliveryInfoDto storeDeliveryInfoDto = null;
        if (StringUtils.isNotBlank(queryDeliveryAddressVo.getShopId())) {
            //TODO 查询门店信息
            StoreResponseDto storeResponseDto = storeService.getStoreInfo(userLoginInfoDto.getPartnerId(), storeId);
            //TODO 查询门店外卖信息
            storeDeliveryInfoDto = storeService.getStoreDeliveryInfo(storeResponseDto, userLoginInfoDto.getWxAppid());
            queryDeliveryAddressVo.setLongitude(storeDeliveryInfoDto.getLongitude());
            queryDeliveryAddressVo.setLatitude(storeDeliveryInfoDto.getLatitude());
        }
        GetReceiveAddressListDto getReceiveAddressListDto = new GetReceiveAddressListDto(userLoginInfoDto.getMemberId(),
                userLoginInfoDto.getPartnerId(), queryDeliveryAddressVo.getLatitude(), queryDeliveryAddressVo.getLongitude(),
                queryDeliveryAddressVo.getPageNo(), queryDeliveryAddressVo.getPageSize());
        GetReceiveAddressListResponseDto responseDto;
        try {
            responseDto = customerClient.getReceiveAddressList(getReceiveAddressListDto);
            LogUtil.info("customerClient.getReceiveAddressList", gson.toJson(getReceiveAddressListDto), gson.toJson(responseDto));
            if (!ResponseResult.SUCCESS.getCode().equals(responseDto.getCode()) || responseDto.getData() == null) {
                log.error("getDeliveryAddress is faild ,request:{},response:{}", gson.toJson(getReceiveAddressListDto), gson.toJson(responseDto));
                return ResponseUtil.error(ResponseResult.USER_GETRECEIVEADDRESS_ERROR);
            }
        } catch (Exception e) {
            log.error("getDeliveryAddress is error ,request:{}", gson.toJson(getReceiveAddressListDto), e);
            return ResponseUtil.error(ResponseResult.USER_GETRECEIVEADDRESS_ERROR);
        }
        QueryReceiveAddressResponseVo responseVo = userAdapter.getQueryReceiveAddress(responseDto, storeDeliveryInfoDto);
        LogUtil.info("getDeliveryAddress end", null, gson.toJson(responseVo));
        return ResponseUtil.success(responseVo);
    }

    @Override
    public BaseResponse addDeliveryAddress(AddDeliveryAddressVo addDeliveryAddressVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(addDeliveryAddressVo.getSessionId());
        if (userInfoMap == null) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        String partnerId = userInfoMap.get(UserInfoKeyConstant.PARTNER_ID).toString();
        String memberId = userInfoMap.get(UserInfoKeyConstant.MEMBER_ID).toString();
        if (SexType.getByCode(addDeliveryAddressVo.getSex()) == null) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "收货人性别不能为空");
        }
        if (StringUtils.isNotBlank(addDeliveryAddressVo.getLabel())) {
            if (ReceiveAddressLabelType.getByDesc(addDeliveryAddressVo.getLabel()) == null) {
                return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "标签选择错误");
            }
        }
        if (StringUtils.isBlank(addDeliveryAddressVo.getReceiveId())) {
            AddReceiveAddressDto addReceiveAddressDto = userAdapter.convent2AddReceiveAddressDto(addDeliveryAddressVo, partnerId, memberId);
            LogUtil.info("addDeliveryAddress add start", gson.toJson(addReceiveAddressDto), null);
            AddReceiveAddressResponseDto addressResponseDto = customerClient.addReceiveAddress(addReceiveAddressDto);
            LogUtil.info("addDeliveryAddress add end", gson.toJson(addReceiveAddressDto), gson.toJson(addressResponseDto));
            if (!ResponseResult.SUCCESS.getCode().equals(addressResponseDto.getCode())) {
                return ResponseUtil.error(ResponseResult.USER_ADDRECEIVEADDRESS_ERROR);
            }
        } else {
            UpdateReceiveAddressDto updateReceiveAddressDto = userAdapter.convent2UpdateReceiveAddressDto(addDeliveryAddressVo, partnerId, memberId);
            LogUtil.info("updateReceiveAddressDto add start", gson.toJson(updateReceiveAddressDto), null);
            UpdateReceiveAddressResponseDto updateReceiveAddressResponseDto = customerClient.updateReceiveAddress(updateReceiveAddressDto);
            LogUtil.info("updateReceiveAddressDto add end", gson.toJson(updateReceiveAddressDto), gson.toJson(updateReceiveAddressResponseDto));
            if (!ResponseResult.SUCCESS.getCode().equals(updateReceiveAddressResponseDto.getCode())) {
                return ResponseUtil.error(ResponseResult.USER_UPDATERECEIVEADDRESS_ERROR);
            }
        }
        return ResponseUtil.success();
    }

    @Override
    public BaseResponse deleteDeliveryAddress(DeleteDeliveryAddressVo deleteDeliveryAddressVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(deleteDeliveryAddressVo.getSessionId());
        if (userInfoMap == null) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        String partnerId = userInfoMap.get(UserInfoKeyConstant.PARTNER_ID).toString();
        DeleteReceiveAddressDto deleteReceiveAddressDto = new DeleteReceiveAddressDto(deleteDeliveryAddressVo.getReceiveId(), partnerId);
        LogUtil.info("deleteDeliveryAddress start", gson.toJson(deleteReceiveAddressDto), null);
        DeleteReceiveAddressResponseDto responseDto = customerClient.deleteReceiveAddress(deleteReceiveAddressDto);
        LogUtil.info("deleteDeliveryAddress end", gson.toJson(deleteReceiveAddressDto), gson.toJson(responseDto));
        if (!ResponseResult.SUCCESS.getCode().equals(responseDto.getCode())) {
            return ResponseUtil.error(ResponseResult.USER_DELETERECEIVEADDRESS_ERROR);
        }
        return ResponseUtil.success();
    }


    /**
     * 校验 GetPhoneNumberVo
     */
    private BaseResponse checkPhoneNumberVo(GetPhoneNumberVo phoneNumberVo) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(phoneNumberVo.getSessionId());
        if (userInfoMap == null || userInfoMap.isEmpty()) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        String sessionKey = (String) userInfoMap.get(UserInfoKeyConstant.SESSION_KEY);
        String openid = (String) userInfoMap.get(UserInfoKeyConstant.OPEN_ID);
        String partnerId = (String) userInfoMap.get(UserInfoKeyConstant.PARTNER_ID);
        if (StringUtils.isBlank(openid) || StringUtils.isBlank(partnerId) || StringUtils.isBlank(sessionKey)) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        return null;
    }

    /**
     * 校验用户信息签名
     */
    private boolean checkUserSign(String rawData, String signature, String sessionKey) {
        return signature.equals(Sha1Util.sha1(rawData + sessionKey));
    }

    /**
     * 校验用户是否登录
     */
    public void checkUserLogin(String sessionId) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(sessionId);
        log.info("submit userInfoMap:{}", gson.toJson(userInfoMap));
        if (userInfoMap == null || userInfoMap.size() <= 0 || userInfoMap.get(UserInfoKeyConstant.MEMBER_ID) == null) {
            throw new ServiceException(ResponseResult.NOT_LOGIN);
        }
    }
    /**
     * 校验用户是否登录
     */
    public boolean checkUserLoginFlag(String sessionId) {
        Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(sessionId);
        log.info("submit userInfoMap:{}", gson.toJson(userInfoMap));
        if (userInfoMap == null || userInfoMap.size() <= 0 || userInfoMap.get(UserInfoKeyConstant.MEMBER_ID) == null) {
            return false;
        }
        return true;
    }

    /**
     * 获取缓存用户信息
     */
    @Override
    public Map<String, Object> getUserInfoMapBySessionId(String sessionId) {
        String redisKey = RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId;
        Map<String, Object> map;
        try {
            map = redisCache.getValue(redisKey);
        }catch (Exception e){
            map = redisCache.getValue(redisKey);
        }
        return map;
    }

    /**
     * 获取缓存用户信息
     *
     * @param sessionId
     * @return
     */
    @Override
    public UserLoginInfoDto getUserLoginInfoBySessionId(String sessionId) {
        checkUserLogin(sessionId);

        String redisKey = RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId;
        Map<String, Object> map = redisCache.getValue(redisKey);
        return userAdapter.getUserLoginInfoDto(map);
    }

    /**
     * 解密用户信息获取手机号
     */
    private String getPhoneNumber(String sessionkey, String encryptedData, String iv) {
        String response = decrptWeiXinEncryptedData(sessionkey, encryptedData, iv);
        if (response == null) {
            return null;
        }
        log.info("[getPhoneNumber]  response :{}", response);
        String phoneNumber = null;
        try {
            if (response.contains("phoneNumber")) {
                JSONObject jsonObject = JSON.parseObject(response);
                phoneNumber = jsonObject.getString("phoneNumber");
            }
        } catch (Exception e) {
            log.error("[UserServiceImpl][getPhoneNumber] is error !!", sessionkey + "_" + encryptedData + "_" + iv, e);
            return null;
        }
        return phoneNumber;
    }

    /**
     * 获取用户登录信息
     *
     * @param openid
     * @param sessionKey
     * @param appid
     * @param partnerId
     * @return
     */
    public UserLoginVo getUserLoginInfo(String openid, String sessionKey, String appid, String partnerId, GetUserLoginSessionIdVo requestUserLoginVo) {
        LogUtil.info("getUserOpenid", openid + "_" + sessionKey + "_" + appid + "_" + partnerId, null);
        MemberInfoDto memberInfoDto = this.getUserInfo(openid, partnerId, null);
        String mobile = memberInfoDto != null && StringUtils.isNotBlank(memberInfoDto.getMobile()) ? memberInfoDto.getMobile() : "";
        String memberId = memberInfoDto != null && StringUtils.isNotBlank(memberInfoDto.getMemberId()) ? memberInfoDto.getMemberId() : "";
        boolean newMemeber = memberInfoDto != null ? memberInfoDto.getNewMember() : true;
        //TODo 将用户信息加密生成session
        String sessionId = Sha1Util.sha1(MD5Util.getMD5String(openid + sessionKey + partnerId + memberId + System.currentTimeMillis()));
        String redisKey = RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId;
        UserInfoDto userInfoDto = UserInfoDto.builder()
                .openId(openid)
                .unionId("")
                .wxAppid(appid)
                .sessionKey(sessionKey)
                .mobile(mobile)
                .appsecret("")
                .memberId(memberId)
                .partnerId(partnerId)
                .newMemeber(newMemeber)
                .devBrand(requestUserLoginVo.getDevBrand())
                .devModel(requestUserLoginVo.getDevModel())
                .channel(requestUserLoginVo.getChannel())
                .build();
        Map<String, Object> userInfoMap = createUserInfoMap(null, userInfoDto);
        this.saveUserInfoMap(redisKey, userInfoMap);
        UserLoginVo responseUserLoginVo = new UserLoginVo();
        responseUserLoginVo.setRegistered(StringUtils.isNotBlank(memberId) ? 1 : 0);
        responseUserLoginVo.setMobile(mobile);
        responseUserLoginVo.setSessionId(sessionId);

        // 查询用户是否有昵称 替换成用户是否有图像
        boolean hasPhotoUrl = memberInfoDto != null && StringUtils.isNotEmpty(memberInfoDto.getPhotoUrl());
        responseUserLoginVo.setNickNamed(hasPhotoUrl ? 1 : 0);
        responseUserLoginVo.setNickName(memberInfoDto != null && StringUtils.isNotEmpty(memberInfoDto.getNickName()) ? memberInfoDto.getNickName() : "");

        // 发送凭证给消息中心
        if (StringUtils.isNotBlank(memberId)) {
            PushMessageTokenDto pushMessageTokenDto = messageNoticeAdapter.convent2PushMessageTokenDto(partnerId,
                    null, memberId, sessionId);
            LogUtil.info("registerToken is start", gson.toJson(pushMessageTokenDto), gson.toJson(pushMessageTokenDto));
            try {
                String message = messageNoticeClient.registerToken(pushMessageTokenDto);
                log.info("registerToken is end", gson.toJson(pushMessageTokenDto), message);
            } catch (Exception e) {
                log.error("registerToken is error !!!", gson.toJson(pushMessageTokenDto), null, e);
            }
        }
        return responseUserLoginVo;
    }


    /**
     * 获取用户登录信息New
     *
     * @param openid
     * @param sessionKey
     * @param appid
     * @param partnerId
     * @return
     */
    public UserLoginVo getUserLoginInfoNew(String openid, String sessionKey, String appid, String partnerId, GetUserLoginSessionIdVo requestUserLoginVo) {
        LogUtil.info("getUserOpenid", openid + "_" + sessionKey + "_" + appid + "_" + partnerId, null);
        MemberInfoDto memberInfoDto = getUserInfoNew(openid, partnerId, null);
        String mobile = "";
        String memberId = "";
        boolean newMemeber = true;
        String unionId = "";
        if (memberInfoDto != null) {
            mobile = memberInfoDto.getMobile();
            memberId = memberInfoDto.getMemberId();
            newMemeber = memberInfoDto.getNewMember();
            unionId = memberInfoDto.getUnionId();
        }
        //TODo 将用户信息加密生成session
        String sessionId = Sha1Util.sha1(MD5Util.getMD5String(openid + sessionKey + partnerId + memberId + System.currentTimeMillis()));
        String redisKey = RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId;
        UserInfoDto userInfoDto = UserInfoDto.builder()
                .openId(openid)
                .unionId(unionId)
                .wxAppid(appid)
                .sessionKey(sessionKey)
                .mobile(mobile)
                .appsecret("")
                .memberId(memberId)
                .partnerId(partnerId)
                .newMemeber(newMemeber)
                .devBrand(requestUserLoginVo.getDevBrand())
                .devModel(requestUserLoginVo.getDevModel())
                .channel(requestUserLoginVo.getChannel())
                .build();
        Map<String, Object> userInfoMap = createUserInfoMap(null, userInfoDto);
        this.saveUserInfoMap(redisKey, userInfoMap);
        UserLoginVo responseUserLoginVo = new UserLoginVo();
        responseUserLoginVo.setRegistered(StringUtils.isNotBlank(memberId) ? 1 : 0);
        responseUserLoginVo.setMobile(mobile);
        responseUserLoginVo.setSessionId(sessionId);
        responseUserLoginVo.setUnionId(unionId);
        responseUserLoginVo.setMemberId(memberId);

        // 查询用户是否有昵称
        boolean hasPhotoUrl = memberInfoDto != null && StringUtils.isNotEmpty(memberInfoDto.getPhotoUrl());
        responseUserLoginVo.setNickNamed(hasPhotoUrl ? 1 : 0);
        responseUserLoginVo.setNickName(memberInfoDto != null && StringUtils.isNotEmpty(memberInfoDto.getNickName()) ? memberInfoDto.getNickName() : "");

        // 发送凭证给消息中心
        if (StringUtils.isNotBlank(memberId)) {
            PushMessageTokenDto pushMessageTokenDto = messageNoticeAdapter.convent2PushMessageTokenDto(partnerId,
                    null, memberId, sessionId);
            LogUtil.info("registerToken is start", gson.toJson(pushMessageTokenDto), gson.toJson(pushMessageTokenDto));
            try {
                String message = messageNoticeClient.registerToken(pushMessageTokenDto);
                log.info("registerToken is end", gson.toJson(pushMessageTokenDto), message);
            } catch (Exception e) {
                log.error("registerToken is error !!!", gson.toJson(pushMessageTokenDto), null, e);
            }
        }
        return responseUserLoginVo;
    }


    /**
     * @param openid    openId
     * @param partnerId
     * @param mobile
     * @return
     */
    public MemberInfoDto getUserInfo(String openid, String partnerId, String mobile) {
        GetMemberInfoByChannelRequestDto getMemberInfoByChannelRequestDto = new GetMemberInfoByChannelRequestDto();
        getMemberInfoByChannelRequestDto.setPartnerId(partnerId);
        getMemberInfoByChannelRequestDto.setThirdPartyCode(openid);
        getMemberInfoByChannelRequestDto.setChannelCode("dcxcx");

        try {
            GetMemberInfoByChannelResponseDto getMemberInfoByChannelResponseDto = customerClient.getMemberInfoByChannel(getMemberInfoByChannelRequestDto);
            LogUtil.info("customerClient.getMemberInfoByChannel****", gson.toJson(getMemberInfoByChannelRequestDto), gson.toJson(getMemberInfoByChannelResponseDto));
            if (!ResponseResult.SUCCESS.getCode().equals(getMemberInfoByChannelResponseDto.getCode())) {
                //TODO 如果未注册，注册会员
                if (!ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(getMemberInfoByChannelResponseDto.getCode())) {
                    return this.registerMember(mobile, openid, partnerId);
                }
                log.error("member getUserInfo is error ,getMemberInfoResponseDto：{}", getMemberInfoByChannelResponseDto);
                return null;
            } else {
                MemberInfoDto memberInfo = new MemberInfoDto();
                GetMemberInfoByChannelResponseDto.ResultBean result = getMemberInfoByChannelResponseDto.getData();
                if (result != null) {
                    // 如果手机号信息不一致，更新用户信息
                    log.info("getUserInfo getMemberInfoResponseDto.mobile :{},requestMobile:{}", result.getMobile(), mobile);
                    if (StringUtils.isNotBlank(mobile) && !mobile.equals(result.getMobile())) {
                        String memberId = result.getMemberId();
                        EditMemberInfoRequestDto editMemberInfoRequestDto = EditMemberInfoRequestDto.builder()
                                .partnerId(partnerId)
                                .memberId(memberId)
                                .mobile(mobile)
                                .build();
                        customerClient.editMemberInfo(editMemberInfoRequestDto);
                        result.setMobile(mobile);
                    }
                    if (StringUtils.isBlank(mobile) && StringUtils.isNotBlank(result.getMobile())) {
                        mobile = result.getMobile();
                    }
                    memberInfo.setMobile(mobile);
                    memberInfo.setMemberId(result.getMemberId());
                    memberInfo.setNickName(result.getNickName());
                    memberInfo.setPhotoUrl(result.getPhotoUrl());
                }
                memberInfo.setOpenid(openid);
                return memberInfo;
            }
        } catch (Exception e) {
            LogUtil.error("getUserInfo is error！！", gson.toJson(getMemberInfoByChannelRequestDto), gson.toJson(getMemberInfoByChannelRequestDto), e);
            log.error("[userServiceImpl] getUserInfo is error !!", e);
            return null;
        }
    }


    /**
     * @param openid    openId
     * @param partnerId
     * @param mobile
     * @return
     */
    public MemberInfoDto getUserInfoNew(String openid, String partnerId, String mobile) {
        GetMemberInfoByChannelRequestDto getMemberInfoByChannelRequestDto = new GetMemberInfoByChannelRequestDto();
        getMemberInfoByChannelRequestDto.setPartnerId(partnerId);
        getMemberInfoByChannelRequestDto.setThirdPartyCode(openid);
        getMemberInfoByChannelRequestDto.setChannelCode("dcxcx");

        try {
            GetMemberInfoByChannelResponseDto getMemberInfoByChannelResponseDto = customerClient.getMemberInfoByChannel(getMemberInfoByChannelRequestDto);
            if (!ResponseResult.SUCCESS.getCode().equals(getMemberInfoByChannelResponseDto.getCode())) {
                return null;
            } else {

                MemberInfoDto memberInfo = new MemberInfoDto();
                GetMemberInfoByChannelResponseDto.ResultBean result = getMemberInfoByChannelResponseDto.getData();
                if (result != null) {
                    // 如果手机号信息不一致，更新用户信息
                    log.info("getUserInfo getMemberInfoResponseDto.mobile :{},requestMobile:{}", result.getMobile(), mobile);
                    if (StringUtils.isNotBlank(mobile) && !mobile.equals(result.getMobile())) {
                        String memberId = result.getMemberId();
                        EditMemberInfoRequestDto editMemberInfoRequestDto = EditMemberInfoRequestDto.builder()
                                .partnerId(partnerId)
                                .memberId(memberId)
                                .mobile(mobile)
                                .build();
                        customerClient.editMemberInfo(editMemberInfoRequestDto);
                    }
                    if (StringUtils.isBlank(mobile) && StringUtils.isNotBlank(result.getMobile())) {
                        mobile = result.getMobile();
                    }
                    memberInfo.setMobile(mobile);
                    memberInfo.setMemberId(result.getMemberId());
                    memberInfo.setNickName(result.getNickName());
                    memberInfo.setUnionId(result.getMemberChannels().get(0).getUnionId());
                }
                memberInfo.setOpenid(openid);
                return memberInfo;
            }
        } catch (Exception e) {
            LogUtil.error("getUserInfo is error！！", gson.toJson(getMemberInfoByChannelRequestDto), gson.toJson(getMemberInfoByChannelRequestDto), e);
            log.error("[userServiceImpl] getUserInfo is error !!", e);
            return null;
        }
    }

    /**
     * 注册会员
     */
    public MemberInfoDto registerMember(String mobile, String openId, String partnerId) {
//        MemberRegisterDto memberRegisterDto = userAdapter.getMemberRegister(mobile, openId, partnerId);
        MemberRegisterRequestDto memberRegisterRequestDto = new MemberRegisterRequestDto();
        memberRegisterRequestDto.setChannelCode("dcxcx");
        memberRegisterRequestDto.setPartnerId(partnerId);
        memberRegisterRequestDto.setRegisterType("1");
        memberRegisterRequestDto.setThirdPartyCode(openId);
        memberRegisterRequestDto.setUnionId("");
        memberRegisterRequestDto.setNickName("");
        memberRegisterRequestDto.setMobile(mobile);
        memberRegisterRequestDto.setRegisterInitData("1#1#2#2#2");
        try {
            MemberRegisterResponseDto memberRegisterResponseDto = customerClient.registerByChannel(memberRegisterRequestDto);
            if (RESPONSE_SUCCESS_CODE.equals(memberRegisterResponseDto.getCode())) {
                MemberInfoDto memberInfo = new MemberInfoDto();
                memberInfo.setOpenid(openId);
                memberInfo.setMobile(mobile);
                memberInfo.setMemberId(memberRegisterResponseDto.getData().getMemberId());
                memberInfo.setNewMember(true);
                return memberInfo;
            } else {
                log.error("registerMember is faild !! userRegisterResponse :{} ", memberRegisterResponseDto);
                return null;
            }
        } catch (Exception e) {
            log.error("userRegister is error ，mobile{} !!", mobile + "_" + openId + "_" + partnerId, e);
            return null;
        }
    }

    /**
     * 修改会员手机号
     *
     * @param mobile
     * @param memberId
     * @param partnerId
     * @return
     */
    public String editUserInfo(String mobile, String memberId, String partnerId) {
        JSONObject jsonObject;
        try {
            EditMemberInfoRequestDto editMemberInfoRequestDto = EditMemberInfoRequestDto.builder()
                    .partnerId(partnerId)
                    .memberId(memberId)
                    .mobile(mobile)
                    .build();
            jsonObject = customerClient.editMemberInfo(editMemberInfoRequestDto);
            log.info("editUserInfo jsonObject :{}", jsonObject.toJSONString());
            if (StringUtils.equals(RESPONSE_SUCCESS_CODE, jsonObject.getString("code")) && jsonObject.get("result") != null) {
                return "ok";
            } else {
                log.error("registerMember is faild !! mobile :{}  ,json :{}", mobile + "_" + memberId + "_" + partnerId, jsonObject.toJSONString());
                return null;
            }
        } catch (Exception e) {
            log.error("userRegister is error ，mobile{} !!", mobile + "_" + memberId + "_" + partnerId, e);
            return null;
        }
    }

    /**
     * 验证修改手机号接口参数
     */
    private BaseResponse checkRequestEditMobile(EditMobileVo editMobileVo) {
        if (StringUtils.isBlank(editMobileVo.getSessionId())) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "sessionId 不能为空");
        }
        if (StringUtils.isBlank(editMobileVo.getMobile())) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "手机号不能为空");
        }
        if (editMobileVo.getMobile().length() != 11) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING.getCode(), "请填写11位手机号");
        }
        String key = RedisKeyConstant.SAAS_VERIFICATION_CODE_KEY_PREFIX + editMobileVo.getMobile();
        if (redisCache.getValue(key) == null || !editMobileVo.getSmsCode().equals(redisCache.getValue(key))) {
            return ResponseUtil.error(ResponseResult.SMSCODE_ERROR);
        }
        return null;
    }


    @Override
    public BaseResponse<RegisterByUnionIdResponseVo> registerByUnionId(RegisterByUnionIdRequestVo registerByUnionIdRequestVo) {
        checkUserLogin(registerByUnionIdRequestVo.getSessionId());
        try {
            String sessionId = registerByUnionIdRequestVo.getSessionId();
            Map<String, Object> userInfoMap = this.getUserInfoMapBySessionId(sessionId);
            String sessionKey = (String) userInfoMap.get(UserInfoKeyConstant.SESSION_KEY);
            String decrptedString = decrptWeiXinEncryptedData(sessionKey, registerByUnionIdRequestVo.getEncryptedData(), registerByUnionIdRequestVo.getIv());
            LogUtil.info("registerByUnionI_dencryptedData_end:", decrptedString, null);
            JSONObject jsonObject = JSONObject.parseObject(decrptedString);
            String unionId = jsonObject.getString(UserInfoKeyConstant.UNION_ID);
            String openId = jsonObject.getString("openId");
            String nickName = jsonObject.getString("nickName");
            nickName = UnicodeUtil.filterSpecialChars(nickName);

            String memberId = (String) userInfoMap.get(UserInfoKeyConstant.MEMBER_ID);
            String partnerId = registerByUnionIdRequestVo.getPartnerId();
            LogUtil.info("registerByUnionId_start", memberId + "_" + unionId, null);
            // 当memberId为空时注册会员
            if (StringUtils.isEmpty(memberId)) {
                MemberRegisterRequestDto memberRegisterRequestDto = new MemberRegisterRequestDto();
                memberRegisterRequestDto.setChannelCode("dcxcx");
                memberRegisterRequestDto.setPartnerId(partnerId);
                memberRegisterRequestDto.setRegisterType("2");
                memberRegisterRequestDto.setThirdPartyCode(openId);
                memberRegisterRequestDto.setUnionId(unionId);
                memberRegisterRequestDto.setNickName(nickName);
                MemberRegisterResponseDto memberRegisterResponseDto = null;
                for (int i = 2; i >= 0; i--) {
                    try {
                        memberRegisterResponseDto = customerClient.registerByChannel(memberRegisterRequestDto);
                    } catch (RuntimeException ex) {
                        if (i == 0) {
                            throw ex;
                        }
                    }
                    if (memberRegisterResponseDto != null
                            && StringUtils.equals(memberRegisterResponseDto.getCode(), "100")) {
                        break;
                    }
                }
                memberId = memberRegisterResponseDto.getData().getMemberId();
                String redisKey = RedisKeyConstant.SAAS_USER_INFO_SESSIONID_KEY_PREFIX + sessionId;
                UserInfoDto userInfoDto = UserInfoDto.builder()
                        .openId(openId)
                        .unionId(unionId)
                        .wxAppid(registerByUnionIdRequestVo.getAppId())
                        .sessionKey(sessionKey)
                        .mobile(String.valueOf(userInfoMap.get(UserInfoKeyConstant.MOBILE)))
                        .appsecret("")
                        .memberId(memberId)
                        .partnerId(partnerId)
                        .newMemeber(true)
                        .devBrand(registerByUnionIdRequestVo.getDevBrand())
                        .devModel(registerByUnionIdRequestVo.getDevModel())
                        .channel(registerByUnionIdRequestVo.getChannel())
                        .build();
                userInfoMap = createUserInfoMap(userInfoMap, userInfoDto);
                this.saveUserInfoMap(redisKey, userInfoMap);

                String trackingId = TrackingIdUtil.getTrackingId();

                //埋点
                Map<String, Object> buryingPointMap = userInfoMap;
                ThreadPoolUtil.getPoolExecutorForNull(ApplicationConstant.BURYINGPOINT).execute(() -> {
                    if (StringUtils.isBlank(registerByUnionIdRequestVo.getCts()) || StringUtils.isBlank(registerByUnionIdRequestVo.getDevBrand()) || StringUtils.isBlank(registerByUnionIdRequestVo.getDevModel()) || StringUtils.isBlank(registerByUnionIdRequestVo.getChannel())) {
                        return;
                    }
                    BuryingPointBigDto buryingPointBigDto = null;
                    try {
                        buryingPointBigDto = bigDataAdapter.convert2PointRegister(registerByUnionIdRequestVo, partnerId, sessionId, buryingPointMap);
                        LogUtil.info(trackingId, "登录埋点数据", JSON.toJSONString(bigDataFeiginClient.syncLoginData(buryingPointBigDto)), null);
                    } catch (Exception e) {
                        LogUtil.error(trackingId, "埋点发送异常", JSON.toJSONString(buryingPointBigDto), null, e);
                    }
                });
            }
            // 已注册会员更新unionId
            else {
                if (StringUtils.isBlank(unionId)) {
                    throw new ServiceException(ResponseResult.USER_REGISTER_ERROR);
                }
                // 创建更新会员unionId类
                UpdateMemUnionIdRequestDto updateMemUnionIdRequestDto = new UpdateMemUnionIdRequestDto();
                updateMemUnionIdRequestDto.setPartnerId(partnerId);
                updateMemUnionIdRequestDto.setMemberId(memberId);
                updateMemUnionIdRequestDto.setUnionId(unionId);
                updateMemUnionIdRequestDto.setChannelCode("dcxcx");
                // 请求会员服务
                JSONObject res;
                res = customerClient.updateUserUnionId(updateMemUnionIdRequestDto);
                if (res == null
                        || !StringUtils.equals(res.getString("code"), "100")) {
                    throw new ServiceException(ResponseResult.USER_REGISTER_ERROR);
                }
            }
            RegisterByUnionIdResponseVo registerByUnionIdResponseVo = new RegisterByUnionIdResponseVo();
            registerByUnionIdResponseVo.setSessionId(sessionId);
            return ResponseUtil.success(registerByUnionIdResponseVo);
        } catch (ServiceException ex) {
            throw ex;
        } catch (RuntimeException ex) {
            LogUtil.error("registerByUnionId_failed", JSONObject.toJSONString(registerByUnionIdRequestVo), "", ex);
            throw new ServiceException(ResponseResult.USER_REGISTER_ERROR);
        } catch (Throwable ex) {
            throw new ServiceException(ResponseResult.SYSTEM_ERROR);
        }
    }

    /**
     * 对微信传过来的数据解密
     *
     * @param sessionkey
     * @param encryptedData
     * @param iv
     * @return
     */


    private String decrptWeiXinEncryptedData(String sessionkey, String encryptedData, String iv) {
        byte[] encData = Base64.decodeBase64(encryptedData.getBytes());
        byte[] ivs = Base64.decodeBase64(iv.getBytes());
        byte[] key = Base64.decodeBase64(sessionkey.getBytes());
        String decrptedString = null;
        try {
            AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivs);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            decrptedString = new String(cipher.doFinal(encData), "UTF-8");
        } catch (BadPaddingException ex) {
            try {
                Security.addProvider(new BouncyCastleProvider());
                AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivs);
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
                SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                decrptedString = new String(cipher.doFinal(encData), "UTF-8");
            } catch (Exception e) {
                LogUtil.error("解密微信数据失败", "sessionKey:" + sessionkey
                        + ",encryptedData:" + encryptedData
                        + ",iv:" + iv, null, e);
            }
        } catch (Exception ex) {
            LogUtil.error("解密微信数据失败", "sessionKey:" + sessionkey
                    + ",encryptedData:" + encryptedData
                    + ",iv:" + iv, null, ex);
        }
        return decrptedString;
    }

    /**
     * 创建userInfoMap
     */
    private Map<String, Object> createUserInfoMap(Map<String, Object> userInfoMap, UserInfoDto userInfoDto) {
        if (userInfoMap == null || userInfoMap.size() == 0) {
            userInfoMap = Maps.newTreeMap();
        }
        userInfoMap.put(UserInfoKeyConstant.OPEN_ID, StringUtils.isBlank(userInfoDto.getOpenId()) ? "" : userInfoDto.getOpenId());
        userInfoMap.put(UserInfoKeyConstant.UNION_ID, StringUtils.isBlank(userInfoDto.getUnionId()) ? "" : userInfoDto.getUnionId());
        userInfoMap.put(UserInfoKeyConstant.WX_APPID, StringUtils.isBlank(userInfoDto.getWxAppid()) ? "" : userInfoDto.getWxAppid());
        userInfoMap.put(UserInfoKeyConstant.SESSION_KEY, StringUtils.isBlank(userInfoDto.getSessionKey()) ? "" : userInfoDto.getSessionKey());
        userInfoMap.put(UserInfoKeyConstant.MOBILE, StringUtils.isBlank(userInfoDto.getMobile()) ? "" : userInfoDto.getMobile());
        userInfoMap.put(UserInfoKeyConstant.APP_SECRET, StringUtils.isBlank(userInfoDto.getAppsecret()) ? "" : userInfoDto.getAppsecret());
        userInfoMap.put(UserInfoKeyConstant.MEMBER_ID, StringUtils.isBlank(userInfoDto.getMemberId()) ? "" : userInfoDto.getMemberId());
        userInfoMap.put(UserInfoKeyConstant.PARTNER_ID, StringUtils.isBlank(userInfoDto.getPartnerId()) ? "" : userInfoDto.getPartnerId());
        userInfoMap.put(UserInfoKeyConstant.NEW_MEMBER, (userInfoDto.getNewMemeber() != null) ? userInfoDto.getNewMemeber() : false);
        userInfoMap.put(UserInfoKeyConstant.DEVBRAND, StringUtils.isBlank(userInfoDto.getDevBrand()) ? "" : userInfoDto.getDevBrand());
        userInfoMap.put(UserInfoKeyConstant.DEVMODEL, StringUtils.isBlank(userInfoDto.getDevModel()) ? "" : userInfoDto.getDevModel());
        userInfoMap.put(UserInfoKeyConstant.CHANNEL, StringUtils.isBlank(userInfoDto.getChannel()) ? "" : userInfoDto.getChannel());
        return userInfoMap;
    }

    /**
     * 保存userInfoMap到redis
     *
     * @param key
     * @param userInfoMap
     */
    private void saveUserInfoMap(String key, Map<String, Object> userInfoMap) {
        redisCache.save(key, userInfoMap, 10L, TimeUnit.HOURS);
    }
}
