yujian
2020-05-09 7e7db2fa55a9a3af46d4fd8ede0dee147f101d64
fanli/src/main/java/com/yeshi/fanli/service/impl/user/UserAccountServiceImpl.java
@@ -1,11 +1,6 @@
package com.yeshi.fanli.service.impl.user;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.io.InputStream;
import java.util.List;
import javax.annotation.Resource;
@@ -15,47 +10,48 @@
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.UserAccountException;
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.hongbao.ThreeSaleSerivce;
import com.yeshi.fanli.service.inter.msg.UserAccountMsgNotificationService;
import com.yeshi.fanli.service.inter.user.BindingAccountService;
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.UserExtraTaoBaoInfoService;
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.FilePathEnum;
import com.yeshi.fanli.util.RedisKeyEnum;
import com.yeshi.fanli.util.RedisManager;
import com.yeshi.fanli.util.StringUtil;
import com.yeshi.fanli.util.TimeUtil;
import com.yeshi.fanli.util.ThreadUtil;
import com.yeshi.fanli.util.factory.msg.MsgAccountDetailFactory;
import com.yeshi.fanli.util.wx.WXLoginUtil;
@@ -80,13 +76,7 @@
   private BindingAccountService bindingAccountService;
   @Resource
   private UserConnectHistoryMapper userConnectHistoryMapper;
   @Resource
   private ThreeSaleSerivce threeSaleSerivce;
   @Resource
   private AccountMessageMapper accountMessageMapper;
   @Resource
   private SpreadUserImgService spreadUserImgService;
@@ -111,16 +101,16 @@
   @Resource
   private JedisPool jedisPool;
   @Lazy
   @Resource
   private UserInfoModifyRecordService userInfoModifyRecordService;
   @Transactional
   @Transactional(rollbackFor = Exception.class)
   @Override
   public LoginResult login(HttpServletRequest request, Boolean first, String appId, String code, String phone,
         UserInfo tbUserInfo, boolean wxinstall, int loginType) throws UserAccountException {
   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);
@@ -152,8 +142,7 @@
            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.getState() != UserInfo.STATE_NORMAL))
               userInfo = null;
            if (userInfo == null) {// 原先的账号不存在
               userInfo = new UserInfo();
@@ -182,7 +171,9 @@
         case 2:// 微信
               // 通过Code换取信息
            weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(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));
@@ -195,8 +186,8 @@
            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.getState() != UserInfo.STATE_NORMAL
                     ))
               userInfo = null;
            // 直接用的微信登录
            if (lastUser == null) {
@@ -214,6 +205,8 @@
                  updateUserInfo.setLastLoginTime(System.currentTimeMillis());
                  updateUserInfo.setLoginType(loginType);
                  updateUserInfo.setLastLoginIp(request.getRemoteHost());
                  // 更新openId
                  updateUserInfo.setOpenid(weiXinUser.getOpenid());
                  userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
                  // 删除邀请图片
@@ -332,8 +325,7 @@
            userInfo = getUserInfoByPhone(appId, phone);
            // 判断用户是否被删除
            if (userInfo != null && userInfo.getState() != null
                  && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
                        || userInfo.getState() == UserInfo.STATE_DELETE))
                  && (userInfo.getState() != UserInfo.STATE_NORMAL))
               userInfo = null;
            if (userInfo == null) {// 原先的账号不存在
@@ -363,17 +355,17 @@
         }
      } else {// 没有安装微信
         LoginResult result = loginNoInstallWX(appId, code, phone, tbUserInfo, loginType);
         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
   @Transactional(rollbackFor = Exception.class)
   @Override
   public LoginResult loginNoInstallWX(String appId, String code, String phone, UserInfo tbUserInfo, int loginType)
         throws UserAccountException {
   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);
@@ -397,7 +389,9 @@
         break;
      case 2:// 微信
            // 通过Code换取信息
         weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code);
         WXAccountInfoDTO wxAccount = Constant.getWXAccount(acceptData.getPlatform(), acceptData.getVersion());
         weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code, wxAccount.getAppId(),
               wxAccount.getAppSecret());
         if (weiXinUser == null)
            throw new UserAccountException(1001, "无法获取到微信个人信息");
