浏览代码

add(operation-backend):[子账号管理]

wangxiao 4 年之前
父节点
当前提交
19969b95c0

+ 42 - 7
operation-backend/src/main/java/com/idiot/operationbackend/controller/AccountController.java

@@ -1,7 +1,9 @@
 package com.idiot.operationbackend.controller;
 
 import com.idiot.operationbackend.entity.Account;
+import com.idiot.operationbackend.entity.AuthUser;
 import com.idiot.operationbackend.service.facade.AccountService;
+import com.idiot.operationbackend.service.facade.AuthUserService;
 import com.idiot.operationbackend.support.JsonResult;
 import com.idiot.operationbackend.util.JwtTokenUtil;
 import io.swagger.annotations.Api;
@@ -10,12 +12,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author wang xiao
@@ -32,13 +33,47 @@ public class AccountController {
     @Autowired
     private AccountService accountService;
 
+    @Autowired
+    private AuthUserService userService;
+
+
+
     @GetMapping
     @ApiOperation(value = "查询公众号列表")
     public ResponseEntity<JsonResult<List<Account>>> list (@RequestHeader(value = "AUTH_TOKEN") String token) {
-
         String userId = JwtTokenUtil.getUserId(token);
         logger.info("用户:{}查询公众号列表",userId);
-        accountService.list();
-        return null;
+        List<Account> accounts  = accountService.queryAccountByUserId(userId);;
+        List<AuthUser> authUsers =  userService.querySubAuthUser(userId);
+        /**
+         * fixme 暂定权限是 用户能够查询所属子账号下所有公众号,即无权限
+         */
+        if (! CollectionUtils.isEmpty(authUsers)) {
+            List<String> userIds = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
+            List<Account> subAccounts = accountService.queryAccountBuSubUserIds(userIds);
+            accounts.addAll(subAccounts);
+        }
+        return ResponseEntity.ok(JsonResult.success(accounts));
     }
+
+
+    @GetMapping("confirmAccount")
+    @ApiOperation(value = "确认授权的微信公众号")
+    public ResponseEntity<JsonResult<Boolean>> confirmAccount (@RequestHeader String token,
+                                                               @RequestParam String accountId) {
+        String userId = JwtTokenUtil.getUserId(token);
+        boolean ifUpdate = accountService.updateUserIdByAccount(accountId,userId);
+        return ResponseEntity.ok(JsonResult.success(ifUpdate));
+    }
+
+    @GetMapping("/{id}")
+    @ApiOperation(value = "根据id查询微信公众号")
+    public ResponseEntity<JsonResult<Account>> getAccount (@RequestHeader String token,
+                                                           @PathVariable String id) {
+        String userId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}查询公众号:{}",userId,id);
+        Account account = accountService.getById(id);
+        return ResponseEntity.ok(JsonResult.success(account));
+    }
+
 }

+ 70 - 0
operation-backend/src/main/java/com/idiot/operationbackend/controller/AuthController.java

@@ -3,6 +3,7 @@ package com.idiot.operationbackend.controller;
 import com.baomidou.kaptcha.Kaptcha;
 import com.idiot.operationbackend.entity.AuthUser;
 import com.idiot.operationbackend.service.facade.AuthUserService;
+import com.idiot.operationbackend.support.Constants;
 import com.idiot.operationbackend.support.CustomException;
 import com.idiot.operationbackend.support.JsonResult;
 import com.idiot.operationbackend.util.JwtTokenUtil;
@@ -13,9 +14,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -56,9 +60,75 @@ public class AuthController {
         if (Objects.isNull(authUser)) {
             throw new CustomException(500,"账号或者密码错误!请检查大小写");
         }
+        if (!authUser.getState()) {
+            throw new CustomException(500,"您的账号已经被冻结!请联系父属账号");
+        }
         authUser.setPassword("");
         String  token = JwtTokenUtil.sign(authUser.getNikeName(),authUser.getId());
         return ResponseEntity.ok().header("AUTH_TOKEN",token)
                 .body(JsonResult.success(authUser));
     }
