qzyReal 1 рік тому
батько
коміт
b68d59eddd

+ 8 - 16
sp-core/sp-base/src/main/java/com/pj/current/mybatis/DataScopePermissionHandler.java

@@ -61,14 +61,14 @@ public class DataScopePermissionHandler implements Interceptor {
 
                     //根据用户权限拼接sql
                     String column = requiredPermission.value();
-                    String checkSql=sql.toLowerCase();
-                    if (checkSql.contains("select count(0) from")){
-                        if (checkSql.contains("where")){
-                            sql=sql+" and "+column+" = "+tradeAreaId;
-                        }else {
-                            sql=sql+" where "+column+" = "+tradeAreaId;
+                    String checkSql = sql.toLowerCase();
+                    if (checkSql.contains("select count(0) from")) {
+                        if (checkSql.contains("where")) {
+                            sql = sql + " and " + column + " = " + tradeAreaId;
+                        } else {
+                            sql = sql + " where " + column + " = " + tradeAreaId;
                         }
-                    }else {
+                    } else {
                         sql = "select * from (" + sql + " ) as p where p." + column + " = " + tradeAreaId;
                     }
                     //将sql注入boundSql
@@ -81,15 +81,7 @@ public class DataScopePermissionHandler implements Interceptor {
     }
 
     private Long getTradeAreaId() {
-        PCLoginUserInfo pcLoginUserInfo = StpUserUtil.getPCLoginInfo();
-        if (pcLoginUserInfo != null) {
-            return pcLoginUserInfo.getTradeAreaId();
-        }
-        APPLoginUserInfo appLoginUserInfo = StpAPPUserUtil.getAPPLoginInfo();
-        if (appLoginUserInfo != null) {
-            return appLoginUserInfo.getTradeAreaId();
-        }
-        return 0L;
+        return StpAPPUserUtil.isLogin() ? StpAPPUserUtil.getAPPLoginInfo().getTradeAreaId() : StpAPPUserUtil.isLogin() ? StpAPPUserUtil.getAPPLoginInfo().getTradeAreaId() : 0L;
 
     }
 

+ 6 - 0
sp-core/sp-base/src/main/java/com/pj/face/handler/IFaceHandler.java

@@ -34,5 +34,11 @@ public interface IFaceHandler {
      */
     boolean verify(String faceId, String baseImage);
 
+    /**
+     * 人脸搜索
+     * @param baseImg
+     * @return
+     */
+    String faceSearch(String baseImg);
     FaceBrand faceBrand();
 }

+ 36 - 7
sp-core/sp-base/src/main/java/com/pj/face/handler/impl/TencenFaceHandlerImpl.java

@@ -1,14 +1,8 @@
 package com.pj.face.handler.impl;
 
-import cn.hutool.core.net.URLEncoder;
-import cn.hutool.crypto.digest.MD5;
-import cn.hutool.http.HttpUtil;
 import com.pj.face.brand.FaceBrand;
 import com.pj.face.handler.IFaceHandler;
 import com.pj.face.properties.TencenProperties;
-import com.pj.sms.brand.SmsType;
-import com.pj.sms.handler.ISmsHandler;
-import com.pj.sms.properties.DuanXinBaoProperties;
 import com.pj.utils.sg.AjaxError;
 import com.tencentcloudapi.common.Credential;
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
@@ -20,7 +14,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * 人脸库管理地址
@@ -48,6 +44,37 @@ public class TencenFaceHandlerImpl implements IFaceHandler {
         }
         return resp != null && resp.getIsMatch();
     }
+
+    /**
+     * 查找人脸库
+     * @param baseImg
+     * @return
+     */
+    public String faceSearch(String baseImg) {
+        IaiClient client = this.createClient();
+        SearchFacesRequest request = new SearchFacesRequest();
+        request.setImage(baseImg);
+        request.setMaxFaceNum(1L);
+        request.setMinFaceSize(80L);
+        request.setMaxPersonNum(2L);
+        request.setGroupIds(new String[]{tencenProperties.getGroupId()});
+        SearchFacesResponse response;
+        AtomicReference<String> faceId = new AtomicReference<>("");
+        try {
+            response = client.SearchFaces(request);
+        } catch (TencentCloudSDKException e) {
+            throw new AjaxError("无人脸信息");
+        }
+        Arrays.stream(response.getResults())
+                .forEach(result -> {
+                    Optional<Candidate> optionalCandidate = Arrays.stream(result.getCandidates())
+                            .filter(candidate -> candidate.getScore() >= 80)
+                            .findFirst();
+                    optionalCandidate.ifPresent(candidate -> faceId.set(candidate.getPersonId()));
+                });
+        return faceId.get();
+    }
+
     public void createPersonByBase(String personId, String name, String imageBase) {
         IaiClient client = this.createClient();
         // 实例化一个请求对象,每个接口都会对应一个request对象
@@ -64,6 +91,7 @@ public class TencenFaceHandlerImpl implements IFaceHandler {
         }
 
     }
+
     public boolean checkIsLive(String baseImg) {
         IaiClient client = this.createClient();
         DetectLiveFaceRequest req = new DetectLiveFaceRequest();
@@ -78,6 +106,7 @@ public class TencenFaceHandlerImpl implements IFaceHandler {
         }
         return resp != null && resp.getIsLiveness();
     }
+
     @Override
     public FaceBrand faceBrand() {
         return FaceBrand.TENCEN_SMS;

+ 3 - 3
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrder.java

@@ -324,7 +324,7 @@ public class TbOrder extends Model<TbOrder> implements Serializable {
 	/**
 	 * 边民确认
 	 */
-	private Integer peopleConfirmStatus;
+	private Integer peopleConfirmStatus=0;
 
 	/**
 	 * 边民确认类型
@@ -339,7 +339,7 @@ public class TbOrder extends Model<TbOrder> implements Serializable {
 	/**
 	 * 互助委托申报确认状态
 	 */
-	private Integer cooperEntrustStatus;
+	private Integer cooperEntrustStatus=0;
 
 	/**
 	 * 互助委托申报确认时间
@@ -349,7 +349,7 @@ public class TbOrder extends Model<TbOrder> implements Serializable {
 	/**
 	 * 边民进口申报确认状态
 	 */
-	private Integer applyConfirmStatus;
+	private Integer applyConfirmStatus=0;
 
 	/**
 	 * 边民进口申报确认时间

+ 0 - 1
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderMapper.java

@@ -26,7 +26,6 @@ public interface TbOrderMapper extends BaseMapper <TbOrder> {
 	 * @param so 参数集合
 	 * @return 数据列表
 	 */
-	@DataScope("trade_area_id")
 	List<TbOrder> getList(SoMap so);
 
 	ConfirmVo getConfirmStatus(Long orderId);

+ 22 - 25
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderService.java

@@ -4,6 +4,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.pj.api.client.admin.AdminInterface;
 import com.pj.api.client.async_server.AsyncServerInterface;
@@ -185,9 +186,7 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
         if (appLoginInfo == null || appLoginInfo.getLoginId() == null)
             throw new RuntimeException("当前登陆用户信息已失效!");
-        so.put("buyUserId", appLoginInfo.getLoginId());
-        so.put("deleteStatus", DeleteStatus.DELETE_STATUS_ON.getCode());
-        return tbOrderMapper.getList(so);
+        return findByBuyUserId(appLoginInfo.getLoginId());
     }
 
     /**
@@ -393,25 +392,17 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         }
         // TODO: 2023/8/28 边民发起支付申请,调用银行接口:验证边民支付信息,将货款先存入银行第三方账户,并给出回执
         // 银行返回支付回执为"交易成功"时,方法往下执行
-
-        //获取登录人
-        APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
-
         // TODO: 2023/8/29 更新状态保存交易记录
-        LambdaUpdateWrapper<TbOrder> wrapper = new LambdaUpdateWrapper<>();
-        wrapper.set(TbOrder::getPeopleConfirmStatus, ConfirmStatus.CONFIRM_STATUS_ONE.getCode());//边民确认:1=确认
-        wrapper.set(TbOrder::getPeopleConfirmTime, new Date());
-        wrapper.set(TbOrder::getUpdateBy, appLoginInfo.getLoginId());
-        wrapper.set(TbOrder::getUpdateName, appLoginInfo.getLoginName());
-        wrapper.set(TbOrder::getUpdateTime, new Date());
-        wrapper.eq(TbOrder::getId, orderId);
-        boolean result = update(wrapper);
-
-        if (result && "1".equals(tbOrder.getDeclareType())) {
+        tbOrder.setPeopleConfirmTime(new Date())
+                .setPeopleConfirmStatus(ConfirmStatus.CONFIRM_STATUS_ONE.getCode())
+                .setUpdateTime(new Date());
+        if ("1".equals(tbOrder.getDeclareType())) {
             // TODO: 2023/8/29 调用航通009接口,发送信息
             sendConfirmMsgToHt(tbOrder);
         }
-        return result;
+       return super.updateById(tbOrder);
+
+
     }
 
     /**
@@ -490,14 +481,8 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
         TbPeople tbPeople = tbPeopleMapper.selectById(appLoginInfo.getFk());
         if (tbPeople == null) throw new ServiceException("当前用户不存在,请联系管理员!");
-
-        SoMap so = new SoMap();
-        so.put("buyUserId", appLoginInfo.getFk());
-        so.put("deleteStatus", DeleteStatus.DELETE_STATUS_ON.getCode());
-        List<TbOrder> orderList = tbOrderMapper.getList(so);
-
+        List<TbOrder> orderList = findByBuyUserId(appLoginInfo.getFk());
         OrderVo orderVo = new OrderVo();
-
         //被委托订单,并且三个状态中有一个未确认
         List<TbOrder> declareList2 = orderList.stream().filter(item -> !"1".equals(item.getDeclareType()) &&
                 (item.getPeopleConfirmStatus() == 0 || item.getCooperEntrustStatus() == 0 || item.getApplyConfirmStatus() == 0)).collect(Collectors.toList());
@@ -515,6 +500,18 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         return null;
     }
 
+    /**
+     * 根据购买者ID查询
+     * @param buyUserId
+     * @return
+     */
+    private List<TbOrder> findByBuyUserId(Long buyUserId) {
+        QueryWrapper<TbOrder>ew=new QueryWrapper<>();
+        ew.lambda().eq(TbOrder::getBuyUserId,buyUserId)
+                .eq(TbOrder::getDeleteStatus,DeleteStatus.DELETE_STATUS_ON.getCode());
+        return list(ew);
+    }
+
 
 
     /*-----           正常业务逻辑👆👆    rpc远程调用👇👇 -----*/

+ 3 - 0
sp-service/level-two-server/src/main/java/com/pj/tb_fee_item/TbFeeItem.java

@@ -79,6 +79,9 @@ public class TbFeeItem extends Model<TbFeeItem> implements Serializable {
 	 * 状态(0=禁用,1=启用) 
 	 */
 	private Integer status=1;
+	private String goodsCodes;
+	private String goodsType;
+	private String action;
 
 	/**
 	 * 创建时间 

+ 10 - 6
sp-service/sp-admin/src/main/java/com/pj/project/app_user/AppUserApiController.java

@@ -12,6 +12,7 @@ import com.pj.utils.so.SoMap;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.Date;
 import java.util.HashMap;
@@ -60,15 +61,18 @@ public class AppUserApiController {
 
     /** 边民首次使用APP人脸认证 */
     @PostMapping("face")
-    public AjaxJson face(){
-        AppUser user=new AppUser();
-        user.setId(StpAPPUserUtil.getAPPLoginInfo().getLoginId());
-        user.setFace(1);
-        user.setFaceTime(new Date());
-        return AjaxJson.toAjax(appUserService.updateById(user));
+    public AjaxJson face(@RequestPart MultipartFile file){
+        appUserService.authFace(StpAPPUserUtil.getAPPLoginInfo().getLoginId(),file);
+        return AjaxJson.getSuccess();
+    }
+    @PostMapping("faceLogin")
+    public AjaxJson faceLogin(@RequestPart MultipartFile file){
+        return  appUserService.faceLogin(file);
     }
 
 
+
+
     /**
      * 用户注册
      */

+ 110 - 6
sp-service/sp-admin/src/main/java/com/pj/project/app_user/AppUserService.java

@@ -1,7 +1,9 @@
 package com.pj.project.app_user;
 
 import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.hutool.core.codec.Base64;
 import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -18,6 +20,7 @@ import com.pj.current.satoken.StpAPPUserUtil;
 import com.pj.current.satoken.StpUserUtil;
 import com.pj.enummj.DeleteStatus;
 import com.pj.enummj.IsLock;
+import com.pj.face.factory.FaceFactory;
 import com.pj.project.app_user.dto.ForgetPasswordDto;
 import com.pj.project.app_user.dto.LoginDto;
 import com.pj.project.app_user.dto.PassDto;
@@ -40,7 +43,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -79,7 +85,7 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
      * 阿里云验证码
      */
     @Autowired
-    private SmsRetryService smsRetryService;
+    private FaceFactory faceFactory;
     @Autowired
     private LevelOneServerInterface levelOneServerInterface;
     @Autowired
@@ -121,11 +127,12 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
 
     /**
      * 修改密码
+     *
      * @param dto
      * @return
      */
     boolean pass(PassDto dto) {
-        AppUser user=new AppUser();
+        AppUser user = new AppUser();
         user.setId(dto.getId());
         user.setUpdateTime(new Date());
         user.setPassword(passwordEncoder.encode(dto.getPassword()));
@@ -232,7 +239,7 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
         //注册身份
         appUser.setUserType(registerDto.getType());
         //加密并设置登陆密码
-        String password =Aes.aesDecrypt(registerDto.getPassword());
+        String password = Aes.aesDecrypt(registerDto.getPassword());
         String encode = passwordEncoder.encode(password);
         appUser.setPassword(encode);
         //创建单位
@@ -277,9 +284,12 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
         }
         //获取登录用户
         AppUser appUser = userList.get(0);
+        if (appUser.getFace() == 1) {
+           // return AjaxJson.getError("该账号只支持人脸登录");
+        }
         //比对密码
         String userPassword = appUser.getPassword();
-        boolean matches = passwordEncoder.matches(Aes.aesDecrypt(dto.getPassword()),userPassword);
+        boolean matches = passwordEncoder.matches(Aes.aesDecrypt(dto.getPassword()), userPassword);
         if (!matches) {
             loginLog.setStatus("1");
             appUserLoginLogService.save(loginLog);
@@ -577,7 +587,6 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
     }
 
 
-
     /**
      * 用户数量统计
      *
@@ -595,7 +604,7 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
      * @param createDTO
      */
     public void createUser(AppUserCreateDTO createDTO) {
-        log.info("创建账号:{}",JSONUtil.toJsonStr(createDTO));
+        log.info("创建账号:{}", JSONUtil.toJsonStr(createDTO));
         String phone = createDTO.getPhone().trim();
         AppUser appUser = this.findByPhone(phone);
         if (appUser != null) {
@@ -617,4 +626,99 @@ public class AppUserService extends ServiceImpl<AppUserMapper, AppUser> implemen
     }
 
 
+    public void authFace(Long loginId, MultipartFile file) {
+        String img;
+        try (InputStream is = file.getInputStream()) {
+            img = Base64.encode(is);
+            boolean isLive = faceFactory.handler().checkIsLive(img);
+            if (!isLive) {
+                log.error("人脸注册为非活体人脸:{}", loginId);
+                throw new AjaxError("非活体人脸");
+            }
+        } catch (IOException e) {
+            throw new AjaxError("识别失败");
+        }
+        String faceId = RandomUtil.randomString(32);
+        AppUser appUser = this.getById(loginId);
+        appUser.setFace(1);
+        appUser.setFaceTime(new Date()).setFaceId(faceId);
+        this.updateById(appUser);
+        faceFactory.handler().createPersonByBase(faceId, appUser.getName(), img);
+    }
+
+    public AjaxJson faceLogin(MultipartFile file) {
+        String img;
+        try (InputStream is = file.getInputStream()) {
+            img = Base64.encode(is);
+            boolean isLive = faceFactory.handler().checkIsLive(img);
+            if (!isLive) {
+                throw new AjaxError("非活体人脸");
+            }
+        } catch (IOException e) {
+            throw new AjaxError("识别失败");
+        }
+        String faceId = faceFactory.handler().faceSearch(img);
+        if (StrUtil.isEmpty(faceId)) {
+            return AjaxJson.getError("人员未录入人脸");
+        }
+        AppUser appUser = findByFaceId(faceId);
+        if (appUser == null) {
+            return AjaxJson.getError("人员信息未找到");
+        }
+        if (appUser.getUserType() != 1) {
+            return AjaxJson.getError("当前用户不支持人脸登录");
+        }
+        AppUserLoginLog loginLog = new AppUserLoginLog();
+        loginLog.setCreateTime(new Date());
+        loginLog.setUserName(appUser.getPhone());
+        loginLog.setLoginIp(WebNbUtil.getIP(SpringMVCUtil.getRequest()));
+        appUserLoginLogService.save(loginLog);
+        //设置登录次数
+        appUser.setLoginCount(appUser.getLoginCount() + 1);
+        //设置登陆时间
+        appUser.setLastLoginTime(new Date());
+        //保存
+        appUserMapper.updateById(appUser);
+
+        //开始执行登录
+        StpAPPUserUtil.login(appUser.getId());
+        // 组织返回参数,直接拿过来用的,然后自己改吧改吧
+        SoMap map = new SoMap();
+        //敏感信息置空
+        appUser.setPassword(null);
+        //执行
+        map.put("appUser", appUser);
+        //获取当前用户角色权限字符
+        List<ReRoleMenu> reRoleMenus = reRoleMenuMapper.selectList(new LambdaQueryWrapper<ReRoleMenu>().eq(ReRoleMenu::getAppRoleId, appUser.getUserType()));
+        //使用stream流对其reRoleMenus集合的权限字符进行过滤顺便转成String类型
+        List<String> per_list = reRoleMenus.stream().map(ReRoleMenu::getAppMenuId).collect(Collectors.toList()).stream().map(String::valueOf).collect(Collectors.toList());
+        //过滤出权限字符
+        map.put("per_list", per_list);
+        map.put("tokenInfo", StpAPPUserUtil.getTokenInfo());
+        APPLoginUserInfo info = new APPLoginUserInfo();
+        PeopleDto rpcById = levelOneServerInterface.getRpcById(appUser.getFkId());
+        if (rpcById != null) {
+            info.setTradeAreaId(rpcById.getTradeAreaId());
+            info.setTradeAreaName(rpcById.getTradeAreaName());
+        }
+        info.setLoginId(appUser.getId());
+        info.setLoginName(appUser.getName());
+        info.setFk(appUser.getFkId());
+        info.setUserType(appUser.getUserType());
+        StpAPPUserUtil.cacheAPPLoginInfo(info);
+        return AjaxJson.getSuccessData(map);
+    }
+
+    /**
+     * 根据人脸ID查找数据库
+     *
+     * @param faceId
+     * @return
+     */
+    private AppUser findByFaceId(String faceId) {
+        QueryWrapper<AppUser> ew = new QueryWrapper<>();
+        ew.lambda().eq(AppUser::getFaceId, faceId);
+        List<AppUser> list = list(ew);
+        return list.isEmpty() ? null : list.get(0);
+    }
 }