@@ -420,8 +414,7 @@
      }
      // 判断用户是否被删除
      if (userInfo != null && userInfo.getState() != null && (userInfo.getState() == UserInfo.STATE_DELETE_OUT_OF_DATE
            || userInfo.getState() == UserInfo.STATE_DELETE))
      if (userInfo != null && userInfo.getState() != null && (userInfo.getState() != UserInfo.STATE_NORMAL))
         userInfo = null;
      if (userInfo != null) {
@@ -458,112 +451,6 @@
      }
   }
   @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寻找用户
@@ -582,8 +469,7 @@
      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) {
         if (list.get(i).getState() == UserInfo.STATE_NORMAL) {
            list.remove(i);
            i--;
         }
@@ -610,8 +496,7 @@
      // 剔除被删除掉的用户
      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) {
         if (list.get(i).getState() != UserInfo.STATE_NORMAL) {
            list.remove(i);
            i--;
         }
@@ -639,8 +524,7 @@
      // 剔除被删除掉的用户
      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) {
         if (list.get(i).getState() !=UserInfo.STATE_NORMAL) {
            list.remove(i);
            i--;
         }
@@ -658,6 +542,7 @@
      userInfoMapper.updateByPrimaryKeySelective(userInfo);
   }
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void register(UserInfo userInfo) throws UserAccountException {
      if (!StringUtil.isNullOrEmpty(userInfo.getPhone())) {
@@ -681,6 +566,7 @@
      addUser(userInfo);
   }
   @Transactional
   @Override
   public void addUser(UserInfo user) {
@@ -698,7 +584,7 @@
      if (StringUtil.isNullOrEmpty(user.getPortrait()))
         user.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
      userInfoMapper.insertSelective(user);
      // 昵称为空时 默认昵称
      if (StringUtil.isNullOrEmpty(user.getNickName())) {
         UserInfo updateUserInfo = new UserInfo(user.getId());
@@ -712,14 +598,13 @@
      } catch (Exception e) {
         e.printStackTrace();
      }
      if (!StringUtil.isNullOrEmpty(user.getPhone()))
      // 添加账号绑定历史
      if (!StringUtil.isNullOrEmpty(user.getPhone()))
         userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, user.getPhone());
      if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
      if (!StringUtil.isNullOrEmpty(user.getWxUnionId()))
         userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindWeiXin, user.getWxUnionId());
   }
   @Override
@@ -729,7 +614,7 @@
   @Override
   public void bindPhone(Long uid, String phone) throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
@@ -744,14 +629,13 @@
      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.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
@@ -773,7 +657,7 @@
   @Override
   public void bindTaoBao(Long uid, String tbOpenId, String tbNickName, String tbPortrait)
         throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
@@ -803,7 +687,7 @@
   @Override
   public void unBindTaoBao(Long uid) throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      if (StringUtil.isNullOrEmpty(user.getOpenid()))
@@ -830,11 +714,13 @@
   }
   @Override
   public void changeWXBind(Long uid, String code) throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
   public void changeWXBind(AcceptData acceptData, Long uid, String code) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         throw new UserAccountException(4, "用户不存在");
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code);
      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()))