+
+
+    @GetMapping("/subManage")
+    @ApiOperation(value = "子账号管理")
+    public ResponseEntity<JsonResult<List<AuthUser>>> subUserManage(@RequestHeader String token) {
+        String userId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}子账号管理",userId);
+        List<AuthUser> authUsers = userService.querySubAuthUser(userId);
+        return ResponseEntity.ok(JsonResult.success(authUsers));
+    }
+
+
+    @PostMapping("/subManage/{userId}")
+    @ApiOperation(value = "子账号冻结/解冻")
+    public ResponseEntity<JsonResult<Boolean>> manageSubUser(@PathVariable String userId,
+                                                             @RequestHeader String  token) {
+        String parentUserId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}操作子账号:{}",parentUserId,userId);
+        AuthUser authUser = userService.queryAuthUserByParentIdAndId(parentUserId,userId);
+        if (Objects.isNull(authUser)) {
+            throw new CustomException(500,"您的账号无权操作其他人的账号,只能管理自己的子账号");
+        }
+        boolean before = authUser.getState();
+        authUser.setState(!before);
+        return ResponseEntity.ok(JsonResult.success(before));
+    }
+
+
+    @GetMapping("/subPre")
+    @ApiOperation(value = "获取子账号名称前缀")
+    public ResponseEntity<JsonResult<String>> getSubPre(@RequestHeader String  token) {
+        String parentUserId = JwtTokenUtil.getUserId(token);
+
+        return ResponseEntity.ok(JsonResult.success(parentUserId+"@"));
+    }
+
+    @PostMapping("/subCreate")
+    @ApiOperation(value = "子账号创建")
+    public ResponseEntity<JsonResult<Boolean>> createSubUser(@RequestBody AuthUser authUser,
+                                                             @RequestHeader String  token) {
+        String parentUserId = JwtTokenUtil.getUserId(token);
+        logger.info("用户:{}创建 子账号",parentUserId);
+        AuthUser parentUser = userService.getById(parentUserId);
+        if (Objects.isNull(parentUser) || !StringUtils.isEmpty(parentUser.getParentUerId())) {
+            throw new CustomException(500,"您的账号无权是子账号无权创建子账号");
+        }
+        if (Objects.isNull(authUser) || StringUtils.isEmpty(authUser.getUserCode())
+                || StringUtils.isEmpty(authUser.getPassword())) {
+            throw new CustomException(500,"您创建账号信息录入不全,请您补全信息!");
+        }
+        if (! authUser.getUserCode().startsWith(parentUserId)) {
+            throw new CustomException(500,"您创建账号信息非法,账号开始部分不容修改!!");
+        }
+        authUser.setState(true);
+        authUser.setId(null);
+        authUser.setParentUerId(parentUserId);
+        authUser.setCreateTime(Constants.DATE_TIME_FORMATTER.format(LocalDateTime.now()));
+        boolean ifSave = userService.saveUserAndDigPassword(authUser);
+        return ResponseEntity.ok(JsonResult.success(ifSave));
+    }
+
+
+
 }

+ 20 - 10
operation-backend/src/main/java/com/idiot/operationbackend/controller/WeChatController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.idiot.operationbackend.entity.Account;
 import com.idiot.operationbackend.service.facade.AccountService;
 import com.idiot.operationbackend.service.facade.WeChatService;
+import com.idiot.operationbackend.support.AccountState;
 import com.idiot.operationbackend.support.Constants;
 import com.idiot.operationbackend.support.JsonResult;
 import io.swagger.annotations.Api;
