admin
2025-02-25 30d8e227e8d823b6c38c3b9c90ac2df03b63befe
fanli/src/main/java/com/yeshi/fanli/service/impl/user/UserAccountServiceImpl.java
@@ -1,1583 +1,1896 @@
package com.yeshi.fanli.service.impl.user;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.HttpUtil;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.entity.FileUploadResult;
import org.yeshi.utils.tencentcloud.COSManager;
import com.google.gson.Gson;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.ObjectListing;
import com.yeshi.fanli.dao.mybatis.AccountMessageMapper;
import com.yeshi.fanli.dao.mybatis.UserConnectHistoryMapper;
import com.yeshi.fanli.dao.mybatis.UserInfoMapper;
import com.yeshi.fanli.dto.wx.WXAccountInfoDTO;
import com.yeshi.fanli.entity.accept.AcceptData;
import com.yeshi.fanli.entity.bus.user.BindingAccount;
import com.yeshi.fanli.entity.bus.user.ForbiddenUserIdentifyCode;
import com.yeshi.fanli.entity.bus.user.ForbiddenUserIdentifyCode.ForbiddenUserIdentifyCodeTypeEnum;
import com.yeshi.fanli.entity.bus.user.LoginResult;
import com.yeshi.fanli.entity.bus.user.SMSHistory;
import com.yeshi.fanli.entity.bus.user.ThreeSale;
import com.yeshi.fanli.entity.bus.user.UserAccountBindingHistory;
import com.yeshi.fanli.entity.bus.user.UserConnectHistory;
import com.yeshi.fanli.entity.bus.user.UserExtraTaoBaoInfo;
import com.yeshi.fanli.entity.bus.user.UserInfo;
import com.yeshi.fanli.entity.bus.user.UserInfoModifyRecord.ModifyTypeEnum;
import com.yeshi.fanli.entity.bus.user.WeiXinUser;
import com.yeshi.fanli.exception.user.ForbiddenUserIdentifyCodeException;
import com.yeshi.fanli.exception.user.UserAccountException;
import com.yeshi.fanli.log.LogHelper;
import com.yeshi.fanli.service.inter.money.extract.BindingAccountService;
import com.yeshi.fanli.service.inter.user.ForbiddenUserIdentifyCodeService;
import com.yeshi.fanli.service.inter.user.SpreadUserImgService;
import com.yeshi.fanli.service.inter.user.UserAccountBindingHistoryService;
import com.yeshi.fanli.service.inter.user.UserAccountService;
import com.yeshi.fanli.service.inter.user.UserInfoDeleteRecordService;
import com.yeshi.fanli.service.inter.user.UserInfoExtraService;
import com.yeshi.fanli.service.inter.user.UserInfoModifyRecordService;
import com.yeshi.fanli.service.inter.user.UserInfoService;
import com.yeshi.fanli.service.inter.user.invite.ThreeSaleSerivce;
import com.yeshi.fanli.service.inter.user.msg.UserAccountMsgNotificationService;
import com.yeshi.fanli.service.inter.user.tb.UserExtraTaoBaoInfoService;
import com.yeshi.fanli.util.Constant;
import com.yeshi.fanli.util.FileUtil;
import com.yeshi.fanli.util.RedisManager;
import com.yeshi.fanli.util.StringUtil;
import com.yeshi.fanli.util.ThreadUtil;
import com.yeshi.fanli.util.TimeUtil;
import com.yeshi.fanli.util.factory.msg.MsgAccountDetailFactory;
import com.yeshi.fanli.util.wx.WXLoginUtil;
import net.sf.json.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;
@Service
public class UserAccountServiceImpl implements UserAccountService {
   @Resource
   private RedisManager redisManager;
   @Resource
   private UserInfoMapper userInfoMapper;
   @Resource
   private UserInfoService userInfoService;
   @Resource
   private BindingAccountService bindingAccountService;
   @Resource
   private UserConnectHistoryMapper userConnectHistoryMapper;
   @Resource
   private ThreeSaleSerivce threeSaleSerivce;
   @Resource
   private AccountMessageMapper accountMessageMapper;
   @Resource
   private SpreadUserImgService spreadUserImgService;
   @Resource
   private UserAccountMsgNotificationService userAccountMsgNotificationService;
   @Resource
   private UserExtraTaoBaoInfoService userExtraTaoBaoInfoService;
   @Resource
   private ForbiddenUserIdentifyCodeService forbiddenUserIdentifyCodeService;
   @Resource
   private UserInfoExtraService userInfoExtraService;
   @Resource
   private UserAccountBindingHistoryService userAccountBindingHistoryService;
   @Resource
   private UserInfoDeleteRecordService userInfoDeleteRecordService;
   @Resource
   private JedisPool jedisPool;
   @Lazy
   @Resource
   private UserInfoModifyRecordService userInfoModifyRecordService;
   @Transactional
   @Override
   public LoginResult login(HttpServletRequest request, AcceptData acceptData, Boolean first, String appId,
         String code, String phone, UserInfo tbUserInfo, boolean wxinstall, int loginType)
         throws UserAccountException {
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
      logInfo.put("code", code);
      logInfo.put("phone", phone);
      if (tbUserInfo != null)
         logInfo.put("tbUserInfo", tbUserInfo.getId());
      logInfo.put("loginType", loginType);
      LogHelper.lgoinInfo(logInfo.toString());
      HttpSession session = request.getSession();
      if (first != null && first == true)
         session.removeAttribute("LAST_LOGIN_USER");
      // 会话中上次登录的用户
      if (wxinstall) {// 安装了微信的状态
         UserInfo lastUser = (UserInfo) session.getAttribute("LAST_LOGIN_USER");
         UserInfo userInfo = null;
         WeiXinUser weiXinUser = null;
         switch (loginType) {
         case 1:// 淘宝
               // 判断淘宝是否被封禁
            if (!StringUtil.isNullOrEmpty(tbUserInfo.getTaoBaoUid())) {
               ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                     ForbiddenUserIdentifyCodeTypeEnum.taobaoUid, tbUserInfo.getTaoBaoUid());
               if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
                  throw new UserAccountException(Constant.CODE_FORBIDDEN_USER,
                        Constant.FORBIDDEN_USER_REASON_DESC);
            }
            userInfo = getUserInfoByTaoBaoOpenId(appId, tbUserInfo.getOpenid());
            // 判断用户是否被删除
            if (userInfo != null && userInfo.getState() != null
                  && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
                        || userInfo.getState() == UserInfo.STATE_DELETE))
               userInfo = null;
            if (userInfo == null) {// 原先的账号不存在
               userInfo = new UserInfo();
               userInfo.setAppId(appId);
               userInfo.setTbName(tbUserInfo.getTbName());
               userInfo.setOpenid(tbUserInfo.getOpenid());
               userInfo.setTbPic(tbUserInfo.getTbPic());
               userInfo.setNickName(tbUserInfo.getNickName());
               userInfo.setPortrait(tbUserInfo.getPortrait());
               userInfo.setLoginType(loginType);
               session.setAttribute("LAST_LOGIN_USER", userInfo);
               // 需要微信登录
               return new LoginResult(LoginResult.TYPE_WX, userInfo);
            } else {// 原先的账号存在
               // 判定是否绑定了微信
               if (StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {// 没有绑定微信
                  userInfo.setLoginType(loginType);
                  session.setAttribute("LAST_LOGIN_USER", userInfo);
                  // 需要微信登录
                  return new LoginResult(LoginResult.TYPE_WX, userInfo);
               } else {// 绑定了微信
                  updateLatestLoginTime(userInfo.getId());
                  return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
               }
            }
         case 2:// 微信
               // 通过Code换取信息
            WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
            weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
                  wxAccount.getAppSecret());
            if (weiXinUser == null)
               throw new UserAccountException(1001, "无法获取到微信个人信息");
            LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
            // 判断微信unionid是否被封禁
            ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                  ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
            if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
               throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
            userInfo = getUserInfoByWXUnionId(appId, weiXinUser.getUnionid());
            // 判断用户是否被删除
            if (userInfo != null && userInfo.getState() != null
                  && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
                        || userInfo.getState() == UserInfo.STATE_DELETE))
               userInfo = null;
            // 直接用的微信登录
            if (lastUser == null) {
               if (userInfo != null) {
                  // 使分销关系生效
                  threeSaleSerivce.effective(userInfo);
                  // 更新头像与昵称
                  UserInfo updateUserInfo = new UserInfo(userInfo.getId());
                  updateUserInfo.setNickName(weiXinUser.getNickname());
                  if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()))
                     updateUserInfo.setPortrait(weiXinUser.getHeadimgurl());
                  updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
                  updateUserInfo.setWxName(weiXinUser.getNickname());
                  // 设置登录时间与登录类型
                  updateUserInfo.setLastLoginTime(System.currentTimeMillis());
                  updateUserInfo.setLoginType(loginType);
                  updateUserInfo.setLastLoginIp(request.getRemoteHost());
                  //更新openId
                  updateUserInfo.setOpenid(weiXinUser.getOpenid());
                  userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
                  // 删除邀请图片
                  spreadUserImgService.deleteImgUrl(userInfo.getId());
                  return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
               }
               userInfo = new UserInfo();
               userInfo.setPortrait(weiXinUser.getHeadimgurl());
               userInfo.setAppId(appId);
               userInfo.setNickName(weiXinUser.getNickname());
               userInfo.setWxName(weiXinUser.getNickname());
               userInfo.setWxOpenId(weiXinUser.getOpenid());
               userInfo.setWxUnionId(weiXinUser.getUnionid());
               userInfo.setWxPic(weiXinUser.getHeadimgurl());
               userInfo.setLastLoginTime(System.currentTimeMillis());
               userInfo.setLoginType(loginType);
               userInfo.setLastLoginIp(request.getRemoteHost());
               addUser(userInfo);
               return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
            } else {
               // 本会话采用过其他账号登录
               if (userInfo != null)// 微信账号存在
               {
                  if (lastUser.getLoginType() == 2) {
                     session.removeAttribute("LAST_LOGIN_USER");
                     throw new UserAccountException(1002, "微信不能绑定微信");
                  }
                  if (lastUser.getLoginType() == 1 && !StringUtil.isNullOrEmpty(userInfo.getOpenid())) {
                     session.removeAttribute("LAST_LOGIN_USER");
                     throw new UserAccountException(1003, "该微信已经绑定了淘宝账号,请先解绑");
                  }
                  if (lastUser.getLoginType() == 3 && !StringUtil.isNullOrEmpty(userInfo.getPhone())) {
                     session.removeAttribute("LAST_LOGIN_USER");
                     throw new UserAccountException(1003, "该微信已经绑定了电话号码,请先解绑");
                  }
                  // 删除邀请图片
                  spreadUserImgService.deleteImgUrl(userInfo.getId());
                  // 还没有绑定同类型的账号
                  // 两个账号没有同时有独立的UID
                  if (lastUser.getId() == null || lastUser.getId() == 0
                        || lastUser.getId() == userInfo.getId().longValue()) {
                     // 绑定关系
                     UserInfo updateUserInfo = new UserInfo(userInfo.getId());
                     if (!StringUtil.isNullOrEmpty(lastUser.getPhone())) {
                        updateUserInfo.setPhone(lastUser.getPhone());
                        userAccountMsgNotificationService.bindingSuccess(userInfo.getId(),
                              MsgAccountDetailFactory.TYPE_PHONE);
                     }
                     if (!StringUtil.isNullOrEmpty(lastUser.getOpenid())) {
                        updateUserInfo.setOpenid(lastUser.getOpenid());
                        updateUserInfo.setTbName(lastUser.getTbName());
                        updateUserInfo.setTbPic(lastUser.getTbPic());
                        userAccountMsgNotificationService.bindingSuccess(userInfo.getId(),
                              MsgAccountDetailFactory.TYPE_TB);
                     }
                     updateUserInfo.setLastLoginTime(System.currentTimeMillis());
                     userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
                     session.removeAttribute("LAST_LOGIN_USER");
                     // 使分销关系生效
                     threeSaleSerivce.effective(userInfo);
                     return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                  } else {// 两个账号拥有不同的UID
                     // 询问是否打通
                     // 暂存微信账号
                     // session.setAttribute("WEIXIN_USERINFO",
                     // userInfo);
                     session.removeAttribute("LAST_LOGIN_USER");
                     LoginResult result = new LoginResult(LoginResult.TYPE_CONNECT, lastUser);
                     result.setMainUser(userInfo);
                     result.setLessUser(lastUser);
                     // 使分销关系生效
                     threeSaleSerivce.effective(userInfo);
                     return result;
                  }
               } else {// 微信账号不存在
                  // 创建账号,绑定账号
                  userInfo = new UserInfo();
                  userInfo.setPortrait(weiXinUser.getHeadimgurl());
                  userInfo.setAppId(appId);
                  userInfo.setNickName(weiXinUser.getNickname());
                  userInfo.setWxName(weiXinUser.getNickname());
                  userInfo.setWxOpenId(weiXinUser.getOpenid());
                  userInfo.setWxUnionId(weiXinUser.getUnionid());
                  userInfo.setWxPic(weiXinUser.getHeadimgurl());
                  if (!StringUtil.isNullOrEmpty(lastUser.getPhone()))
                     userInfo.setPhone(lastUser.getPhone());
                  if (!StringUtil.isNullOrEmpty(lastUser.getOpenid())) {
                     userInfo.setOpenid(lastUser.getOpenid());
                     userInfo.setTbName(lastUser.getTbName());
                     userInfo.setTbPic(lastUser.getTbPic());
                  }
                  userInfo.setLastLoginTime(System.currentTimeMillis());
                  userInfo.setLoginType(loginType);
                  userInfo.setLastLoginIp(request.getRemoteHost());
                  addUser(userInfo);
                  session.removeAttribute("LAST_LOGIN_USER");
                  return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
               }
            }
         case 3:// 手机号码
               // 判断手机号码是否被封禁
            ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                  .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
            if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
               throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
            userInfo = getUserInfoByPhone(appId, phone);
            // 判断用户是否被删除
            if (userInfo != null && userInfo.getState() != null
                  && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
                        || userInfo.getState() == UserInfo.STATE_DELETE))
               userInfo = null;
            if (userInfo == null) {// 原先的账号不存在
               userInfo = new UserInfo();
               userInfo.setAppId(appId);
               userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
               userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
               userInfo.setPhone(phone);
               userInfo.setLoginType(loginType);
               session.setAttribute("LAST_LOGIN_USER", userInfo);
               // 询问是否绑定微信
               return new LoginResult(LoginResult.TYPE_WX, userInfo);
            } else {// 原先的账号存在
               // 判定是否绑定了微信
               if (StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {// 没有绑定微信
                  userInfo.setLoginType(loginType);
                  session.setAttribute("LAST_LOGIN_USER", userInfo);
                  // 需要微信登录
                  return new LoginResult(LoginResult.TYPE_WX, userInfo);
               } else {// 绑定了微信
                  updateLatestLoginTime(userInfo.getId());
                  return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
               }
            }
         default:
            return null;
         }
      } else {// 没有安装微信
         LoginResult result = loginNoInstallWX(acceptData, appId, code, phone, tbUserInfo, loginType);
         if (result.getType() == LoginResult.TYPE_CREATE)
            session.setAttribute("LAST_LOGIN_USER", result.getUser());
         return result;
      }
   }
   @Transactional
   @Override
   public LoginResult loginNoInstallWX(AcceptData acceptData, String appId, String code, String phone,
         UserInfo tbUserInfo, int loginType) throws UserAccountException {
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
      logInfo.put("code", code);
      logInfo.put("phone", phone);
      if (tbUserInfo != null)
         logInfo.put("tbUserInfo", tbUserInfo.getId());
      logInfo.put("loginType", loginType);
      LogHelper.lgoinInfo(logInfo.toString());
      UserInfo userInfo = null;
      WeiXinUser weiXinUser = null;
      switch (loginType) {
      case 1:// 淘宝
         if (!StringUtil.isNullOrEmpty(tbUserInfo.getTaoBaoUid())) {
            ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                  ForbiddenUserIdentifyCodeTypeEnum.taobaoUid, tbUserInfo.getTaoBaoUid());
            if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
               throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
         }
         userInfo = getUserInfoByTaoBaoOpenId(appId, tbUserInfo.getOpenid());
         break;
      case 2:// 微信
            // 通过Code换取信息
         WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
         weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
               wxAccount.getAppSecret());
         if (weiXinUser == null)
            throw new UserAccountException(1001, "无法获取到微信个人信息");
         // 判断是否被封禁
         ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
               .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
         if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
         userInfo = getUserInfoByWXUnionId(appId, weiXinUser.getUnionid());
         break;
      case 3:// 手机号码
            // 判断是否被封禁
         ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
               .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
         if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
         userInfo = getUserInfoByPhone(appId, phone);
         break;
      }
      // 判断用户是否被删除
      if (userInfo != null && userInfo.getState() != null && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
            || userInfo.getState() == UserInfo.STATE_DELETE))
         userInfo = null;
      if (userInfo != null) {
         UserInfo updateUserInfo = new UserInfo(userInfo.getId());
         updateUserInfo.setLastLoginTime(System.currentTimeMillis());
         userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
         return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
      } else {// 询问是否创建用户
         userInfo = new UserInfo();
         userInfo.setAppId(appId);
         switch (loginType) {
         case 1:// 淘宝
            userInfo.setTbName(tbUserInfo.getNickName());
            userInfo.setTbPic(tbUserInfo.getPortrait());
            userInfo.setNickName(tbUserInfo.getNickName());
            userInfo.setPortrait(tbUserInfo.getPortrait());
            break;
         case 2:// 微信
            userInfo.setPortrait(weiXinUser.getHeadimgurl());
            userInfo.setNickName(weiXinUser.getNickname());
            userInfo.setWxName(weiXinUser.getNickname());
            userInfo.setWxOpenId(weiXinUser.getOpenid());
            userInfo.setWxUnionId(weiXinUser.getUnionid());
            userInfo.setWxPic(weiXinUser.getHeadimgurl());
            break;
         case 3:// 手机号码
               // 默认头像与昵称
            userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
            userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
            userInfo.setPhone(phone);
            break;
         }
         return new LoginResult(LoginResult.TYPE_CREATE, userInfo);
      }
   }
   @Override
   public void connectUsers(HttpSession session) throws UserAccountException {
      UserInfo mainUser = (UserInfo) session.getAttribute("WEIXIN_USERINFO");
      UserInfo lessUser = (UserInfo) session.getAttribute("LAST_LOGIN_USER");
      int lessUserLoginType = lessUser.getLoginType();
      if (mainUser == null || lessUser == null || mainUser.getId() == null || lessUser.getId() == null)
         throw new UserAccountException(30001, "缺少打通账号");
      mainUser = userInfoMapper.selectByPrimaryKeyForUpdate(mainUser.getId());
      lessUser = userInfoMapper.selectByPrimaryKeyForUpdate(lessUser.getId());
      session.removeAttribute("WEIXIN_USERINFO");
      session.removeAttribute("LAST_LOGIN_USER");
      if (mainUser == null || lessUser == null)
         throw new UserAccountException(30002, "缺少打通账号");
      // 判断是否有绑定相同类型的账号
      if (lessUserLoginType == 1) {// 次账号以淘宝登录
         if (!StringUtil.isNullOrEmpty(mainUser.getPhone()) && !StringUtil.isNullOrEmpty(lessUser.getPhone())
               && !lessUser.getPhone().equalsIgnoreCase(mainUser.getPhone()))
            throw new UserAccountException(30003, "请先解除其中一个账号的手机绑定");
      } else if (lessUserLoginType == 3) {// 次账号以手机号登录
         if (!StringUtil.isNullOrEmpty(mainUser.getOpenid()) && !StringUtil.isNullOrEmpty(lessUser.getOpenid())
               && !lessUser.getOpenid().equalsIgnoreCase(mainUser.getOpenid()))
            throw new UserAccountException(30003, "请先解除其中一个账号的淘宝绑定");
      }
      connectUsers(mainUser, lessUser);
   }
   @Transactional
   @Override
   public void connectUsers(UserInfo mainUser, UserInfo lessUser) throws UserAccountException {
      mainUser = userInfoMapper.selectByPrimaryKeyForUpdate(mainUser.getId());
      lessUser = userInfoMapper.selectByPrimaryKeyForUpdate(lessUser.getId());
      if (!StringUtil.isNullOrEmpty(mainUser.getOpenid()) && !StringUtil.isNullOrEmpty(lessUser.getOpenid()))
         throw new UserAccountException(9, "两个账号都绑定了淘宝,请解绑其中一个");
      if (!StringUtil.isNullOrEmpty(mainUser.getPhone()) && !StringUtil.isNullOrEmpty(lessUser.getPhone()))
         throw new UserAccountException(9, "两个账号都绑定了手机号码,请解绑其中一个");
      if (lessUser.getMyHongBao().compareTo(new BigDecimal("10")) >= 0
            && mainUser.getMyHongBao().compareTo(new BigDecimal("10")) > 0)
         throw new UserAccountException(10, String.format("账户ID:%s 的资金超过10元,为保证资金安全请联系客服打通", lessUser.getId() + ""));
      // 判定是否绑定了同一支付宝
      BindingAccount mainUserAccount = bindingAccountService.getBindingAccountByUidAndType(mainUser.getId(),
            BindingAccount.TYPE_ALIPAY);
      BindingAccount lessUserAccount = bindingAccountService.getBindingAccountByUidAndType(lessUser.getId(),
            BindingAccount.TYPE_ALIPAY);
      // 有不同的支付宝账号
      boolean hasDiffrentAlipayAccount = false;
      if (mainUserAccount != null && lessUserAccount != null) {
         if (!mainUserAccount.getAccount().equalsIgnoreCase(lessUserAccount.getAccount()))
            hasDiffrentAlipayAccount = true;
      }
      if (hasDiffrentAlipayAccount)
         throw new UserAccountException(10, "两个账户都绑定了支付宝,请先解绑其中一个");
      // 判定是否有重叠的账号
      UserInfo updateUser = new UserInfo(mainUser.getId());
      if (!StringUtil.isNullOrEmpty(lessUser.getOpenid())) {
         updateUser.setOpenid(lessUser.getOpenid());
         updateUser.setTbName(lessUser.getTbName());
         updateUser.setTbPic(lessUser.getTbPic());
      }
      if (!StringUtil.isNullOrEmpty(lessUser.getPhone())) {
         updateUser.setPhone(lessUser.getPhone());
      }
      // 备份原来的用户信息
      String logUrl = backupUserImportantInfo(lessUser.getId());
      // 添加打通记录
      UserConnectHistory userConnectHistory = new UserConnectHistory();
      userConnectHistory.setCreateTime(new Date());
      userConnectHistory.setLessUser(lessUser);
      userConnectHistory.setMainUser(mainUser);
      userConnectHistory.setLogUrl(logUrl);
      userConnectHistoryMapper.insertSelective(userConnectHistory);
      userInfoMapper.updateByPrimaryKeySelective(updateUser);
      // 删除原来的账号
      UserInfo updateLessUser = new UserInfo(lessUser.getId());
      updateLessUser.setState(UserInfo.STATE_DELETE);
      updateLessUser.setStateDesc("账号被打通删除");
      userInfoMapper.updateByPrimaryKeySelective(updateLessUser);
      // 融合业务
      userInfoMapper.connectUser(mainUser.getId(), lessUser.getId());
      // 查询是否有多余的新人红包
      int subCount = 0;
      int addCount = 0;
      userAccountMsgNotificationService.connectSuccess(mainUser.getId(), lessUser.getId());
      userInfoDeleteRecordService.addDeleteRecord(lessUser.getId(), UserInfo.STATE_DELETE, "删除:账号被打通删除");
   }
   /**
    * 根据系统与unionid寻找用户
    *
    * @param appId
    * @param unionId
    * @return
    */
   @Override
   public UserInfo getUserInfoByWXUnionId(String appId, String unionId) throws UserAccountException {
      if (StringUtil.isNullOrEmpty(appId))
         throw new UserAccountException(1, "appId为空");
      if (StringUtil.isNullOrEmpty(unionId))
         throw new UserAccountException(2, "unionId为空");
      List<UserInfo> list = userInfoMapper.listByAppIdAndWXUnionId(appId, unionId);
      // 剔除被删除掉的用户
      for (int i = 0; i < list.size(); i++) {
         if (list.get(i).getState() == UserInfo.STATE_DELETE
               || list.get(i).getState() == UserInfo.STATE_DELETE_OUT_OF_DATE) {
            list.remove(i);
            i--;
         }
      }
      if (list.size() > 0)
         return list.get(list.size() - 1);
      else
         return null;
   }
   /**
    * 根据系统和淘宝的Openid寻找用户
    *
    * @param appId
    * @param openId
    * @return
    */
   public UserInfo getUserInfoByTaoBaoOpenId(String appId, String openId) throws UserAccountException {
      if (StringUtil.isNullOrEmpty(appId))
         throw new UserAccountException(1, "appId为空");
      if (StringUtil.isNullOrEmpty(openId))
         throw new UserAccountException(2, "openId为空");
      List<UserInfo> list = userInfoMapper.listByAppIdAndTaoBaoOpenId(appId, openId);
      // 剔除被删除掉的用户
      for (int i = 0; i < list.size(); i++) {
         if (list.get(i).getState() == UserInfo.STATE_DELETE
               || list.get(i).getState() == UserInfo.STATE_DELETE_OUT_OF_DATE) {
            list.remove(i);
            i--;
         }
      }
      if (list.size() > 0)
         return list.get(list.size() - 1);
      else
         return null;
   }
   /**
    * 根据系统和电话号码寻找用户
    *
    * @param appId
    * @param phone
    * @return
    */
   public UserInfo getUserInfoByPhone(String appId, String phone) throws UserAccountException {
      if (StringUtil.isNullOrEmpty(appId))
         throw new UserAccountException(1, "appId为空");
      if (StringUtil.isNullOrEmpty(phone))
         throw new UserAccountException(2, "phone为空");
      List<UserInfo> list = userInfoMapper.listByAppIdAndPhone(appId, phone);
      // 剔除被删除掉的用户
      for (int i = 0; i < list.size(); i++) {
         if (list.get(i).getState() == UserInfo.STATE_DELETE
               || list.get(i).getState() == UserInfo.STATE_DELETE_OUT_OF_DATE) {
            list.remove(i);
            i--;
         }
      }
      if (list.size() > 0)
         return list.get(list.size() - 1);
      else
         return null;
   }
   private void updateLatestLoginTime(Long uid) {
      UserInfo userInfo = new UserInfo(uid);
      userInfo.setLastLoginTime(System.currentTimeMillis());
      userInfoMapper.updateByPrimaryKeySelective(userInfo);
   }
   @Override
   public void register(UserInfo userInfo) throws UserAccountException {
      if (!StringUtil.isNullOrEmpty(userInfo.getPhone())) {
         UserInfo user = getUserInfoByPhone(userInfo.getAppId(), userInfo.getPhone());
         if (user != null)
            throw new UserAccountException(50001, "电话号码已经被绑定");
      }
      if (!StringUtil.isNullOrEmpty(userInfo.getOpenid())) {
         UserInfo user = getUserInfoByTaoBaoOpenId(userInfo.getAppId(), userInfo.getOpenid());
         if (user != null)
            throw new UserAccountException(50002, "淘宝号已经被绑定");
      }
      if (!StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {
         UserInfo user = getUserInfoByWXUnionId(userInfo.getAppId(), userInfo.getWxUnionId());
         if (user != null)
            throw new UserAccountException(50003, "微信号已经被注册");
      }
      addUser(userInfo);
   }
   @Override
   public void addUser(UserInfo user) {
      Long maxUid = userInfoMapper.getMaxUid();
      if (maxUid == null)
         maxUid = 100000L;
      long dd = (long) (Math.random() * 100);
      if (dd == 0) {
         dd = 1;
      }
      long uid = maxUid + dd;
      user.setId(uid);
      user.setCreatetime(System.currentTimeMillis());
      user.setRank(0);
      if (StringUtil.isNullOrEmpty(user.getPortrait()))
         user.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
      userInfoMapper.insertSelective(user);
      // 昵称为空时 默认昵称
      if (StringUtil.isNullOrEmpty(user.getNickName())) {
         UserInfo updateUserInfo = new UserInfo(user.getId());
         updateUserInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName() + user.getId());
         userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
      }
      try {
         // 第一次登录时创建用户额外信息
         userInfoExtraService.createUserInfoExtra(user.getId());
      } catch (Exception e) {
         e.printStackTrace();
      }
      if (!StringUtil.isNullOrEmpty(user.getPhone()))
         userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, user.getPhone());
      if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
         userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, user.getWxUnionId());
   }
   @Override
   public void updateUserSelective(UserInfo user) {
      userInfoMapper.updateByPrimaryKeySelective(user);
   }
   @Override
   public void bindPhone(Long uid, String phone) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      if (!StringUtil.isNullOrEmpty(user.getPhone()))
         throw new UserAccountException(5, "当前账号已经绑定了手机号,请先解绑");
      UserInfo phoneUser = getUserInfoByPhone(user.getAppId(), phone);
      if (phoneUser != null)
         throw new UserAccountException(6, "当前电话号码已经被绑定");
      UserInfo update = new UserInfo(user.getId());
      update.setPhone(phone);
      userInfoMapper.updateByPrimaryKeySelective(update);
      userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
      userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
   }
   @Override
   public void unBindPhone(Long uid, String phone) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      if (StringUtil.isNullOrEmpty(user.getPhone()))
         throw new UserAccountException(4, "尚未绑定电话号码");
      if (!user.getPhone().equalsIgnoreCase(phone))
         throw new UserAccountException(4, "原绑定手机号输入错误");
      if (StringUtil.isNullOrEmpty(user.getWxUnionId()) && StringUtil.isNullOrEmpty(user.getOpenid()))
         throw new UserAccountException(5, "不能解除绑定");
      UserInfo updateUserInfo = new UserInfo(uid);
      updateUserInfo.setPhone("");
      userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
      userAccountMsgNotificationService.unBindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
   }
   @Override
   public void bindTaoBao(Long uid, String tbOpenId, String tbNickName, String tbPortrait)
         throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      if (!StringUtil.isNullOrEmpty(user.getOpenid()) && !user.getOpenid().equalsIgnoreCase(tbOpenId))
         throw new UserAccountException(5, "当前账号已经绑定了淘宝,请先解绑");
      // 绑定同一个淘宝号
      if (!StringUtil.isNullOrEmpty(user.getOpenid()) && user.getOpenid().equalsIgnoreCase(tbOpenId))
         return;
      UserInfo taoBaoUser = getUserInfoByTaoBaoOpenId(user.getAppId(), tbOpenId);
      if (taoBaoUser != null)
         throw new UserAccountException(6, "当前淘宝号已经被绑定");
      UserInfo update = new UserInfo(user.getId());
      update.setOpenid(tbOpenId);
      update.setTbName(tbNickName);
      update.setTbPic(tbPortrait);
      // 如果没有绑定微信就以淘宝的头像和昵称作为用户的头像与昵称
      if (StringUtil.isNullOrEmpty(user.getWxUnionId())) {
         update.setNickName(tbNickName);
         update.setPortrait(tbPortrait);
      }
      userInfoMapper.updateByPrimaryKeySelective(update);
      userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_TB);
   }
   @Override
   public void unBindTaoBao(Long uid) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      if (StringUtil.isNullOrEmpty(user.getOpenid()))
         throw new UserAccountException(5, "当前账号尚未绑定淘宝");
      if (StringUtil.isNullOrEmpty(user.getWxUnionId()) && StringUtil.isNullOrEmpty(user.getPhone()))
         throw new UserAccountException(5, "不能接触绑定");
      UserInfo update = new UserInfo(user.getId());
      update.setOpenid("");
      update.setTbName("");
      update.setTbPic("");
      // 判断是否有微信绑定
      if (StringUtil.isNullOrEmpty(user.getWxUnionId())) {
         update.setNickName(Constant.systemCommonConfig.getDefaultNickName() + user.getId());
         update.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
      }
      userInfoMapper.updateByPrimaryKeySelective(update);
      userExtraTaoBaoInfoService.unBindUid(uid);
      userAccountMsgNotificationService.unBindingSuccess(uid, MsgAccountDetailFactory.TYPE_TB);
   }
   @Override
   public void changeWXBind(AcceptData acceptData, Long uid, String code) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
            wxAccount.getAppSecret());
      if (weiXinUser == null)
         throw new UserAccountException(10, "获取微信用户信息失败");
      if (weiXinUser.getUnionid().equalsIgnoreCase(user.getWxUnionId()))
         throw new UserAccountException(12, "亲,请登录其它微信号进行更换绑定");
      UserInfo newUser = getUserInfoByWXUnionId(user.getAppId(), weiXinUser.getUnionid());
      if (newUser != null)
         throw new UserAccountException(13, "该微信号已被其他账号绑定");
      UserInfo updateUserInfo = new UserInfo(uid);
      updateUserInfo.setWxName(weiXinUser.getNickname());
      updateUserInfo.setWxOpenId(weiXinUser.getOpenid());
      updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
      updateUserInfo.setWxUnionId(weiXinUser.getUnionid());
      // 将默认昵称替换成微信昵称
      String defaultNickName = Constant.systemCommonConfig.getDefaultNickName();
      if (!StringUtil.isNullOrEmpty(defaultNickName) && !StringUtil.isNullOrEmpty(weiXinUser.getNickname())) {
         defaultNickName = defaultNickName + uid;
         if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
            updateUserInfo.setNickName(weiXinUser.getNickname());
         }
      }
      // 将默认头像替换成微信头像
      String defaultPortrait = Constant.systemCommonConfig.getDefaultPortrait();
      if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()) && !StringUtil.isNullOrEmpty(defaultPortrait)
            && defaultPortrait.equals(user.getPortrait())) {
         updateUserInfo.setPortrait(weiXinUser.getHeadimgurl());
      }
      userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
      userAccountMsgNotificationService.changeBindingSuccess(uid, MsgAccountDetailFactory.TYPE_WX);
      userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, weiXinUser.getUnionid());
   }
   @Override
   public String backupUserImportantInfo(Long uid) {
      String logPath = String.format(FileUtil.getCacheDir() + "/benfen_%s_" + uid + ".log",
            TimeUtil.getGernalTime(System.currentTimeMillis(), "yyyyMMddHHmmss"));
      // 备份用户信息
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      // TODO 备份资金明细
      // 备份邀请关系
      List<ThreeSale> threeSaleList = new ArrayList<>();
      FileWriter fw = null;
      try {
         // 设置为:True,表示写入的时候追加数据
         fw = new FileWriter(new File(logPath), true);
         fw.write("#UserInfo" + "\r\n");
         fw.write(JsonUtil.getSimpleGsonWithDate().toJson(user) + "\r\n");
         fw.write("#ThreeSale" + "\r\n");
         fw.write(JsonUtil.getSimpleGsonWithDate().toJson(threeSaleList) + "\r\n");
         fw.close();
         String logUrl = COSManager.getInstance()
               .uploadFile(new File(logPath), "beifen/" + new File(logPath).getName()).getUrl();
         return logUrl;
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
         if (new File(logPath).exists())
            new File(logPath).delete();
      }
      return null;
   }
   @Override
   public void clearUserPortrait(Long uid) {
      if (uid == null)
         return;
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      String prefix = String.format("/portrait/wx/%s_", user.getWxUnionId());
      ObjectListing list = COSManager.getInstance().getObjectList(prefix, null, 30);
      if (list != null && list.getObjectSummaries() != null)
         for (COSObjectSummary object : list.getObjectSummaries()) {
            if (user.getWxPic() != null && !user.getWxPic().contains(object.getKey())) {
               COSManager.getInstance().deleteFile(object.getKey());
            }
         }
   }
   @Override
   public String repairPortrait(Long uid) {
      if (uid == null)
         return null;
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         return null;
      String prefix = String.format("/portrait/wx/%s_", user.getWxUnionId());
      ObjectListing list = COSManager.getInstance().getObjectList(prefix, null, 30);
      // 查询头像文件是否还存在
      boolean exist = false;
      if (list != null && list.getObjectSummaries() != null)
         for (COSObjectSummary object : list.getObjectSummaries()) {
            if (user.getPortrait().contains(object.getKey())) {
               exist = true;
               break;
            }
         }
      if (!exist && list.getObjectSummaries() != null && list.getObjectSummaries().size() > 0) {
         COSObjectSummary object = list.getObjectSummaries().get(list.getObjectSummaries().size() - 1);
         String portrait = String.format("https://%s.file.myqcloud.com/%s", object.getBucketName(), object.getKey());
         if (!StringUtil.isNullOrEmpty(portrait)) {
            UserInfo updateUser = new UserInfo(uid);
            updateUser.setPortrait(portrait);
            userInfoMapper.updateByPrimaryKeySelective(updateUser);
            return portrait;
         }
      }
      return user.getPortrait();
   }
   @Transactional
   @Override
   public UserInfo loginPhone(HttpServletRequest request, int loginType, String vcode, String phone, String appId)
         throws UserAccountException {
      // 空额清理
      if (phone == null || phone.trim().length() == 0) {
         throw new UserAccountException(1, "请输入手机号码");
      }
      phone = phone.replaceAll(" ", "");
      // 苹果应用商店上线测试号码
      if ("17316780233".equalsIgnoreCase(phone) && "2581".equalsIgnoreCase(vcode)) {
         ;
      } else {
         if (StringUtil.isNullOrEmpty(vcode)) {
            throw new UserAccountException(1, "请输入验证码");
         }
         String oldVcode = redisManager.getSMSVCode(phone, SMSHistory.TYPE_LOGIN);
         LogHelper.test("----------------------登录验证码: " + oldVcode);
         if (!Constant.IS_TEST)
            if (StringUtil.isNullOrEmpty(oldVcode) || !oldVcode.equalsIgnoreCase(vcode)) {
               throw new UserAccountException(1, "验证码错误,重新输入");
            } else {// 验证码输入正确
               redisManager.clearSMSVCode(phone, SMSHistory.TYPE_LOGIN);
            }
      }
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
      logInfo.put("phone", phone);
      logInfo.put("loginType", loginType);
      LogHelper.lgoinInfo(logInfo.toString());
      // 判断手机号码是否被封禁
      ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
            .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
      if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective()) {
         throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
      }
      // 清空限制
      redisManager.clearSMSFrequencyLimit(phone, SMSHistory.TYPE_LOGIN);
      // 清理次数
      redisManager.removeCommonString("sendMSNLoginCount" + phone);
      // 采用redis事务防止一个手机号多次注册问题
      String watchKey = StringUtil.Md5("REGISTER:" + phone);
      Jedis jedis = jedisPool.getResource();
      try {
         jedis.watch(watchKey);
         if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
            throw new UserAccountException(10, "请稍后再试");
         Transaction tran = jedis.multi();
         tran.incr(watchKey);
         List<Object> exec = tran.exec();
         if (exec == null || exec.size() == 0) {
            throw new UserAccountException(10, "请稍后再试");
         } else {
            // 查询是否存在该电话历史用户
            UserInfo userInfo = userInfoMapper.getEffectiveUserInfoByPhone(phone);
            if (userInfo != null) {
               // 更新账户登录信息
               updateLonginInfo(userInfo, loginType, request);
            } else {
               userInfo = new UserInfo();
               userInfo.setAppId(appId);
               // userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
               userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
               userInfo.setPhone(phone);
               userInfo.setLoginType(loginType);
               userInfo.setState(UserInfo.STATE_NORMAL);
               // 创建用户
               addUser(userInfo);
               try {
                  // 第一次登录时创建用户额外信息
                  userInfoExtraService.createUserInfoExtra(userInfo.getId());
               } catch (Exception e) {
                  e.printStackTrace();
               }
               userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindPhone, phone);
            }
            return userInfo;
         }
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         jedis.del(watchKey);
         jedis.unwatch();
         jedisPool.returnResource(jedis);
      }
      throw new UserAccountException(10, "请稍后再试");
   }
   @Transactional
   @Override
   public UserInfo loginWinXin(HttpServletRequest request, AcceptData acceptData, int loginType, String code,
         String appId) throws UserAccountException {
      // 日志信息
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
      logInfo.put("code", code);
      logInfo.put("loginType", loginType);
      LogHelper.lgoinInfo(logInfo.toString());
      // 通过Code换取信息
      WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUser(code, wxAccount.getAppId(),
            wxAccount.getAppSecret());
      if (weiXinUser == null) {
         throw new UserAccountException(1, "微信帐号授权失败");
      }
      LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
      // 判断微信unionid是否被封禁
      ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
            .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
      if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective()) {
         throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
      }
      // 采用redis事务防止一个微信号多次注册问题
      String watchKey = StringUtil.Md5("REGISTER:" + weiXinUser.getUnionid());
      Jedis jedis = jedisPool.getResource();
      try {
         jedis.watch(watchKey);
         if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
            throw new UserAccountException(10, "请稍后再试");
         Transaction tran = jedis.multi();
         tran.incr(watchKey);
         List<Object> exec = tran.exec();
         if (exec == null || exec.size() == 0) {
            throw new UserAccountException(10, "请稍后再试");
         } else {
            UserInfo userInfo = userInfoMapper.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid());
            // 直接用的微信登录
            if (userInfo != null) {
               LogHelper.test("微信unionID存在:" + weiXinUser.getUnionid());
               // 更新账户登录信息
               updateLonginInfo(userInfo, loginType, request);
               // 删除邀请分享图
               spreadUserImgService.deleteImgUrl(userInfo.getId());
            } else {
               LogHelper.test("微信unionID不存在:" + weiXinUser.getUnionid());
               String portrait = null;
               if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl())) {
                  InputStream asInputStream = HttpUtil.getAsInputStream(weiXinUser.getHeadimgurl());
                  if (asInputStream != null) {
                     FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                           String.format("/portrait/wx/%s_%s.jpg", weiXinUser.getUnionid(), System.currentTimeMillis() + ""));
                     if (result != null && !StringUtil.isNullOrEmpty(result.getUrl()))
                        portrait = result.getUrl();
                  } else {
                     portrait = weiXinUser.getHeadimgurl();
                  }
               }
               if (StringUtil.isNullOrEmpty(portrait))
                  portrait = Constant.systemCommonConfig.getDefaultPortrait();
               // 创建新账户
               userInfo = new UserInfo();
               userInfo.setPortrait(portrait);
               userInfo.setAppId(appId);
               userInfo.setNickName(weiXinUser.getNickname());
               userInfo.setWxName(weiXinUser.getNickname());
               userInfo.setWxOpenId(weiXinUser.getOpenid());
               userInfo.setWxUnionId(weiXinUser.getUnionid());
               userInfo.setWxPic(weiXinUser.getHeadimgurl());
               userInfo.setLastLoginTime(System.currentTimeMillis());
               userInfo.setLoginType(loginType);
               userInfo.setLastLoginIp(request.getRemoteHost());
               userInfo.setState(UserInfo.STATE_NORMAL);
               addUser(userInfo);
               try {
                  // 第一次登录时创建用户额外信息
                  userInfoExtraService.createUserInfoExtra(userInfo.getId());
               } catch (Exception e) {
                  e.printStackTrace();
               }
               userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindWeiXin,
                     weiXinUser.getUnionid());
            }
            return userInfo;
         }
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         jedis.del(watchKey);
         jedis.unwatch();
         jedisPool.returnResource(jedis);
      }
      throw new UserAccountException(10, "请稍后再试");
   }
   @Transactional
   @Override
   public UserInfo loginWeiXinNew(HttpServletRequest request, AcceptData acceptData, int loginType, String wxCode, String appId) throws UserAccountException {
      // 日志信息
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
      logInfo.put("wxCode", wxCode);
      logInfo.put("loginType", loginType);
      LogHelper.lgoinInfo(logInfo.toString());
      // 通过Code换取信息
      WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUser(wxCode, wxAccount.getAppId(),
            wxAccount.getAppSecret());
      if (weiXinUser == null) {
         throw new UserAccountException(1, "微信帐号授权失败");
      }
      LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
      // 判断微信unionid是否被封禁
      ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
            .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
      if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective()) {
         throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
      }
      UserInfo userInfo = userInfoMapper.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid());
      if (userInfo == null) {
         String longinKey = StringUtil.Md5("WXLogin:" + weiXinUser.getUnionid());
         redisManager.cacheCommonString(longinKey, JsonUtil.getSimpleGson().toJson(weiXinUser), 60 * 20);
         throw new UserAccountException(101, longinKey);
      }
      // 更新账户登录信息
      updateLonginInfo(userInfo, loginType, request);
      Long uid = userInfo.getId();
      ThreadUtil.run(new Runnable() {
         public void run() {
            // 删除邀请分享图
            spreadUserImgService.deleteImgUrl(uid);
         }
      });
      return userInfo;
   }
   /**
    * 更新账户登录信息
    *
    * @param userInfo
    * @param loginType
    * @param request
    */
   public void updateLonginInfo(UserInfo userInfo, int loginType, HttpServletRequest request) {
      // 设置登录时间与登录类型
      UserInfo updateUserInfo = new UserInfo(userInfo.getId());
      updateUserInfo.setLastLoginTime(System.currentTimeMillis());
      updateUserInfo.setLoginType(loginType);
      updateUserInfo.setLastLoginIp(request.getRemoteHost());
      userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
   }
   @Override
   public void bindPhoneNew(Long uid, String phone) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null) {
         throw new UserAccountException(1, "用户不存在");
      }
      String hasPhone = user.getPhone();
      if (!StringUtil.isNullOrEmpty(hasPhone) && hasPhone.equals(phone)) {
         throw new UserAccountException(2, "您已经绑定了该电话号码");
      }
      UserInfo phoneUser = userInfoMapper.getEffectiveUserInfoByPhone(phone);
      if (phoneUser != null) {
         throw new UserAccountException(2, "号码已经被占用");
      }
      // 更新电话号码
      UserInfo update = new UserInfo(user.getId());
      update.setPhone(phone);
      userInfoMapper.updateByPrimaryKeySelective(update);
      // 加入绑定记录
      UserAccountBindingHistory history = new UserAccountBindingHistory();
      history.setContent(phone);
      history.setType(UserAccountBindingHistory.TYPE_PHONE);
      history.setUid(uid);
      // 之前已经绑定电话号码
      if (!StringUtil.isNullOrEmpty(user.getPhone()))
         history.setFirst(false);
      else
         history.setFirst(true);
      userAccountBindingHistoryService.addUserAccountBindingHistory(history);
      // 发送消息
      userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
      userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
   }
   @Override
   public void bindWeiXin(AcceptData acceptData, Long uid, String code) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null) {
         throw new UserAccountException(1, "用户不存在");
      }
      WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUser(code, wxAccount.getAppId(),
            wxAccount.getAppSecret());
      if (weiXinUser == null) {
         throw new UserAccountException(2, "微信帐号授权失败");
      }
      String wxUnionId = weiXinUser.getUnionid();
      if (StringUtil.isNullOrEmpty(wxUnionId)) {
         throw new UserAccountException(2, "微信帐号授权失败");
      }
      String wxUnionIdExist = user.getWxUnionId();
      if (StringUtil.isNullOrEmpty(wxUnionIdExist)) {
         UserInfo newUser = userInfoMapper.getEffectiveUserInfoByWXUnionId(wxUnionId);
         if (newUser != null) {
            throw new UserAccountException(4, "该微信号已被其他帐号绑定");
         }
      } else if (wxUnionId.equalsIgnoreCase(wxUnionIdExist)) {
         throw new UserAccountException(3, "微信帐号一致无需更换");
      }
      if (StringUtil.isNullOrEmpty(user.getPhone())) {
         throw new UserAccountException(5, "该帐号没有绑定手机号码,需绑定手机号码才能完成微信更换");
      }
      UserInfo updateUserInfo = new UserInfo(uid);
      updateUserInfo.setWxName(weiXinUser.getNickname());
      updateUserInfo.setWxOpenId(weiXinUser.getOpenid());
      updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
      updateUserInfo.setWxUnionId(weiXinUser.getUnionid());
      // 将默认昵称替换成微信昵称
      String defaultNickName = Constant.systemCommonConfig.getDefaultNickName();
      if (!StringUtil.isNullOrEmpty(defaultNickName) && !StringUtil.isNullOrEmpty(weiXinUser.getNickname())) {
         defaultNickName = defaultNickName + uid;
         if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
            updateUserInfo.setNickName(weiXinUser.getNickname());
         }
      }
      // 将默认头像替换成微信头像
      String defaultPortrait = Constant.systemCommonConfig.getDefaultPortrait();
      if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()) && !StringUtil.isNullOrEmpty(defaultPortrait)
            && defaultPortrait.equals(user.getPortrait())) {
         String headimgurl = weiXinUser.getHeadimgurl();
         InputStream asInputStream = HttpUtil.getAsInputStream(headimgurl);
         if (asInputStream == null) {
            LogHelper.test("微信头像下载失败: " +weiXinUser.getUnionid()+ " " + headimgurl);
         } else {
            FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                  String.format("/portrait/wx/%s_%s.jpg", weiXinUser.getUnionid(), System.currentTimeMillis() + ""));
            if (result != null && !StringUtil.isNullOrEmpty(result.getUrl())) {
               headimgurl = result.getUrl();
            } else {
               LogHelper.test("微信头像上传失败: " +weiXinUser.getUnionid()+ " " + headimgurl);
            }
         }
         updateUserInfo.setPortrait(headimgurl);
      }
      userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
      // 加入绑定记录
      UserAccountBindingHistory history = new UserAccountBindingHistory();
      history.setContent(weiXinUser.getUnionid());
      history.setType(UserAccountBindingHistory.TYPE_WX);
      history.setUid(uid);
      // 之前已经绑定电话号码
      if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
         history.setFirst(false);
      else
         history.setFirst(true);
      userAccountBindingHistoryService.addUserAccountBindingHistory(history);
      userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_WX);
      userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, wxUnionId);
   }
   @Override
   public UserInfo bindPhoneToLogin(String phone, String key, String appId, HttpServletRequest request) throws UserAccountException {
      UserInfo phoneUser = userInfoMapper.getEffectiveUserInfoByPhone(phone);
      if (phoneUser != null)
         throw new UserAccountException(1, "号码已经被占用");
      // 判断手机号码是否被封禁
      ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
            .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
      if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
         throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
      String value = redisManager.getCommonString(key);
      if (StringUtil.isNullOrEmpty(value))
         throw new UserAccountException(1, "微信授权失效,请使用微信重新登录");
      WeiXinUser weiXinUser = JsonUtil.getSimpleGson().fromJson(value, WeiXinUser.class);
      if (weiXinUser == null)
         throw new UserAccountException(1, "微信授权失效,请使用微信重新登录");
      UserInfo userInfo = userInfoMapper.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid());
      // 直接用的微信登录
      if (userInfo != null)
         throw new UserAccountException(10, "该微信号已被占用");
      String portrait = null;
      if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl())) {
         InputStream asInputStream = HttpUtil.getAsInputStream(weiXinUser.getHeadimgurl());
         if (asInputStream != null) {
            FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                  String.format("/portrait/wx/%s_%s.jpg", weiXinUser.getUnionid(), System.currentTimeMillis() + ""));
            if (result != null && !StringUtil.isNullOrEmpty(result.getUrl()))
               portrait = result.getUrl();
         } else {
            portrait = weiXinUser.getHeadimgurl();
         }
      }
      if (StringUtil.isNullOrEmpty(portrait))
         portrait = Constant.systemCommonConfig.getDefaultPortrait();
      // 创建新账户
      userInfo = new UserInfo();
      userInfo.setPhone(phone);
      userInfo.setPortrait(portrait);
      userInfo.setAppId(appId);
      userInfo.setNickName(weiXinUser.getNickname());
      userInfo.setWxName(weiXinUser.getNickname());
      userInfo.setWxOpenId(weiXinUser.getOpenid());
      userInfo.setWxUnionId(weiXinUser.getUnionid());
      userInfo.setWxPic(weiXinUser.getHeadimgurl());
      userInfo.setLastLoginTime(System.currentTimeMillis());
      userInfo.setLoginType(2);
      userInfo.setLastLoginIp(request.getRemoteHost());
      userInfo.setState(UserInfo.STATE_NORMAL);
      addUser(userInfo);
      Long uid = userInfo.getId();
      ThreadUtil.run(new Runnable() {
         public void run() {
            try {
               // 第一次登录时创建用户额外信息
               userInfoExtraService.createUserInfoExtra(uid);
            } catch (Exception e) {
               e.printStackTrace();
            }
            // 加入绑定记录
            UserAccountBindingHistory history = new UserAccountBindingHistory();
            history.setContent(phone);
            history.setType(UserAccountBindingHistory.TYPE_PHONE);
            history.setUid(uid);
            history.setFirst(true);
            userAccountBindingHistoryService.addUserAccountBindingHistory(history);
            userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
            userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin,   weiXinUser.getUnionid());
         }
      });
      // 删除缓存
      redisManager.removeCommonString(key);
      return userInfo;
   }
   @Override
   public void forbiddenUserAll(Long uid, String reason) {
      UserInfo currentInfo = userInfoService.selectByPKey(uid);
      if (currentInfo == null) {
         return;
      }
      if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
         return;
      }
      currentInfo.setState(UserInfo.STATE_FORBIDDEN);
      currentInfo.setStateDesc(reason);
      userInfoService.updateByPrimaryKeySelective(currentInfo);
      // 插入记录
      userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_FORBIDDEN, reason);
      // 加入封禁的账号列表
      ForbiddenUserIdentifyCode forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
      forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId);
      forbiddenUserIdentifyCode.setIdentifyCode(currentInfo.getWxUnionId());
      forbiddenUserIdentifyCode.setBeiZhu(currentInfo.getWxName());
      try {
         forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
      } catch (ForbiddenUserIdentifyCodeException e) {
         e.printStackTrace();
      }
      // 电话号码
      forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
      forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.phone);
      forbiddenUserIdentifyCode.setIdentifyCode(currentInfo.getPhone());
      try {
         forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
      } catch (ForbiddenUserIdentifyCodeException e) {
         e.printStackTrace();
      }
      // 淘宝
      UserExtraTaoBaoInfo taoBao = userExtraTaoBaoInfoService.getByUid(uid);
      if (taoBao != null && !StringUtil.isNullOrEmpty(taoBao.getTaoBaoUid())) {
         forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
         forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.taobaoUid);
         forbiddenUserIdentifyCode.setIdentifyCode(taoBao.getTaoBaoUid());
         try {
            forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
         } catch (ForbiddenUserIdentifyCodeException e) {
            e.printStackTrace();
         }
      }
      // 查询支付宝绑定
      List<BindingAccount> list = bindingAccountService.getBindingAccountByUid(uid);
      if (list != null) {
         for (BindingAccount ba : list) {
            forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
            forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.alipayAccount);
            forbiddenUserIdentifyCode.setIdentifyCode(ba.getAccount());
            forbiddenUserIdentifyCode.setBeiZhu(ba.getName());
            try {
               forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
            } catch (ForbiddenUserIdentifyCodeException e) {
               e.printStackTrace();
            }
         }
      }
   }
   @Override
   public void forbiddenUser(Long uid, String reason) {
      UserInfo currentInfo = userInfoService.selectByPKey(uid);
      if (currentInfo == null) {
         return;
      }
      if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
         return;
      }
      currentInfo.setState(UserInfo.STATE_FORBIDDEN);
      currentInfo.setStateDesc(reason);
      userInfoService.updateByPrimaryKeySelective(currentInfo);
      // 插入记录
      userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_FORBIDDEN, reason);
   }
   @Override
   public void DeleteUser(Long uid, String reason) {
      UserInfo currentInfo = userInfoService.selectByPKey(uid);
      if (currentInfo == null) {
         return;
      }
      if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
         return;
      }
      currentInfo.setState(UserInfo.STATE_DELETE);
      currentInfo.setStateDesc(reason);
      userInfoService.updateByPrimaryKeySelective(currentInfo);
      // 插入记录
      userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE, reason);
   }
   @Override
   public void DeleteUserOutOfDate(Long uid, String reason) {
      UserInfo currentInfo = userInfoService.selectByPKey(uid);
      if (currentInfo == null) {
         return;
      }
      if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
         return;
      }
      currentInfo.setState(UserInfo.STATE_DELETE_OUT_OF_DATE);
      currentInfo.setStateDesc(reason);
      userInfoService.updateByPrimaryKeySelective(currentInfo);
      // 插入记录
      userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE_OUT_OF_DATE, reason);
   }
}
package com.yeshi.fanli.service.impl.user;
import java.io.InputStream;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.yeshi.fanli.entity.SystemEnum;
import com.yeshi.fanli.entity.config.SMSConfig;
import com.yeshi.fanli.entity.system.BusinessSystem;
import com.yeshi.fanli.entity.system.ConfigKeyEnum;
import com.yeshi.fanli.service.inter.config.ConfigService;
import com.yeshi.fanli.service.inter.config.SystemConfigService;
import com.yeshi.fanli.util.*;
import com.yeshi.fanli.vo.taobao.TaoBaoUser;
import com.yeshi.fanli.vo.user.QQUserInfoVO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.HttpUtil;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.entity.FileUploadResult;
import org.yeshi.utils.entity.ProxyIP;
import org.yeshi.utils.entity.wx.WeiXinUser;
import org.yeshi.utils.tencentcloud.COSManager;
import com.google.gson.Gson;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.model.ObjectListing;
import com.yeshi.fanli.dto.wx.WXAccountInfoDTO;
import com.yeshi.fanli.entity.accept.AcceptData;
import com.yeshi.fanli.entity.bus.user.BindingAccount;
import com.yeshi.fanli.entity.bus.user.ForbiddenUserIdentifyCode;
import com.yeshi.fanli.entity.bus.user.ForbiddenUserIdentifyCode.ForbiddenUserIdentifyCodeTypeEnum;
import com.yeshi.fanli.entity.bus.user.LoginResult;
import com.yeshi.fanli.entity.bus.user.SMSHistory;
import com.yeshi.fanli.entity.bus.user.UserAccountBindingHistory;
import com.yeshi.fanli.entity.bus.user.UserExtraTaoBaoInfo;
import com.yeshi.fanli.entity.bus.user.UserInfo;
import com.yeshi.fanli.entity.bus.user.UserInfoModifyRecord.ModifyTypeEnum;
import com.yeshi.fanli.exception.user.ForbiddenUserIdentifyCodeException;
import com.yeshi.fanli.exception.user.UserAccountException;
import com.yeshi.fanli.log.LogHelper;
import com.yeshi.fanli.service.inter.money.extract.BindingAccountService;
import com.yeshi.fanli.service.inter.user.ForbiddenUserIdentifyCodeService;
import com.yeshi.fanli.service.inter.user.SpreadUserImgService;
import com.yeshi.fanli.service.inter.user.UserAccountBindingHistoryService;
import com.yeshi.fanli.service.inter.user.UserAccountService;
import com.yeshi.fanli.service.inter.user.UserInfoDeleteRecordService;
import com.yeshi.fanli.service.inter.user.UserInfoExtraService;
import com.yeshi.fanli.service.inter.user.UserInfoModifyRecordService;
import com.yeshi.fanli.service.inter.user.UserInfoService;
import com.yeshi.fanli.service.inter.user.invite.ThreeSaleSerivce;
import com.yeshi.fanli.service.inter.user.msg.UserAccountMsgNotificationService;
import com.yeshi.fanli.service.inter.user.tb.UserExtraTaoBaoInfoService;
import com.yeshi.fanli.util.factory.msg.MsgAccountDetailFactory;
import com.yeshi.fanli.util.wx.MyWXLoginUtil;
import net.sf.json.JSONObject;
import org.yeshi.utils.wx.WXAppLoginUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
@Service
public class UserAccountServiceImpl implements UserAccountService {
    @Resource
    private RedisManager redisManager;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private BindingAccountService bindingAccountService;
    @Resource
    private ThreeSaleSerivce threeSaleSerivce;
    @Resource
    private SpreadUserImgService spreadUserImgService;
    @Resource
    private UserAccountMsgNotificationService userAccountMsgNotificationService;
    @Resource
    private UserExtraTaoBaoInfoService userExtraTaoBaoInfoService;
    @Resource
    private ForbiddenUserIdentifyCodeService forbiddenUserIdentifyCodeService;
    @Resource
    private UserInfoExtraService userInfoExtraService;
    @Resource
    private UserAccountBindingHistoryService userAccountBindingHistoryService;
    @Resource
    private UserInfoDeleteRecordService userInfoDeleteRecordService;
    @Resource
    private ConfigService configService;
    @Lazy
    @Resource
    private UserInfoModifyRecordService userInfoModifyRecordService;
    @Resource
    private SystemConfigService systemConfigService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoginResult login(HttpServletRequest request, AcceptData acceptData, Boolean first, String appId,
                             String code, String phone, UserInfo tbUserInfo, boolean wxinstall, int loginType)
            throws UserAccountException {
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", appId);
        logInfo.put("code", code);
        logInfo.put("phone", phone);
        if (tbUserInfo != null)
            logInfo.put("tbUserInfo", tbUserInfo.getId());
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        HttpSession session = request.getSession();
        if (first != null && first == true) {
            session.removeAttribute("LAST_LOGIN_USER");
        }
        String defaultPortrait = userInfoService.getDefaultPortrait(acceptData.getSystem());
        // 会话中上次登录的用户
        if (wxinstall) {// 安装了微信的状态
            UserInfo lastUser = (UserInfo) session.getAttribute("LAST_LOGIN_USER");
            UserInfo userInfo = null;
            WeiXinUser weiXinUser = null;
            switch (loginType) {
                case 1:// 淘宝
                    // 判断淘宝是否被封禁
                    if (!StringUtil.isNullOrEmpty(tbUserInfo.getTaoBaoUid())) {
                        ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                                ForbiddenUserIdentifyCodeTypeEnum.taobaoUid, tbUserInfo.getTaoBaoUid());
                        if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
                            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER,
                                    Constant.FORBIDDEN_USER_REASON_DESC);
                    }
                    userInfo = getUserInfoByTaoBaoOpenId(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), tbUserInfo.getOpenid());
                    // 判断用户是否被删除
                    if (userInfo != null && userInfo.getState() != null && (userInfo.getState() != UserInfo.STATE_NORMAL))
                        userInfo = null;
                    if (userInfo == null) {// 原先的账号不存在
                        userInfo = new UserInfo();
                        userInfo.setAppId(appId);
                        userInfo.setTbName(tbUserInfo.getTbName());
                        userInfo.setOpenid(tbUserInfo.getOpenid());
                        userInfo.setTbPic(tbUserInfo.getTbPic());
                        userInfo.setNickName(tbUserInfo.getNickName());
                        userInfo.setPortrait(tbUserInfo.getPortrait());
                        userInfo.setLoginType(loginType);
                        userInfo.setSystem(SystemInfoUtil.getSystem(acceptData));
                        session.setAttribute("LAST_LOGIN_USER", userInfo);
                        // 需要微信登录
                        return new LoginResult(LoginResult.TYPE_WX, userInfo);
                    } else {// 原先的账号存在
                        // 判定是否绑定了微信
                        if (StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {// 没有绑定微信
                            userInfo.setLoginType(loginType);
                            session.setAttribute("LAST_LOGIN_USER", userInfo);
                            // 需要微信登录
                            return new LoginResult(LoginResult.TYPE_WX, userInfo);
                        } else {// 绑定了微信
                            updateLatestLoginTime(userInfo.getId());
                            return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                        }
                    }
                case 2:// 微信
                    // 通过Code换取信息
                    WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
                    weiXinUser = MyWXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
                            wxAccount.getAppSecret());
                    if (weiXinUser == null)
                        throw new UserAccountException(1001, "无法获取到微信个人信息");
                    LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
                    // 判断微信unionid是否被封禁
                    ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                            ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
                    if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
                        throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
                    userInfo = getUserInfoByWXUnionId(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), weiXinUser.getUnionid());
                    // 判断用户是否被删除
                    if (userInfo != null && userInfo.getState() != null && (userInfo.getState() != UserInfo.STATE_NORMAL))
                        userInfo = null;
                    // 直接用的微信登录
                    if (lastUser == null) {
                        if (userInfo != null) {
                            // 使分销关系生效
                            threeSaleSerivce.effective(userInfo);
                            // 更新头像与昵称
                            UserInfo updateUserInfo = new UserInfo(userInfo.getId());
                            updateUserInfo.setNickName(weiXinUser.getNickname());
                            if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()))
                                updateUserInfo.setPortrait(weiXinUser.getHeadimgurl());
                            updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
                            updateUserInfo.setWxName(weiXinUser.getNickname());
                            // 设置登录时间与登录类型
                            updateUserInfo.setLastLoginTime(System.currentTimeMillis());
                            updateUserInfo.setLoginType(loginType);
                            updateUserInfo.setLastLoginIp(request.getRemoteHost());
                            // 更新openId
                            updateUserInfo.setOpenid(weiXinUser.getOpenid());
                            userInfoService.updateByPrimaryKeySelective(updateUserInfo);
                            // 删除邀请图片
                            spreadUserImgService.deleteImgUrl(userInfo.getId());
                            return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                        }
                        userInfo = new UserInfo();
                        userInfo.setPortrait(weiXinUser.getHeadimgurl());
                        userInfo.setAppId(appId);
                        userInfo.setNickName(weiXinUser.getNickname());
                        userInfo.setWxName(weiXinUser.getNickname());
                        userInfo.setWxOpenId(weiXinUser.getOpenid());
                        userInfo.setWxUnionId(weiXinUser.getUnionid());
                        userInfo.setWxPic(weiXinUser.getHeadimgurl());
                        userInfo.setLastLoginTime(System.currentTimeMillis());
                        userInfo.setLoginType(loginType);
                        userInfo.setLastLoginIp(request.getRemoteHost());
                        userInfo.setSystem(SystemInfoUtil.getSystem(acceptData));
                        addUser(userInfo);
                        return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                    } else {
                        // 本会话采用过其他账号登录
                        if (userInfo != null)// 微信账号存在
                        {
                            if (lastUser.getLoginType() == 2) {
                                session.removeAttribute("LAST_LOGIN_USER");
                                throw new UserAccountException(1002, "微信不能绑定微信");
                            }
                            if (lastUser.getLoginType() == 1 && !StringUtil.isNullOrEmpty(userInfo.getOpenid())) {
                                session.removeAttribute("LAST_LOGIN_USER");
                                throw new UserAccountException(1003, "该微信已经绑定了淘宝账号,请先解绑");
                            }
                            if (lastUser.getLoginType() == 3 && !StringUtil.isNullOrEmpty(userInfo.getPhone())) {
                                session.removeAttribute("LAST_LOGIN_USER");
                                throw new UserAccountException(1003, "该微信已经绑定了电话号码,请先解绑");
                            }
                            // 删除邀请图片
                            spreadUserImgService.deleteImgUrl(userInfo.getId());
                            // 还没有绑定同类型的账号
                            // 两个账号没有同时有独立的UID
                            if (lastUser.getId() == null || lastUser.getId() == 0
                                    || lastUser.getId() == userInfo.getId().longValue()) {
                                // 绑定关系
                                UserInfo updateUserInfo = new UserInfo(userInfo.getId());
                                if (!StringUtil.isNullOrEmpty(lastUser.getPhone())) {
                                    updateUserInfo.setPhone(lastUser.getPhone());
                                    userAccountMsgNotificationService.bindingSuccess(userInfo.getId(),
                                            MsgAccountDetailFactory.TYPE_PHONE);
                                }
                                if (!StringUtil.isNullOrEmpty(lastUser.getOpenid())) {
                                    updateUserInfo.setOpenid(lastUser.getOpenid());
                                    updateUserInfo.setTbName(lastUser.getTbName());
                                    updateUserInfo.setTbPic(lastUser.getTbPic());
                                    userAccountMsgNotificationService.bindingSuccess(userInfo.getId(),
                                            MsgAccountDetailFactory.TYPE_TB);
                                }
                                updateUserInfo.setLastLoginTime(System.currentTimeMillis());
                                userInfoService.updateByPrimaryKeySelective(updateUserInfo);
                                session.removeAttribute("LAST_LOGIN_USER");
                                // 使分销关系生效
                                threeSaleSerivce.effective(userInfo);
                                return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                            } else {// 两个账号拥有不同的UID
                                // 询问是否打通
                                // 暂存微信账号
                                // session.setAttribute("WEIXIN_USERINFO",
                                // userInfo);
                                session.removeAttribute("LAST_LOGIN_USER");
                                LoginResult result = new LoginResult(LoginResult.TYPE_CONNECT, lastUser);
                                result.setMainUser(userInfo);
                                result.setLessUser(lastUser);
                                // 使分销关系生效
                                threeSaleSerivce.effective(userInfo);
                                return result;
                            }
                        } else {// 微信账号不存在
                            // 创建账号,绑定账号
                            userInfo = new UserInfo();
                            userInfo.setPortrait(weiXinUser.getHeadimgurl());
                            userInfo.setAppId(appId);
                            userInfo.setNickName(weiXinUser.getNickname());
                            userInfo.setWxName(weiXinUser.getNickname());
                            userInfo.setWxOpenId(weiXinUser.getOpenid());
                            userInfo.setWxUnionId(weiXinUser.getUnionid());
                            userInfo.setWxPic(weiXinUser.getHeadimgurl());
                            if (!StringUtil.isNullOrEmpty(lastUser.getPhone()))
                                userInfo.setPhone(lastUser.getPhone());
                            if (!StringUtil.isNullOrEmpty(lastUser.getOpenid())) {
                                userInfo.setOpenid(lastUser.getOpenid());
                                userInfo.setTbName(lastUser.getTbName());
                                userInfo.setTbPic(lastUser.getTbPic());
                            }
                            userInfo.setLastLoginTime(System.currentTimeMillis());
                            userInfo.setLoginType(loginType);
                            userInfo.setLastLoginIp(request.getRemoteHost());
                            userInfo.setSystem(SystemInfoUtil.getSystem(acceptData));
                            addUser(userInfo);
                            session.removeAttribute("LAST_LOGIN_USER");
                            return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                        }
                    }
                case 3:// 手机号码
                    // 判断手机号码是否被封禁
                    ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                            .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
                    if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
                        throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
                    userInfo = getUserInfoByPhone(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), phone);
                    // 判断用户是否被删除
                    if (userInfo != null && userInfo.getState() != null && (userInfo.getState() != UserInfo.STATE_NORMAL))
                        userInfo = null;
                    if (userInfo == null) {// 原先的账号不存在
                        userInfo = new UserInfo();
                        userInfo.setAppId(appId);
                        userInfo.setNickName(null);
                        userInfo.setPortrait(defaultPortrait);
                        userInfo.setPhone(phone);
                        userInfo.setLoginType(loginType);
                        userInfo.setSystem(SystemInfoUtil.getSystem(acceptData));
                        session.setAttribute("LAST_LOGIN_USER", userInfo);
                        // 询问是否绑定微信
                        return new LoginResult(LoginResult.TYPE_WX, userInfo);
                    } else {// 原先的账号存在
                        // 判定是否绑定了微信
                        if (StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {// 没有绑定微信
                            userInfo.setLoginType(loginType);
                            session.setAttribute("LAST_LOGIN_USER", userInfo);
                            // 需要微信登录
                            return new LoginResult(LoginResult.TYPE_WX, userInfo);
                        } else {// 绑定了微信
                            updateLatestLoginTime(userInfo.getId());
                            return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
                        }
                    }
                default:
                    return null;
            }
        } else {// 没有安装微信
            LoginResult result = loginNoInstallWX(acceptData, appId, code, phone, tbUserInfo, loginType);
            if (result.getType() == LoginResult.TYPE_CREATE)
                session.setAttribute("LAST_LOGIN_USER", result.getUser());
            return result;
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public LoginResult loginNoInstallWX(AcceptData acceptData, String appId, String code, String phone,
                                        UserInfo tbUserInfo, int loginType) throws UserAccountException {
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", appId);
        logInfo.put("code", code);
        logInfo.put("phone", phone);
        if (tbUserInfo != null)
            logInfo.put("tbUserInfo", tbUserInfo.getId());
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        String defaultPortrait = userInfoService.getDefaultPortrait(acceptData.getSystem());
        UserInfo userInfo = null;
        WeiXinUser weiXinUser = null;
        switch (loginType) {
            case 1:// 淘宝
                if (!StringUtil.isNullOrEmpty(tbUserInfo.getTaoBaoUid())) {
                    ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService.listByTypeAndIdentifyCode(
                            ForbiddenUserIdentifyCodeTypeEnum.taobaoUid, tbUserInfo.getTaoBaoUid());
                    if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
                        throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
                }
                userInfo = getUserInfoByTaoBaoOpenId(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), tbUserInfo.getOpenid());
                break;
            case 2:// 微信
                // 通过Code换取信息
                WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
                weiXinUser = MyWXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
                        wxAccount.getAppSecret());
                if (weiXinUser == null)
                    throw new UserAccountException(1001, "无法获取到微信个人信息");
                // 判断是否被封禁
                ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
                        .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
                if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective())
                    throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
                userInfo = getUserInfoByWXUnionId(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), weiXinUser.getUnionid());
                break;
            case 3:// 手机号码
                // 判断是否被封禁
                ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                        .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
                if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
                    throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
                userInfo = getUserInfoByPhone(SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()), phone);
                break;
        }
        // 判断用户是否被删除
        if (userInfo != null && userInfo.getState() != null && (userInfo.getState() != UserInfo.STATE_NORMAL))
            userInfo = null;
        if (userInfo != null) {
            UserInfo updateUserInfo = new UserInfo(userInfo.getId());
            updateUserInfo.setLastLoginTime(System.currentTimeMillis());
            userInfoService.updateByPrimaryKeySelective(updateUserInfo);
            return new LoginResult(LoginResult.TYPE_NORMAL, userInfo);
        } else {// 询问是否创建用户
            userInfo = new UserInfo();
            userInfo.setAppId(appId);
            switch (loginType) {
                case 1:// 淘宝
                    userInfo.setTbName(tbUserInfo.getNickName());
                    userInfo.setTbPic(tbUserInfo.getPortrait());
                    userInfo.setNickName(tbUserInfo.getNickName());
                    userInfo.setPortrait(tbUserInfo.getPortrait());
                    break;
                case 2:// 微信
                    userInfo.setPortrait(weiXinUser.getHeadimgurl());
                    userInfo.setNickName(weiXinUser.getNickname());
                    userInfo.setWxName(weiXinUser.getNickname());
                    userInfo.setWxOpenId(weiXinUser.getOpenid());
                    userInfo.setWxUnionId(weiXinUser.getUnionid());
                    userInfo.setWxPic(weiXinUser.getHeadimgurl());
                    break;
                case 3:// 手机号码
                    // 默认头像与昵称
                    userInfo.setPortrait(defaultPortrait);
                    userInfo.setNickName(null);
                    userInfo.setPhone(phone);
                    break;
            }
            userInfo.setSystem(SystemInfoUtil.getSystem(acceptData));
            return new LoginResult(LoginResult.TYPE_CREATE, userInfo);
        }
    }
    /**
     * 根据系统与unionid寻找用户
     *
     * @param system
     * @param unionId
     * @return
     * @throws UserAccountException
     */
    @Override
    public UserInfo getUserInfoByWXUnionId(SystemEnum system, String unionId) throws UserAccountException {
        if (system == null)
            throw new UserAccountException(1, "系统");
        if (StringUtil.isNullOrEmpty(unionId))
            throw new UserAccountException(2, "unionId为空");
        List<UserInfo> list = userInfoService.listBySystemAndWXUnionId(system, unionId);
        // 剔除被删除掉的用户
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getState() == UserInfo.STATE_NORMAL) {
                list.remove(i);
                i--;
            }
        }
        if (list.size() > 0)
            return list.get(list.size() - 1);
        else
            return null;
    }
    /**
     * 根据系统和淘宝的Openid寻找用户
     *
     * @param system
     * @param openId
     * @return
     * @throws UserAccountException
     */
    public UserInfo getUserInfoByTaoBaoOpenId(SystemEnum system, String openId) throws UserAccountException {
        if (system == null)
            throw new UserAccountException(1, "系统为空");
        if (StringUtil.isNullOrEmpty(openId))
            throw new UserAccountException(2, "openId为空");
        List<UserInfo> list = userInfoService.listBySystemAndTaoBaoOpenId(system, openId);
        // 剔除被删除掉的用户
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getState() != UserInfo.STATE_NORMAL) {
                list.remove(i);
                i--;
            }
        }
        if (list.size() > 0)
            return list.get(list.size() - 1);
        else
            return null;
    }
    /**
     * 根据系统和电话号码寻找用户
     *
     * @param system
     * @param phone
     * @return
     * @throws UserAccountException
     */
    public UserInfo getUserInfoByPhone(SystemEnum system, String phone) throws UserAccountException {
        if (system == null)
            throw new UserAccountException(1, "系统为空");
        if (StringUtil.isNullOrEmpty(phone))
            throw new UserAccountException(2, "phone为空");
        List<UserInfo> list = userInfoService.listBySystemAndPhone(system, phone);
        // 剔除被删除掉的用户
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getState() != UserInfo.STATE_NORMAL) {
                list.remove(i);
                i--;
            }
        }
        if (list.size() > 0)
            return list.get(list.size() - 1);
        else
            return null;
    }
    private void updateLatestLoginTime(Long uid) {
        UserInfo userInfo = new UserInfo(uid);
        userInfo.setLastLoginTime(System.currentTimeMillis());
        userInfoService.updateByPrimaryKeySelective(userInfo);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void register(UserInfo userInfo) throws UserAccountException {
        if (!StringUtil.isNullOrEmpty(userInfo.getPhone())) {
            UserInfo user = getUserInfoByPhone(userInfo.getSystem(), userInfo.getPhone());
            if (user != null)
                throw new UserAccountException(50001, "电话号码已经被绑定");
        }
        if (!StringUtil.isNullOrEmpty(userInfo.getOpenid())) {
            UserInfo user = getUserInfoByTaoBaoOpenId(userInfo.getSystem(), userInfo.getOpenid());
            if (user != null)
                throw new UserAccountException(50002, "淘宝号已经被绑定");
        }
        if (!StringUtil.isNullOrEmpty(userInfo.getWxUnionId())) {
            UserInfo user = getUserInfoByWXUnionId(userInfo.getSystem(), userInfo.getWxUnionId());
            if (user != null)
                throw new UserAccountException(50003, "微信号已经被注册");
        }
        addUser(userInfo);
    }
    @Transactional
    @Override
    public void addUser(UserInfo user) {
        user.setCreatetime(System.currentTimeMillis());
        user.setRank(0);
        if (StringUtil.isNullOrEmpty(user.getPortrait())) {
            String defaultPortrait = userInfoService.getDefaultPortrait(user.getSystem());
            user.setPortrait(defaultPortrait);
        }
        userInfoService.createUser(user, user.getSystem());
        // 昵称为空时 默认昵称
        if (StringUtil.isNullOrEmpty(user.getNickName())) {
            UserInfo updateUserInfo = new UserInfo(user.getId());
            String defaultNickName = userInfoService.getDefaultNickName(user.getSystem(), user.getId());
            updateUserInfo.setNickName(defaultNickName);
            userInfoService.updateByPrimaryKeySelective(updateUserInfo);
        }
        try {
            // 第一次登录时创建用户额外信息
            userInfoExtraService.createUserInfoExtra(user.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 添加账号绑定历史
        if (!StringUtil.isNullOrEmpty(user.getPhone()))
            userInfoModifyRecordService.addModifyRecord(user.getId(), ModifyTypeEnum.bindPhone, user.getPhone());
        if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
            userInfoModifyRecordService.addModifyRecord(user.getId(), ModifyTypeEnum.bindWeiXin, user.getWxUnionId());
    }
    @Override
    public void updateUserSelective(UserInfo user) {
        userInfoService.updateByPrimaryKeySelective(user);
    }
    @Override
    public void bindPhone(Long uid, String phone) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            throw new UserAccountException(4, "用户不存在");
        if (!StringUtil.isNullOrEmpty(user.getPhone()))
            throw new UserAccountException(5, "当前账号已经绑定了手机号,请先解绑");
        UserInfo phoneUser = getUserInfoByPhone(user.getSystem(), phone);
        if (phoneUser != null)
            throw new UserAccountException(6, "当前电话号码已经被绑定");
        UserInfo update = new UserInfo(user.getId());
        update.setPhone(phone);
        userInfoService.updateByPrimaryKeySelective(update);
        userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
        userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
    }
    @Override
    public void unBindPhone(Long uid, String phone) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            throw new UserAccountException(4, "用户不存在");
        if (StringUtil.isNullOrEmpty(user.getPhone()))
            throw new UserAccountException(4, "尚未绑定电话号码");
        if (!user.getPhone().equalsIgnoreCase(phone))
            throw new UserAccountException(4, "原绑定手机号输入错误");
        if (StringUtil.isNullOrEmpty(user.getWxUnionId()) && StringUtil.isNullOrEmpty(user.getOpenid()))
            throw new UserAccountException(5, "不能解除绑定");
        UserInfo updateUserInfo = new UserInfo(uid);
        updateUserInfo.setPhone("");
        userInfoService.updateByPrimaryKeySelective(updateUserInfo);
        userAccountMsgNotificationService.unBindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
    }
    @Override
    public void bindTaoBao(Long uid, String tbOpenId, String tbNickName, String tbPortrait)
            throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            throw new UserAccountException(4, "用户不存在");
        if (!StringUtil.isNullOrEmpty(user.getOpenid()) && !user.getOpenid().equalsIgnoreCase(tbOpenId))
            throw new UserAccountException(5, "当前账号已经绑定了淘宝,请先解绑");
        // 绑定同一个淘宝号
        if (!StringUtil.isNullOrEmpty(user.getOpenid()) && user.getOpenid().equalsIgnoreCase(tbOpenId))
            return;
        UserInfo taoBaoUser = getUserInfoByTaoBaoOpenId(user.getSystem(), tbOpenId);
        if (taoBaoUser != null)
            throw new UserAccountException(6, "当前淘宝号已经被绑定");
        UserInfo update = new UserInfo(user.getId());
        update.setOpenid(tbOpenId);
        update.setTbName(tbNickName);
        update.setTbPic(tbPortrait);
        // 如果没有绑定微信就以淘宝的头像和昵称作为用户的头像与昵称
        if (StringUtil.isNullOrEmpty(user.getWxUnionId())) {
            update.setNickName(tbNickName);
            update.setPortrait(tbPortrait);
        }
        userInfoService.updateByPrimaryKeySelective(update);
        userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_TB);
    }
    @Override
    public void unBindTaoBao(Long uid) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            throw new UserAccountException(4, "用户不存在");
        if (StringUtil.isNullOrEmpty(user.getOpenid()))
            throw new UserAccountException(5, "当前账号尚未绑定淘宝");
        if (StringUtil.isNullOrEmpty(user.getWxUnionId()) && StringUtil.isNullOrEmpty(user.getPhone()))
            throw new UserAccountException(5, "不能接触绑定");
        UserInfo update = new UserInfo(user.getId());
        update.setOpenid("");
        update.setTbName("");
        update.setTbPic("");
        // 判断是否有微信绑定
        if (StringUtil.isNullOrEmpty(user.getWxUnionId())) {
            update.setNickName(userInfoService.getDefaultNickName(user.getSystem(), user.getId()));
            update.setPortrait(userInfoService.getDefaultPortrait(user.getSystem()));
        }
        userInfoService.updateByPrimaryKeySelective(update);
        userExtraTaoBaoInfoService.unBindUid(uid);
        userAccountMsgNotificationService.unBindingSuccess(uid, MsgAccountDetailFactory.TYPE_TB);
    }
    @Override
    public void changeWXBind(AcceptData acceptData, Long uid, String code) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            throw new UserAccountException(4, "用户不存在");
        WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
        WeiXinUser weiXinUser = MyWXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
                wxAccount.getAppSecret());
        if (weiXinUser == null)
            throw new UserAccountException(10, "获取微信用户信息失败");
        if (weiXinUser.getUnionid().equalsIgnoreCase(user.getWxUnionId()))
            throw new UserAccountException(12, "亲,请登录其它微信号进行更换绑定");
        UserInfo newUser = getUserInfoByWXUnionId(user.getSystem(), weiXinUser.getUnionid());
        if (newUser != null)
            throw new UserAccountException(13, "该微信号已被其他账号绑定");
        UserInfo updateUserInfo = new UserInfo(uid);
        updateUserInfo.setWxName(weiXinUser.getNickname());
        updateUserInfo.setWxOpenId(weiXinUser.getOpenid());
        updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
        updateUserInfo.setWxUnionId(weiXinUser.getUnionid());
        // 将默认昵称替换成微信昵称
        if (!StringUtil.isNullOrEmpty(weiXinUser.getNickname())) {
            String defaultNickName = userInfoService.getDefaultNickName(user.getSystem(), uid);
            if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
                updateUserInfo.setNickName(weiXinUser.getNickname());
            }
        }
        // 将默认头像替换成微信头像
        String defaultPortrait = userInfoService.getDefaultPortrait(user.getSystem());
        if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()) && !StringUtil.isNullOrEmpty(defaultPortrait)
                && defaultPortrait.equals(user.getPortrait())) {
            updateUserInfo.setPortrait(weiXinUser.getHeadimgurl());
        }
        userInfoService.updateByPrimaryKeySelective(updateUserInfo);
        userAccountMsgNotificationService.changeBindingSuccess(uid, MsgAccountDetailFactory.TYPE_WX);
        userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, weiXinUser.getUnionid());
    }
    @Override
    public void clearUserPortrait(Long uid) {
        if (uid == null)
            return;
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        String prefix = String.format("/portrait/wx/%s_", user.getWxUnionId());
        ObjectListing list = COSManager.getInstance().getObjectList(prefix, null, 30);
        if (list != null && list.getObjectSummaries() != null)
            for (COSObjectSummary object : list.getObjectSummaries()) {
                if (user.getWxPic() != null && !user.getWxPic().contains(object.getKey())) {
                    COSManager.getInstance().deleteFile(object.getKey());
                }
            }
    }
    @Override
    public String repairPortrait(Long uid) {
        if (uid == null)
            return null;
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null)
            return null;
        String prefix = String.format("/portrait/wx/%s_", user.getWxUnionId());
        ObjectListing list = COSManager.getInstance().getObjectList(prefix, null, 30);
        // 查询头像文件是否还存在
        boolean exist = false;
        if (list != null && list.getObjectSummaries() != null)
            for (COSObjectSummary object : list.getObjectSummaries()) {
                if (user.getPortrait().contains(object.getKey())) {
                    exist = true;
                    break;
                }
            }
        if (!exist && list.getObjectSummaries() != null && list.getObjectSummaries().size() > 0) {
            COSObjectSummary object = list.getObjectSummaries().get(list.getObjectSummaries().size() - 1);
            String portrait = String.format("https://%s.file.myqcloud.com/%s", object.getBucketName(), object.getKey());
            if (!StringUtil.isNullOrEmpty(portrait)) {
                UserInfo updateUser = new UserInfo(uid);
                updateUser.setPortrait(portrait);
                userInfoService.updateByPrimaryKeySelective(updateUser);
                return portrait;
            }
        }
        return user.getPortrait();
    }
    @Override
    public String getMobile(String vcode, String phone, String aliAccessToken, SystemEnum system, int vcodeType) throws UserAccountException {
        if (!StringUtil.isNullOrEmpty(aliAccessToken)) {
            String mobile = AliyunOneKeyLoginUtil.getMobile(aliAccessToken, "");
            if (StringUtil.isNullOrEmpty(mobile)) {
                throw new UserAccountException(1, "手机号获取失败");
            }
            return mobile;
        } else {
            // 空额清理
            if (phone == null || phone.trim().length() == 0) {
                throw new UserAccountException(1, "请输入手机号码");
            }
            phone = phone.replaceAll(" ", "");
            boolean isDemo = false;
            //查询上线测试的号码与验证码
            String demoLogin = configService.getValue(ConfigKeyEnum.demoLoginUser, system);
            if (!StringUtil.isNullOrEmpty(demoLogin)) {
                String demoPhone = demoLogin.split("#")[0];
                String demoCode = demoLogin.split("#")[1];
                if (phone.equalsIgnoreCase(demoPhone) && demoCode.equalsIgnoreCase(vcode)) {
                    isDemo = true;
                }
            }
            // 苹果应用商店上线测试号码
            if (!isDemo) {
                if (StringUtil.isNullOrEmpty(vcode)) {
                    throw new UserAccountException(1, "请输入验证码");
                }
                String oldVcode = redisManager.getSMSVCode(phone, vcodeType);
                LogHelper.test("----------------------登录验证码: " + oldVcode);
                if (!Constant.IS_TEST)
                    if (StringUtil.isNullOrEmpty(oldVcode) || !oldVcode.equalsIgnoreCase(vcode)) {
                        throw new UserAccountException(1, "验证码错误,重新输入");
                    } else {// 验证码输入正确
                        redisManager.clearSMSVCode(phone, vcodeType);
                    }
            }
            return phone;
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo loginPhone(ProxyIP ipInfo, int loginType, String vcode, String phone, String aliAccessToken, BusinessSystem businessSystem)
            throws UserAccountException {
        String mobile = getMobile(vcode, phone, aliAccessToken, businessSystem.getSystem(), SMSHistory.TYPE_LOGIN);
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", businessSystem.getAppid());
        logInfo.put("phone", mobile);
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        // 判断手机号码是否被封禁
        ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, mobile);
        if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective()) {
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        }
        // 清空限制
        redisManager.clearSMSFrequencyLimit(mobile, SMSHistory.TYPE_LOGIN);
        // 清理次数
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMSLoginCount, mobile);
        redisManager.removeCommonString(key);
        // 采用redis事务防止一个手机号多次注册问题
        String watchKey = StringUtil.Md5("REGISTER:" + mobile);
        Jedis jedis = redisManager.getJedis();
        try {
            jedis.watch(watchKey);
            if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
                throw new UserAccountException(10, "请稍后再试");
            Transaction tran = jedis.multi();
            tran.incr(watchKey);
            List<Object> exec = tran.exec();
            if (exec == null || exec.size() == 0) {
                throw new UserAccountException(10, "请稍后再试");
            } else {
                // 查询是否存在该电话历史用户
                UserInfo userInfo = userInfoService.getEffectiveUserInfoByPhone(mobile, businessSystem.getSystem());
                if (userInfo != null) {
                    // 更新账户登录信息
                    updateLonginInfo(userInfo, loginType, ipInfo);
                } else {
                    userInfo = new UserInfo();
                    userInfo.setAppId(businessSystem.getAppid());
                    userInfo.setPortrait(null);
                    userInfo.setPhone(mobile);
                    userInfo.setLoginType(loginType);
                    userInfo.setState(UserInfo.STATE_NORMAL);
                    userInfo.setSystem(businessSystem.getSystem());
                    // 创建用户
                    addUser(userInfo);
                    try {
                        // 第一次登录时创建用户额外信息
                        userInfoExtraService.createUserInfoExtra(userInfo.getId());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindPhone, mobile);
                }
                return userInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.del(watchKey);
            jedis.unwatch();
            jedis.close();
        }
        throw new UserAccountException(10, "请稍后再试");
    }
    @Override
    public UserInfo loginTB(ProxyIP ipInfo, TaoBaoUser taoBaoUser, BusinessSystem businessSystem) throws UserAccountException {
        if (StringUtil.isNullOrEmpty(taoBaoUser.getUserid()))
            throw new UserAccountException(1, "淘宝授权信息不完整");
        UserInfo userInfo = userInfoService.getEffectiveUserInfoByOpenId(taoBaoUser.getOpenId(), businessSystem.getSystem());
        if (userInfo != null) {
            // 更新账户登录信息
            updateLonginInfo(userInfo, 1, ipInfo);
        } else {
            userInfo = new UserInfo();
            userInfo.setNickName(taoBaoUser.getNick());
            userInfo.setPortrait(taoBaoUser.getAvatarUrl());
            userInfo.setAppId(businessSystem.getAppid());
            userInfo.setTaoBaoUid(taoBaoUser.getUserid());
            userInfo.setOpenid(taoBaoUser.getOpenId());
            userInfo.setLoginType(1);
            userInfo.setState(UserInfo.STATE_NORMAL);
            userInfo.setSystem(businessSystem.getSystem());
            // 创建用户
            addUser(userInfo);
            try {
                // 第一次登录时创建用户额外信息
                userInfoExtraService.createUserInfoExtra(userInfo.getId());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return userInfo;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo loginPhoneNew(ProxyIP ipInfo, AcceptData acceptData, int loginType, String vcode, String
            phone, String appId)
            throws UserAccountException {
        // 空额清理
        if (phone == null || phone.trim().length() == 0) {
            throw new UserAccountException(1, "请输入手机号码");
        }
        phone = phone.replaceAll(" ", "");
        // 苹果应用商店上线测试号码
        if ("17316780233".equalsIgnoreCase(phone) && "2581".equalsIgnoreCase(vcode)) {
            ;
        } else {
            if (StringUtil.isNullOrEmpty(vcode)) {
                throw new UserAccountException(1, "请输入验证码");
            }
            String oldVcode = redisManager.getSMSVCode(phone, SMSHistory.TYPE_LOGIN);
            LogHelper.test("----------------------登录验证码: " + oldVcode);
            if (!Constant.IS_TEST)
                if (StringUtil.isNullOrEmpty(oldVcode) || !oldVcode.equalsIgnoreCase(vcode)) {
                    throw new UserAccountException(1, "验证码错误,重新输入");
                } else {// 验证码输入正确
                    redisManager.clearSMSVCode(phone, SMSHistory.TYPE_LOGIN);
                }
        }
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", appId);
        logInfo.put("phone", phone);
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        // 判断手机号码是否被封禁
        ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
        if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective()) {
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        }
        // 清空限制
        redisManager.clearSMSFrequencyLimit(phone, SMSHistory.TYPE_LOGIN);
        // 清理次数
        String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMSLoginCount, phone);
        redisManager.removeCommonString(key);
        // 采用redis事务防止一个手机号多次注册问题
        String watchKey = StringUtil.Md5("REGISTER:" + phone);
        Jedis jedis = redisManager.getJedis();
        try {
            jedis.watch(watchKey);
            if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
                throw new UserAccountException(10, "请稍后再试");
            Transaction tran = jedis.multi();
            tran.incr(watchKey);
            List<Object> exec = tran.exec();
            if (exec == null || exec.size() == 0) {
                throw new UserAccountException(10, "请稍后再试");
            } else {
                // 查询是否存在该电话历史用户
                UserInfo userInfo = userInfoService.getEffectiveUserInfoByPhone(phone, SystemInfoUtil.getSystem(acceptData.getPlatform(), acceptData.getPackages()));
                if (userInfo != null) {
                    // 更新账户登录信息
                    updateLonginInfo(userInfo, loginType, ipInfo);
                } else {
                    // 绑定微信
                    String keylogin = RedisKeyEnum.getRedisKey(RedisKeyEnum.emptyKey, StringUtil.Md5("phoneLogin:" + phone));
                    redisManager.cacheCommonString(keylogin, phone, 60 * 20);
                    throw new UserAccountException(102, keylogin);
                }
                return userInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.del(watchKey);
            jedis.unwatch();
            jedis.close();
        }
        throw new UserAccountException(10, "请稍后再试");
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo loginWeiXin(ProxyIP ipInfo, int loginType, String code,
                                BusinessSystem businessSystem) throws UserAccountException {
        // 日志信息
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", businessSystem.getAppid());
        logInfo.put("code", code);
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        // 通过Code换取信息
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(code, businessSystem.getWxAppId(), businessSystem.getWxAppSecret());
        if (weiXinUser == null) {
            throw new UserAccountException(1, "微信帐号授权失败");
        }
        LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
        // 判断微信unionid是否被封禁
        ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
        if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective()) {
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        }
        // 采用redis事务防止一个微信号多次注册问题
        String watchKey = StringUtil.Md5("REGISTER:" + weiXinUser.getUnionid());
        Jedis jedis = redisManager.getJedis();
        try {
            jedis.watch(watchKey);
            if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
                throw new UserAccountException(10, "请稍后再试");
            Transaction tran = jedis.multi();
            tran.incr(watchKey);
            List<Object> exec = tran.exec();
            if (exec == null || exec.size() == 0) {
                throw new UserAccountException(10, "请稍后再试");
            } else {
                UserInfo userInfo = userInfoService.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid(), businessSystem.getSystem());
                // 直接用的微信登录
                if (userInfo != null) {
                    LogHelper.test("微信unionID存在:" + weiXinUser.getUnionid());
                    // 更新账户登录信息
                    updateLonginInfo(userInfo, loginType, ipInfo);
                    // 删除邀请分享图
                    spreadUserImgService.deleteImgUrl(userInfo.getId());
                } else {
                    LogHelper.test("微信unionID不存在:" + weiXinUser.getUnionid());
                    String portrait = null;
                    if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl())) {
                        InputStream asInputStream = HttpUtil.getAsInputStream(weiXinUser.getHeadimgurl());
                        if (asInputStream != null) {
                            FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                                    String.format(FilePathEnum.userWXPortrait.getPath() + "%s_%s.jpg",
                                            weiXinUser.getUnionid(), System.currentTimeMillis() + ""));
                            if (result != null && !StringUtil.isNullOrEmpty(result.getUrl()))
                                portrait = result.getUrl();
                        } else {
                            portrait = weiXinUser.getHeadimgurl();
                        }
                    }
                    if (StringUtil.isNullOrEmpty(portrait))
                        portrait = userInfoService.getDefaultPortrait(businessSystem.getSystem());
                    // 创建新账户
                    userInfo = new UserInfo();
                    userInfo.setPortrait(portrait);
                    userInfo.setAppId(businessSystem.getAppid());
                    userInfo.setNickName(weiXinUser.getNickname());
                    userInfo.setWxName(weiXinUser.getNickname());
                    userInfo.setWxOpenId(weiXinUser.getOpenid());
                    userInfo.setWxUnionId(weiXinUser.getUnionid());
                    userInfo.setWxPic(weiXinUser.getHeadimgurl());
                    userInfo.setLastLoginTime(System.currentTimeMillis());
                    userInfo.setLoginType(loginType);
                    userInfo.setLastLoginIp(ipInfo.getIp());
                    userInfo.setState(UserInfo.STATE_NORMAL);
                    userInfo.setSystem(businessSystem.getSystem());
                    addUser(userInfo);
                    try {
                        // 第一次登录时创建用户额外信息
                        userInfoExtraService.createUserInfoExtra(userInfo.getId());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindWeiXin,
                            weiXinUser.getUnionid());
                }
                return userInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.del(watchKey);
            jedis.unwatch();
            jedis.close();
        }
        throw new UserAccountException(10, "请稍后再试");
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo loginWeiXinNew(ProxyIP ipInfo, int loginType, String wxCode,
                                   BusinessSystem businessSystem) throws UserAccountException {
        // 日志信息
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", businessSystem.getAppid());
        logInfo.put("wxCode", wxCode);
        logInfo.put("loginType", loginType);
        LogHelper.lgoinInfo(logInfo.toString());
        // 通过Code换取信息
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(wxCode, businessSystem.getWxAppId(), businessSystem.getWxAppSecret());
        if (weiXinUser == null) {
            throw new UserAccountException(1, "微信帐号授权失败");
        }
        LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
        // 判断微信unionid是否被封禁
        ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
        if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective()) {
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        }
        UserInfo userInfo = userInfoService.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid(), businessSystem.getSystem());
        if (userInfo == null) {
            String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.emptyKey,
                    "WXLogin#" + StringUtil.Md5(weiXinUser.getUnionid()));
            redisManager.cacheCommonString(key, JsonUtil.getSimpleGson().toJson(weiXinUser), 60 * 20);
            throw new UserAccountException(UserAccountException.CODE_NEED_BIND_PHONE, key);
        }
        // 更新账户登录信息
        updateLonginInfo(userInfo, loginType, ipInfo);
        Long uid = userInfo.getId();
        ThreadUtil.run(new Runnable() {
            public void run() {
                // 删除邀请分享图
                spreadUserImgService.deleteImgUrl(uid);
            }
        });
        return userInfo;
    }
    @Override
    public UserInfo loginQQ(ProxyIP ipInfo, int loginType, QQUserInfoVO qqUserInfo, BusinessSystem businessSystem) throws UserAccountException {
        // 通过Code换取信息
        if (qqUserInfo == null) {
            throw new UserAccountException(1, "QQ信息为空");
        }
        UserInfo userInfo = userInfoService.getEffectiveUserInfoByQQOpenId(qqUserInfo.getOpenid(), businessSystem.getSystem());
        if (userInfo == null) {
            String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.emptyKey,
                    "QQLogin#" + StringUtil.Md5(qqUserInfo.getOpenid()));
            redisManager.cacheCommonString(key, JsonUtil.getSimpleGson().toJson(qqUserInfo), 60 * 20);
            throw new UserAccountException(UserAccountException.CODE_NEED_BIND_PHONE, key);
        }
        // 更新账户登录信息
        updateLonginInfo(userInfo, loginType, ipInfo);
        Long uid = userInfo.getId();
        ThreadUtil.run(new Runnable() {
            public void run() {
                // 删除邀请分享图
                spreadUserImgService.deleteImgUrl(uid);
            }
        });
        return userInfo;
    }
    /**
     * 更新账户登录信息
     *
     * @param userInfo
     * @param loginType
     * @param ipInfo
     */
    private void updateLonginInfo(UserInfo userInfo, int loginType, ProxyIP ipInfo) {
        // 设置登录时间与登录类型
        UserInfo updateUserInfo = new UserInfo(userInfo.getId());
        updateUserInfo.setLastLoginTime(System.currentTimeMillis());
        updateUserInfo.setLoginType(loginType);
        updateUserInfo.setLastLoginIp(ipInfo.getIp());
        userInfoService.updateByPrimaryKeySelective(updateUserInfo);
    }
    @Override
    public void bindPhoneNew(Long uid, String phone) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null) {
            throw new UserAccountException(1, "用户不存在");
        }
        String hasPhone = user.getPhone();
        if (!StringUtil.isNullOrEmpty(hasPhone) && hasPhone.equals(phone)) {
            throw new UserAccountException(2, "您已经绑定了该电话号码");
        }
        UserInfo phoneUser = userInfoService.getEffectiveUserInfoByPhone(phone, user.getSystem());
        if (phoneUser != null) {
            throw new UserAccountException(2, "号码已经被占用");
        }
        // 更新电话号码
        UserInfo update = new UserInfo(user.getId());
        update.setPhone(phone);
        userInfoService.updateByPrimaryKeySelective(update);
        // 加入绑定记录
        UserAccountBindingHistory history = new UserAccountBindingHistory();
        history.setContent(phone);
        history.setType(UserAccountBindingHistory.TYPE_PHONE);
        history.setUid(uid);
        // 之前已经绑定电话号码
        if (!StringUtil.isNullOrEmpty(user.getPhone()))
            history.setFirst(false);
        else
            history.setFirst(true);
        userAccountBindingHistoryService.addUserAccountBindingHistory(history);
        // 发送消息
        userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
        userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
    }
    @Transactional(rollbackFor = UserAccountException.class)
    @Override
    public void bindWeiXin(BusinessSystem system, Long uid, String code) throws UserAccountException {
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(code, system.getWxAppId(), system.getWxAppSecret());
        if (weiXinUser == null) {
            throw new UserAccountException(2, "微信帐号授权失败");
        }
        String wxUnionId = weiXinUser.getUnionid();
        if (StringUtil.isNullOrEmpty(wxUnionId)) {
            throw new UserAccountException(2, "微信帐号授权失败");
        }
        bindWeiXin(uid, weiXinUser);
    }
    @Transactional(rollbackFor = UserAccountException.class)
    @Override
    public void bindWeiXin(Long uid, WeiXinUser weiXinUser) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null) {
            throw new UserAccountException(1, "用户不存在");
        }
        if (weiXinUser == null) {
            throw new UserAccountException(2, "微信帐号授权失败");
        }
        String wxUnionId = weiXinUser.getUnionid();
        if (StringUtil.isNullOrEmpty(wxUnionId)) {
            throw new UserAccountException(2, "微信帐号授权失败");
        }
        String wxUnionIdExist = user.getWxUnionId();
        if (StringUtil.isNullOrEmpty(wxUnionIdExist)) {
            UserInfo newUser = userInfoService.getEffectiveUserInfoByWXUnionId(wxUnionId, user.getSystem());
            if (newUser != null) {
                throw new UserAccountException(4, "该微信号已被其他帐号绑定");
            }
        } else if (wxUnionId.equalsIgnoreCase(wxUnionIdExist)) {
            throw new UserAccountException(3, "微信帐号一致无需更换");
        }
        if (StringUtil.isNullOrEmpty(user.getPhone())) {
            throw new UserAccountException(5, "该帐号没有绑定手机号码,需绑定手机号码才能完成微信更换");
        }
        UserInfo updateUserInfo = new UserInfo(uid);
        updateUserInfo.setWxName(weiXinUser.getNickname());
        updateUserInfo.setWxOpenId(weiXinUser.getOpenid());
        updateUserInfo.setWxPic(weiXinUser.getHeadimgurl());
        updateUserInfo.setWxUnionId(weiXinUser.getUnionid());
        // 将默认昵称替换成微信昵称
        String defaultNickName = userInfoService.getDefaultNickName(user.getSystem(), user.getId());
        if (!StringUtil.isNullOrEmpty(defaultNickName) && !StringUtil.isNullOrEmpty(weiXinUser.getNickname())) {
            defaultNickName = defaultNickName + uid;
            if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
                updateUserInfo.setNickName(weiXinUser.getNickname());
            }
        }
        // 将默认头像替换成微信头像
        String defaultPortrait = userInfoService.getDefaultPortrait(user.getSystem());
        if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl()) && !StringUtil.isNullOrEmpty(defaultPortrait)
                && defaultPortrait.equals(user.getPortrait())) {
            String headimgurl = weiXinUser.getHeadimgurl();
            InputStream asInputStream = HttpUtil.getAsInputStream(headimgurl);
            if (asInputStream == null) {
                LogHelper.test("微信头像下载失败: " + weiXinUser.getUnionid() + " " + headimgurl);
            } else {
                FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                        String.format(FilePathEnum.userWXPortrait.getPath() + "%s_%s.jpg", weiXinUser.getUnionid(),
                                System.currentTimeMillis() + ""));
                if (result != null && !StringUtil.isNullOrEmpty(result.getUrl())) {
                    headimgurl = result.getUrl();
                } else {
                    LogHelper.test("微信头像上传失败: " + weiXinUser.getUnionid() + " " + headimgurl);
                }
            }
            updateUserInfo.setPortrait(headimgurl);
        }
        userInfoService.updateByPrimaryKeySelective(updateUserInfo);
        // 加入绑定记录
        UserAccountBindingHistory history = new UserAccountBindingHistory();
        history.setContent(weiXinUser.getUnionid());
        history.setType(UserAccountBindingHistory.TYPE_WX);
        history.setUid(uid);
        // 之前已经绑定电话号码
        if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
            history.setFirst(false);
        else
            history.setFirst(true);
        userAccountBindingHistoryService.addUserAccountBindingHistory(history);
        userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_WX);
        userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, wxUnionId);
    }
    @Override
    public void bindQQ(Long uid, QQUserInfoVO qqUser) throws UserAccountException {
        UserInfo user = userInfoService.selectAvailableByPrimaryKey(uid);
        if (user == null) {
            throw new UserAccountException(1, "用户不存在");
        }
        if (qqUser == null || StringUtil.isNullOrEmpty(qqUser.getOpenid())) {
            throw new UserAccountException(2, "qq用户信息为空");
        }
        String qqOpenIdExist = user.getQqOpenId();
        if (StringUtil.isNullOrEmpty(qqOpenIdExist)) {
            UserInfo newUser = userInfoService.getEffectiveUserInfoByQQOpenId(qqUser.getOpenid(), user.getSystem());
            if (newUser != null) {
                throw new UserAccountException(4, "该QQ号已被其他帐号绑定");
            }
        } else if (qqUser.getOpenid().equalsIgnoreCase(qqOpenIdExist)) {
            throw new UserAccountException(3, "QQ帐号一致无需更换");
        }
        if (StringUtil.isNullOrEmpty(user.getPhone())) {
            throw new UserAccountException(5, "该帐号没有绑定手机号码,需绑定手机号码才能完成QQ更换");
        }
        UserInfo updateUserInfo = new UserInfo(uid);
        updateUserInfo.setQqNickName(qqUser.getNickname());
        updateUserInfo.setQqOpenId(qqUser.getOpenid());
        // 将默认昵称替换成微信昵称
        String defaultNickName = userInfoService.getDefaultNickName(user.getSystem(), user.getId());
        if (!StringUtil.isNullOrEmpty(defaultNickName) && !StringUtil.isNullOrEmpty(qqUser.getNickname())) {
            defaultNickName = defaultNickName + uid;
            if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
                updateUserInfo.setNickName(qqUser.getNickname());
            }
        }
        // 将默认头像替换成QQ头像
        String defaultPortrait = userInfoService.getDefaultPortrait(user.getSystem());
        if (!StringUtil.isNullOrEmpty(qqUser.getFigureurl_2()) && !StringUtil.isNullOrEmpty(defaultPortrait)
                && defaultPortrait.equals(user.getPortrait())) {
            String headimgurl = qqUser.getFigureurl_2();
            updateUserInfo.setPortrait(headimgurl);
        }
        userInfoService.updateByPrimaryKeySelective(updateUserInfo);
        // 加入绑定记录
        UserAccountBindingHistory history = new UserAccountBindingHistory();
        history.setContent(qqUser.getOpenid());
        history.setType(UserAccountBindingHistory.TYPE_QQ);
        history.setUid(uid);
        // 之前已经绑定电话号码
        if (!StringUtil.isNullOrEmpty(user.getQqOpenId()))
            history.setFirst(false);
        else
            history.setFirst(true);
        userAccountBindingHistoryService.addUserAccountBindingHistory(history);
        userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_QQ);
        userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindQQ, user.getQqOpenId());
    }
    @Override
    public UserInfo bindPhoneToLogin(ProxyIP ipinfo, AcceptData acceptData, String phone, String key)
            throws UserAccountException {
        // 判断手机号码是否被封禁
        ForbiddenUserIdentifyCode identifyCode1 = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.phone, phone);
        if (identifyCode1 != null && identifyCode1.getEffective() != null && identifyCode1.getEffective())
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        int loginType = 0;
        String loginName = "";
        if (key.contains("QQLogin#")) {
            //qq登录
            loginType = 4;
            loginName = "QQ";
        } else {
            //微信登录
            loginType = 2;
            loginName = "微信";
        }
        String value = redisManager.getCommonString(key);
        if (StringUtil.isNullOrEmpty(value))
            throw new UserAccountException(1, String.format("%s授权失效,请使用%s重新登录", loginName, loginName));
        SystemEnum system = SystemInfoUtil.getSystem(acceptData);
        String thirdPortrait;
        String thirdCode;
        String thirdNickName;
        QQUserInfoVO qqUser = null;
        WeiXinUser weiXinUser = null;
        if (loginType == 4) {
            qqUser = JsonUtil.getSimpleGson().fromJson(value, QQUserInfoVO.class);
            if (qqUser == null)
                throw new UserAccountException(1, "QQ授权失效,请使用QQ重新授权登录");
            thirdPortrait = qqUser.getFigureurl_2();
            thirdCode = qqUser.getOpenid();
            thirdNickName = qqUser.getNickname();
            UserInfo userInfo = userInfoService.getEffectiveUserInfoByQQOpenId(qqUser.getOpenid(), system);
            // 直接用的QQ登录
            if (userInfo != null)
                throw new UserAccountException(10, "该QQ号已被占用");
        } else {
            weiXinUser = JsonUtil.getSimpleGson().fromJson(value, WeiXinUser.class);
            if (weiXinUser == null)
                throw new UserAccountException(1, "三方授权失效,请使用三方重新授权登录");
            thirdPortrait = weiXinUser.getHeadimgurl();
            thirdCode = weiXinUser.getUnionid();
            thirdNickName = weiXinUser.getNickname();
            UserInfo userInfo = userInfoService.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid(), system);
            // 直接用的微信登录
            if (userInfo != null)
                throw new UserAccountException(10, "该微信号已被占用");
        }
        String portrait = null;
        if (!StringUtil.isNullOrEmpty(thirdPortrait)) {
            InputStream asInputStream = HttpUtil.getAsInputStream(thirdPortrait);
            if (asInputStream != null) {
                String path = "";
                if (loginType == 4) {
                    path = String.format(FilePathEnum.userQQPortrait.getPath() + "%s_%s.jpg", thirdCode,
                            System.currentTimeMillis() + "");
                } else {
                    path = String.format(FilePathEnum.userWXPortrait.getPath() + "%s_%s.jpg", thirdCode,
                            System.currentTimeMillis() + "");
                }
                FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream, path);
                if (result != null && !StringUtil.isNullOrEmpty(result.getUrl()))
                    portrait = result.getUrl();
            } else {
                portrait = thirdPortrait;
            }
        }
        if (StringUtil.isNullOrEmpty(portrait)) {
            portrait = userInfoService.getDefaultPortrait(system);
        }
        // 是否需要创建新账户
        UserInfo phoneUser = userInfoService.getEffectiveUserInfoByPhone(phone, system);
        UserInfo userInfo = null;
        if (phoneUser != null) {
            // 绑定微信
            if (weiXinUser != null) {
                if (StringUtil.isNullOrEmpty(phoneUser.getWxUnionId())) {
                    try {
                        bindWeiXin(phoneUser.getId(), weiXinUser);
                    } catch (Exception e) {
                        throw new UserAccountException(1, "微信绑定失败");
                    }
                } else {
                    throw new UserAccountException(1, "该微信已被绑定");
                }
            }
            if (qqUser != null) {
                if (StringUtil.isNullOrEmpty(phoneUser.getQqOpenId())) {
                    try {
                        bindQQ(phoneUser.getId(), qqUser);
                    } catch (Exception e) {
                        throw new UserAccountException(1, "QQ绑定失败");
                    }
                } else {
                    throw new UserAccountException(1, "该QQ已被绑定");
                }
            }
            userInfo = userInfoService.selectAvailableByPrimaryKey(phoneUser.getId());
        } else {
            // 创建新账户
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setPortrait(portrait);
            userInfo.setAppId(null);
            if (weiXinUser != null) {
                userInfo.setNickName(weiXinUser.getNickname());
                userInfo.setWxName(weiXinUser.getNickname());
                userInfo.setWxOpenId(weiXinUser.getOpenid());
                userInfo.setWxUnionId(weiXinUser.getUnionid());
                userInfo.setWxPic(weiXinUser.getHeadimgurl());
                userInfo.setLoginType(2);
            }
            if (qqUser != null) {
                userInfo.setQqOpenId(qqUser.getOpenid());
                userInfo.setQqNickName(qqUser.getNickname());
                userInfo.setLoginType(4);
            }
            userInfo.setLastLoginTime(System.currentTimeMillis());
            userInfo.setLastLoginIp(ipinfo.getIp());
            userInfo.setState(UserInfo.STATE_NORMAL);
            userInfo.setSystem(system);
            addUser(userInfo);
        }
        Long uid = userInfo.getId();
        final WeiXinUser tempWeiXinUser = weiXinUser;
        final QQUserInfoVO tempQQUser = qqUser;
        ThreadUtil.run(new Runnable() {
            public void run() {
                try {
                    // 第一次登录时创建用户额外信息
                    userInfoExtraService.createUserInfoExtra(uid);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 加入绑定记录
                UserAccountBindingHistory history = new UserAccountBindingHistory();
                history.setContent(phone);
                history.setType(UserAccountBindingHistory.TYPE_PHONE);
                history.setUid(uid);
                history.setFirst(true);
                userAccountBindingHistoryService.addUserAccountBindingHistory(history);
                userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
                if (tempWeiXinUser != null)
                    userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, tempWeiXinUser.getUnionid());
                if (tempQQUser != null)
                    userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindQQ, tempQQUser.getOpenid());
            }
        });
        // 删除缓存
        redisManager.removeCommonString(key);
        return userInfo;
    }
    @Override
    public UserInfo bindWXToLogin(ProxyIP ipInfo, AcceptData acceptData, String code, String appId, String key) throws
            UserAccountException {
        // 日志信息
        JSONObject logInfo = new JSONObject();
        logInfo.put("appId", appId);
        logInfo.put("code", code);
        logInfo.put("loginType", 2);
        LogHelper.lgoinInfo(logInfo.toString());
        SystemEnum system = SystemInfoUtil.getSystem(acceptData);
        // 通过Code换取信息
        WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
        WeiXinUser weiXinUser = WXAppLoginUtil.getWeiXinUser(code, wxAccount.getAppId(), wxAccount.getAppSecret());
        if (weiXinUser == null) {
            throw new UserAccountException(1, "微信帐号授权失败");
        }
        LogHelper.test("微信授权用户信息:" + new Gson().toJson(weiXinUser));
        // 判断微信unionid是否被封禁
        ForbiddenUserIdentifyCode identifyCode = forbiddenUserIdentifyCodeService
                .listByTypeAndIdentifyCode(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId, weiXinUser.getUnionid());
        if (identifyCode != null && identifyCode.getEffective() != null && identifyCode.getEffective()) {
            throw new UserAccountException(Constant.CODE_FORBIDDEN_USER, Constant.FORBIDDEN_USER_REASON_DESC);
        }
        String phone = redisManager.getCommonString(key);
        if (StringUtil.isNullOrEmpty(phone))
            throw new UserAccountException(1, "手机号登录失效,请使发送短信登录");
        // 采用redis事务防止一个微信号多次注册问题
        String watchKey = StringUtil.Md5("REGISTER:" + weiXinUser.getUnionid());
        Jedis jedis = redisManager.getJedis();
        try {
            jedis.watch(watchKey);
            if (jedis.get(watchKey) != null && Integer.parseInt(jedis.get(watchKey)) > 1)
                throw new UserAccountException(10, "请稍后再试");
            Transaction tran = jedis.multi();
            tran.incr(watchKey);
            List<Object> exec = tran.exec();
            if (exec == null || exec.size() == 0) {
                throw new UserAccountException(10, "请稍后再试");
            } else {
                UserInfo userInfo = userInfoService.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid(), system);
                // 直接用的微信登录
                if (userInfo != null) {
                    // 绑定微信
                    if (!StringUtil.isNullOrEmpty(userInfo.getPhone()) && !phone.equals(userInfo.getPhone().trim())) {
                        throw new UserAccountException(1, "该微信已被绑定");
                    }
                    // 删除邀请分享图
                    //spreadUserImgService.deleteImgUrl(userInfo.getId());
                } else {
                    LogHelper.test("微信unionID不存在:" + weiXinUser.getUnionid());
                    String portrait = null;
                    if (!StringUtil.isNullOrEmpty(weiXinUser.getHeadimgurl())) {
                        InputStream asInputStream = HttpUtil.getAsInputStream(weiXinUser.getHeadimgurl());
                        if (asInputStream != null) {
                            FileUploadResult result = COSManager.getInstance().uploadFile(asInputStream,
                                    String.format(FilePathEnum.userWXPortrait.getPath() + "%s_%s.jpg",
                                            weiXinUser.getUnionid(), System.currentTimeMillis() + ""));
                            if (result != null && !StringUtil.isNullOrEmpty(result.getUrl()))
                                portrait = result.getUrl();
                        } else {
                            portrait = weiXinUser.getHeadimgurl();
                        }
                    }
                    if (StringUtil.isNullOrEmpty(portrait)) {
                        portrait = userInfoService.getDefaultPortrait(system);
                    }
                    // 创建新账户
                    userInfo = new UserInfo();
                    userInfo.setPhone(phone);
                    userInfo.setPortrait(portrait);
                    userInfo.setAppId(appId);
                    userInfo.setNickName(weiXinUser.getNickname());
                    userInfo.setWxName(weiXinUser.getNickname());
                    userInfo.setWxOpenId(weiXinUser.getOpenid());
                    userInfo.setWxUnionId(weiXinUser.getUnionid());
                    userInfo.setWxPic(weiXinUser.getHeadimgurl());
                    userInfo.setLastLoginTime(System.currentTimeMillis());
                    userInfo.setLoginType(2);
                    userInfo.setLastLoginIp(ipInfo.getIp());
                    userInfo.setState(UserInfo.STATE_NORMAL);
                    userInfo.setSystem(system);
                    addUser(userInfo);
                    Long uid = userInfo.getId();
                    ThreadUtil.run(new Runnable() {
                        public void run() {
                            try {
                                // 第一次登录时创建用户额外信息
                                userInfoExtraService.createUserInfoExtra(uid);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            // 加入绑定记录
                            UserAccountBindingHistory history = new UserAccountBindingHistory();
                            history.setContent(phone);
                            history.setType(UserAccountBindingHistory.TYPE_PHONE);
                            history.setUid(uid);
                            history.setFirst(true);
                            userAccountBindingHistoryService.addUserAccountBindingHistory(history);
                            userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
                            userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, weiXinUser.getUnionid());
                        }
                    });
                }
                return userInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.del(watchKey);
            jedis.unwatch();
            jedis.close();
        }
        throw new UserAccountException(10, "请稍后再试");
    }
    @Override
    public void forbiddenUserAll(Long uid, String reason) {
        UserInfo currentInfo = userInfoService.selectByPKey(uid);
        if (currentInfo == null) {
            return;
        }
        if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
            return;
        }
        currentInfo.setState(UserInfo.STATE_FORBIDDEN);
        currentInfo.setStateDesc(reason);
        userInfoService.updateByPrimaryKeySelective(currentInfo);
        // 插入记录
        userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_FORBIDDEN, reason);
        // 加入封禁的账号列表
        ForbiddenUserIdentifyCode forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
        forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.wxUnionId);
        forbiddenUserIdentifyCode.setIdentifyCode(currentInfo.getWxUnionId());
        forbiddenUserIdentifyCode.setBeiZhu(currentInfo.getWxName());
        try {
            forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
        } catch (ForbiddenUserIdentifyCodeException e) {
            e.printStackTrace();
        }
        // 电话号码
        forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
        forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.phone);
        forbiddenUserIdentifyCode.setIdentifyCode(currentInfo.getPhone());
        try {
            forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
        } catch (ForbiddenUserIdentifyCodeException e) {
            e.printStackTrace();
        }
        // 淘宝
        UserExtraTaoBaoInfo taoBao = userExtraTaoBaoInfoService.getByUid(uid);
        if (taoBao != null && !StringUtil.isNullOrEmpty(taoBao.getTaoBaoUid())) {
            forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
            forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.taobaoUid);
            forbiddenUserIdentifyCode.setIdentifyCode(taoBao.getTaoBaoUid());
            try {
                forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
            } catch (ForbiddenUserIdentifyCodeException e) {
                e.printStackTrace();
            }
        }
        // 查询支付宝绑定
        List<BindingAccount> list = bindingAccountService.getBindingAccountByUid(uid);
        if (list != null) {
            for (BindingAccount ba : list) {
                forbiddenUserIdentifyCode = new ForbiddenUserIdentifyCode();
                forbiddenUserIdentifyCode.setType(ForbiddenUserIdentifyCodeTypeEnum.alipayAccount);
                forbiddenUserIdentifyCode.setIdentifyCode(ba.getAccount());
                forbiddenUserIdentifyCode.setBeiZhu(ba.getName());
                try {
                    forbiddenUserIdentifyCodeService.forbiddenIdentifyCode(forbiddenUserIdentifyCode);
                } catch (ForbiddenUserIdentifyCodeException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Override
    public void unRegisterUser(Long uid,String reason) {
        UserInfo currentInfo = userInfoService.selectByPKey(uid);
        if (currentInfo == null) {
            return;
        }
        if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
            return;
        }
        currentInfo.setState(UserInfo.STATE_FORBIDDEN);
        currentInfo.setStateDesc(reason);
        userInfoService.updateByPrimaryKeySelective(currentInfo);
        // 插入记录
        userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE, reason);
    }
    @Override
    public void forbiddenUser(Long uid, String reason) {
        UserInfo currentInfo = userInfoService.selectByPKey(uid);
        if (currentInfo == null) {
            return;
        }
        if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
            return;
        }
        currentInfo.setState(UserInfo.STATE_FORBIDDEN);
        currentInfo.setStateDesc(reason);
        userInfoService.updateByPrimaryKeySelective(currentInfo);
        // 插入记录
        userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_FORBIDDEN, reason);
    }
    @Override
    public void DeleteUser(Long uid, String reason) {
        UserInfo currentInfo = userInfoService.selectByPKey(uid);
        if (currentInfo == null) {
            return;
        }
        if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
            return;
        }
        currentInfo.setState(UserInfo.STATE_DELETE);
        currentInfo.setStateDesc(reason);
        userInfoService.updateByPrimaryKeySelective(currentInfo);
        // 插入记录
        userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE, reason);
    }
    @Override
    public void DeleteUserOutOfDate(Long uid, String reason) {
        UserInfo currentInfo = userInfoService.selectByPKey(uid);
        if (currentInfo == null) {
            return;
        }
        if (currentInfo.getState() != UserInfo.STATE_NORMAL) {
            return;
        }
        currentInfo.setState(UserInfo.STATE_DELETE_OUT_OF_DATE);
        currentInfo.setStateDesc(reason);
        userInfoService.updateByPrimaryKeySelective(currentInfo);
        // 插入记录
        userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE_OUT_OF_DATE, reason);
    }
}