@@ -842,18 +728,21 @@
      UserInfo newUser = getUserInfoByWXUnionId(user.getAppId(), weiXinUser.getUnionid());
      if (newUser != null)
         throw new UserAccountException(13, "亲,你要更换绑定的微信号已被其他账号绑定");
         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(weiXinUser.getNickname()) && !StringUtil.isNullOrEmpty(defaultNickName)
            && (defaultNickName.equals(user.getNickName()) || "返利券".equals(user.getNickName()))) {
         updateUserInfo.setNickName(weiXinUser.getNickname());
      if (!StringUtil.isNullOrEmpty(defaultNickName) && !StringUtil.isNullOrEmpty(weiXinUser.getNickname())) {
         defaultNickName = defaultNickName + uid;
         if ((defaultNickName.equals(user.getNickName()) || "板栗快省".equals(user.getNickName()))) {
            updateUserInfo.setNickName(weiXinUser.getNickname());
         }
      }
      // 将默认头像替换成微信头像
@@ -862,60 +751,19 @@
            && 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.selectByPrimaryKey(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.selectByPrimaryKey(uid);
      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)
@@ -930,7 +778,7 @@
   public String repairPortrait(Long uid) {
      if (uid == null)
         return null;
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null)
         return null;
      String prefix = String.format("/portrait/wx/%s_", user.getWxUnionId());
@@ -959,7 +807,7 @@
      return user.getPortrait();
   }
   @Transactional
   @Transactional(rollbackFor = Exception.class)
   @Override
   public UserInfo loginPhone(HttpServletRequest request, int loginType, String vcode, String phone, String appId)
         throws UserAccountException {
@@ -1005,7 +853,9 @@
      // 清空限制
      redisManager.clearSMSFrequencyLimit(phone, SMSHistory.TYPE_LOGIN);
      // 清理次数
      redisManager.removeCommonString("sendMSNLoginCount" + phone);
      String key = RedisKeyEnum.getRedisKey(RedisKeyEnum.SMSLoginCount, phone);
      redisManager.removeCommonString(key);
      // 采用redis事务防止一个手机号多次注册问题
      String watchKey = StringUtil.Md5("REGISTER:" + phone);
@@ -1020,7 +870,7 @@
         if (exec == null || exec.size() == 0) {
            throw new UserAccountException(10, "请稍后再试");
         } else {
            // 查询是否存在该电话历史用户
            UserInfo userInfo = userInfoMapper.getEffectiveUserInfoByPhone(phone);
            if (userInfo != null) {
@@ -1029,7 +879,7 @@
            } else {
               userInfo = new UserInfo();
               userInfo.setAppId(appId);
               //userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
               // userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
               userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
               userInfo.setPhone(phone);
               userInfo.setLoginType(loginType);
@@ -1043,10 +893,10 @@
               } catch (Exception e) {
                  e.printStackTrace();
               }
               userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindPhone, phone);
            }
            return userInfo;
         }
      } catch (Exception e) {
@@ -1054,15 +904,15 @@
      } finally {
         jedis.del(watchKey);
         jedis.unwatch();
         jedisPool.returnResource(jedis);
         jedis.close();
      }
      throw new UserAccountException(10, "请稍后再试");
   }
   @Transactional
   @Transactional(rollbackFor = Exception.class)
   @Override
   public UserInfo loginWinXin(HttpServletRequest request, int loginType, String code, String appId)
         throws UserAccountException {
   public UserInfo loginWinXin(HttpServletRequest request, AcceptData acceptData, int loginType, String code,
         String appId) throws UserAccountException {
      // 日志信息
      JSONObject logInfo = new JSONObject();
      logInfo.put("appId", appId);
@@ -1071,7 +921,8 @@
      LogHelper.lgoinInfo(logInfo.toString());
      // 通过Code换取信息
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(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, "微信帐号授权失败");
      }
@@ -1108,9 +959,27 @@
               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 = Constant.systemCommonConfig.getDefaultPortrait();
               // 创建新账户
               userInfo = new UserInfo();
               userInfo.setPortrait(weiXinUser.getHeadimgurl());
               userInfo.setPortrait(portrait);
               userInfo.setAppId(appId);
               userInfo.setNickName(weiXinUser.getNickname());
               userInfo.setWxName(weiXinUser.getNickname());
@@ -1129,8 +998,9 @@
               } catch (Exception e) {
                  e.printStackTrace();
               }
               userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindWeiXin, weiXinUser.getUnionid());
               userInfoModifyRecordService.addModifyRecord(userInfo.getId(), ModifyTypeEnum.bindWeiXin,
                     weiXinUser.getUnionid());
            }
            return userInfo;
         }