@@ -11,13 +12,15 @@ import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
-
+import java.io.IOException;
 
 
 /**
@@ -32,10 +35,12 @@ public class WeChatController {
     private final Logger logger = LoggerFactory.getLogger(WeChatController.class);
 
 
-    @Autowired
-    private WeChatService weChatService;
+    @Value("${confirm-domain}")
+    private String confirmDomain;
 
 
+    @Autowired
+    private WeChatService weChatService;
 
 
     @GetMapping("preAuth")
@@ -79,24 +84,25 @@ public class WeChatController {
 
     @GetMapping("/authCallBack")
     @ApiOperation(value = "授权地址回调")
-    public String authCallBack(@RequestParam(name = "auth_code") String authCode,
-                               @RequestParam(name = "expires_in") String expiresIn)  {
+    public void authCallBack(@RequestParam(name = "auth_code") String authCode,
+                             @RequestParam(name = "expires_in") String expiresIn,
+                             HttpServletResponse response) throws IOException {
         logger.info("微信授权回调 ------->start,authCode is :{},expiresIn:{}",authCode,expiresIn);
         try {
+            // 请求微信数据
             String authorizationInfoStr =  weChatService.getAuthorizationInfo(authCode);
             JSONObject authorizationInfoObj = JSONObject.parseObject(authorizationInfoStr);
             JSONObject authorizationInfo = authorizationInfoObj.getJSONObject("authorization_info");
-
             String authorizerAppId = authorizationInfo.getString("authorizer_appid");
             String authorizerInfoStr = weChatService.getAuthorizerInfo(authorizerAppId);
             JSONObject authorizerInfoObj = JSONObject.parseObject(authorizerInfoStr);
-
+            // 授权信息
             Account account = new Account(authorizerAppId);
             String authorizerAccessToken = authorizationInfo.getString("authorizer_access_token");
             account.setAuthorizerAccessToken(authorizerAccessToken);
             account.setExpiresIn(authorizationInfo.getInteger("expires_in"));
             account.setAuthorizerRefreshToken(authorizationInfo.getString("authorizer_refresh_token"));
-
+            // 授权方信息
             JSONObject authorizerInfo = authorizerInfoObj.getJSONObject("authorizer_info");
             account.setHeadImg(authorizerInfo.getString("head_img"));
             account.setNickName(authorizerInfo.getString("nick_name"));
@@ -107,14 +113,18 @@ public class WeChatController {
             account.setBusinessInfo(authorizerInfo.getJSONObject("business_info").toJSONString());
             account.setAlias(authorizerInfo.getString("alias"));
             account.setQrcodeUrl(authorizerInfo.getString("qrcode_url"));
+            account.setState(AccountState.SUCCESS);
+            // 保存 数据和token
             boolean ifResult = weChatService.saveOrUpdateWechatAcc(account);
             weChatService.cacheAuthorizerAccessToken(account.getId(),authorizerAccessToken);
+            // 重定向到 用户确认中介页面
+
+            response.sendRedirect(confirmDomain+"?accountId="+account.getId());
         }catch (Exception e) {
+            response.sendRedirect(confirmDomain+"?accountId=");
             logger.error("微信授权回调 ------->失败,authCode is :{},expiresIn:{},error message is :{}",authCode,expiresIn,e.getMessage());
-            return Constants.SUCCESS;
         }
 
-        return Constants.SUCCESS;
     }
 
 

+ 3 - 3
operation-backend/src/main/java/com/idiot/operationbackend/entity/Account.java

@@ -16,11 +16,11 @@ public class Account {
     @TableId
     private String id;
 
-    private String authorizerAppId;
+    private transient String authorizerAppId;
 
-    private String authorizerAccessToken;
+    private transient String authorizerAccessToken;
 
-    private String authorizerRefreshToken;
+    private transient String authorizerRefreshToken;
 
     private int expiresIn;
 

+ 10 - 0
operation-backend/src/main/java/com/idiot/operationbackend/entity/AuthUser.java

@@ -30,6 +30,8 @@ public class AuthUser {
 
     private String parentUerId;
 
+    private Boolean state;
+
     private String createTime;
 
     @TableField(exist = false)
@@ -92,6 +94,14 @@ public class AuthUser {
         this.parentUerId = parentUerId;
     }
 
+    public Boolean getState() {
+        return state;
+    }
+
+    public void setState(Boolean state) {
+        this.state = state;
+    }
+
     public String getCreateTime() {
         return createTime;
     }

+ 34 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/facade/AccountService.java

@@ -3,6 +3,8 @@ package com.idiot.operationbackend.service.facade;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.idiot.operationbackend.entity.Account;
 
+import java.util.List;
+
 /**
  * @author wang xiao
  * @date Created in 17:56 2020/9/10
@@ -17,4 +19,36 @@ public interface AccountService extends IService<Account> {
      * @return int
      */
     boolean saveOrUpdateAccount(Account account);
+
+
+    /**
+     *  更新公众号的userId
+     * @author wangxiao
+     * @date 17:05 2020/9/12
+     * @param accountId
+     * @param userId
+     * @return boolean
+     */
+    boolean updateUserIdByAccount(String accountId,String userId);
+
+
+
+    /**
+     *  查询当前账号下的公众号 (不包含子账号)
+     * @author wangxiao
+     * @date 17:57 2020/9/12
+     * @param userId
+     * @return java.util.List<com.idiot.operationbackend.entity.Account>
+     */
+    List<Account> queryAccountByUserId(String userId);
+
+
+    /**
+     *  查询一批账号下的公众号 (不包含子账号)
+     * @author wangxiao
+     * @date 17:59 2020/9/12
+     * @param userIds
+     * @return java.util.List<com.idiot.operationbackend.entity.Account>
+     */
+    List<Account> queryAccountBuSubUserIds(List<String> userIds);
 }

+ 33 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/facade/AuthUserService.java

@@ -3,6 +3,8 @@ package com.idiot.operationbackend.service.facade;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.idiot.operationbackend.entity.AuthUser;
 
+import java.util.List;
+
 /**
  * @author wang xiao
  * @date Created in 15:47 2020/9/10
@@ -18,4 +20,35 @@ public interface AuthUserService extends IService<AuthUser> {
      * @return com.idiot.operationbackend.entity.AuthUser
      */
     AuthUser queryByUserCodeAndPassword(String password,String userCode);
+
+
+    /**
+     *  查询子账号
+     * @author wangxiao
+     * @date 17:45 2020/9/12
+     * @param userId
+     * @return java.util.List<com.idiot.operationbackend.entity.AuthUser>
+     */
+    List<AuthUser> querySubAuthUser(String userId);
+
+
+    /**
+     *  查询账号
+     * @author wangxiao
+     * @date 18:48 2020/9/12
+     * @param parentId
+     * @param id
+     * @return com.idiot.operationbackend.entity.AuthUser
+     */
+    AuthUser queryAuthUserByParentIdAndId(String parentId,String id);
+
+
+    /**
+     *  保存账号并且 加密密码 用来创建子账号
+     * @author wangxiao
+     * @date 19:24 2020/9/12
+     * @param authUser
+     * @return boolean
+     */
+    boolean saveUserAndDigPassword(AuthUser authUser);
 }

