|
|
@@ -1,36 +1,71 @@
|
|
|
package org.dromara.backstage.wx.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.codec.Base64;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.img.Img;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.RandomUtil;
|
|
|
+import cn.hutool.crypto.digest.MD5;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import com.arcsoft.face.FaceInfo;
|
|
|
+import com.arcsoft.face.toolkit.ImageInfo;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.dromara.backstage.cardCenter.domain.PtCard;
|
|
|
import org.dromara.backstage.cardCenter.mapper.PtCardMapper;
|
|
|
import org.dromara.backstage.consumption.mapper.XfCreditAccountMapper;
|
|
|
+import org.dromara.backstage.payment.domain.PtUserAccount;
|
|
|
+import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;
|
|
|
import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
|
|
|
import org.dromara.backstage.payment.mapper.PtUserAccountMapper;
|
|
|
import org.dromara.backstage.wx.domain.vo.WxCreditAccountVo;
|
|
|
+import org.dromara.backstage.wx.service.FaceEngineService;
|
|
|
import org.dromara.backstage.wx.service.IWxService;
|
|
|
+import org.dromara.common.core.domain.R;
|
|
|
+import org.dromara.common.core.exception.ServiceException;
|
|
|
+import org.dromara.common.core.utils.MapstructUtils;
|
|
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|
|
import org.dromara.system.api.RemoteDictService;
|
|
|
import org.dromara.system.api.domain.vo.RemoteDictDataVo;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.TreeMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
|
|
|
+
|
|
|
/**
|
|
|
* 微信Service业务层处理
|
|
|
*
|
|
|
*/
|
|
|
@RequiredArgsConstructor
|
|
|
@Service
|
|
|
+@Slf4j
|
|
|
public class WxServiceImpl implements IWxService {
|
|
|
|
|
|
private final PtUserAccountMapper accountMapper;
|
|
|
private final XfCreditAccountMapper creditAccountMapper;
|
|
|
private final PtCardMapper cardMapper;
|
|
|
private final RemoteDictService dictService;
|
|
|
+ private FaceEngineService faceEngineService;
|
|
|
+
|
|
|
+ @Value("${upload.upload-path}/") // 文件上传路径
|
|
|
+ private String uploadPath;
|
|
|
+ @Value("${upload.image.user}/") // 用户头像路径
|
|
|
+ private String userPath;
|
|
|
+ @Value("${dzbp.sync-img.url}/") // 电子班牌照片推送接口
|
|
|
+ private String syncImgToDzbpUrl;
|
|
|
|
|
|
@Override
|
|
|
public PtUserAccountVo getUserInfoByUserId(Long userId) {
|
|
|
@@ -57,4 +92,168 @@ public class WxServiceImpl implements IWxService {
|
|
|
.eq(PtCard::getUserId, userId));
|
|
|
return count > 0;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public R<String> uploadUserPhoto(Long userId, String imgData) {
|
|
|
+ //1.查询用户信息,用于判断身份
|
|
|
+ PtUserAccountVo vo = accountMapper.selectVoById(userId);
|
|
|
+ if (ObjectUtil.isEmpty(vo)) {
|
|
|
+ throw new RuntimeException("用户不存在");
|
|
|
+ }
|
|
|
+ //2.调用虹软,识别人脸是否正确
|
|
|
+ int strIndex = imgData.indexOf(";base64,");
|
|
|
+ if (strIndex > 0) {
|
|
|
+ imgData = imgData.substring(strIndex + 8); // 过滤掉data:image/jpg;base64,字符串
|
|
|
+ }
|
|
|
+
|
|
|
+ byte[] imageBytes = Base64.decode(imgData);
|
|
|
+ ImageInfo imageInfo = getRGBData(imageBytes);
|
|
|
+ List<FaceInfo> faceInfosList = faceEngineService.detectFaces(imageInfo);
|
|
|
+ if (faceInfosList == null || faceInfosList.size() == 0) {
|
|
|
+ return R.fail("人脸识别不成功!");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ //3.图片压缩处理
|
|
|
+ imageBytes = imgCompression(imageBytes);
|
|
|
+
|
|
|
+ //4.更新账户表人脸照片地址,上传照片到服务器
|
|
|
+ uploadUserPhoto(userId, imageBytes);
|
|
|
+
|
|
|
+ //5.如果用户是学员身份,则将照片同步给电子班牌
|
|
|
+ if("2".equals(vo.getCategory())){
|
|
|
+ syncImgToDZBP(vo, imgData);
|
|
|
+ }
|
|
|
+ }catch (ServiceException e){
|
|
|
+ return R.fail(e.getMessage());
|
|
|
+ }
|
|
|
+ return R.ok("上传图片成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 同步照片到电子班牌
|
|
|
+ * @param vo
|
|
|
+ * @param imgData
|
|
|
+ */
|
|
|
+ private void syncImgToDZBP(PtUserAccountVo vo, String imgData){
|
|
|
+ String timestamp = Long.toString(System.currentTimeMillis());
|
|
|
+ TreeMap<String, Object> params = new TreeMap<String, Object>();
|
|
|
+ params.put("pid", "hnswdx");
|
|
|
+ params.put("random", RandomUtil.randomString(16));
|
|
|
+ params.put("timestamp", timestamp);
|
|
|
+ StringBuilder s1 = new StringBuilder();
|
|
|
+ for (String key : params.keySet()) {
|
|
|
+ s1.append(key).append("=").append(params.get(key)).append("&");
|
|
|
+ }
|
|
|
+ s1.append("key=").append("WPDRUiVRo0KIKf4s20hhbyk1GgMmibtT");
|
|
|
+ String sign = MD5.create().digestHex(s1.toString()).toUpperCase();
|
|
|
+ params.put("sign", sign);
|
|
|
+
|
|
|
+ s1 = new StringBuilder();
|
|
|
+ for (String key : params.keySet()) {
|
|
|
+ s1.append(key).append("=").append(params.get(key)).append("&");
|
|
|
+ }
|
|
|
+ s1.deleteCharAt(s1.length() - 1);
|
|
|
+
|
|
|
+ JSONObject face = new JSONObject();
|
|
|
+ face.put("type", "face");
|
|
|
+ JSONArray array = new JSONArray();
|
|
|
+ JSONObject data = new JSONObject();
|
|
|
+ data.put("p_key", vo.getOtherId());
|
|
|
+ data.put("no", vo.getOtherId());
|
|
|
+ data.put("face_image", imgData);
|
|
|
+ data.put("update_date", System.currentTimeMillis());
|
|
|
+ array.put(data);
|
|
|
+ face.put("data", array);
|
|
|
+
|
|
|
+ String res = HttpRequest.post(syncImgToDzbpUrl + "?" + s1.toString())
|
|
|
+ .body(face.toString())
|
|
|
+ .execute().body();
|
|
|
+ log.info("同步照片到电子班牌返回结果:{}", res);
|
|
|
+ }
|
|
|
+ private void uploadUserPhoto(Long userId, byte[] imageBytes) {
|
|
|
+ //1.上传照片到指定目录
|
|
|
+ ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
|
|
|
+ byte[] bytes = new byte[1024];
|
|
|
+ int index;
|
|
|
+
|
|
|
+ String localFileName = uploadPath + userPath + userId + ".jpg";
|
|
|
+ FileOutputStream downloadFile = null;
|
|
|
+ try {
|
|
|
+ downloadFile = new FileOutputStream(localFileName);
|
|
|
+ while ((index = bis.read(bytes)) != -1) {
|
|
|
+ downloadFile.write(bytes, 0, index);
|
|
|
+ downloadFile.flush();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("图片处理失败,请稍后重试!", e);
|
|
|
+ throw new ServiceException("图片处理失败,请稍后重试!");
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ bis.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("inputStream关闭失败!", e);
|
|
|
+ }
|
|
|
+ if (downloadFile != null) {
|
|
|
+ try {
|
|
|
+ downloadFile.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("downloadFile关闭失败!", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //2.保存图片路径到数据库
|
|
|
+ String photoUrl = userPath + userId + ".jpg";
|
|
|
+ PtUserAccountBo bo = PtUserAccountBo.builder().userId(userId).photo(photoUrl).build();
|
|
|
+ accountMapper.updateById(MapstructUtils.convert(bo, PtUserAccount.class));
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 图片压缩
|
|
|
+ * @param imageBytes
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static byte[] imgCompression(byte[] imageBytes) {
|
|
|
+ // 小于1M就不进行压缩里,浪费执行时间
|
|
|
+ float quality = 0f;
|
|
|
+ if (imageBytes.length > 1024 * 1024 * 10) { // 大于10M
|
|
|
+ quality = 0.1f;
|
|
|
+ } else if (imageBytes.length > 1024 * 1024 * 5) { // 大于5M
|
|
|
+ quality = 0.2f;
|
|
|
+ } else if (imageBytes.length > 1024 * 1024 * 1) {// 大于1M
|
|
|
+ quality = 0.5f;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (quality != 0) {
|
|
|
+ ByteArrayInputStream bis = null;
|
|
|
+ ByteArrayOutputStream bos = null;
|
|
|
+ try {
|
|
|
+ bis = new ByteArrayInputStream(imageBytes);
|
|
|
+ bos = new ByteArrayOutputStream();
|
|
|
+ Img.from(bis).setQuality(quality).write(bos);
|
|
|
+ imageBytes = bos.toByteArray();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ServiceException("图片处理失败,请稍后重试!");
|
|
|
+ } finally {
|
|
|
+ if (bis != null) {
|
|
|
+ try {
|
|
|
+ bis.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (bos != null) {
|
|
|
+ try {
|
|
|
+ bos.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return imageBytes;
|
|
|
+ }
|
|
|
+
|
|
|
}
|