@@ -1139,9 +1009,53 @@
      } finally {
         jedis.del(watchKey);
         jedis.unwatch();
         jedisPool.returnResource(jedis);
         jedis.close();
      }
      throw new UserAccountException(10, "请稍后再试");
   }
   @Transactional(rollbackFor = Exception.class)
   @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 key = RedisKeyEnum.getRedisKey(RedisKeyEnum.emptyKey, StringUtil.Md5("WXLogin:" + weiXinUser.getUnionid()));
         redisManager.cacheCommonString(key, JsonUtil.getSimpleGson().toJson(weiXinUser), 60 * 20);
         throw new UserAccountException(101, key);
      }
      // 更新账户登录信息
      updateLonginInfo(userInfo, loginType, request);
      Long uid = userInfo.getId();
      ThreadUtil.run(new Runnable() {
         public void run() {
            // 删除邀请分享图
            spreadUserImgService.deleteImgUrl(uid);
         }
      });
      return userInfo;
   }
   /**
@@ -1162,7 +1076,7 @@
   @Override
   public void bindPhoneNew(Long uid, String phone) throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null) {
         throw new UserAccountException(1, "用户不存在");
      }
@@ -1196,19 +1110,38 @@
      // 发送消息
      userAccountMsgNotificationService.bindingSuccess(uid, MsgAccountDetailFactory.TYPE_PHONE);
      userInfoModifyRecordService.addModifyRecord(uid, ModifyTypeEnum.bindPhone, phone);
   }
   @Transactional(rollbackFor=UserAccountException.class)
   @Override
   public void bindWeiXin(Long uid, String code) throws UserAccountException {
      UserInfo user = userInfoMapper.selectByPrimaryKey(uid);
   public void bindWeiXin(AcceptData acceptData, Long uid, String code) throws UserAccountException {
      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, "微信帐号授权失败");
      }
      bindWeiXin(uid, weiXinUser);
   }
   @Transactional(rollbackFor=UserAccountException.class)
   @Override
   public void bindWeiXin(Long uid,WeiXinUser weiXinUser) throws UserAccountException {
      UserInfo user = userInfoMapper.selectAvailableByPrimaryKey(uid);
      if (user == null) {
         throw new UserAccountException(1, "用户不存在");
      }
      WeiXinUser weiXinUser = WXLoginUtil.getWeiXinUserWithSavePortrait(code);
      if (weiXinUser == null) {
         throw new UserAccountException(2, "微信帐号授权失败");
      }
@@ -1224,7 +1157,7 @@
         if (newUser != null) {
            throw new UserAccountException(4, "该微信号已被其他帐号绑定");
         }
      } else if (wxUnionId.equals(wxUnionIdExist)) {
      } else if (wxUnionId.equalsIgnoreCase(wxUnionIdExist)) {
         throw new UserAccountException(3, "微信帐号一致无需更换");
      }
@@ -1240,16 +1173,31 @@
      // 将默认昵称替换成微信昵称
      String defaultNickName = Constant.systemCommonConfig.getDefaultNickName();
      if (!StringUtil.isNullOrEmpty(weiXinUser.getNickname()) && !StringUtil.isNullOrEmpty(defaultNickName)
            && (defaultNickName.equals(user.getNickName()) || "返利券".equals(user.getNickName()))) {
         updateUserInfo.setNickName(weiXinUser.getNickname());
      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());
         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);
      }
      userInfoMapper.updateByPrimaryKeySelective(updateUserInfo);
@@ -1267,9 +1215,94 @@
      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(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 = 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
@@ -1394,4 +1427,6 @@
      // 插入记录
      userInfoDeleteRecordService.addDeleteRecord(uid, UserInfo.STATE_DELETE_OUT_OF_DATE, reason);
   }
}