+ 21 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/impl/AccountServiceImpl.java

@@ -7,6 +7,7 @@ import com.idiot.operationbackend.mappers.AccountMapper;
 import com.idiot.operationbackend.service.facade.AccountService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -27,4 +28,24 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account>
             return saveOrUpdate(account);
         }
     }
+
+
+    @Override
+    public boolean updateUserIdByAccount(String accountId, String userId) {
+        return update(Wrappers.<Account>lambdaUpdate()
+                .set(Account::getCreateUserId,userId)
+                .eq(Account::getId,accountId));
+    }
+
+
+    @Override
+    public List<Account> queryAccountByUserId(String userId) {
+        return list(Wrappers.<Account>lambdaQuery().eq(Account::getCreateUserId,userId));
+    }
+
+
+    @Override
+    public List<Account> queryAccountBuSubUserIds(List<String> userIds) {
+        return list(Wrappers.<Account>lambdaQuery().in(Account::getCreateUserId,userIds));
+    }
 }

+ 28 - 0
operation-backend/src/main/java/com/idiot/operationbackend/service/impl/AuthUserServiceImpl.java

@@ -7,6 +7,9 @@ import com.idiot.operationbackend.mappers.AuthUserMapper;
 import com.idiot.operationbackend.service.facade.AuthUserService;
 import org.springframework.stereotype.Service;
 import org.springframework.util.DigestUtils;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
 
 
 /**
@@ -26,4 +29,29 @@ public class AuthUserServiceImpl extends ServiceImpl<AuthUserMapper, AuthUser>
                 .eq(AuthUser::getPassword,password),false);
         return authUser;
     }
+
+
+    @Override
+    public List<AuthUser> querySubAuthUser(String userId) {
+        return list(Wrappers.<AuthUser>lambdaQuery().eq(AuthUser::getParentUerId,userId).eq(AuthUser::getState,"1"));
+    }
+
+
+    @Override
+    public AuthUser queryAuthUserByParentIdAndId(String parentId, String id) {
+        return getOne(Wrappers.<AuthUser>lambdaQuery().eq(AuthUser::getId,id).
+                eq(AuthUser::getParentUerId,parentId),false);
+    }
+
+
+    @Override
+    public boolean saveUserAndDigPassword(AuthUser authUser) {
+        String password = authUser.getPassword();
+        if (!StringUtils.isEmpty(password)) {
+            password = DigestUtils.md5DigestAsHex(password.getBytes());
+            password = DigestUtils.md5DigestAsHex(password.getBytes());
+            authUser.setPassword(password);
+        }
+        return save(authUser);
+    }
 }

+ 10 - 0
operation-backend/src/main/java/com/idiot/operationbackend/support/Constants.java

@@ -1,5 +1,8 @@
 package com.idiot.operationbackend.support;
 
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
 /**
  * @author wang xiao
  * @date Created in 11:52 2020/9/11
@@ -7,4 +10,11 @@ package com.idiot.operationbackend.support;
 public class Constants {
 
     public static final String SUCCESS = "success";
+
+    public static final Locale DEFAULT_LOCALE = Locale.CHINA;
+
+    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss",DEFAULT_LOCALE);
+
+
+    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd",DEFAULT_LOCALE);
 }

+ 3 - 1
operation-backend/src/main/resources/application-dev.yml

@@ -61,4 +61,6 @@ wechat:
     # 开发平台配置token
     token: xxxxxx
     # authCallBackUrl 授权回调地址
-    authCallBack: https://xxxx/wechat/authCallBack
+    authCallBack: https://xxxx/wechat/authCallBack
+# 授权确认界面地址 前端界面路由地址
+confirm-domain: https://www.xxxx

+ 2 - 3
operation-backend/src/main/resources/application.yml

@@ -2,9 +2,8 @@ spring:
   application:
     name: operationBackendApplication
   profiles:
-    active: dev
+    active: test
 server:
   port: 38090
   servlet:
-    context-path: /wxoperate
-
+    context-path: /wxoperate

+ 1 - 0
sql/dataBase.sql

@@ -12,6 +12,7 @@ CREATE TABLE `t_auth_user`  (
   `nike_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '昵称',
   `avatar_url` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '头像',
   `parent_user_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '父账号',
+  `state` tinyint(1) NULL DEFAULT NULL COMMENT '0 无效,1有效',
   `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '登录用户' ROW_FORMAT = Dynamic;