admin
2025-02-25 30d8e227e8d823b6c38c3b9c90ac2df03b63befe
fanli/src/main/java/com/yeshi/fanli/service/impl/user/UserAccountServiceImpl.java
@@ -1,1639 +1,1896 @@
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.system.BusinessSystem;
import com.yeshi.fanli.util.*;
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.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.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.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 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 JedisPool jedisPool;
    @Lazy
    @Resource
    private UserInfoModifyRecordService userInfoModifyRecordService;
    @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");
        // 会话中上次登录的用户
        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 = 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(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(Constant.systemCommonConfig.getDefaultNickName());
                        userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
                        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());
        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 = 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(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(Constant.systemCommonConfig.getDefaultPortrait());
                    userInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName());
                    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()))
            user.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
        userInfoService.createUser(user,user.getSystem());
        // 昵称为空时 默认昵称
        if (StringUtil.isNullOrEmpty(user.getNickName())) {
            UserInfo updateUserInfo = new UserInfo(user.getId());
            updateUserInfo.setNickName(Constant.systemCommonConfig.getDefaultNickName() + user.getId());
            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(Constant.systemCommonConfig.getDefaultNickName() + user.getId());
            update.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
        }
        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 = 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.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());
        // 将默认昵称替换成微信昵称
        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());
        }
        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();
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserInfo loginPhone(ProxyIP ipInfo, int loginType, String vcode, String phone, BusinessSystem businessSystem)
            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", businessSystem.getAppid());
        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, businessSystem.getSystem());
                if (userInfo != null) {
                    // 更新账户登录信息
                    updateLonginInfo(userInfo, loginType, ipInfo);
                } else {
                    userInfo = new UserInfo();
                    userInfo.setAppId(businessSystem.getAppid());
                    userInfo.setPortrait(Constant.systemCommonConfig.getDefaultPortrait());
                    userInfo.setPhone(phone);
                    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, phone);
                }
                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 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 = WXLoginUtil.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 = Constant.systemCommonConfig.getDefaultPortrait();
                    // 创建新账户
                    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 = WXLoginUtil.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,
                    StringUtil.Md5("WXLogin:" + weiXinUser.getUnionid()));
            redisManager.cacheCommonString(key, JsonUtil.getSimpleGson().toJson(weiXinUser), 60 * 20);
            throw new UserAccountException(101, 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(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 = 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 = 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(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 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);
        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, "微信授权失效,请使用微信重新登录");
        SystemEnum system = SystemInfoUtil.getSystem(acceptData);
        UserInfo userInfo = userInfoService.getEffectiveUserInfoByWXUnionId(weiXinUser.getUnionid(), system);
        // 直接用的微信登录
        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 phoneUser = userInfoService.getEffectiveUserInfoByPhone(phone, system);
        if (phoneUser != null) {
            // 绑定微信
            if (StringUtil.isNullOrEmpty(phoneUser.getWxUnionId())) {
                try {
                    bindWeiXin(phoneUser.getId(), weiXinUser);
                } catch (Exception e) {
                    throw new UserAccountException(1, "微信绑定失败");
                }
            } else {
                throw new UserAccountException(1, "该微信已被绑定");
            }
            userInfo = userInfoService.selectAvailableByPrimaryKey(phoneUser.getId());
        } else {
            // 创建新账户
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setPortrait(portrait);
            userInfo.setAppId(null);
            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());
            }
        });
        // 删除缓存
        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 = 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);
        }
        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 = 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(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 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);
    }
}