diff --git a/mallinkBApi/src/main/java/com/iformall/controller/BaseController.java b/mallinkBApi/src/main/java/com/iformall/controller/BaseController.java index 89249f077..4bd571436 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/BaseController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/BaseController.java @@ -1,16 +1,13 @@ package com.iformall.controller; -import java.beans.PropertyEditorSupport; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - import cn.binarywang.wx.miniapp.api.WxMaService; import com.iformall.common.ErrorCode; import com.iformall.domain.po.WxAppinfo; +import com.iformall.domain.po.WxBuser; import com.iformall.domain.po.WxMerchantBUser; import com.iformall.exception.MallinkException; import com.iformall.service.WxAppinfoService; +import com.iformall.service.WxBuserService; import com.iformall.service.WxMerchantBUserService; import com.iformall.service.wechat.FmOpenService; import com.iformall.utils.Constant; @@ -24,6 +21,10 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; +import java.beans.PropertyEditorSupport; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; @RestController public class BaseController { @@ -38,6 +39,9 @@ public class BaseController { @Autowired private FmOpenService openService; + @Autowired + private WxBuserService wxBuserService; + @InitBinder public void InitBinder(WebDataBinder dataBinder) { dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { @@ -60,20 +64,31 @@ public class BaseController { }); } - public Long getUserId() { + public Long getBuserId() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); - Long bUserId = (Long) request.getAttribute(Constant.LOGIN_USER_KEY); - return bUserId; + Long id = (Long) request.getAttribute(Constant.LOGIN_USER_KEY); + return id; } public WxMerchantBUser getUser() { - Long bUserId = getUserId(); - WxMerchantBUser user = wxMerchantBUserService.getById(bUserId); - if (user == null) + Long userId = getBuser().getUserId(); + WxMerchantBUser user = wxMerchantBUserService.getById(userId); + if (user == null) { throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } return user; } + public WxBuser getBuser() { + Long id = getBuserId(); + WxBuser user = wxBuserService.getById(id); + if (user == null) { + throw new MallinkException(ErrorCode.USER_IS_EMPTY); + } + return user; + } + + public String getTenantId() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String tenantId = (String) request.getAttribute(Constant.TENANT_ID); diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxInfoController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxInfoController.java index 956993e89..534b4fd2e 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxInfoController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxInfoController.java @@ -4,6 +4,8 @@ package com.iformall.controller; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import com.alibaba.fastjson.JSONObject; import com.iformall.annotation.AuthIgnore; import com.iformall.common.ErrorCode; import com.iformall.common.Result; @@ -11,11 +13,9 @@ import com.iformall.common.ResultData; import com.iformall.domain.po.*; import com.iformall.enums.EnumMallUserStatus; import com.iformall.exception.MallinkException; -import com.iformall.service.MallRolePermissionService; -import com.iformall.service.MallUserInfoService; -import com.iformall.service.MallUserRoleService; -import com.iformall.service.WxAppinfoService; +import com.iformall.service.*; import com.iformall.utils.Constant; +import com.iformall.utils.IPUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import me.chanjar.weixin.common.error.WxErrorException; @@ -27,7 +27,11 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -56,25 +60,148 @@ public class WxInfoController extends BaseController { @Autowired MallRolePermissionService mallRolePermissionService; + @Autowired + WxBuserService wxBuserService; + + @Autowired + WxAuthorizerInfoService wxAuthorizerInfoService; + + @Autowired + WxBuserTokenService wxBuserTokenService; + + @AuthIgnore @ApiOperation("获取OPENID") @PostMapping("getOpenId") public ResultData getOpenId(@RequestBody Map param) { String appId = param.get("appId"); String code = param.get("code"); + String userId = param.get("bUserId"); if (StringUtils.isBlank(appId)) { return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空"); } if (StringUtils.isBlank(code)) { return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "code不能为空"); } + if (StringUtils.isBlank(userId)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "userId不能为空"); + } + String scene = param.get("scene"); + WxAppinfo wxAppinfo = getAppInfo(appId); + // 通过authorizerInfo得到tenant_id + WxAuthorizerInfo wxAuthorizerInfo = null; + WxMaService wxMaService = null; + + wxAuthorizerInfo = wxAuthorizerInfoService.getByAppId(appId); + if (wxAuthorizerInfo == null) { + return new ResultData(ErrorCode.APP_ID_NOT_FOUND); + } + if (isFmOpen) { + wxMaService = getWeappService(appId); + } else { + wxMaService = getWeappServiceByAppInfo(wxAppinfo); + if (StringUtils.isBlank(wxAppinfo.getAccessToken())) { + // 如果没有accessToken,主动获取保存到数据库中,下次访问可以拿来使用 + updateAccessToken(wxAppinfo, wxMaService); + wxMaService = getWeappServiceByAppInfo(wxAppinfo); + + } else { + // 检查token是否已过期, 小时就重新获取 + Date curDate = new Date(); + if (curDate.getTime() > wxAppinfo.getLastTokenTime().getTime() + Constant.H_EXPIRE) { + updateAccessToken(wxAppinfo, wxMaService); + wxMaService = getWeappServiceByAppInfo(wxAppinfo); + } + } + } + + String token = null; + String session_key = null; + String openId = null; + String unionId = null; + boolean boolHaveUnionId = false; + Map resultMap = new HashMap<>(); try { - Map returnMap = new HashMap<>(); - Map retMap = getOpenIdInfo(appId, code); - returnMap.put("openId", retMap.get("openId")); - return new ResultData(returnMap); - } catch (Exception e) { - return new ResultData(Result.ERROR, "解密异常"); + WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code); + //获取会话密钥(session_key) + session_key = session.getSessionKey(); + openId = session.getOpenid(); + unionId = session.getUnionid(); + if (StringUtils.isNotBlank(unionId)) { + boolHaveUnionId = true; + } + resultMap.put("openId", openId); + resultMap.put("session_key", session_key); + } catch (WxErrorException e) { + logger.error(e.getMessage(), e); + throw new MallinkException(ErrorCode.SESSION_KEY_DECODE_ERR.getCode(), e.getMessage()); } + + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + + WxBuser newUser = new WxBuser(); + newUser.setTenantId(wxAuthorizerInfo.getTenantId()); + newUser.setAppId(appId); + newUser.setOpenId(openId); + if (boolHaveUnionId) { + newUser.setUnionId(unionId); + } + + WxBuser oldUser = null; + if (boolHaveUnionId) { + // 优先根据unionId查询 + WxBuser userQ = new WxBuser(); + userQ.setTenantId(wxAuthorizerInfo.getTenantId()); + userQ.setUnionId(unionId); + oldUser = wxBuserService.getByObject(userQ); + } + if (oldUser == null) { + oldUser = wxBuserService.getByOpenId(newUser); + } + if (oldUser != null) { + // 已有用户 + token = oldUser.createToken(new Date()); + resultMap.put("token", token); + request.setAttribute(Constant.LOGIN_USER_KEY, oldUser.getId()); + request.setAttribute(Constant.TENANT_ID, oldUser.getTenantId()); + + oldUser.setRegisterIp(ipaddress); + oldUser.setSessionKey(session_key); + oldUser.setAppId(appId); + oldUser.setOpenId(openId); + if (boolHaveUnionId) { + oldUser.setUnionId(unionId); + } + if (StringUtils.isNotBlank(wxAuthorizerInfo.getOpenAppid())) { + oldUser.setOpenAppId(wxAuthorizerInfo.getOpenAppid()); + } + if (StringUtils.isBlank(oldUser.getScene()) || + oldUser.getScene().equals("undefined")) { // from pages/index/index onLoad.options.scene + oldUser.setScene(scene); + } + oldUser.setLoginCount(oldUser.getLoginCount() + 1); + oldUser.setUserId(Long.parseLong(userId)); + wxBuserTokenService.saveOrUpdate(oldUser); + } else { + // 新用户 + newUser.setTenantId(wxAuthorizerInfo.getTenantId()); + token = newUser.createToken(new Date()); + newUser.setRegisterIp(ipaddress); + newUser.setSessionKey(session_key); + + if (StringUtils.isBlank(newUser.getScene()) || + newUser.getScene().equals("undefined")) { // from pages/index/index onLoad.options.scene + newUser.setScene(scene); + } + newUser.setLoginCount(0); + newUser.setUserId(Long.parseLong(userId)); + wxBuserTokenService.saveOrUpdate(newUser); + resultMap.put("token", token); + request.setAttribute(Constant.LOGIN_USER_KEY, newUser.getId()); + request.setAttribute(Constant.TENANT_ID, newUser.getTenantId()); + } + return new ResultData(resultMap); + } @AuthIgnore @@ -118,56 +245,30 @@ public class WxInfoController extends BaseController { private Map getOpenIdInfo(String appId, String code) { WxAppinfo wxAppinfo = getAppInfo(appId); - - WxMaService wxMaService = null; - if(isFmOpen) { + WxMaService wxMaService = null; + if(isFmOpen) { wxMaService = getWeappService(appId); } else { wxMaService = getWeappServiceByAppInfo(wxAppinfo); if(StringUtils.isBlank(wxAppinfo.getAccessToken())) { // 如果没有accessToken,主动获取保存到数据库中,下次访问可以拿来使用 - try { - String accessToken = wxMaService.getAccessToken(true); - wxAppinfo.setAccessToken(accessToken); - wxAppinfo.setLastTokenTime(new Date()); - wxAppinfo.setExpiresIn(7200); - wxAppinfoService.saveOrUpdate(wxAppinfo); - } catch (WxErrorException e) { - logger.error(e.getMessage()); - } catch (Exception e) { - logger.error(e.getMessage()); - } - + updateAccessToken(wxAppinfo, wxMaService); wxMaService = getWeappServiceByAppInfo(wxAppinfo); - } else { // 检查token是否已过期, 小时就重新获取 Date curDate = new Date(); if(curDate.getTime() > wxAppinfo.getLastTokenTime().getTime() + Constant.H_EXPIRE) { - try { - String accessToken = wxMaService.getAccessToken(true); - wxAppinfo.setAccessToken(accessToken); - wxAppinfo.setLastTokenTime(new Date()); - wxAppinfo.setExpiresIn(7200); - wxAppinfoService.saveOrUpdate(wxAppinfo); - } catch (WxErrorException e) { - logger.error(e.getMessage()); - } catch (Exception e) { - logger.error(e.getMessage()); - } + updateAccessToken(wxAppinfo, wxMaService); wxMaService = getWeappServiceByAppInfo(wxAppinfo); } } } - try { WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code); //获取会话密钥(session_key) String session_key = session.getSessionKey(); String openId = session.getOpenid(); logger.info("openId: " + openId); - - // update admin user by Map resultMap=new HashMap<>(); resultMap.put("openId",openId); resultMap.put("session_key", session_key); @@ -176,6 +277,21 @@ public class WxInfoController extends BaseController { logger.error(e.getMessage(), e); throw new MallinkException(ErrorCode.SESSION_KEY_DECODE_ERR.getCode(), e.getMessage()); } + + } + + private void updateAccessToken(WxAppinfo wxAppinfo, WxMaService wxMaService) { + try { + String accessToken = wxMaService.getAccessToken(true); + wxAppinfo.setAccessToken(accessToken); + wxAppinfo.setLastTokenTime(new Date()); + wxAppinfo.setExpiresIn(7200); + wxAppinfoService.saveOrUpdate(wxAppinfo); + } catch (WxErrorException e) { + logger.error(e.getMessage()); + } catch (Exception e) { + logger.error(e.getMessage()); + } } /** @@ -241,4 +357,187 @@ public class WxInfoController extends BaseController { } } + + /** + * 检查微信用户状态 + * + * @return + */ + @RequestMapping("/checkWechatStatus") + @ApiOperation(value = "判断用户是否完成授权", notes = "") + public ResultData checkWechatStatus() { + Map resultMap = new HashMap(); + WxBuser user = getBuser(); + if (StringUtils.isNotBlank(user.getNickName())) { + resultMap.put("nickName", user.getNickName()); + } else { + logger.warn("用户昵称未授权,跳转到用户授权页!"); + return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权,请跳转到用户昵称授权页!", resultMap); + } + if (StringUtils.isNotBlank(user.getPhone())) { + resultMap.put("phone", user.getPhone()); + } else { + if (StringUtils.isBlank(user.getPhone())) { + logger.warn("用户手机号未授权,跳转到授权手机号页!"); + return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权,请跳转到授权手机号页!", resultMap); + } + if (user.getPhone().contains("*")) { + logger.warn("用户手机号已加密,跳转到手工输入手机号页!"); + return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密,手工输入手机号页!", resultMap); + } + } + return new ResultData(Result.SUCCESS, "是老用户,已完成用户昵称/手机号授权", resultMap); + } + + /** + * 检查用户状态 + * + * @return + */ + @RequestMapping("/checkUserStatus") + @ApiOperation(value = "判断用户是否完成昵称授权", notes = "") + public ResultData checkUserStatus() { + Map resultMap = new HashMap(); + WxBuser user = getBuser(); + if (StringUtils.isNotBlank(user.getNickName())) { + resultMap.put("nickName", user.getNickName()); + } else { + logger.warn("用户昵称未授权,跳转到用户授权页!"); + return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权,请跳转到用户昵称授权页!", resultMap); + } + return new ResultData(Result.SUCCESS, "是老用户,已完成用户昵称授权", resultMap); + } + + /** + * 检查用户状态 + * + * @return + */ + @RequestMapping("/checkPhoneStatus") + @ApiOperation(value = "判断用户是否完成手机授权", notes = "") + public ResultData checkPhoneStatus() { + Map resultMap = new HashMap(); + WxBuser user = getBuser(); + if (StringUtils.isNotBlank(user.getPhone())) { + resultMap.put("phone", user.getPhone()); + } else { + if (StringUtils.isBlank(user.getPhone())) { + logger.warn("用户手机号未授权,跳转到授权手机号页!"); + return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权,请跳转到授权手机号页!", resultMap); + } + if (user.getPhone().contains("*")) { + logger.warn("用户手机号已加密,跳转到手工输入手机号页!"); + return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密,手工输入手机号页!", resultMap); + } + } + return new ResultData(Result.SUCCESS, "是老用户,已完成手机号授权", resultMap); + } + + /** + * 获取用户的昵称等信息 + * + * @param map + * @return + */ + @PostMapping("/getUserInfo") + @ApiOperation(value = "授权后获取用户的昵称,unionId等信息", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}") + public ResultData getUserInfo(@RequestBody Map map) { + logger.debug(map.toString()); + Map resultMap = new HashMap(); + + String encryptedData = map.get("encryptedData"); + String iv = map.get("iv"); + + if (StringUtils.isBlank(encryptedData)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData不能为空"); + } + if (StringUtils.isBlank(iv)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv不能为空"); + } + + WxBuser user = getBuser(); + + if (user != null) { + logger.debug(user.toString()); + WxMaService wxMaService = getWeappService(user.getAppId()); + String session_key = user.getSessionKey(); + try { + // 解密用户信息 + WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(session_key, encryptedData, iv); + if (userInfo != null) { + logger.debug(userInfo.toString()); + user.setUnionId(userInfo.getUnionId()); + user.setNickName(userInfo.getNickName()); + user.setGender(Integer.parseInt(userInfo.getGender())); + user.setAvatarUrl(userInfo.getAvatarUrl()); + user.setProvince(userInfo.getProvince()); + user.setCity(userInfo.getCity()); + user.setLanguage(userInfo.getLanguage()); + wxBuserService.saveOrUpdate(user); + resultMap.put("openId", user.getOpenId()); + resultMap.put("unionId", user.getUnionId()); + resultMap.put("msg", "获取用户信息成功!"); + return new ResultData(resultMap); + } else { + return new ResultData(ErrorCode.NICK_NAME_DECODE_ERR, resultMap); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap); + } + } else { + return new ResultData(ErrorCode.USER_LOGIN_FAILED); + } + } + + @PostMapping("/updateExtInfo") + @ApiOperation(value = "用户更新扩展信息(手机)", notes = "{\"systemInfo\":\"string\"}") + public ResultData updateExtInfo(@RequestBody Map map) { + logger.debug(map.toString()); + + String systemInfo = map.get("systemInfo"); + + WxBuser user = getBuser(); + if (StringUtils.isNotBlank(systemInfo)) { + JSONObject extraInfo = new JSONObject(); + extraInfo.put("systemInfo", JSONObject.parseObject(systemInfo)); + user.setExtraInfo(extraInfo.toJSONString()); + } + wxBuserService.updateExtInfo(user); + return new ResultData(); + } + + @PostMapping("/updateLBS") + @ApiOperation(value = "用户更新位置信息", notes = "{\"latitude\":\"string\",\"longitude\":\"string\"}") + public ResultData updateLBS(@RequestBody Map map) { + logger.debug(map.toString()); + + String longitude = map.get("longitude"); + String latitude = map.get("latitude"); + + WxBuser user = getBuser(); + if (!StringUtils.isBlank(longitude)) + user.setLongitude(BigDecimal.valueOf(Double.valueOf(longitude))); + if (!StringUtils.isBlank(latitude)) + user.setLatitude(BigDecimal.valueOf(Double.valueOf(latitude))); + wxBuserService.updateLBS(user); + return new ResultData(); + } + + @PostMapping("/updateScene") + @ApiOperation(value = "用户更新scene", notes = "{\"scene\":\"string\"}") + public ResultData updateScene(@RequestBody Map map) { + logger.debug(map.toString()); + + String scene = map.get("scene"); + + WxBuser user = getBuser(); + if (StringUtils.isBlank(user.getScene())) { + if (StringUtils.isNotBlank(scene)) { + user.setScene(scene); + wxBuserService.updateScene(user); + } + } + return new ResultData(); + } } diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantBUserController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantBUserController.java index 7481119af..a6d6c795c 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantBUserController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantBUserController.java @@ -10,7 +10,6 @@ import com.iformall.domain.po.WxMerchantBUser; import com.iformall.enums.EnumMerchantBUserStatus; import com.iformall.enums.EnumMerchantStatus; import com.iformall.service.*; -import com.iformall.utils.Constant; import com.iformall.utils.HashUtil; import com.iformall.utils.IPUtil; import io.swagger.annotations.Api; @@ -24,7 +23,6 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; -import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -112,8 +110,6 @@ public class WxMerchantBUserController extends BaseController { public ResultData userLogin(@RequestBody Map map) { logger.debug(map.toString()); - Map resultMap = new HashMap(); - String appId = map.get("appId"); String phone = map.get("phone"); String password = map.get("password"); @@ -127,21 +123,16 @@ public class WxMerchantBUserController extends BaseController { return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "密码不能为空"); } - String token = null; HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String ipaddress = IPUtil.getIpAddr(request); if (!StringUtils.isBlank(latitude) && !StringUtils.isBlank(longitude)) { logger.info("B端用户: " + phone + " 登录 IP" + ipaddress + ", 经纬度(" + longitude + "," + latitude + ")"); } - WxMerchantBUser user = new WxMerchantBUser(); user.setAppId(appId); user.setPhone(phone); user.setStatus(EnumMerchantBUserStatus.VALID.getCode()); - - Date currentDate = new Date(); WxMerchantBUser user1 = null; - try { user1 = wxMerchantBUserService.getBUserByAppId(user); } catch (Exception e) { @@ -169,19 +160,14 @@ public class WxMerchantBUserController extends BaseController { } // check password if (user1.getUserPwd().equalsIgnoreCase(password)) { - token = user1.createToken(currentDate); - resultMap.put("token", token); - resultMap.put("bUserId",user1.getId()); - request.setAttribute(Constant.LOGIN_USER_KEY, user1.getId()); - request.setAttribute(Constant.TENANT_ID, user1.getTenantId()); try { wxMerchantBUserService.saveOrUpdate(user1); } catch (Exception e) { logger.error("B端用户更新用户信息失败, e:" + e.getMessage()); return new ResultData(ErrorCode.DB_FAIL.getCode(), "数据库保存失败,e:" + e.getMessage()); } - - + Map resultMap = new HashMap<>(); + resultMap.put("bUserId", user1.getId()); return new ResultData(resultMap); } else { return new ResultData(ErrorCode.PASSWORD_ERROR); diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantController.java index b8ee96263..69ecbd91f 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxMerchantController.java @@ -2,7 +2,9 @@ package com.iformall.controller; import com.iformall.common.ErrorCode; import com.iformall.common.ResultData; +import com.iformall.domain.po.WxBuser; import com.iformall.domain.po.WxMerchant; +import com.iformall.domain.po.WxMerchantBUser; import com.iformall.domain.po.WxProfitSharingReceiver; import com.iformall.enums.EnumMsgSend; import com.iformall.service.WxMerchantService; @@ -81,4 +83,20 @@ public class WxMerchantController extends BaseController { return wxProfitSharingReceiverService.delReceiver(receiver, EnumMsgSend.MSG_SEND_IMMEDIATELY.getCode()); } + @ApiOperation("查询是否有权限修改账户") + @GetMapping("/permitModifiy") + public ResultData permitModifiy() { + log.debug("[" + getIpAddr() + "] WxMerchantController::permitModifiy"); + WxMerchantBUser user = getUser(); + WxBuser buser = getBuser(); + WxMerchant merchant = new WxMerchant(); + merchant.setId(user.getMerchantId()); + WxMerchant wxMerchant = wxMerchantService.findOne(merchant); + if (wxMerchant == null) { + return new ResultData(false); + } + boolean has = buser.getPhone().equals(wxMerchant.getLinkPhone()); + return new ResultData(has); + } + } diff --git a/mallinkBApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java b/mallinkBApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java index 9ea12dff8..21eb0e188 100644 --- a/mallinkBApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java +++ b/mallinkBApi/src/main/java/com/iformall/interceptor/AuthorizationInterceptor.java @@ -3,9 +3,9 @@ package com.iformall.interceptor; import com.iformall.annotation.AuthIgnore; import com.iformall.common.ErrorCode; -import com.iformall.domain.po.WxMerchantBUser; +import com.iformall.domain.po.WxBuser; import com.iformall.exception.MallinkException; -import com.iformall.service.WxMerchantBUserService; +import com.iformall.service.WxBuserTokenService; import com.iformall.utils.Constant; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -24,8 +24,9 @@ import javax.servlet.http.HttpServletResponse; */ @Component public class AuthorizationInterceptor extends HandlerInterceptorAdapter { + @Autowired - private WxMerchantBUserService wxMerchantBUserService; + private WxBuserTokenService userTokenService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { @@ -53,16 +54,17 @@ public class AuthorizationInterceptor extends HandlerInterceptorAdapter { throw new MallinkException(ErrorCode.NET_TOKEN_EMPTY); } - ///// TODO use b端用户表 // 查询token信息 - WxMerchantBUser wxMerchantBUser = wxMerchantBUserService.getByToken(token); - if(wxMerchantBUser == null || wxMerchantBUser.getExpireTime().getTime() < System.currentTimeMillis()){ + + + WxBuser wxBuser = userTokenService.getByToken(token); + if (wxBuser == null || wxBuser.getExpireTime().getTime() < System.currentTimeMillis()) { throw new MallinkException(ErrorCode.NET_TOKEN_INVALID.getCode(), "URL:" + request.getRequestURL() + " token失效,请重新登录"); } //设置userId到request里,后续根据userId,获取用户信息 - request.setAttribute(Constant.LOGIN_USER_KEY, wxMerchantBUser.getId()); - request.setAttribute(Constant.TENANT_ID, wxMerchantBUser.getTenantId()); + request.setAttribute(Constant.LOGIN_USER_KEY, wxBuser.getId()); + request.setAttribute(Constant.TENANT_ID, wxBuser.getTenantId()); return true; } diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxBuser.java b/mallinkService/src/main/java/com/iformall/domain/po/WxBuser.java new file mode 100644 index 000000000..17bb5e2c8 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxBuser.java @@ -0,0 +1,161 @@ +package com.iformall.domain.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.iformall.utils.Constant; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * @author gongbiao + */ +@TableName(value = "wx_buser") +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class WxBuser extends BaseEntity { + + protected Long id; + + @io.swagger.annotations.ApiModelProperty(value = "租户ID", name = "tenantId") + private String tenantId; + @io.swagger.annotations.ApiModelProperty(value = "微信openId", name = "openId") + private String openId; + @io.swagger.annotations.ApiModelProperty(value = "微信unionId", name = "unionId") + private String unionId; + @io.swagger.annotations.ApiModelProperty(value = "用户昵称", name = "nickName") + private String nickName; + @io.swagger.annotations.ApiModelProperty(value = "用户性别", name = "gender") + private Integer gender; + @io.swagger.annotations.ApiModelProperty(value = "用户头像地址", name = "avatarUrl") + private String avatarUrl; + @io.swagger.annotations.ApiModelProperty(value = "用户绑定的手机号", name = "phone") + private String phone; + @io.swagger.annotations.ApiModelProperty(value = "用户没有区号的手机号", name = "purePhone") + private String purePhone; + @io.swagger.annotations.ApiModelProperty(value = "用户所在城市", name = "city") + private String city; + @io.swagger.annotations.ApiModelProperty(value = "用户所在省份", name = "province") + private String province; + @io.swagger.annotations.ApiModelProperty(value = "用户所在语言", name = "language") + private String language; + @io.swagger.annotations.ApiModelProperty(value = "用户手机区号", name = "countryCode") + private String countryCode; + @io.swagger.annotations.ApiModelProperty(value = "用户注册IP", name = "registerIp") + private String registerIp; + @io.swagger.annotations.ApiModelProperty(value = "验证码手机", name = "verifyCodePhone") + private String verifyCodePhone; + @io.swagger.annotations.ApiModelProperty(value = "注册时记录用户扫码渠道,如朋友圈广告", name = "qrcodeSource") + private String qrcodeSource; + @io.swagger.annotations.ApiModelProperty(value = "二维码来源,小程序", name = "scene") + private String scene; + @io.swagger.annotations.ApiModelProperty(value = "渠道,小程序", name = "sceneAddress") + private String sceneAddress; + @io.swagger.annotations.ApiModelProperty(value = "session key for 微信小程序", name = "sessionKey") + private String sessionKey; + @io.swagger.annotations.ApiModelProperty(value = "成长值", name = "score") + private Integer score; + @io.swagger.annotations.ApiModelProperty(value = "更新时间", name = "updateDate") + private Date updateDate; + @io.swagger.annotations.ApiModelProperty(value = "上次活跃时间", name = "activeTime") + private Date activeTime; + @io.swagger.annotations.ApiModelProperty(value = "创建时间", name = "createDate") + private Date createDate; + @io.swagger.annotations.ApiModelProperty(value = "小程序的appId", name = "appId") + private String appId; + /*用户登录用token**/ + @io.swagger.annotations.ApiModelProperty(value = "用户登录用token", name = "token") + private String token; + /*用户过期时间**/ + @io.swagger.annotations.ApiModelProperty(value = "用户过期时间", name = "expireTime") + private Date expireTime; + /*经度**/ + @io.swagger.annotations.ApiModelProperty(value = "经度", name = "longitude") + private BigDecimal longitude; + /*纬度**/ + @io.swagger.annotations.ApiModelProperty(value = "纬度", name = "latitude") + private BigDecimal latitude; + /*登录次数**/ + @io.swagger.annotations.ApiModelProperty(value = "登录次数", name = "loginCount") + private Integer loginCount; + /*附加信息**/ + @io.swagger.annotations.ApiModelProperty(value = "附加信息", name = "extraInfo") + private String extraInfo; + /** + * 是否关注公众号 + **/ + @io.swagger.annotations.ApiModelProperty(value = "是否关注公众号", name = "isSubscribe") + private Integer isSubscribe; + + @io.swagger.annotations.ApiModelProperty(value = "微信开放平台appId", name = "openAppId") + private String openAppId; + @io.swagger.annotations.ApiModelProperty(value = "服务号openId", name = "mpOpenId") + private String mpOpenId; + @io.swagger.annotations.ApiModelProperty(value = "服务号appId", name = "mpAppId") + private String mpAppId; + @io.swagger.annotations.ApiModelProperty(value = "是否关注服务号", name = "mpSubscribe") + private Integer mpSubscribe; + @io.swagger.annotations.ApiModelProperty(value = "关注服务号时间", name = "mpSubscribeTime") + private Date mpSubscribeTime; + @io.swagger.annotations.ApiModelProperty(value = "关注服务号Scene", name = "mpSubscribeScene") + private String mpSubscribeScene; + @io.swagger.annotations.ApiModelProperty(value = "订阅号openId", name = "subsOpenId") + private String subsOpenId; + @io.swagger.annotations.ApiModelProperty(value = "订阅号appId", name = "subsAppId") + private String subsAppId; + @io.swagger.annotations.ApiModelProperty(value = "是否关注订阅号", name = "subsSubscribe") + private Integer subsSubscribe; + @io.swagger.annotations.ApiModelProperty(value = "关注订阅号时间", name = "subsSubscribeTime") + private Date subsSubscribeTime; + @io.swagger.annotations.ApiModelProperty(value = "关注订阅号Scene", name = "subsSubscribeScene") + private String subsSubscribeScene; + + @io.swagger.annotations.ApiModelProperty(value = "积分", name = "credit") + private Integer credit; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value = "渠道名称", name = "channelName") + private String channelName; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value = "渠道描述", name = "sceneDescription") + protected String sceneDescription; + + @TableField(exist = false) + List sceneList; + + @TableField(exist = false) + protected Date startDate; + + @TableField(exist = false) + protected Date endDate; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value = "操作人类型 枚举:EnumUserType", name = "operatorType") + private Integer operatorType; + + @TableField(exist = false) + @io.swagger.annotations.ApiModelProperty(value = "操作人ID", name = "operatorId") + private Long operatorId; + + @io.swagger.annotations.ApiModelProperty(value = "登录用户ID", name = "userId") + private Long userId; + + public String createToken(Date currentDate) { + if (expireTime == null || expireTime.getTime() - Constant.H_EXPIRE < currentDate.getTime()) { + //生成一个token + this.token = UUID.randomUUID().toString(); + //过期时间 + this.expireTime = new Date(currentDate.getTime() + Constant.EXPIRE); + } + return this.token; + } +} diff --git a/mallinkService/src/main/java/com/iformall/mapper/WxBuserMapper.java b/mallinkService/src/main/java/com/iformall/mapper/WxBuserMapper.java new file mode 100644 index 000000000..e67480165 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/mapper/WxBuserMapper.java @@ -0,0 +1,25 @@ +package com.iformall.mapper; + +import com.iformall.common.CommonMapper; +import com.iformall.domain.dto.WxCUserBasicInfoDto; +import com.iformall.domain.po.WxBuser; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.vo.UserCountVo; + +import java.util.List; +import java.util.Map; + +/** + * @author gongbiao + */ +public interface WxBuserMapper extends CommonMapper { + + List findList(WxBuser record); + + WxBuser findByOpenId(WxBuser record); + + WxBuser findByUnionId(WxBuser record); + + WxBuser findByToken(String token); + +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxBuserService.java b/mallinkService/src/main/java/com/iformall/service/WxBuserService.java new file mode 100644 index 000000000..0155c0177 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/WxBuserService.java @@ -0,0 +1,61 @@ +package com.iformall.service; + +import com.github.pagehelper.PageInfo; +import com.iformall.domain.po.WxBuser; + +public interface WxBuserService { + + /** + * 根据实体查询分页列表 + * + * @param record + * @param pageIndex + * @param pageSize + * @return + */ + PageInfo listAsPage(WxBuser record, Integer pageIndex, Integer pageSize); + + /** + * 根据Id获得实体 + * + * @param id + * @return + */ + WxBuser getById(Long id); + + /** + * 根据openId获得实体 + * + * @param record + * @return + */ + WxBuser getByOpenId(WxBuser record); + + /** + * 根据object获得实体 + * + * @param record + * @return + */ + WxBuser getByObject(WxBuser record); + + /** + * 保存或更新实体 + * + * @param record + */ + int saveOrUpdate(WxBuser record); + + /** + * 根据Id删除实体 + * + * @param id + */ + void deleteById(Long id); + + int updateExtInfo(WxBuser user); + + int updateLBS(WxBuser user); + + int updateScene(WxBuser user); +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxBuserTokenService.java b/mallinkService/src/main/java/com/iformall/service/WxBuserTokenService.java new file mode 100644 index 000000000..3160503c7 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/WxBuserTokenService.java @@ -0,0 +1,21 @@ +package com.iformall.service; + +import com.iformall.domain.po.WxBuser; + +public interface WxBuserTokenService { + + /** + * 根据token获得实体 + * + * @param token + * @return + */ + WxBuser getByToken(String token); + + /** + * 保存或更新实体 + * + * @param record + */ + int saveOrUpdate(WxBuser record); +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxBuserServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxBuserServiceImpl.java new file mode 100644 index 000000000..1c6c4a603 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxBuserServiceImpl.java @@ -0,0 +1,124 @@ +package com.iformall.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.iformall.common.IdWorker; +import com.iformall.domain.po.WxBuser; +import com.iformall.mapper.WxBuserMapper; +import com.iformall.service.WxBuserService; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; + +/** + * @author gongbiao + */ +@Service +public class WxBuserServiceImpl implements WxBuserService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxBuserMapper wxBuserMapper; + + @Override + public PageInfo listAsPage(WxBuser record, Integer pageIndex, Integer pageSize) { + return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxBuserMapper.findList(record)); + } + + @Override + public WxBuser getById(Long id) { + return wxBuserMapper.selectById(id); + } + + @Override + public WxBuser getByOpenId(WxBuser record) { + return wxBuserMapper.findByOpenId(record); + } + + @Override + public WxBuser getByObject(WxBuser record) { + try { + return wxBuserMapper.selectOne(new QueryWrapper(record)); + } catch (Exception e) { + logger.error("NOT found: " + e.getMessage()); + } + return null; + } + + @Override + public int saveOrUpdate(WxBuser user) { + int ret = 0; + Date curr = new Date(); + if (user.getId() == null) { + // 检查用户是否已有同一微信开放平台账号 + if (StringUtils.isNotBlank(user.getUnionId()) && StringUtils.isNotBlank(user.getOpenAppId())) { + WxBuser oldUser = wxBuserMapper.findByUnionId(user); + if (oldUser != null) { + // 已有,更新 + user.setId(oldUser.getId()); + // TODO 是否其他信息需要更新 + ret = wxBuserMapper.updateById(user); + return ret; + } + } + final IdWorker idWorker = IdWorker.get(); + user.setId(idWorker.nextId()); + user.setLoginCount(1); + user.setCreateDate(curr); + user.setUpdateDate(curr); + ret = wxBuserMapper.insert(user); + } else { + user.setUpdateDate(curr); + ret = wxBuserMapper.updateById(user); + } + + return ret; + } + + @Override + public void deleteById(Long id) { + wxBuserMapper.deleteById(id); + } + + + @Override + public int updateScene(WxBuser record) { + Date curr = new Date(); + WxBuser userL = new WxBuser(); + userL.setId(record.getId()); + userL.setScene(record.getScene()); + userL.setUpdateDate(curr); + int ret = wxBuserMapper.updateById(userL); + return ret; + } + + @Override + public int updateLBS(WxBuser record) { + Date curr = new Date(); + WxBuser userL = new WxBuser(); + userL.setId(record.getId()); + userL.setLongitude(record.getLongitude()); + userL.setLatitude(record.getLatitude()); + userL.setUpdateDate(curr); + int ret = wxBuserMapper.updateById(userL); + return ret; + } + + @Override + public int updateExtInfo(WxBuser record) { + Date curr = new Date(); + WxBuser userL = new WxBuser(); + userL.setId(record.getId()); + userL.setExtraInfo(record.getExtraInfo()); + userL.setUpdateDate(curr); + int ret = wxBuserMapper.updateById(userL); + return ret; + } + + +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxBuserTokenServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxBuserTokenServiceImpl.java new file mode 100644 index 000000000..c0e628075 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxBuserTokenServiceImpl.java @@ -0,0 +1,77 @@ +package com.iformall.service.impl; + +import com.iformall.common.IdWorker; +import com.iformall.domain.po.WxBuser; +import com.iformall.mapper.WxBuserMapper; +import com.iformall.service.WxBuserTokenService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@Service +public class WxBuserTokenServiceImpl implements WxBuserTokenService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private String tokenPrev = "weapp:b:token:"; + + @Autowired + WxBuserMapper wxBuserMapper; + + @Autowired + @Qualifier("buserTokenRedisTemplate") + RedisTemplate bUserTokenRedisTemplate; + + @Override + public WxBuser getByToken(String token) { + logger.info("获取用户信息start ..."); + String key = tokenPrev + token; + ValueOperations operations = bUserTokenRedisTemplate.opsForValue(); + + // 缓存 + boolean hasKey = bUserTokenRedisTemplate.hasKey(key); + if (hasKey) { + // 从缓存获取用户信息 + WxBuser user = operations.get(key); + return user; + } + WxBuser user = wxBuserMapper.findByToken(token); + // 插入缓存 + operations.set(key, user, 3600, TimeUnit.SECONDS); + + return user; + } + + @Override + public int saveOrUpdate(WxBuser user) { + int ret = 0; + Date curr = new Date(); + if (user.getId() == null) { + final IdWorker idWorker = IdWorker.get(); + user.setId(idWorker.nextId()); + user.setLoginCount(1); + user.setCreateDate(curr); + user.setUpdateDate(curr); + ret = wxBuserMapper.insert(user); + } else { + user.setUpdateDate(curr); + ret = wxBuserMapper.updateById(user); + } + String key = tokenPrev + user.getToken(); + // 缓存已存在,删除 + boolean hasKey = bUserTokenRedisTemplate.hasKey(key); + if (hasKey) { + bUserTokenRedisTemplate.delete(key); + logger.info("更新用户,从缓存中删除用户 token >> " + user.getToken()); + } + + return ret; + } + +} diff --git a/mallinkService/src/main/resources/mapper/WxBuserMapper.xml b/mallinkService/src/main/resources/mapper/WxBuserMapper.xml new file mode 100644 index 000000000..d1901bdf3 --- /dev/null +++ b/mallinkService/src/main/resources/mapper/WxBuserMapper.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `id`,`tenant_id`,`open_id`,`union_id`,`nick_name`,`gender`,`avatar_url`,`phone`,`pure_phone`, + `city`,`province`,`language`,`country_code`,`register_ip`,`verify_code_phone`, + `qrcode_source`,`scene`,`scene_address`,`session_key`,`score`, + `update_date`,`create_date`,`app_id`,`token`,`expire_time`,`latitude`, `longitude`, + `login_count`, `extra_info`, `is_subscribe`,`open_app_id`,`user_id`, + `mp_open_id`,`mp_app_id`,`mp_subscribe`,`mp_subscribe_time`,`mp_subscribe_scene`, + `subs_open_id`,`subs_app_id`,`subs_subscribe`,`subs_subscribe_time`,`subs_subscribe_scene`,`credit`,`active_time` + + + + where 1 = 1 + + + and `id` = #{id} + + + + and `tenant_id`= #{tenantId} + + + + and `open_id` = #{openId} + + + + and `union_id` = #{unionId} + + + + and `nick_name` like concat('%', #{nickName},'%') + + + + and `gender` = #{gender} + + + + and `avatar_url` like concat('%', #{avatarUrl},'%') + + + + and `phone` like concat('%', #{phone},'%') + + + + and `pure_phone` like concat('%', #{purePhone},'%') + + + + and `city` like concat('%', #{city},'%') + + + + and `province` like concat('%', #{province},'%') + + + + and `language` like concat('%', #{language},'%') + + + + and `country_code` like concat('%', #{countryCode},'%') + + + + and `register_ip` like concat('%', #{registerIp},'%') + + + + and `verify_code_phone` like concat('%', #{verifyCodePhone},'%') + + + + and `qrcode_source` like concat('%', #{qrcodeSource},'%') + + + + and `scene` like concat('%', #{scene},'%') + + + + and `scene_address` like concat('%', #{sceneAddress},'%') + + + + and `session_key` like concat('%', #{sessionKey},'%') + + + + and `score` = #{score} + + + + and `update_date` = #{updateDate} + + + + and `create_date` = #{createDate} + + + + and `app_id` like concat('%', #{appId},'%') + + + + and `token` like concat('%', #{token},'%') + + + + and `expire_time` = #{expireTime} + + + + and `latitude` = #{latitude} + + + + and `longitude` = #{longitude} + + + + and `login_count` = #{loginCount} + + + + and `extra_info` = #{extraInfo} + + + + and `is_subscribe` = #{isSubscribe} + + + + and `open_app_id` = #{openAppId} + + + + and `mp_open_id` = #{mpOpenId} + + + + and `mp_app_id` = #{mpAppId} + + + + and `subs_open_id` = #{subsOpenId} + + + + and `subs_app_id` = #{subsAppId} + + + + and `credit` = #{credit} + + + + and `user_id` = #{userId} + + + and id in + + #{idItem} + + + order by ${sortColumns} + + + + + + + + + + + + +