Compare commits
24 Commits
79ea08898b
...
da20a44049
Author | SHA1 | Date | |
---|---|---|---|
da20a44049 | |||
877f37b6f9 | |||
f6f847e41c | |||
8ac386242d | |||
3f11aadd75 | |||
d620bde5fa | |||
5a7c39429e | |||
7234e08616 | |||
45409ba1ab | |||
b5b9064f30 | |||
d0d4e37526 | |||
73d393b436 | |||
2835346447 | |||
75eb3732fc | |||
692df3a1a2 | |||
fe0397af8e | |||
f17e2364b6 | |||
59978b6be5 | |||
20d78cb487 | |||
4e9d6807d6 | |||
8af8bd6bcf | |||
248c06a30c | |||
dabdde33a6 | |||
c9a4116ed6 |
@ -1,11 +0,0 @@
|
|||||||
package com.ycwl.basic.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(value = {ElementType.METHOD})
|
|
||||||
public @interface RequestToFile {
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package com.ycwl.basic.aspectj;
|
|
||||||
|
|
||||||
import com.ycwl.basic.annotation.RequestToFile;
|
|
||||||
import com.ycwl.basic.config.CachedBodyHttpServletRequest;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
|
||||||
import org.aspectj.lang.annotation.After;
|
|
||||||
import org.aspectj.lang.annotation.Around;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Aspect
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class HttpSaver {
|
|
||||||
|
|
||||||
@Pointcut("@annotation(com.ycwl.basic.annotation.RequestToFile)")
|
|
||||||
public void requestToFilePointCut() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@After("requestToFilePointCut()")
|
|
||||||
public void requestToFile() throws IOException {
|
|
||||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
||||||
if (attributes == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HttpServletRequest request = attributes.getRequest();
|
|
||||||
saveRequestToFile(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveRequestToFile(HttpServletRequest request) throws IOException {
|
|
||||||
File file = new File("./request/"+System.currentTimeMillis()+".http");
|
|
||||||
// 写入文件
|
|
||||||
if (!file.getParentFile().exists()) {
|
|
||||||
file.getParentFile().mkdirs();
|
|
||||||
}
|
|
||||||
if (!file.exists()) {
|
|
||||||
file.createNewFile();
|
|
||||||
}
|
|
||||||
try (java.io.FileWriter writer = new java.io.FileWriter(file, true)) {
|
|
||||||
writer.append(request.getMethod()).append(" ").append(request.getRequestURL());
|
|
||||||
String queryString = request.getQueryString();
|
|
||||||
if (queryString != null) {
|
|
||||||
writer.append("?").append(queryString);
|
|
||||||
}
|
|
||||||
writer.append("\r\n");
|
|
||||||
Enumeration<String> headerNames = request.getHeaderNames();
|
|
||||||
while (headerNames.hasMoreElements()) {
|
|
||||||
String headerName = headerNames.nextElement();
|
|
||||||
writer.append(headerName).append(": ").append(request.getHeader(headerName)).append("\r\n");
|
|
||||||
}
|
|
||||||
writer.append("\r\n");
|
|
||||||
// 获取body
|
|
||||||
CachedBodyHttpServletRequest cachedRequest = (CachedBodyHttpServletRequest) request;
|
|
||||||
writer.append(new String(cachedRequest.getCachedBody()));
|
|
||||||
writer.append("\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package com.ycwl.basic.config;
|
|
||||||
|
|
||||||
import javax.servlet.ReadListener;
|
|
||||||
import javax.servlet.ServletInputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
|
|
||||||
private final byte[] cachedBody;
|
|
||||||
|
|
||||||
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
|
|
||||||
super(request);
|
|
||||||
// 缓存请求体内容
|
|
||||||
InputStream requestInputStream = request.getInputStream();
|
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int read;
|
|
||||||
while ((read = requestInputStream.read(buffer)) != -1) {
|
|
||||||
byteArrayOutputStream.write(buffer, 0, read);
|
|
||||||
}
|
|
||||||
cachedBody = byteArrayOutputStream.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ServletInputStream getInputStream() {
|
|
||||||
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachedBody);
|
|
||||||
return new ServletInputStream() {
|
|
||||||
@Override
|
|
||||||
public int read() {
|
|
||||||
return byteArrayInputStream.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFinished() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReady() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setReadListener(ReadListener readListener) {
|
|
||||||
// 不需要实现
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BufferedReader getReader() {
|
|
||||||
return new BufferedReader(new InputStreamReader(this.getInputStream()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getCachedBody() {
|
|
||||||
return cachedBody;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,8 +3,7 @@ package com.ycwl.basic.config;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.ycwl.basic.interceptor.AuthInterceptor;
|
import com.ycwl.basic.interceptor.AuthInterceptor;
|
||||||
import com.ycwl.basic.xss.XssJacksonDeserializer;
|
import com.ycwl.basic.stats.interceptor.StatsInterceptor;
|
||||||
import com.ycwl.basic.xss.XssJacksonSerializer;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -29,13 +28,17 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthInterceptor authInterceptor;
|
private AuthInterceptor authInterceptor;
|
||||||
|
@Autowired
|
||||||
|
private StatsInterceptor statsInterceptor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(authInterceptor)
|
registry.addInterceptor(authInterceptor)
|
||||||
// 拦截除指定接口外的所有请求,通过判断 注解 来决定是否需要做登录验证
|
// 拦截除指定接口外的所有请求,通过判断 注解 来决定是否需要做登录验证
|
||||||
.addPathPatterns("/**")
|
.addPathPatterns("/**")
|
||||||
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/api-docs", "/doc.html/**", "/error", "/csrf", "/");
|
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/api-docs", "/doc.html/**", "/error", "/");
|
||||||
|
registry.addInterceptor(statsInterceptor)
|
||||||
|
.addPathPatterns("/api/mobile/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,25 +81,6 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public WebMvcConfigurer createConvert() {
|
|
||||||
return new WebMvcConfigurer() {
|
|
||||||
@Override
|
|
||||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
|
||||||
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
|
|
||||||
ObjectMapper mapper = builder.build();
|
|
||||||
/*注入自定义的序列化工具,将RequestBody的参数进行转译后传输*/
|
|
||||||
SimpleModule simpleModule = new SimpleModule();
|
|
||||||
// XSS序列化
|
|
||||||
simpleModule.addSerializer(String.class, new XssJacksonSerializer());
|
|
||||||
simpleModule.addDeserializer(String.class, new XssJacksonDeserializer());
|
|
||||||
mapper.registerModule(simpleModule);
|
|
||||||
converters.add(new MappingJackson2HttpMessageConverter(mapper));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StringHttpMessageConverter stringHttpMessageConverter;
|
private StringHttpMessageConverter stringHttpMessageConverter;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
package com.ycwl.basic.config;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信小程序配置
|
|
||||||
*
|
|
||||||
* @author songmingsong
|
|
||||||
**/
|
|
||||||
@Data
|
|
||||||
@Component
|
|
||||||
@ConfigurationProperties(prefix = "wx")
|
|
||||||
public class WechatConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公众号的appId
|
|
||||||
*/
|
|
||||||
private String appId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 公众号的密钥
|
|
||||||
*/
|
|
||||||
private String appSecret;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序的AppId
|
|
||||||
*/
|
|
||||||
private String miniProgramAppId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小程序的secret
|
|
||||||
*/
|
|
||||||
private String miniProgramSecret;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 申请openid授权
|
|
||||||
*/
|
|
||||||
private String grandType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商户号
|
|
||||||
*/
|
|
||||||
private String mchId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商户证书序列号
|
|
||||||
*/
|
|
||||||
private String mchSerialNo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支付回调接口地址
|
|
||||||
*/
|
|
||||||
private String payNotifyUrl;
|
|
||||||
/**
|
|
||||||
* 退款回调接口地址
|
|
||||||
*/
|
|
||||||
private String refundNotifyUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商户API私钥路径
|
|
||||||
*/
|
|
||||||
private String keyPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 商户APIV3密钥
|
|
||||||
*/
|
|
||||||
private String apiV3;
|
|
||||||
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import com.ycwl.basic.biz.PriceBiz;
|
|||||||
import com.ycwl.basic.constant.BaseContextHandler;
|
import com.ycwl.basic.constant.BaseContextHandler;
|
||||||
import com.ycwl.basic.mapper.FaceMapper;
|
import com.ycwl.basic.mapper.FaceMapper;
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
import com.ycwl.basic.model.mobile.goods.GoodsPriceQueryReq;
|
|
||||||
import com.ycwl.basic.model.mobile.order.IsBuyBatchRespVO;
|
import com.ycwl.basic.model.mobile.order.IsBuyBatchRespVO;
|
||||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||||
import com.ycwl.basic.model.mobile.order.OrderAppPageReq;
|
import com.ycwl.basic.model.mobile.order.OrderAppPageReq;
|
||||||
@ -14,12 +13,7 @@ import com.ycwl.basic.model.mobile.order.RefundOrderReq;
|
|||||||
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||||
import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO;
|
import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO;
|
||||||
import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO;
|
import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO;
|
||||||
import com.ycwl.basic.model.pc.order.req.OrderAddReq;
|
|
||||||
import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO;
|
import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
|
||||||
import com.ycwl.basic.repository.OrderRepository;
|
|
||||||
import com.ycwl.basic.repository.PriceRepository;
|
|
||||||
import com.ycwl.basic.service.mobile.GoodsService;
|
|
||||||
import com.ycwl.basic.service.pc.OrderService;
|
import com.ycwl.basic.service.pc.OrderService;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import com.ycwl.basic.utils.JwtTokenUtil;
|
import com.ycwl.basic.utils.JwtTokenUtil;
|
||||||
@ -28,6 +22,8 @@ import io.swagger.annotations.ApiOperation;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author:longbinbin
|
* @Author:longbinbin
|
||||||
* @Date:2024/12/4 17:16
|
* @Date:2024/12/4 17:16
|
||||||
@ -62,7 +58,7 @@ public class AppOrderController {
|
|||||||
|
|
||||||
@ApiOperation("用户端订单新增")
|
@ApiOperation("用户端订单新增")
|
||||||
@PostMapping("/addOrder")
|
@PostMapping("/addOrder")
|
||||||
public ApiResponse<WxPayRespVO> addOrder(@RequestBody CreateOrderReqVO orderAddReq) throws Exception {
|
public ApiResponse<Map<String, Object>> addOrder(@RequestBody CreateOrderReqVO orderAddReq) throws Exception {
|
||||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||||
return orderService.createOrder(worker.getUserId(), orderAddReq);
|
return orderService.createOrder(worker.getUserId(), orderAddReq);
|
||||||
}
|
}
|
||||||
@ -70,7 +66,7 @@ public class AppOrderController {
|
|||||||
|
|
||||||
@ApiOperation("用户端打包订单新增")
|
@ApiOperation("用户端打包订单新增")
|
||||||
@PostMapping("/addBatchOrder")
|
@PostMapping("/addBatchOrder")
|
||||||
public ApiResponse<WxPayRespVO> addOrder(@RequestBody CreateBatchOrderReqVO batchOrderReqVO) throws Exception {
|
public ApiResponse<Map<String, Object>> addOrder(@RequestBody CreateBatchOrderReqVO batchOrderReqVO) throws Exception {
|
||||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||||
return orderService.createBatchOrder(worker.getUserId(), batchOrderReqVO);
|
return orderService.createBatchOrder(worker.getUserId(), batchOrderReqVO);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
|
|||||||
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
|
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||||
|
import com.ycwl.basic.model.pc.scenic.resp.ScenicConfigResp;
|
||||||
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
import com.ycwl.basic.service.mobile.AppScenicService;
|
import com.ycwl.basic.service.mobile.AppScenicService;
|
||||||
@ -51,9 +52,26 @@ public class AppScenicController {
|
|||||||
|
|
||||||
@GetMapping("/{id}/config")
|
@GetMapping("/{id}/config")
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
public ApiResponse<ScenicConfigEntity> getConfig(@PathVariable Long id){
|
public ApiResponse<ScenicConfigResp> getConfig(@PathVariable Long id){
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(id);
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(id);
|
||||||
return ApiResponse.success(scenicConfig);
|
ScenicConfigResp resp = new ScenicConfigResp();
|
||||||
|
resp.setBookRoutine(scenicConfig.getBookRoutine());
|
||||||
|
resp.setForceFinishTime(scenicConfig.getForceFinishTime());
|
||||||
|
resp.setTourTime(scenicConfig.getTourTime());
|
||||||
|
resp.setSampleStoreDay(scenicConfig.getSampleStoreDay());
|
||||||
|
resp.setFaceStoreDay(scenicConfig.getFaceStoreDay());
|
||||||
|
resp.setVideoStoreDay(scenicConfig.getVideoStoreDay());
|
||||||
|
resp.setAllFree(scenicConfig.getAllFree());
|
||||||
|
resp.setDisableSourceVideo(scenicConfig.getDisableSourceVideo());
|
||||||
|
resp.setDisableSourceImage(scenicConfig.getDisableSourceImage());
|
||||||
|
resp.setAntiScreenRecordType(scenicConfig.getAntiScreenRecordType());
|
||||||
|
resp.setVideoSourceStoreDay(scenicConfig.getVideoSourceStoreDay());
|
||||||
|
resp.setImageSourceStoreDay(scenicConfig.getImageSourceStoreDay());
|
||||||
|
resp.setUserSourceExpireDay(scenicConfig.getUserSourceExpireDay());
|
||||||
|
resp.setBrokerDirectRate(scenicConfig.getBrokerDirectRate());
|
||||||
|
resp.setVideoSourcePackHint(scenicConfig.getVideoSourcePackHint());
|
||||||
|
resp.setImageSourcePackHint(scenicConfig.getImageSourcePackHint());
|
||||||
|
return ApiResponse.success(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("查询景区设备总数和拍到用户的机位数量")
|
@ApiOperation("查询景区设备总数和拍到用户的机位数量")
|
||||||
|
@ -2,8 +2,6 @@ package com.ycwl.basic.controller.mobile;
|
|||||||
|
|
||||||
|
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
import com.ycwl.basic.annotation.RequestToFile;
|
|
||||||
import com.ycwl.basic.aspectj.HttpSaver;
|
|
||||||
import com.ycwl.basic.enums.BizCodeEnum;
|
import com.ycwl.basic.enums.BizCodeEnum;
|
||||||
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
import com.ycwl.basic.model.wx.WxPayRespVO;
|
||||||
@ -12,6 +10,7 @@ import com.ycwl.basic.utils.ApiResponse;
|
|||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -35,12 +34,6 @@ public class AppWxPayController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private WxPayService wxPayService;
|
private WxPayService wxPayService;
|
||||||
|
|
||||||
@ApiOperation(value = "微信预支付", notes = "微信预支付")
|
|
||||||
@PostMapping("/createOrder")
|
|
||||||
public ApiResponse<WxPayRespVO> createOrder(@RequestBody WXPayOrderReqVO req) throws Exception {
|
|
||||||
return ApiResponse.success(wxPayService.createOrder(req));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation(value = "微信支付回调", notes = "微信支付回调")
|
@ApiOperation(value = "微信支付回调", notes = "微信支付回调")
|
||||||
@PostMapping("/payNotify")
|
@PostMapping("/payNotify")
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
@ -48,29 +41,19 @@ public class AppWxPayController {
|
|||||||
wxPayService.payNotify(request);
|
wxPayService.payNotify(request);
|
||||||
return ApiResponse.success(BizCodeEnum.REQUEST_OK);
|
return ApiResponse.success(BizCodeEnum.REQUEST_OK);
|
||||||
}
|
}
|
||||||
|
@PostMapping("/{scenicId}/payNotify")
|
||||||
@ApiOperation(value = "微信退款", notes = "微信退款")
|
@IgnoreToken
|
||||||
@PostMapping("/refundOrder")
|
public ApiResponse<?> payNotifyByScenicId(@PathVariable Long scenicId, HttpServletRequest request) {
|
||||||
public ApiResponse<?> refundOrder(@RequestBody String orderId) throws Exception {
|
wxPayService.payNotify(scenicId, request);
|
||||||
return ApiResponse.buildResult(wxPayService.refundOrder(orderId) ?
|
return ApiResponse.success(BizCodeEnum.REQUEST_OK);
|
||||||
BizCodeEnum.SUCCESS :
|
|
||||||
BizCodeEnum.ADVANCE_PAYMENT_REFUND_FAILED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "微信支付退款回调", notes = "微信支付退款回调")
|
@ApiOperation(value = "微信支付退款回调", notes = "微信支付退款回调")
|
||||||
@PostMapping("/refundNotify")
|
@PostMapping("/{scenicId}/refundNotify")
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
public ApiResponse<?> refundNotify(@RequestBody String refundResult) throws GeneralSecurityException, IOException {
|
public ApiResponse<?> refundNotify(@PathVariable Long scenicId, HttpServletRequest request) throws GeneralSecurityException, IOException {
|
||||||
return ApiResponse.buildResult(wxPayService.refundNotify(refundResult) ?
|
return ApiResponse.buildResult(wxPayService.refundNotify(scenicId, request) ?
|
||||||
BizCodeEnum.SUCCESS :
|
BizCodeEnum.SUCCESS :
|
||||||
BizCodeEnum.ADVANCE_PAYMENT_CALLBACK_REFUND_FAILED);
|
BizCodeEnum.ADVANCE_PAYMENT_CALLBACK_REFUND_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "微信关闭订单", notes = "微信关闭订单")
|
|
||||||
@PostMapping("/closeOrder")
|
|
||||||
@IgnoreToken
|
|
||||||
public ApiResponse<?> closeOrder(@RequestBody String orderId) {
|
|
||||||
wxPayService.closeOrder(orderId);
|
|
||||||
return ApiResponse.buildResult(BizCodeEnum.REQUEST_OK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package com.ycwl.basic.controller.pc;
|
|||||||
import com.ycwl.basic.model.pc.broker.entity.BrokerEntity;
|
import com.ycwl.basic.model.pc.broker.entity.BrokerEntity;
|
||||||
import com.ycwl.basic.model.pc.broker.req.BrokerRecordReqQuery;
|
import com.ycwl.basic.model.pc.broker.req.BrokerRecordReqQuery;
|
||||||
import com.ycwl.basic.model.pc.broker.req.BrokerReqQuery;
|
import com.ycwl.basic.model.pc.broker.req.BrokerReqQuery;
|
||||||
import com.ycwl.basic.model.pc.broker.resp.BrokerRecordRespVO;
|
|
||||||
import com.ycwl.basic.model.pc.broker.resp.BrokerRespVO;
|
import com.ycwl.basic.model.pc.broker.resp.BrokerRespVO;
|
||||||
import com.ycwl.basic.model.pc.broker.resp.DailySummaryRespVO;
|
import com.ycwl.basic.model.pc.broker.resp.DailySummaryRespVO;
|
||||||
import com.ycwl.basic.service.pc.BrokerRecordService;
|
import com.ycwl.basic.service.pc.BrokerRecordService;
|
||||||
@ -131,7 +130,7 @@ public class BrokerController {
|
|||||||
try {
|
try {
|
||||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
String s = adapter.uploadFile(file, filePath);
|
String s = adapter.uploadFile(null, file, filePath);
|
||||||
file.delete();
|
file.delete();
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||||
return ApiResponse.success(s);
|
return ApiResponse.success(s);
|
||||||
|
@ -47,6 +47,15 @@ public class PriceConfigController {
|
|||||||
public ApiResponse<Boolean> deletePriceConfig(@PathVariable Integer id) {
|
public ApiResponse<Boolean> deletePriceConfig(@PathVariable Integer id) {
|
||||||
priceRepository.clearPriceCache(id);
|
priceRepository.clearPriceCache(id);
|
||||||
priceConfigService.removeById(id);
|
priceConfigService.removeById(id);
|
||||||
|
priceRepository.clearPriceCache(id);
|
||||||
|
return ApiResponse.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/status")
|
||||||
|
public ApiResponse<Boolean> updateStatus(@PathVariable Integer id) {
|
||||||
|
priceRepository.clearPriceCache(id);
|
||||||
|
priceConfigService.updateStatus(id);
|
||||||
|
priceRepository.clearPriceCache(id);
|
||||||
return ApiResponse.success(true);
|
return ApiResponse.success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.ycwl.basic.controller.pc;
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||||
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||||
|
import com.ycwl.basic.service.mobile.AppStatisticsService;
|
||||||
import com.ycwl.basic.service.pc.ScenicService;
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
import com.ycwl.basic.storage.StorageFactory;
|
import com.ycwl.basic.storage.StorageFactory;
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
@ -35,6 +37,8 @@ public class ScenicController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScenicRepository scenicRepository;
|
private ScenicRepository scenicRepository;
|
||||||
|
@Autowired
|
||||||
|
private AppStatisticsService appStatisticsService;
|
||||||
|
|
||||||
@ApiOperation("分页查询景区")
|
@ApiOperation("分页查询景区")
|
||||||
@PostMapping("/page")
|
@PostMapping("/page")
|
||||||
@ -117,7 +121,7 @@ public class ScenicController {
|
|||||||
try {
|
try {
|
||||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
String s = adapter.uploadFile(file, filePath);
|
String s = adapter.uploadFile(null, file, filePath);
|
||||||
file.delete();
|
file.delete();
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||||
return ApiResponse.success(s);
|
return ApiResponse.success(s);
|
||||||
@ -125,4 +129,25 @@ public class ScenicController {
|
|||||||
return ApiResponse.fail("生成二维码失败");
|
return ApiResponse.fail("生成二维码失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{scenicId}/one")
|
||||||
|
public ApiResponse getStatisticsOne(@PathVariable("scenicId") Long scenicId, @RequestBody CommonQueryReq query) {
|
||||||
|
query.setScenicId(scenicId);
|
||||||
|
return appStatisticsService.oneStatistics(query);
|
||||||
|
}
|
||||||
|
@PostMapping("/{scenicId}/two")
|
||||||
|
public ApiResponse getStatisticsTwo(@PathVariable("scenicId") Long scenicId, @RequestBody CommonQueryReq query) {
|
||||||
|
query.setScenicId(scenicId);
|
||||||
|
return appStatisticsService.twoStatistics(query);
|
||||||
|
}
|
||||||
|
@PostMapping("/{scenicId}/three")
|
||||||
|
public ApiResponse getStatisticsThree(@PathVariable("scenicId") Long scenicId, @RequestBody CommonQueryReq query) {
|
||||||
|
query.setScenicId(scenicId);
|
||||||
|
return appStatisticsService.freeStatistics(query);
|
||||||
|
}
|
||||||
|
@PostMapping("/{scenicId}/fun")
|
||||||
|
public ApiResponse getStatisticsFun(@PathVariable("scenicId") Long scenicId, @RequestBody CommonQueryReq query) {
|
||||||
|
query.setScenicId(scenicId);
|
||||||
|
return appStatisticsService.userConversionFunnel(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.ycwl.basic.controller.proxy;
|
||||||
|
|
||||||
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class ProxyController {
|
||||||
|
@IgnoreToken
|
||||||
|
@RequestMapping(value = "/proxy", method = RequestMethod.GET)
|
||||||
|
public void proxy(@RequestParam(value = "url") String url,
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response) throws IOException {
|
||||||
|
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||||
|
url = "http://" + url; // 或根据业务逻辑选择默认协议
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增User-Agent检测逻辑
|
||||||
|
String userAgent = request.getHeader("User-Agent");
|
||||||
|
if (userAgent != null && userAgent.contains("Lavf/")) {
|
||||||
|
response.sendRedirect(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 创建HTTP连接
|
||||||
|
URL urlObj = new URL(url);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
|
||||||
|
|
||||||
|
// 设置请求方法和请求头
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
for (Enumeration<String> headers = request.getHeaderNames(); headers.hasMoreElements();) {
|
||||||
|
String headerName = headers.nextElement();
|
||||||
|
connection.addRequestProperty(headerName, request.getHeader(headerName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理响应
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
response.setStatus(responseCode);
|
||||||
|
|
||||||
|
// 转发响应头
|
||||||
|
Map<String, List<String>> headerFields = connection.getHeaderFields();
|
||||||
|
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
|
||||||
|
if (entry.getKey() != null) {
|
||||||
|
for (String value : entry.getValue()) {
|
||||||
|
response.addHeader(entry.getKey(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 流式传输响应体
|
||||||
|
try (InputStream inputStream = connection.getInputStream();
|
||||||
|
OutputStream outputStream = response.getOutputStream()) {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
@RestController
|
@RestController
|
||||||
@Api(tags = "渲染端对接接口")
|
@Api(tags = "渲染端对接接口")
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package com.ycwl.basic.controller.viid;
|
package com.ycwl.basic.controller.viid;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
import com.ycwl.basic.annotation.RequestToFile;
|
|
||||||
import com.ycwl.basic.aspectj.HttpSaver;
|
|
||||||
import com.ycwl.basic.facebody.FaceBodyFactory;
|
|
||||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||||
import com.ycwl.basic.mapper.DeviceMapper;
|
import com.ycwl.basic.mapper.DeviceMapper;
|
||||||
@ -17,14 +14,11 @@ import com.ycwl.basic.mapper.SourceMapper;
|
|||||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
|
||||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||||
import com.ycwl.basic.model.viid.entity.DeviceIdObject;
|
import com.ycwl.basic.model.viid.entity.DeviceIdObject;
|
||||||
import com.ycwl.basic.model.viid.entity.FaceListObject;
|
import com.ycwl.basic.model.viid.entity.FaceListObject;
|
||||||
import com.ycwl.basic.model.viid.entity.FaceObject;
|
import com.ycwl.basic.model.viid.entity.FaceObject;
|
||||||
import com.ycwl.basic.model.viid.entity.FacePositionObject;
|
import com.ycwl.basic.model.viid.entity.FacePositionObject;
|
||||||
import com.ycwl.basic.model.viid.entity.ImageListObject;
|
|
||||||
import com.ycwl.basic.model.viid.entity.ImageObject;
|
|
||||||
import com.ycwl.basic.model.viid.entity.ResponseStatusObject;
|
import com.ycwl.basic.model.viid.entity.ResponseStatusObject;
|
||||||
import com.ycwl.basic.model.viid.entity.SubImageInfoObject;
|
import com.ycwl.basic.model.viid.entity.SubImageInfoObject;
|
||||||
import com.ycwl.basic.model.viid.entity.SubImageList;
|
import com.ycwl.basic.model.viid.entity.SubImageList;
|
||||||
@ -69,12 +63,12 @@ import java.util.TimeZone;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.ycwl.basic.constant.StorageConstant.PHOTO_PATH;
|
import static com.ycwl.basic.constant.StorageConstant.PHOTO_PATH;
|
||||||
import static com.ycwl.basic.service.task.impl.TaskFaceServiceImpl.generateEntityId;
|
|
||||||
|
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
@RestController
|
@RestController
|
||||||
@ -93,17 +87,20 @@ public class ViidController {
|
|||||||
private ScenicRepository scenicRepository;
|
private ScenicRepository scenicRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskFaceService taskFaceService;
|
private TaskFaceService taskFaceService;
|
||||||
private final Map<String, ThreadPoolExecutor> executors = new ConcurrentHashMap<>();
|
private final Map<Long, ThreadPoolExecutor> executors = new ConcurrentHashMap<>();
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScenicService scenicService;
|
private ScenicService scenicService;
|
||||||
|
|
||||||
private ThreadPoolExecutor getExecutor(String deviceId) {
|
private ThreadPoolExecutor getExecutor(Long scenicId) {
|
||||||
ThreadPoolExecutor executor = executors.get(deviceId);
|
return executors.computeIfAbsent(scenicId, k -> {
|
||||||
if (executor == null) {
|
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||||
executor = new ThreadPoolExecutor(4, 4096, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(4096));
|
.setNamePrefix("VIID-" + scenicId + "-t")
|
||||||
executors.put(deviceId, executor);
|
.build();
|
||||||
}
|
return new ThreadPoolExecutor(
|
||||||
return executor;
|
4, 4096, 0L, TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue<>(4096),
|
||||||
|
threadFactory);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// region 注册注销基础接口
|
// region 注册注销基础接口
|
||||||
@ -310,11 +307,11 @@ public class ViidController {
|
|||||||
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
||||||
faceSample.setFaceUrl(url);
|
faceSample.setFaceUrl(url);
|
||||||
faceSampleMapper.add(faceSample);
|
faceSampleMapper.add(faceSample);
|
||||||
ThreadPoolExecutor executor = getExecutor(device.getId().toString());
|
ThreadPoolExecutor executor = getExecutor(scenicId);
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
if (faceBodyAdapter != null) {
|
if (faceBodyAdapter != null) {
|
||||||
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
||||||
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), generateEntityId(faceSample), url, newFaceSampleId.toString());
|
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), faceSample.getId().toString(), url, newFaceSampleId.toString());
|
||||||
if (addFaceResp != null) {
|
if (addFaceResp != null) {
|
||||||
faceSample.setScore(addFaceResp.getScore());
|
faceSample.setScore(addFaceResp.getScore());
|
||||||
faceSampleMapper.update(faceSample);
|
faceSampleMapper.update(faceSample);
|
||||||
@ -372,11 +369,11 @@ public class ViidController {
|
|||||||
faceSample.setFaceUrl(url);
|
faceSample.setFaceUrl(url);
|
||||||
faceSampleMapper.add(faceSample);
|
faceSampleMapper.add(faceSample);
|
||||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||||
ThreadPoolExecutor executor = getExecutor(device.getId().toString());
|
ThreadPoolExecutor executor = getExecutor(scenicId);
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
if (faceBodyAdapter != null) {
|
if (faceBodyAdapter != null) {
|
||||||
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
||||||
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), generateEntityId(faceSample), url, newFaceSampleId.toString());
|
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), faceSample.getId().toString(), url, newFaceSampleId.toString());
|
||||||
if (addFaceResp != null) {
|
if (addFaceResp != null) {
|
||||||
faceSample.setScore(addFaceResp.getScore());
|
faceSample.setScore(addFaceResp.getScore());
|
||||||
faceSampleMapper.update(faceSample);
|
faceSampleMapper.update(faceSample);
|
||||||
@ -402,8 +399,6 @@ public class ViidController {
|
|||||||
@RequestMapping(value = "/Images", method = RequestMethod.POST)
|
@RequestMapping(value = "/Images", method = RequestMethod.POST)
|
||||||
@IgnoreLogReq
|
@IgnoreLogReq
|
||||||
public VIIDBaseResp images(HttpServletRequest request, @RequestBody ImageUploadReq req) throws IOException {
|
public VIIDBaseResp images(HttpServletRequest request, @RequestBody ImageUploadReq req) throws IOException {
|
||||||
// log.info("Images:{}", req);
|
|
||||||
HttpSaver.saveRequestToFile(request);
|
|
||||||
return new VIIDBaseResp(
|
return new VIIDBaseResp(
|
||||||
new ResponseStatusObject("1", "/VIID/Images", "0", "OK", sdfTime.format(new Date()))
|
new ResponseStatusObject("1", "/VIID/Images", "0", "OK", sdfTime.format(new Date()))
|
||||||
);
|
);
|
||||||
|
@ -1,25 +1,18 @@
|
|||||||
package com.ycwl.basic.controller.vpt;
|
package com.ycwl.basic.controller.vpt;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
import com.ycwl.basic.constant.StorageConstant;
|
import com.ycwl.basic.constant.StorageConstant;
|
||||||
import com.ycwl.basic.device.entity.common.FileObject;
|
import com.ycwl.basic.device.entity.common.FileObject;
|
||||||
import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
|
import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
|
||||||
import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
|
|
||||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
|
||||||
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
|
||||||
import com.ycwl.basic.service.pc.ScenicService;
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
import com.ycwl.basic.storage.StorageFactory;
|
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||||
import com.ycwl.basic.storage.utils.StorageUtil;
|
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -29,7 +22,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
@ -48,7 +40,7 @@ public class VptController {
|
|||||||
}
|
}
|
||||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
IStorageAdapter adapter = scenicService.getScenicLocalStorageAdapter(scenicId);
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||||
@ -56,7 +48,7 @@ public class VptController {
|
|||||||
}
|
}
|
||||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
IStorageAdapter adapter = scenicService.getScenicLocalStorageAdapter(scenicId);
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||||
fileObject.setUrl(adapter.getUrl(filename));
|
fileObject.setUrl(adapter.getUrl(filename));
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
package com.ycwl.basic.controller.wvp;
|
package com.ycwl.basic.controller.wvp;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||||
import com.ycwl.basic.annotation.IgnoreToken;
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
import com.ycwl.basic.constant.StorageConstant;
|
import com.ycwl.basic.constant.StorageConstant;
|
||||||
import com.ycwl.basic.device.entity.common.FileObject;
|
import com.ycwl.basic.device.entity.common.FileObject;
|
||||||
import com.ycwl.basic.device.operator.WvpPassiveStorageOperator;
|
import com.ycwl.basic.device.operator.WvpPassiveStorageOperator;
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
|
||||||
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
|
||||||
import com.ycwl.basic.service.pc.DeviceService;
|
import com.ycwl.basic.service.pc.DeviceService;
|
||||||
import com.ycwl.basic.service.pc.ScenicService;
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
import com.ycwl.basic.storage.StorageFactory;
|
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||||
import com.ycwl.basic.storage.utils.StorageUtil;
|
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -28,7 +23,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@IgnoreToken
|
@IgnoreToken
|
||||||
@ -51,7 +45,7 @@ public class WvpController {
|
|||||||
|
|
||||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
IStorageAdapter adapter = scenicService.getScenicLocalStorageAdapter(scenicId);
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||||
@ -59,7 +53,7 @@ public class WvpController {
|
|||||||
}
|
}
|
||||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
IStorageAdapter adapter = scenicService.getScenicLocalStorageAdapter(scenicId);
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||||
fileObject.setUrl(adapter.getUrl(filename));
|
fileObject.setUrl(adapter.getUrl(filename));
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package com.ycwl.basic.enums;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否同意用户协议枚举
|
|
||||||
*
|
|
||||||
* @author songmingsong
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum AgreementEnum {
|
|
||||||
AGREE(1, "同意"),
|
|
||||||
NOT_AGREE(0, "未同意");
|
|
||||||
private int type;
|
|
||||||
private String remark;
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package com.ycwl.basic.enums;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author:longbinbin
|
|
||||||
* @Date:2024/12/6 16:46
|
|
||||||
*/
|
|
||||||
public enum GoodsTypeEnum {
|
|
||||||
VIDEO(1,"成片"),
|
|
||||||
SOURCE(2,"源素材")
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
public Integer code;
|
|
||||||
|
|
||||||
private String value;
|
|
||||||
public static final Map<Integer, GoodsTypeEnum> cacheMap;
|
|
||||||
|
|
||||||
static {
|
|
||||||
cacheMap = new HashMap<>(GoodsTypeEnum.values().length);
|
|
||||||
for (GoodsTypeEnum value : GoodsTypeEnum.values()) {
|
|
||||||
cacheMap.put(value.code, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static final java.util.Map<String, GoodsTypeEnum> valueMap;
|
|
||||||
|
|
||||||
static {
|
|
||||||
valueMap = new HashMap<>(GoodsTypeEnum.values().length);
|
|
||||||
for (GoodsTypeEnum value : GoodsTypeEnum.values()) {
|
|
||||||
valueMap.put(value.value, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GoodsTypeEnum(Integer code, String value) {
|
|
||||||
this.code = code;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取value值
|
|
||||||
*/
|
|
||||||
public static String getValue(Integer noticeMethod) {
|
|
||||||
if (noticeMethod == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
GoodsTypeEnum GoodsTypeEnum = cacheMap.get(noticeMethod);
|
|
||||||
if (GoodsTypeEnum == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return GoodsTypeEnum.value;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取code值
|
|
||||||
*/
|
|
||||||
public static Integer getCode(String noticeMethod) {
|
|
||||||
if (noticeMethod == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GoodsTypeEnum GoodsTypeEnum = valueMap.get(noticeMethod);
|
|
||||||
if (GoodsTypeEnum == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return GoodsTypeEnum.code;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,6 @@
|
|||||||
package com.ycwl.basic.exception;
|
package com.ycwl.basic.exception;
|
||||||
|
|
||||||
import com.ycwl.basic.aspectj.HttpSaver;
|
|
||||||
import com.ycwl.basic.enums.BizCodeEnum;
|
import com.ycwl.basic.enums.BizCodeEnum;
|
||||||
import com.ycwl.basic.notify.NotifyFactory;
|
|
||||||
import com.ycwl.basic.notify.entity.NotifyContent;
|
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
|
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -12,14 +9,9 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @date 2022年09月23日 10:19
|
* @date 2022年09月23日 10:19
|
||||||
|
@ -249,7 +249,7 @@ public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
return response.getData().getEntities().stream().map(ListFaceEntitiesResponse.Data.Entity::getEntityId).collect(Collectors.toList());
|
return response.getData().getEntities().stream().map(ListFaceEntitiesResponse.Data.Entity::getEntityId).collect(Collectors.toList());
|
||||||
} catch (ClientException e) {
|
} catch (ClientException e) {
|
||||||
log.error("获取人脸数据失败!", e);
|
log.error("获取人脸数据失败!", e);
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,9 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
AipFace client = getClient();
|
AipFace client = getClient();
|
||||||
HashMap<String, String> options = new HashMap<>();
|
HashMap<String, String> options = new HashMap<>();
|
||||||
List<String> tokenList = listUserFace(dbName, entityId);
|
List<String> tokenList = listUserFace(dbName, entityId);
|
||||||
|
if (tokenList == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
AtomicInteger count = new AtomicInteger(0);
|
AtomicInteger count = new AtomicInteger(0);
|
||||||
tokenList.forEach(faceToken -> {
|
tokenList.forEach(faceToken -> {
|
||||||
try {
|
try {
|
||||||
@ -232,9 +235,14 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<String> listUserFace(String dbName, String entityId) {
|
public List<String> listUserFace(String dbName, String entityId) {
|
||||||
|
IRateLimiter listFaceLimiter = getLimiter(LOCK_TYPE.LIST_FACE);
|
||||||
try {
|
try {
|
||||||
AipFace client = getClient();
|
AipFace client = getClient();
|
||||||
HashMap<String, String> options = new HashMap<>();
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
try {
|
||||||
|
listFaceLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
JSONObject response = client.faceGetlist(entityId, dbName, options);
|
JSONObject response = client.faceGetlist(entityId, dbName, options);
|
||||||
if (response.getInt("error_code") == 0) {
|
if (response.getInt("error_code") == 0) {
|
||||||
JSONObject resultObj = response.getJSONObject("result");
|
JSONObject resultObj = response.getJSONObject("result");
|
||||||
@ -249,13 +257,16 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
} else if (response.getInt("error_code") == 223103) {
|
||||||
|
// 用户不存在
|
||||||
|
return Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
log.warn("获取人脸列表失败!{}", response);
|
log.warn("获取人脸列表失败!{}", response);
|
||||||
return Collections.emptyList();
|
return null;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取人脸列表失败!", e);
|
log.error("获取人脸列表失败!", e);
|
||||||
return Collections.emptyList();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,21 +336,21 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
private IRateLimiter getLimiter(LOCK_TYPE type) {
|
private IRateLimiter getLimiter(LOCK_TYPE type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ADD_DB:
|
case ADD_DB:
|
||||||
return addDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return addDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
case ADD_FACE:
|
case ADD_FACE:
|
||||||
return addFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getAddQps()));
|
return addFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getAddQps()));
|
||||||
case LIST_DB:
|
case LIST_DB:
|
||||||
return listDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return listDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
case LIST_FACE:
|
case LIST_FACE:
|
||||||
return listFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return listFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
case SEARCH_FACE:
|
case SEARCH_FACE:
|
||||||
return searchFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getSearchQps()));
|
return searchFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getSearchQps()));
|
||||||
case DELETE_DB:
|
case DELETE_DB:
|
||||||
return deleteDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return deleteDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
case DELETE_ENTITY:
|
case DELETE_ENTITY:
|
||||||
return deleteEntityLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return deleteEntityLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
case DELETE_FACE:
|
case DELETE_FACE:
|
||||||
return deleteFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
return deleteFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(105, TimeUnit.MILLISECONDS));
|
||||||
default:
|
default:
|
||||||
return new FixedRateLimiter(500, TimeUnit.MILLISECONDS);
|
return new FixedRateLimiter(500, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package com.ycwl.basic.filter;
|
|
||||||
|
|
||||||
import com.ycwl.basic.config.CachedBodyHttpServletRequest;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.*;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class RequestCacheFilter implements Filter {
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
// 包装原始请求
|
|
||||||
HttpServletRequestWrapper wrappedRequest = new CachedBodyHttpServletRequest((HttpServletRequest) request);
|
|
||||||
// 继续处理请求链
|
|
||||||
chain.doFilter(wrappedRequest, response);
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,8 +7,6 @@ import com.ycwl.basic.constant.PermissionConstant;
|
|||||||
import com.ycwl.basic.constant.RequestConstant;
|
import com.ycwl.basic.constant.RequestConstant;
|
||||||
import com.ycwl.basic.exception.CheckTokenException;
|
import com.ycwl.basic.exception.CheckTokenException;
|
||||||
import com.ycwl.basic.exception.MissTokenException;
|
import com.ycwl.basic.exception.MissTokenException;
|
||||||
import com.ycwl.basic.exception.PermissionException;
|
|
||||||
import com.ycwl.basic.exception.TokenExpireException;
|
|
||||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||||
import com.ycwl.basic.utils.JwtTokenUtil;
|
import com.ycwl.basic.utils.JwtTokenUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -24,17 +22,12 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class AuthInterceptor extends HandlerInterceptorAdapter {
|
public class AuthInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
JwtTokenUtil jwtTokenUtil;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RedisTemplate redisTemplate;
|
RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
@ -17,4 +17,6 @@ public interface PriceConfigMapper extends BaseMapper<PriceConfigEntity> {
|
|||||||
List<PriceConfigRespVO> listByCondition(@Param("req") PriceConfigListReq req);
|
List<PriceConfigRespVO> listByCondition(@Param("req") PriceConfigListReq req);
|
||||||
|
|
||||||
PriceConfigEntity getPriceByScenicTypeGoods(Long scenicId, Integer type, String goodsId);
|
PriceConfigEntity getPriceByScenicTypeGoods(Long scenicId, Integer type, String goodsId);
|
||||||
|
|
||||||
|
int updateStatus(Integer id);
|
||||||
}
|
}
|
@ -54,5 +54,5 @@ public interface TaskMapper {
|
|||||||
|
|
||||||
List<TaskEntity> listEntity(TaskReqQuery taskReqQuery);
|
List<TaskEntity> listEntity(TaskReqQuery taskReqQuery);
|
||||||
|
|
||||||
List<TaskRespVO> selectNotRunningByScenicId(Long scenicOnly);
|
List<TaskRespVO> selectNotRunningByScenicList(String scenicOnly);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,12 @@ public class IsBuyBatchRespVO {
|
|||||||
private BigDecimal slashPrice;
|
private BigDecimal slashPrice;
|
||||||
|
|
||||||
public BigDecimal getPrice() {
|
public BigDecimal getPrice() {
|
||||||
|
if (origPrice == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
if (couponPrice == null) {
|
||||||
|
return origPrice;
|
||||||
|
}
|
||||||
return origPrice.subtract(couponPrice);
|
return origPrice.subtract(couponPrice);
|
||||||
}
|
}
|
||||||
public BigDecimal getDiscountPrice() {
|
public BigDecimal getDiscountPrice() {
|
||||||
|
@ -18,6 +18,12 @@ public class IsBuyRespVO {
|
|||||||
private BigDecimal slashPrice;
|
private BigDecimal slashPrice;
|
||||||
|
|
||||||
public BigDecimal getPrice() {
|
public BigDecimal getPrice() {
|
||||||
|
if (origPrice == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
if (couponPrice == null) {
|
||||||
|
return origPrice;
|
||||||
|
}
|
||||||
return origPrice.subtract(couponPrice);
|
return origPrice.subtract(couponPrice);
|
||||||
}
|
}
|
||||||
public BigDecimal getDiscountPrice() {
|
public BigDecimal getDiscountPrice() {
|
||||||
|
@ -33,6 +33,7 @@ public class PriceConfigEntity {
|
|||||||
* 划线价格
|
* 划线价格
|
||||||
*/
|
*/
|
||||||
private BigDecimal slashPrice;
|
private BigDecimal slashPrice;
|
||||||
|
private Integer status;
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
}
|
}
|
@ -30,5 +30,6 @@ public class PriceConfigRespVO {
|
|||||||
* 划线价格
|
* 划线价格
|
||||||
*/
|
*/
|
||||||
private BigDecimal slashPrice;
|
private BigDecimal slashPrice;
|
||||||
|
private Integer status;
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class RenderWorkerEntity {
|
|||||||
/**
|
/**
|
||||||
* 是否仅用于指定景区,空或0不适用,否则为景区ID
|
* 是否仅用于指定景区,空或0不适用,否则为景区ID
|
||||||
*/
|
*/
|
||||||
private Long scenicOnly;
|
private String scenicOnly;
|
||||||
/**
|
/**
|
||||||
* 是否仅用于测试,0不是,1是
|
* 是否仅用于测试,0不是,1是
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||||
|
import com.ycwl.basic.pay.enums.PayAdapterType;
|
||||||
import com.ycwl.basic.storage.enums.StorageType;
|
import com.ycwl.basic.storage.enums.StorageType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -71,6 +72,10 @@ public class ScenicConfigEntity {
|
|||||||
private Float faceScoreThreshold;
|
private Float faceScoreThreshold;
|
||||||
private StorageType storeType;
|
private StorageType storeType;
|
||||||
private String storeConfigJson;
|
private String storeConfigJson;
|
||||||
|
private StorageType tmpStoreType;
|
||||||
|
private String tmpStoreConfigJson;
|
||||||
|
private StorageType localStoreType;
|
||||||
|
private String localStoreConfigJson;
|
||||||
private BigDecimal brokerDirectRate;
|
private BigDecimal brokerDirectRate;
|
||||||
private Integer faceDetectHelperThreshold;
|
private Integer faceDetectHelperThreshold;
|
||||||
|
|
||||||
@ -80,4 +85,10 @@ public class ScenicConfigEntity {
|
|||||||
|
|
||||||
private FaceBodyAdapterType faceType;
|
private FaceBodyAdapterType faceType;
|
||||||
private String faceConfigJson;
|
private String faceConfigJson;
|
||||||
|
|
||||||
|
private PayAdapterType payType;
|
||||||
|
private String payConfigJson;
|
||||||
|
|
||||||
|
private String imageSourcePackHint;
|
||||||
|
private String videoSourcePackHint;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.ycwl.basic.model.pc.scenic.resp;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||||
|
import com.ycwl.basic.pay.enums.PayAdapterType;
|
||||||
|
import com.ycwl.basic.storage.enums.StorageType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author:longbinbin
|
||||||
|
* @Date:2024/12/2 10:53
|
||||||
|
* 景区配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ScenicConfigResp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约流程,1-预约,2-在线,3-全部
|
||||||
|
*/
|
||||||
|
private Integer bookRoutine;
|
||||||
|
private Integer forceFinishTime;
|
||||||
|
private Integer tourTime;
|
||||||
|
/**
|
||||||
|
* 样本保存时间
|
||||||
|
*/
|
||||||
|
private Integer sampleStoreDay;
|
||||||
|
private Integer faceStoreDay;
|
||||||
|
/**
|
||||||
|
* 视频保存时间
|
||||||
|
*/
|
||||||
|
private Integer videoStoreDay;
|
||||||
|
private Integer allFree;
|
||||||
|
private Integer disableSourceVideo;
|
||||||
|
private Integer disableSourceImage;
|
||||||
|
private Integer antiScreenRecordType;
|
||||||
|
private Integer videoSourceStoreDay;
|
||||||
|
private Integer imageSourceStoreDay;
|
||||||
|
private Integer userSourceExpireDay;
|
||||||
|
private BigDecimal brokerDirectRate;
|
||||||
|
|
||||||
|
private String imageSourcePackHint;
|
||||||
|
private String videoSourcePackHint;
|
||||||
|
}
|
58
src/main/java/com/ycwl/basic/pay/PayFactory.java
Normal file
58
src/main/java/com/ycwl/basic/pay/PayFactory.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package com.ycwl.basic.pay;
|
||||||
|
|
||||||
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
|
import com.ycwl.basic.pay.adapter.WxMpPayAdapter;
|
||||||
|
import com.ycwl.basic.pay.enums.PayAdapterType;
|
||||||
|
import com.ycwl.basic.pay.exceptions.PayUndefinedException;
|
||||||
|
import com.ycwl.basic.pay.exceptions.PayUnsupportedException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PayFactory {
|
||||||
|
|
||||||
|
public static IPayAdapter getAdapter(String typeName) {
|
||||||
|
PayAdapterType adapterEnum;
|
||||||
|
try {
|
||||||
|
adapterEnum = PayAdapterType.valueOf(typeName);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new PayUnsupportedException("不支持的Adapter类型");
|
||||||
|
}
|
||||||
|
return getAdapter(adapterEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPayAdapter getAdapter(PayAdapterType type) {
|
||||||
|
switch (type) {
|
||||||
|
case WX_MP_PAY:
|
||||||
|
return new WxMpPayAdapter();
|
||||||
|
default:
|
||||||
|
throw new PayUnsupportedException("不支持的Adapter类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Map<String, IPayAdapter> namedAdapter = new HashMap<>();
|
||||||
|
protected static IPayAdapter defaultAdapter = null;
|
||||||
|
|
||||||
|
public static void register(String name, IPayAdapter adapter) {
|
||||||
|
namedAdapter.put(name, adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPayAdapter use(String name) {
|
||||||
|
IPayAdapter adapter = namedAdapter.get(name);
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new PayUndefinedException("未定义的支付方式:"+name);
|
||||||
|
}
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPayAdapter use() {
|
||||||
|
if (defaultAdapter == null) {
|
||||||
|
throw new PayUndefinedException("未定义默认的支付方式");
|
||||||
|
}
|
||||||
|
return defaultAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefault(String defaultName) {
|
||||||
|
PayFactory.defaultAdapter = use(defaultName);
|
||||||
|
}
|
||||||
|
}
|
42
src/main/java/com/ycwl/basic/pay/adapter/IPayAdapter.java
Normal file
42
src/main/java/com/ycwl/basic/pay/adapter/IPayAdapter.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.ycwl.basic.pay.adapter;
|
||||||
|
|
||||||
|
// 假设request对象所在的包,可根据实际情况修改
|
||||||
|
import com.ycwl.basic.pay.entity.CancelOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.PayResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderResponse;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// 将接口改为抽象类
|
||||||
|
public interface IPayAdapter {
|
||||||
|
// 下单方法
|
||||||
|
CreateOrderResponse createOrder(CreateOrderRequest request);
|
||||||
|
|
||||||
|
// 获取支付参数方法
|
||||||
|
Map<String, Object> getPaymentParams(CreateOrderResponse response);
|
||||||
|
|
||||||
|
// 处理回调信息方法
|
||||||
|
PayResponse handleCallback(HttpServletRequest request) throws IOException;
|
||||||
|
|
||||||
|
// 查询订单状态方法
|
||||||
|
PayResponse queryOrder(String orderNo);
|
||||||
|
|
||||||
|
// 退款方法
|
||||||
|
RefundOrderResponse refund(RefundOrderRequest request);
|
||||||
|
|
||||||
|
// 处理退款回调方法
|
||||||
|
RefundResponse handleRefundCallback(HttpServletRequest request) throws IOException;
|
||||||
|
|
||||||
|
// 查询退款订单状态方法
|
||||||
|
RefundResponse checkRefundStatus(String refundNo);
|
||||||
|
|
||||||
|
void loadConfig(Map<String, String> config);
|
||||||
|
|
||||||
|
void cancelOrder(CancelOrderRequest request);
|
||||||
|
}
|
353
src/main/java/com/ycwl/basic/pay/adapter/WxMpPayAdapter.java
Normal file
353
src/main/java/com/ycwl/basic/pay/adapter/WxMpPayAdapter.java
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
package com.ycwl.basic.pay.adapter;
|
||||||
|
|
||||||
|
import com.wechat.pay.java.core.Config;
|
||||||
|
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||||
|
import com.wechat.pay.java.core.notification.NotificationConfig;
|
||||||
|
import com.wechat.pay.java.core.notification.NotificationParser;
|
||||||
|
import com.wechat.pay.java.core.notification.RequestParam;
|
||||||
|
import com.wechat.pay.java.core.util.PemUtil;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.CloseOrderRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||||
|
import com.wechat.pay.java.service.refund.RefundService;
|
||||||
|
import com.wechat.pay.java.service.refund.model.AmountReq;
|
||||||
|
import com.wechat.pay.java.service.refund.model.CreateRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
|
import com.wechat.pay.java.service.refund.model.RefundNotification;
|
||||||
|
import com.ycwl.basic.constant.NumberConstant;
|
||||||
|
import com.ycwl.basic.pay.entity.CancelOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.PayResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.WxMpPayConfig;
|
||||||
|
import com.ycwl.basic.pay.exceptions.PayWrongConfigException;
|
||||||
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_NONCE;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SERIAL;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SIGNATURE;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_TIMESTAMP;
|
||||||
|
import static com.wechat.pay.java.service.refund.model.Status.SUCCESS;
|
||||||
|
|
||||||
|
public class WxMpPayAdapter implements IPayAdapter {
|
||||||
|
private WxMpPayConfig config;
|
||||||
|
public static final String WECHAT_PAY_SIGNATURE_TYPE = "Wechatpay-Signature-Type";
|
||||||
|
public WxMpPayAdapter() {
|
||||||
|
|
||||||
|
}
|
||||||
|
public WxMpPayAdapter(WxMpPayConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void loadConfig(Map<String, String> _config) {
|
||||||
|
this.config = new WxMpPayConfig();
|
||||||
|
if (_config != null) {
|
||||||
|
this.config.setMerchantId(_config.get("merchantId"));
|
||||||
|
this.config.setAppId(_config.get("appId"));
|
||||||
|
this.config.setPrivateKey(_config.get("privateKey"));
|
||||||
|
this.config.setSerialNumber(_config.get("serialNumber"));
|
||||||
|
this.config.setApiV3Key(_config.get("apiV3Key"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Config clientConfig;
|
||||||
|
|
||||||
|
private Config getConfig() {
|
||||||
|
if (clientConfig == null) {
|
||||||
|
clientConfig = new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(config.getMerchantId())
|
||||||
|
.privateKey(config.getPrivateKey())
|
||||||
|
.merchantSerialNumber(config.getSerialNumber())
|
||||||
|
.apiV3Key(config.getApiV3Key())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return clientConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CreateOrderResponse createOrder(CreateOrderRequest request) {
|
||||||
|
CreateOrderResponse resp = new CreateOrderResponse();
|
||||||
|
if (request.getPrice() <= 0) {
|
||||||
|
resp.setSkipPay(true);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
Config wxConfig = getConfig();
|
||||||
|
JsapiService service = new JsapiService.Builder().config(wxConfig).build();
|
||||||
|
PrepayRequest prepayRequest = new PrepayRequest();
|
||||||
|
Amount amount = new Amount();
|
||||||
|
amount.setTotal(request.getPrice());
|
||||||
|
prepayRequest.setAmount(amount);
|
||||||
|
prepayRequest.setAppid(config.getAppId());
|
||||||
|
prepayRequest.setMchid(config.getMerchantId());
|
||||||
|
prepayRequest.setDescription(request.getDescription());
|
||||||
|
prepayRequest.setNotifyUrl(request.getNotifyUrl());
|
||||||
|
prepayRequest.setOutTradeNo(request.getOrderNo());
|
||||||
|
Payer payer = new Payer();
|
||||||
|
payer.setOpenid(request.getUserIdentify());
|
||||||
|
prepayRequest.setPayer(payer);
|
||||||
|
PrepayResponse response = service.prepay(prepayRequest);
|
||||||
|
resp.setSuccess(true);
|
||||||
|
resp.setSkipPay(false);
|
||||||
|
resp.setOrderNo(response.getPrepayId());
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getPaymentParams(CreateOrderResponse response) {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
if (response.isSkipPay()) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
Long timeStamp = System.currentTimeMillis() / NumberConstant.THOUSAND;
|
||||||
|
params.put("appId", config.getAppId());
|
||||||
|
params.put("timeStamp", timeStamp);
|
||||||
|
String nonce = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
|
||||||
|
params.put("nonceStr", nonce);
|
||||||
|
String signStr = Stream.of(config.getAppId(), String.valueOf(timeStamp), nonce, "prepay_id=" + response.getOrderNo())
|
||||||
|
.collect(Collectors.joining("\n", "", "\n"));
|
||||||
|
String sign;
|
||||||
|
try {
|
||||||
|
sign = getSign(signStr, config.getPrivateKey());
|
||||||
|
} catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException e) {
|
||||||
|
throw new PayWrongConfigException("配置错误");
|
||||||
|
}
|
||||||
|
params.put("paySign", sign);
|
||||||
|
params.put("signType", "RSA-SHA256");
|
||||||
|
params.put("prepayId", "prepay_id=" + response.getOrderNo());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayResponse handleCallback(HttpServletRequest request) throws IOException {
|
||||||
|
ServletInputStream inputStream = request.getInputStream();
|
||||||
|
StringBuffer body = new StringBuffer();
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
String s;
|
||||||
|
// 读取回调请求体
|
||||||
|
while ((s = bufferedReader.readLine()) != null) {
|
||||||
|
body.append(s);
|
||||||
|
}
|
||||||
|
PayResponse resp = new PayResponse();
|
||||||
|
|
||||||
|
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||||
|
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||||
|
String signType = request.getHeader(WECHAT_PAY_SIGNATURE_TYPE);
|
||||||
|
String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
|
||||||
|
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||||
|
NotificationConfig config = (NotificationConfig) getConfig();
|
||||||
|
NotificationParser parser = new NotificationParser(config);
|
||||||
|
RequestParam requestParam = new RequestParam.Builder()
|
||||||
|
.serialNumber(serialNo)
|
||||||
|
.nonce(nonce)
|
||||||
|
.signature(signature)
|
||||||
|
.timestamp(timestamp)
|
||||||
|
// 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
|
||||||
|
.signType(signType)
|
||||||
|
.body(body.toString())
|
||||||
|
.build();
|
||||||
|
Transaction parse = parser.parse(requestParam, Transaction.class);
|
||||||
|
resp.setValid(true);
|
||||||
|
resp.setOrderNo(parse.getOutTradeNo());
|
||||||
|
if (parse.getAmount() != null) {
|
||||||
|
resp.setOrderPrice(parse.getAmount().getTotal());
|
||||||
|
resp.setPayPrice(parse.getAmount().getPayerTotal());
|
||||||
|
}
|
||||||
|
switch (parse.getTradeState()) {
|
||||||
|
case SUCCESS:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.SUCCESS);
|
||||||
|
break;
|
||||||
|
case NOTPAY:
|
||||||
|
case CLOSED:
|
||||||
|
case REVOKED:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.FAIL);
|
||||||
|
break;
|
||||||
|
case REFUND:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.REFUND);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.CANCEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resp.setPayTime(parse.getSuccessTime());
|
||||||
|
resp.setOriginalResponse(parse);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PayResponse queryOrder(String orderNo) {
|
||||||
|
Config wxConfig = getConfig();
|
||||||
|
JsapiService service = new JsapiService.Builder().config(wxConfig).build();
|
||||||
|
QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
|
||||||
|
queryRequest.setMchid(config.getMerchantId());
|
||||||
|
queryRequest.setOutTradeNo(orderNo);
|
||||||
|
PayResponse resp = new PayResponse();
|
||||||
|
Transaction result = service.queryOrderByOutTradeNo(queryRequest);
|
||||||
|
resp.setValid(true);
|
||||||
|
resp.setOrderNo(result.getOutTradeNo());
|
||||||
|
if (result.getAmount() != null) {
|
||||||
|
resp.setOrderPrice(result.getAmount().getTotal());
|
||||||
|
resp.setPayPrice(result.getAmount().getPayerTotal());
|
||||||
|
}
|
||||||
|
switch (result.getTradeState()) {
|
||||||
|
case SUCCESS:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.SUCCESS);
|
||||||
|
break;
|
||||||
|
case NOTPAY:
|
||||||
|
case CLOSED:
|
||||||
|
case REVOKED:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.FAIL);
|
||||||
|
break;
|
||||||
|
case REFUND:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.REFUND);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp.setState(PayResponse.PAY_STATE.CANCEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resp.setPayTime(result.getSuccessTime());
|
||||||
|
resp.setOriginalResponse(result);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefundOrderResponse refund(RefundOrderRequest request) {
|
||||||
|
RefundOrderResponse resp = new RefundOrderResponse();
|
||||||
|
Config wxConfig = getConfig();
|
||||||
|
RefundService service = new RefundService.Builder().config(wxConfig).build();
|
||||||
|
CreateRequest createRequest = new CreateRequest();
|
||||||
|
createRequest.setOutTradeNo(request.getOrderNo());
|
||||||
|
createRequest.setOutRefundNo(request.getRefundNo());
|
||||||
|
AmountReq amountReq = new AmountReq();
|
||||||
|
amountReq.setTotal(Long.valueOf(request.getPrice()));
|
||||||
|
amountReq.setRefund(Long.valueOf(request.getRefundPrice()));
|
||||||
|
amountReq.setCurrency("CNY");
|
||||||
|
createRequest.setAmount(amountReq);
|
||||||
|
createRequest.setNotifyUrl(request.getNotifyUrl());
|
||||||
|
Refund refund = service.create(createRequest);
|
||||||
|
if (refund.getStatus() == SUCCESS) {
|
||||||
|
resp.setSuccess(true);
|
||||||
|
resp.setRefundNo(refund.getOutRefundNo());
|
||||||
|
} else {
|
||||||
|
resp.setSuccess(false);
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefundResponse handleRefundCallback(HttpServletRequest request) throws IOException {
|
||||||
|
ServletInputStream inputStream = request.getInputStream();
|
||||||
|
StringBuffer body = new StringBuffer();
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
String s;
|
||||||
|
// 读取回调请求体
|
||||||
|
while ((s = bufferedReader.readLine()) != null) {
|
||||||
|
body.append(s);
|
||||||
|
}
|
||||||
|
RefundResponse resp = new RefundResponse();
|
||||||
|
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
||||||
|
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
||||||
|
String signType = request.getHeader(WECHAT_PAY_SIGNATURE_TYPE);
|
||||||
|
String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
|
||||||
|
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
||||||
|
NotificationConfig config = (NotificationConfig) getConfig();
|
||||||
|
NotificationParser parser = new NotificationParser(config);RequestParam requestParam = new RequestParam.Builder()
|
||||||
|
.serialNumber(serialNo)
|
||||||
|
.nonce(nonce)
|
||||||
|
.signature(signature)
|
||||||
|
.timestamp(timestamp)
|
||||||
|
// 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
|
||||||
|
.signType(signType)
|
||||||
|
.body(body.toString())
|
||||||
|
.build();
|
||||||
|
RefundNotification parse = parser.parse(requestParam, RefundNotification.class);
|
||||||
|
resp.setValid(true);
|
||||||
|
resp.setOriginalResponse(parse);
|
||||||
|
if (parse.getRefundStatus() == SUCCESS) {
|
||||||
|
//退款成功
|
||||||
|
resp.setSuccess();
|
||||||
|
resp.setRefundTime(parse.getSuccessTime());
|
||||||
|
resp.setOrderNo(parse.getOutTradeNo());
|
||||||
|
resp.setRefundNo(parse.getRefundId());
|
||||||
|
if (parse.getAmount() != null) {
|
||||||
|
resp.setRefundPrice(Math.toIntExact(parse.getAmount().getPayerRefund()));
|
||||||
|
resp.setOrderPrice(Math.toIntExact(parse.getAmount().getTotal()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//退款失败
|
||||||
|
resp.setFail();
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RefundResponse checkRefundStatus(String refundNo) {
|
||||||
|
Config wxConfig = getConfig();
|
||||||
|
RefundService service = new RefundService.Builder().config(wxConfig).build();
|
||||||
|
QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
|
||||||
|
request.setOutRefundNo(refundNo);
|
||||||
|
RefundResponse resp = new RefundResponse();
|
||||||
|
Refund result = service.queryByOutRefundNo(request);
|
||||||
|
resp.setValid(true);
|
||||||
|
resp.setOriginalResponse(result);
|
||||||
|
if (result.getStatus() == SUCCESS) {
|
||||||
|
//退款成功
|
||||||
|
resp.setSuccess();
|
||||||
|
resp.setRefundTime(result.getSuccessTime());
|
||||||
|
resp.setOrderNo(result.getOutTradeNo());
|
||||||
|
resp.setRefundNo(result.getRefundId());
|
||||||
|
if (result.getAmount() != null) {
|
||||||
|
resp.setRefundPrice(Math.toIntExact(result.getAmount().getPayerRefund()));
|
||||||
|
resp.setOrderPrice(Math.toIntExact(result.getAmount().getTotal()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//退款失败
|
||||||
|
resp.setFail();
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelOrder(CancelOrderRequest request) {
|
||||||
|
CloseOrderRequest closeOrderRequest = new CloseOrderRequest();
|
||||||
|
closeOrderRequest.setOutTradeNo(request.getOrderNo());
|
||||||
|
closeOrderRequest.setMchid(config.getMerchantId());
|
||||||
|
Config config = getConfig();
|
||||||
|
JsapiService service = new JsapiService.Builder().config(config).build();
|
||||||
|
service.closeOrder(closeOrderRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSign(String signatureStr,String privateKey) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
|
||||||
|
String replace = privateKey.replace("\\n", "\n");
|
||||||
|
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromString(replace);
|
||||||
|
Signature sign = Signature.getInstance("SHA256withRSA");
|
||||||
|
sign.initSign(merchantPrivateKey);
|
||||||
|
sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Base64Utils.encodeToString(sign.sign());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class CancelOrderRequest {
|
||||||
|
private String orderNo;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class CreateOrderRequest {
|
||||||
|
/**
|
||||||
|
* 价格,单位为分
|
||||||
|
*/
|
||||||
|
private Integer price;
|
||||||
|
private String goodsName;
|
||||||
|
private String orderNo;
|
||||||
|
private String description;
|
||||||
|
private String userIdentify;
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
|
|
||||||
|
public BigDecimal getPriceInYuan() {
|
||||||
|
return new BigDecimal(BigInteger.valueOf(price), 2);
|
||||||
|
}
|
||||||
|
public CreateOrderRequest setPriceInCents(Integer priceInCents) {
|
||||||
|
this.price = priceInCents;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateOrderRequest setPriceInYuan(BigDecimal priceInYuan) {
|
||||||
|
this.price = priceInYuan.multiply(new BigDecimal(100)).intValue();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CreateOrderResponse {
|
||||||
|
private boolean success;
|
||||||
|
private boolean skipPay;
|
||||||
|
private String orderNo;
|
||||||
|
}
|
34
src/main/java/com/ycwl/basic/pay/entity/PayResponse.java
Normal file
34
src/main/java/com/ycwl/basic/pay/entity/PayResponse.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PayResponse {
|
||||||
|
private boolean valid;
|
||||||
|
private String orderNo;
|
||||||
|
private Object originalResponse;
|
||||||
|
private Integer orderPrice;
|
||||||
|
private Integer payPrice;
|
||||||
|
private PAY_STATE state;
|
||||||
|
private String payTime;
|
||||||
|
|
||||||
|
public boolean isPay() {
|
||||||
|
return state == PAY_STATE.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCancel() {
|
||||||
|
return state == PAY_STATE.CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRefund() {
|
||||||
|
return state == PAY_STATE.REFUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PAY_STATE {
|
||||||
|
SUCCESS,
|
||||||
|
CANCEL,
|
||||||
|
REFUND,
|
||||||
|
FAIL,
|
||||||
|
UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class RefundOrderRequest {
|
||||||
|
private Integer price;
|
||||||
|
private Integer refundPrice;
|
||||||
|
private String orderNo;
|
||||||
|
private String refundNo;
|
||||||
|
private String notifyUrl;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RefundOrderResponse {
|
||||||
|
private boolean success;
|
||||||
|
private String refundNo;
|
||||||
|
}
|
28
src/main/java/com/ycwl/basic/pay/entity/RefundResponse.java
Normal file
28
src/main/java/com/ycwl/basic/pay/entity/RefundResponse.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class RefundResponse {
|
||||||
|
private boolean valid;
|
||||||
|
private String orderNo;
|
||||||
|
private String refundNo;
|
||||||
|
private Object originalResponse;
|
||||||
|
private Integer orderPrice;
|
||||||
|
private Integer refundPrice;
|
||||||
|
private PAY_STATE state;
|
||||||
|
private String refundTime;
|
||||||
|
|
||||||
|
public void setSuccess() {
|
||||||
|
state = PAY_STATE.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFail() {
|
||||||
|
state = PAY_STATE.FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PAY_STATE {
|
||||||
|
SUCCESS,
|
||||||
|
FAIL
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/com/ycwl/basic/pay/entity/WxMpPayConfig.java
Normal file
12
src/main/java/com/ycwl/basic/pay/entity/WxMpPayConfig.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.ycwl.basic.pay.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WxMpPayConfig {
|
||||||
|
private String merchantId;
|
||||||
|
private String appId;
|
||||||
|
private String privateKey;
|
||||||
|
private String serialNumber;
|
||||||
|
private String apiV3Key;
|
||||||
|
}
|
20
src/main/java/com/ycwl/basic/pay/enums/PayAdapterType.java
Normal file
20
src/main/java/com/ycwl/basic/pay/enums/PayAdapterType.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.ycwl.basic.pay.enums;
|
||||||
|
|
||||||
|
public enum PayAdapterType {
|
||||||
|
WX_MP_PAY("WX_MP_PAY"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
PayAdapterType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.ycwl.basic.pay.exceptions;
|
||||||
|
|
||||||
|
public class PayException extends RuntimeException {
|
||||||
|
public PayException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.ycwl.basic.pay.exceptions;
|
||||||
|
|
||||||
|
public class PayUndefinedException extends RuntimeException {
|
||||||
|
public PayUndefinedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.ycwl.basic.pay.exceptions;
|
||||||
|
|
||||||
|
public class PayUnsupportedException extends PayException {
|
||||||
|
public PayUnsupportedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.ycwl.basic.pay.exceptions;
|
||||||
|
|
||||||
|
public class PayWrongConfigException extends PayException {
|
||||||
|
public PayWrongConfigException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.ycwl.basic.pay.starter;
|
||||||
|
|
||||||
|
import com.ycwl.basic.pay.PayFactory;
|
||||||
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
|
import com.ycwl.basic.pay.starter.config.OverallPayConfig;
|
||||||
|
import com.ycwl.basic.pay.starter.config.PayConfigItem;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class PayAutoConfiguration {
|
||||||
|
private final OverallPayConfig config;
|
||||||
|
public PayAutoConfiguration(OverallPayConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
if (config != null) {
|
||||||
|
if (config.getConfigs() != null) {
|
||||||
|
loadConfig();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(config.getDefaultUse())) {
|
||||||
|
PayFactory.setDefault(config.getDefaultUse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadConfig() {
|
||||||
|
for (PayConfigItem item : config.getConfigs()) {
|
||||||
|
IPayAdapter adapter = PayFactory.getAdapter(item.getType());
|
||||||
|
adapter.loadConfig(item.getConfig());
|
||||||
|
PayFactory.register(item.getName(), adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.ycwl.basic.pay.starter.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "pay")
|
||||||
|
@Data
|
||||||
|
public class OverallPayConfig {
|
||||||
|
private String defaultUse;
|
||||||
|
private List<PayConfigItem> configs;
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.ycwl.basic.pay.starter.config;
|
||||||
|
|
||||||
|
import com.ycwl.basic.pay.enums.PayAdapterType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PayConfigItem {
|
||||||
|
private String name;
|
||||||
|
private PayAdapterType type;
|
||||||
|
private Map<String, String> config;
|
||||||
|
}
|
@ -47,12 +47,37 @@ public class FeiETicketPrinter {
|
|||||||
//根据打印纸张的宽度,自行调整内容的格式,可参考下面的样例格式
|
//根据打印纸张的宽度,自行调整内容的格式,可参考下面的样例格式
|
||||||
|
|
||||||
String content;
|
String content;
|
||||||
content = "<CB>帧途AI旅拍</CB><BR>";
|
content = "<BR><B>世界再大</B><BR>";
|
||||||
content += "┏━━━━━━━━━━━━━━┓<BR>";
|
content += "<B>你永远是这段旅途</B><BR>";
|
||||||
content += "┃┉3制67表01符45制89表23符6┉┃<BR>";
|
content += "<B>的焦点</B><BR>";
|
||||||
content += "┣━━★━━♢━━◈━━◉━━┫<BR>";
|
content += "━━━━━━━━━━━━━━━━<BR>";
|
||||||
content += "┃123制67表01符45制89表23符678┃<BR>";
|
content += "<B>正片主演:</B><BR>";
|
||||||
content += "┗━━━━━━━━━━━━━━┛<BR>";
|
content += "旅途中最靓的你(测试名字很长很长故意不换行)<BR><BR>";
|
||||||
|
content += "<B>拍摄地点:</B><BR>";
|
||||||
|
content += "泸定桥<BR><BR>";
|
||||||
|
content += "<B>拍摄日期:</B><BR>";
|
||||||
|
content += "2025年4月4日<BR><BR>";
|
||||||
|
content += "<B>大片内容:</B><BR>";
|
||||||
|
content += "1.打卡泸定桥专属微电影(2部+)<BR>";
|
||||||
|
content += "2.打卡录像集(5条)<BR>";
|
||||||
|
content += "3.打卡照片集(5-10张)<BR>";
|
||||||
|
content += "━━━━━━━━━━━━━━━━<BR>";
|
||||||
|
content += "<C>帧帧皆故事 途途有回忆</C>";
|
||||||
|
content += "<C>扫码即可观赏您的照片及视频</C>";
|
||||||
|
content += "<BR><QR>https://zhentuai.com</QR>";
|
||||||
|
content += "<CB>游后微信扫码查看</CB>";
|
||||||
|
content += "<C>精彩指数:★★★★★</C><BR>";
|
||||||
|
|
||||||
|
// content += "┏━━━━━━━━━━━━━━┓<BR>";
|
||||||
|
// content += "┏━━━━━━━━━━━━━━┓<BR>";
|
||||||
|
// content += "┏━━━━━━━━━━━━━━┓<BR>";
|
||||||
|
// content += "┃┉3制67表01符45制89表23符6┉┃<BR>";
|
||||||
|
// content += "┣━━★━━♢━━◈━━◉━━┫<BR>";
|
||||||
|
// content += "┣━━★━━♢━━◈━━◉━━┫<BR>";
|
||||||
|
// content += "┣━━★━━♢━━◈━━◉━━┫<BR>";
|
||||||
|
// content += "┣━━★━━♢━━◈━━◉━━┫<BR>";
|
||||||
|
// content += "┃123制67表01符45制89表23符678┃<BR>";
|
||||||
|
// content += "┗━━━━━━━━━━━━━━┛<BR>";
|
||||||
return doPrint(sn,content,1);
|
return doPrint(sn,content,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
package com.ycwl.basic.service.mobile;
|
package com.ycwl.basic.service.mobile;
|
||||||
|
|
||||||
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
|
||||||
import com.ycwl.basic.model.wx.WxchatCallbackSuccessData;
|
import com.ycwl.basic.model.wx.WxchatCallbackSuccessData;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface WxPayService {
|
public interface WxPayService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信预支付
|
* 微信预支付
|
||||||
*/
|
*/
|
||||||
WxPayRespVO createOrder(WXPayOrderReqVO req) throws Exception;
|
Map<String, Object> createOrder(Long scenicId, WXPayOrderReqVO req) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付回调
|
* 微信支付回调
|
||||||
*/
|
*/
|
||||||
void payNotify(HttpServletRequest xml);
|
void payNotify(HttpServletRequest request);
|
||||||
|
|
||||||
|
void payNotify(Long scenicId, HttpServletRequest request);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +40,7 @@ public interface WxPayService {
|
|||||||
/**
|
/**
|
||||||
* 微信退款回调
|
* 微信退款回调
|
||||||
*/
|
*/
|
||||||
boolean refundNotify(String refundResult) throws IOException, GeneralSecurityException;
|
boolean refundNotify(Long scenicId, HttpServletRequest request) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭订单
|
* 关闭订单
|
||||||
@ -46,4 +48,5 @@ public interface WxPayService {
|
|||||||
* @param orderId 订单id(订单编号)
|
* @param orderId 订单id(订单编号)
|
||||||
*/
|
*/
|
||||||
void closeOrder(String orderId) ;
|
void closeOrder(String orderId) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,9 @@ package com.ycwl.basic.service.mobile.impl;
|
|||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.ycwl.basic.config.WechatConfig;
|
|
||||||
import com.ycwl.basic.constant.BaseContextHandler;
|
import com.ycwl.basic.constant.BaseContextHandler;
|
||||||
import com.ycwl.basic.constant.NumberConstant;
|
import com.ycwl.basic.constant.NumberConstant;
|
||||||
import com.ycwl.basic.constant.WeiXinConstant;
|
import com.ycwl.basic.constant.WeiXinConstant;
|
||||||
import com.ycwl.basic.enums.AgreementEnum;
|
|
||||||
import com.ycwl.basic.enums.BizCodeEnum;
|
import com.ycwl.basic.enums.BizCodeEnum;
|
||||||
import com.ycwl.basic.enums.WechatErrorCodeEnum;
|
import com.ycwl.basic.enums.WechatErrorCodeEnum;
|
||||||
import com.ycwl.basic.exception.AppException;
|
import com.ycwl.basic.exception.AppException;
|
||||||
@ -137,7 +135,7 @@ public class AppMemberServiceImpl implements AppMemberService {
|
|||||||
public ApiResponse<?> agreement() {
|
public ApiResponse<?> agreement() {
|
||||||
MemberEntity memberEntity = new MemberEntity();
|
MemberEntity memberEntity = new MemberEntity();
|
||||||
memberEntity.setId(Long.parseLong(BaseContextHandler.getUserId()));
|
memberEntity.setId(Long.parseLong(BaseContextHandler.getUserId()));
|
||||||
memberEntity.setAgreement(AgreementEnum.AGREE.getType());
|
memberEntity.setAgreement(1);
|
||||||
return ApiResponse.success(memberMapper.update(memberEntity));
|
return ApiResponse.success(memberMapper.update(memberEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,12 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -199,7 +203,20 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
goodsDetailVO.setGoodsType(sourceType);
|
goodsDetailVO.setGoodsType(sourceType);
|
||||||
goodsDetailVO.setSourceType(sourceType);
|
goodsDetailVO.setSourceType(sourceType);
|
||||||
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
||||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
if (sourceRespVO.getVideoUrl() != null) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||||
|
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||||
|
// 内网地址,需要代理
|
||||||
|
goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||||
|
} else {
|
||||||
|
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
log.warn("url地址解析异常:{}", sourceRespVO.getVideoUrl(), e);
|
||||||
|
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
goodsDetailVO.setUrl(sourceRespVO.getUrl());
|
goodsDetailVO.setUrl(sourceRespVO.getUrl());
|
||||||
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
||||||
goodsDetailVO.setIsFree(sourceRespVO.getIsFree());
|
goodsDetailVO.setIsFree(sourceRespVO.getIsFree());
|
||||||
@ -378,7 +395,9 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
response.setCount(finishedTask);
|
response.setCount(finishedTask);
|
||||||
int faceCutStatus = taskStatusBiz.getFaceCutStatus(faceId);
|
int faceCutStatus = taskStatusBiz.getFaceCutStatus(faceId);
|
||||||
if (Integer.valueOf(0).equals(faceCutStatus)) {
|
if (Integer.valueOf(0).equals(faceCutStatus)) {
|
||||||
response.setTemplateId(notFinishedTasks.get(0).getTemplateId());
|
if (!notFinishedTasks.isEmpty()) {
|
||||||
|
response.setTemplateId(notFinishedTasks.get(0).getTemplateId());
|
||||||
|
}
|
||||||
response.setStatus(2);
|
response.setStatus(2);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -430,10 +449,7 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
public ApiResponse<GoodsDetailVO> sourceGoodsInfo(Long sourceId) {
|
public ApiResponse<GoodsDetailVO> sourceGoodsInfo(Long sourceId) {
|
||||||
SourceRespVO sourceRespVO = sourceMapper.getById(sourceId);
|
SourceRespVO sourceRespVO = sourceMapper.getById(sourceId);
|
||||||
if (sourceRespVO == null) {
|
if (sourceRespVO == null) {
|
||||||
sourceRespVO = sourceMapper.getById(sourceId);
|
return ApiResponse.fail("该视频不存在");
|
||||||
if (sourceRespVO == null) {
|
|
||||||
return ApiResponse.fail("该视频不存在");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
|
GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
|
||||||
goodsDetailVO.setGoodsName("原片");
|
goodsDetailVO.setGoodsName("原片");
|
||||||
@ -441,7 +457,20 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
goodsDetailVO.setScenicName(sourceRespVO.getScenicName());
|
goodsDetailVO.setScenicName(sourceRespVO.getScenicName());
|
||||||
goodsDetailVO.setGoodsType(sourceRespVO.getType());
|
goodsDetailVO.setGoodsType(sourceRespVO.getType());
|
||||||
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
||||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
if (sourceRespVO.getVideoUrl() != null) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||||
|
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||||
|
// 内网地址,需要代理
|
||||||
|
goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||||
|
} else {
|
||||||
|
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
log.warn("url地址解析异常:{}", sourceRespVO.getVideoUrl(), e);
|
||||||
|
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
goodsDetailVO.setTemplateCoverUrl(sourceRespVO.getUrl());
|
goodsDetailVO.setTemplateCoverUrl(sourceRespVO.getUrl());
|
||||||
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
||||||
return ApiResponse.success(goodsDetailVO);
|
return ApiResponse.success(goodsDetailVO);
|
||||||
@ -522,7 +551,7 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
log.error("process error", e);
|
log.error("process error", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String url = adapter.uploadFile(watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||||
sourceMapper.addSourceWatermark(item.getGoodsId(), null, ImageWatermarkOperatorEnum.WATERMARK.getType(), url);
|
sourceMapper.addSourceWatermark(item.getGoodsId(), null, ImageWatermarkOperatorEnum.WATERMARK.getType(), url);
|
||||||
tmpFile.add(watermarkedFile);
|
tmpFile.add(watermarkedFile);
|
||||||
@ -634,7 +663,7 @@ public class GoodsServiceImpl implements GoodsService {
|
|||||||
log.error("process error", e);
|
log.error("process error", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String url = adapter.uploadFile(watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||||
sourceMapper.addSourceWatermark(item.getGoodsId(), face.getId(), type.getType(), url);
|
sourceMapper.addSourceWatermark(item.getGoodsId(), face.getId(), type.getType(), url);
|
||||||
tmpFile.add(watermarkedFile);
|
tmpFile.add(watermarkedFile);
|
||||||
|
@ -1,28 +1,8 @@
|
|||||||
package com.ycwl.basic.service.mobile.impl;
|
package com.ycwl.basic.service.mobile.impl;
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.aliyuncs.utils.StringUtils;
|
|
||||||
import com.wechat.pay.java.core.Config;
|
|
||||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
|
||||||
import com.wechat.pay.java.core.exception.ServiceException;
|
|
||||||
import com.wechat.pay.java.core.notification.NotificationConfig;
|
|
||||||
import com.wechat.pay.java.core.notification.NotificationParser;
|
|
||||||
import com.wechat.pay.java.core.notification.RequestParam;
|
|
||||||
import com.wechat.pay.java.core.util.PemUtil;
|
|
||||||
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
|
|
||||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
|
||||||
import com.wechat.pay.java.service.payments.jsapi.model.*;
|
|
||||||
import com.wechat.pay.java.service.payments.model.TransactionAmount;
|
|
||||||
import com.wechat.pay.java.service.refund.RefundService;
|
|
||||||
import com.wechat.pay.java.service.refund.model.AmountReq;
|
|
||||||
import com.wechat.pay.java.service.refund.model.CreateRequest;
|
|
||||||
import com.wechat.pay.java.service.refund.model.Refund;
|
|
||||||
import com.ycwl.basic.biz.OrderBiz;
|
import com.ycwl.basic.biz.OrderBiz;
|
||||||
import com.ycwl.basic.config.WechatConfig;
|
|
||||||
import com.ycwl.basic.constant.HttpConstant;
|
|
||||||
import com.ycwl.basic.constant.NumberConstant;
|
import com.ycwl.basic.constant.NumberConstant;
|
||||||
import com.ycwl.basic.constant.WeiXinConstant;
|
|
||||||
import com.ycwl.basic.enums.BizCodeEnum;
|
import com.ycwl.basic.enums.BizCodeEnum;
|
||||||
import com.ycwl.basic.enums.OrderStateEnum;
|
import com.ycwl.basic.enums.OrderStateEnum;
|
||||||
import com.ycwl.basic.enums.StatisticEnum;
|
import com.ycwl.basic.enums.StatisticEnum;
|
||||||
@ -35,37 +15,28 @@ import com.ycwl.basic.model.pc.order.entity.OrderEntity;
|
|||||||
import com.ycwl.basic.model.pc.order.req.OrderUpdateReq;
|
import com.ycwl.basic.model.pc.order.req.OrderUpdateReq;
|
||||||
import com.ycwl.basic.model.pc.payment.entity.PaymentEntity;
|
import com.ycwl.basic.model.pc.payment.entity.PaymentEntity;
|
||||||
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
|
||||||
import com.ycwl.basic.model.wx.WxchatCallbackSuccessData;
|
import com.ycwl.basic.model.wx.WxchatCallbackSuccessData;
|
||||||
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
|
import com.ycwl.basic.pay.entity.CancelOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.CreateOrderResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.PayResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundResponse;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderRequest;
|
||||||
|
import com.ycwl.basic.pay.entity.RefundOrderResponse;
|
||||||
import com.ycwl.basic.repository.OrderRepository;
|
import com.ycwl.basic.repository.OrderRepository;
|
||||||
import com.ycwl.basic.service.mobile.WxPayService;
|
import com.ycwl.basic.service.mobile.WxPayService;
|
||||||
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
import com.ycwl.basic.utils.WXPayUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import javax.servlet.ServletInputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static com.wechat.pay.java.core.http.Constant.*;
|
|
||||||
import static com.wechat.pay.java.service.refund.model.Status.SUCCESS;
|
|
||||||
import static com.ycwl.basic.constant.WeiXinConstant.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: songmingsong
|
* @Author: songmingsong
|
||||||
@ -77,8 +48,6 @@ import static com.ycwl.basic.constant.WeiXinConstant.*;
|
|||||||
@Service
|
@Service
|
||||||
public class WxPayServiceImpl implements WxPayService {
|
public class WxPayServiceImpl implements WxPayService {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WechatConfig wechatConfig;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PaymentMapper paymentMapper;
|
private PaymentMapper paymentMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -89,116 +58,50 @@ public class WxPayServiceImpl implements WxPayService {
|
|||||||
private OrderBiz orderBiz;
|
private OrderBiz orderBiz;
|
||||||
@Autowired
|
@Autowired
|
||||||
private OrderMapper orderMapper;
|
private OrderMapper orderMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScenicService scenicService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxPayRespVO createOrder(WXPayOrderReqVO req) {
|
public Map<String, Object> createOrder(Long scenicId, WXPayOrderReqVO req) {
|
||||||
PaymentEntity entity = new PaymentEntity();
|
PaymentEntity entity = new PaymentEntity();
|
||||||
entity.setOrderId(req.getOrderSn());
|
entity.setOrderId(req.getOrderSn());
|
||||||
entity.setMemberId(req.getMemberId());
|
entity.setMemberId(req.getMemberId());
|
||||||
entity.setPayPrice(new BigDecimal(BigInteger.valueOf(req.getTotalPrice()), 2));
|
entity.setPayPrice(new BigDecimal(BigInteger.valueOf(req.getTotalPrice()), 2));
|
||||||
Long entityId = paymentMapper.addGetId(entity);
|
Long entityId = paymentMapper.addGetId(entity);
|
||||||
|
IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId);
|
||||||
try {
|
try {
|
||||||
// 使用自动更新平台证书的RSA配置
|
CreateOrderRequest request = new CreateOrderRequest()
|
||||||
Config config = getInstance(wechatConfig);
|
.setOrderNo(String.valueOf(req.getOrderSn()))
|
||||||
// 构建service
|
.setPriceInCents(req.getTotalPrice())
|
||||||
JsapiService service = new JsapiService.Builder().config(config).build();
|
.setDescription(req.getDescription())
|
||||||
|
.setGoodsName(req.getGoodsName())
|
||||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
.setUserIdentify(req.getOpenId())
|
||||||
PrepayRequest request = new PrepayRequest();
|
.setNotifyUrl("https://zhentuai.com/api/mobile/wx/pay/v1/"+scenicId+"/payNotify");
|
||||||
Amount amount = new Amount();
|
CreateOrderResponse order = scenicPayAdapter.createOrder(request);
|
||||||
amount.setTotal(req.getTotalPrice());
|
Map<String, Object> paymentParams = scenicPayAdapter.getPaymentParams(order);
|
||||||
request.setAmount(amount);
|
paymentParams.put("needPay", !order.isSkipPay());
|
||||||
request.setAppid(wechatConfig.getMiniProgramAppId());
|
return paymentParams;
|
||||||
request.setMchid(wechatConfig.getMchId());
|
|
||||||
request.setDescription(req.getGoodsName());
|
|
||||||
request.setNotifyUrl(wechatConfig.getPayNotifyUrl());
|
|
||||||
request.setOutTradeNo(req.getOrderSn().toString());
|
|
||||||
request.setDescription(req.getDescription());
|
|
||||||
|
|
||||||
Payer payer = new Payer();
|
|
||||||
payer.setOpenid(req.getOpenId());
|
|
||||||
request.setPayer(payer);
|
|
||||||
// SettleInfo settleInfo = new SettleInfo();
|
|
||||||
// settleInfo.setProfitSharing(true);
|
|
||||||
// request.setSettleInfo(settleInfo);
|
|
||||||
|
|
||||||
// 调用下单方法,得到应答
|
|
||||||
PrepayResponse response = service.prepay(request);
|
|
||||||
WxPayRespVO vo = new WxPayRespVO();
|
|
||||||
Long timeStamp = System.currentTimeMillis() / NumberConstant.THOUSAND;
|
|
||||||
vo.setTimeStamp(timeStamp);
|
|
||||||
String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
|
|
||||||
vo.setNonceStr(substring);
|
|
||||||
String signatureStr = Stream.of(wechatConfig.getMiniProgramAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId())
|
|
||||||
.collect(Collectors.joining("\n", "", "\n"));
|
|
||||||
String sign = WXPayUtil.getSign(signatureStr, wechatConfig.getKeyPath());
|
|
||||||
vo.setPaySign(sign);
|
|
||||||
vo.setSignType("RSA-SHA256");
|
|
||||||
vo.setPrepayId("prepay_id=" + response.getPrepayId());
|
|
||||||
return vo;
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
JSONObject parse = JSONObject.parseObject(e.getResponseBody());
|
|
||||||
throw new AppException(BizCodeEnum.ADVANCE_PAYMENT_FAILED, parse.getString(HttpConstant.Message));
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AppException(BizCodeEnum.ADVANCE_PAYMENT_FAILED, e.toString());
|
throw new AppException(BizCodeEnum.ADVANCE_PAYMENT_FAILED, e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void payNotify(HttpServletRequest request) {
|
public void payNotify(Long scenicId, HttpServletRequest request) {
|
||||||
|
IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId);
|
||||||
try {
|
try {
|
||||||
// 读取请求体的信息
|
PayResponse callbackResponse = scenicPayAdapter.handleCallback(request);
|
||||||
ServletInputStream inputStream = request.getInputStream();
|
log.info("[微信支付]parse = {}", callbackResponse);
|
||||||
StringBuffer stringBuffer = new StringBuffer();
|
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
|
||||||
String s;
|
|
||||||
// 读取回调请求体
|
|
||||||
while ((s = bufferedReader.readLine()) != null) {
|
|
||||||
stringBuffer.append(s);
|
|
||||||
}
|
|
||||||
String s1 = stringBuffer.toString();
|
|
||||||
log.warn("微信支付回调:{}", s1);
|
|
||||||
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
|
|
||||||
String nonce = request.getHeader(WECHAT_PAY_NONCE);
|
|
||||||
String signType = request.getHeader(WeiXinConstant.WECHATPAY_SIGNATURE_TYPE);
|
|
||||||
String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
|
|
||||||
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
|
|
||||||
|
|
||||||
NotificationConfig config = new RSAAutoCertificateConfig.Builder()
|
|
||||||
.merchantId(wechatConfig.getMchId())
|
|
||||||
.privateKey(wechatConfig.getKeyPath())
|
|
||||||
.merchantSerialNumber(wechatConfig.getMchSerialNo())
|
|
||||||
.apiV3Key(wechatConfig.getApiV3())
|
|
||||||
.build();
|
|
||||||
// 初始化 NotificationParser
|
|
||||||
NotificationParser parser = new NotificationParser(config);
|
|
||||||
RequestParam requestParam = new RequestParam.Builder()
|
|
||||||
.serialNumber(serialNo)
|
|
||||||
.nonce(nonce)
|
|
||||||
.signature(signature)
|
|
||||||
.timestamp(timestamp)
|
|
||||||
// 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
|
|
||||||
.signType(signType)
|
|
||||||
.body(s1)
|
|
||||||
.build();
|
|
||||||
Transaction parse = parser.parse(requestParam, Transaction.class);
|
|
||||||
log.info("[微信支付]parse = {}", parse);
|
|
||||||
|
|
||||||
// 更新订单信息
|
// 更新订单信息
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
long orderId = Long.parseLong(parse.getOutTradeNo());
|
long orderId = Long.parseLong(callbackResponse.getOrderNo());
|
||||||
switch (parse.getTradeState()) {
|
if (callbackResponse.isPay()) {
|
||||||
case SUCCESS:
|
orderBiz.paidOrder(orderId);
|
||||||
orderBiz.paidOrder(orderId);
|
} else if (callbackResponse.isCancel()) {
|
||||||
break;
|
orderBiz.cancelOrder(orderId);
|
||||||
case NOTPAY:
|
} else if (callbackResponse.isRefund()) {
|
||||||
case CLOSED:
|
orderBiz.refundOrder(orderId);
|
||||||
case REVOKED:
|
|
||||||
orderBiz.cancelOrder(orderId);
|
|
||||||
break;
|
|
||||||
case REFUND:
|
|
||||||
orderBiz.refundOrder(orderId);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -207,59 +110,29 @@ public class WxPayServiceImpl implements WxPayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxchatCallbackSuccessData queryPay(Long orderId) {
|
public void payNotify(HttpServletRequest request) {
|
||||||
WxchatCallbackSuccessData wxchatCallbackSuccessData = new WxchatCallbackSuccessData();
|
payNotify(0L, request);
|
||||||
QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
|
}
|
||||||
queryRequest.setMchid(wechatConfig.getMchId());
|
|
||||||
queryRequest.setOutTradeNo(orderId.toString());
|
|
||||||
Config config = getInstance(wechatConfig);
|
|
||||||
// 构建service
|
|
||||||
JsapiService service = new JsapiService.Builder().config(config).build();
|
|
||||||
try {
|
|
||||||
com.wechat.pay.java.service.payments.model.Transaction transaction = service.queryOrderByOutTradeNo(queryRequest);
|
|
||||||
String successTime = transaction.getSuccessTime();
|
|
||||||
|
|
||||||
wxchatCallbackSuccessData.setOrderId(orderId.toString());
|
@Override
|
||||||
wxchatCallbackSuccessData.setSuccessTime(successTime);
|
public WxchatCallbackSuccessData queryPay(Long orderId) {
|
||||||
wxchatCallbackSuccessData.setTradetype(WeiXinConstant.getDescriptionType(transaction.getTradeType()));
|
return null;
|
||||||
wxchatCallbackSuccessData.setTradestate(WeiXinConstant.getDescriptionState(transaction.getTradeState()));
|
|
||||||
TransactionAmount amount = transaction.getAmount();
|
|
||||||
Integer total = amount.getTotal();
|
|
||||||
wxchatCallbackSuccessData.setTotalMoney(new BigDecimal(total).movePointLeft(2));
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
// API返回失败, 例如ORDER_NOT_EXISTS
|
|
||||||
log.error("[微信退款] code={}, message={}", e.getErrorCode(), e.getErrorMessage());
|
|
||||||
log.error("[微信退款] Response_body={}", e.getResponseBody());
|
|
||||||
}
|
|
||||||
return wxchatCallbackSuccessData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean refundOrder(String orderId) {
|
public Boolean refundOrder(String orderId) {
|
||||||
OrderEntity order = orderRepository.getOrder(Long.parseLong(orderId));
|
OrderEntity order = orderRepository.getOrder(Long.parseLong(orderId));
|
||||||
|
IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(order.getScenicId());
|
||||||
BigDecimal payPrice = order.getPayPrice();
|
BigDecimal payPrice = order.getPayPrice();
|
||||||
long priceInCents = payPrice.multiply(new BigDecimal(NumberConstant.HUNDRED)).longValue(); // 转换为分(int)
|
int priceInCents = payPrice.multiply(new BigDecimal(NumberConstant.HUNDRED)).intValue(); // 转换为分(int)
|
||||||
|
RefundOrderRequest request = new RefundOrderRequest()
|
||||||
Config config =
|
.setOrderNo(orderId)
|
||||||
new RSAAutoCertificateConfig.Builder()
|
.setPrice(priceInCents)
|
||||||
.merchantId(wechatConfig.getMchId())
|
.setRefundNo(SnowFlakeUtil.getId())
|
||||||
// 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
|
.setRefundPrice(priceInCents)
|
||||||
.privateKey(wechatConfig.getKeyPath())
|
.setNotifyUrl("https://zhentuai.com/api/mobile/wx/pay/v1/"+order.getScenicId()+"/refundNotify");
|
||||||
.merchantSerialNumber(wechatConfig.getMchSerialNo())
|
RefundOrderResponse response = scenicPayAdapter.refund(request);
|
||||||
.apiV3Key(wechatConfig.getApiV3())
|
if (response.isSuccess()) {
|
||||||
.build();
|
|
||||||
RefundService service = new RefundService.Builder().config(config).build();
|
|
||||||
CreateRequest request = new CreateRequest();
|
|
||||||
request.setNotifyUrl(wechatConfig.getRefundNotifyUrl());
|
|
||||||
AmountReq amountReq = new AmountReq();
|
|
||||||
amountReq.setTotal(priceInCents);
|
|
||||||
amountReq.setRefund(priceInCents);
|
|
||||||
amountReq.setCurrency(WECHATPAY_CURRENCY_CNY);
|
|
||||||
request.setAmount(amountReq);
|
|
||||||
request.setOutTradeNo(orderId);
|
|
||||||
request.setOutRefundNo(SnowFlakeUtil.getId());
|
|
||||||
Refund refundResult = service.create(request);
|
|
||||||
if (refundResult.getStatus() == SUCCESS) {
|
|
||||||
OrderUpdateReq orderUpdateReq = new OrderUpdateReq();
|
OrderUpdateReq orderUpdateReq = new OrderUpdateReq();
|
||||||
orderUpdateReq.setId(Long.parseLong(orderId));
|
orderUpdateReq.setId(Long.parseLong(orderId));
|
||||||
orderUpdateReq.setRefundStatus(OrderStateEnum.REFUNDED.getType());
|
orderUpdateReq.setRefundStatus(OrderStateEnum.REFUNDED.getType());
|
||||||
@ -272,31 +145,14 @@ public class WxPayServiceImpl implements WxPayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean refundNotify(String refundResult) throws IOException, GeneralSecurityException {
|
public boolean refundNotify(Long scenicId, HttpServletRequest request) throws IOException {
|
||||||
// 转为map格式
|
IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(scenicId);
|
||||||
Map<String, String> jsonMap = JSONObject.parseObject(refundResult, Map.class);
|
try {
|
||||||
|
RefundResponse callbackResponse = scenicPayAdapter.handleRefundCallback(request);
|
||||||
|
log.info("[微信支付]parse = {}", callbackResponse);
|
||||||
|
|
||||||
/*
|
// 更新订单信息
|
||||||
* 退款成功后返回一个加密字段resource,以下为解密
|
long orderId = Long.parseLong(callbackResponse.getOrderNo());
|
||||||
* 解密需要从resource参数中,获取到ciphertext,nonce,associated_data这三个参数进行解密
|
|
||||||
*/
|
|
||||||
String resource = JSONObject.toJSONString(jsonMap.get(REFUNDS_RESOURCE));
|
|
||||||
JSONObject object = JSONObject.parseObject(resource);
|
|
||||||
|
|
||||||
String ciphertext = String.valueOf(object.get(REFUNDS_CIPHERTEXT));
|
|
||||||
String nonce = String.valueOf(object.get(REFUNDS_NONCE));
|
|
||||||
String associated_data = String.valueOf(object.get(REFUNDS_ASSOCIATED_DATA));
|
|
||||||
|
|
||||||
String resultStr = decryptToString(associated_data.getBytes(String.valueOf(StandardCharsets.UTF_8)),
|
|
||||||
nonce.getBytes(String.valueOf(StandardCharsets.UTF_8)),
|
|
||||||
ciphertext);
|
|
||||||
Map<String, String> reqInfo = JSONObject.parseObject(resultStr, Map.class);
|
|
||||||
|
|
||||||
String refund_status = reqInfo.get(REFUNDS_REFUND_STATUS);// 退款状态
|
|
||||||
String out_trade_no = reqInfo.get(WECHATPAY_OUT_TRADE_NO); // 订单号
|
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(refund_status) && WECHATPAY_SUCCESS.equals(refund_status)) {
|
|
||||||
long orderId = Long.parseLong(out_trade_no);
|
|
||||||
orderBiz.refundOrder(orderId);
|
orderBiz.refundOrder(orderId);
|
||||||
|
|
||||||
OrderEntity order = orderRepository.getOrder(orderId);
|
OrderEntity order = orderRepository.getOrder(orderId);
|
||||||
@ -306,117 +162,19 @@ public class WxPayServiceImpl implements WxPayService {
|
|||||||
statisticsRecordAddReq.setScenicId(order.getScenicId());
|
statisticsRecordAddReq.setScenicId(order.getScenicId());
|
||||||
statisticsRecordAddReq.setMorphId(orderId);
|
statisticsRecordAddReq.setMorphId(orderId);
|
||||||
statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
|
statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
|
||||||
|
|
||||||
log.info("[微信退款回调]退款成功");
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
log.error("[微信退款回调]退款失败");
|
log.error("微信退款回调失败!", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeOrder(String orderId) {
|
public void closeOrder(String orderId) {
|
||||||
CloseOrderRequest closeOrderRequest = new CloseOrderRequest();
|
OrderEntity order = orderRepository.getOrder(Long.parseLong(orderId));
|
||||||
closeOrderRequest.setOutTradeNo(orderId);
|
IPayAdapter scenicPayAdapter = scenicService.getScenicPayAdapter(order.getScenicId());
|
||||||
closeOrderRequest.setMchid(wechatConfig.getMchId());
|
CancelOrderRequest request = new CancelOrderRequest()
|
||||||
Config config = getInstance(wechatConfig);
|
.setOrderNo(orderId);
|
||||||
// 构建service
|
scenicPayAdapter.cancelOrder(request);
|
||||||
JsapiService service = new JsapiService.Builder().config(config).build();
|
|
||||||
service.closeOrder(closeOrderRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款回调 解密数据
|
|
||||||
*
|
|
||||||
* @param associatedData
|
|
||||||
* @param nonce
|
|
||||||
* @param ciphertext
|
|
||||||
* @return
|
|
||||||
* @throws GeneralSecurityException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {
|
|
||||||
try {
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
|
||||||
SecretKeySpec key = new SecretKeySpec(wechatConfig.getApiV3().getBytes(), "AES");
|
|
||||||
GCMParameterSpec spec = new GCMParameterSpec(128, nonce);
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
|
||||||
cipher.updateAAD(associatedData);
|
|
||||||
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8);
|
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成退款请求token
|
|
||||||
*
|
|
||||||
* @param method
|
|
||||||
* @param orderId
|
|
||||||
* @param body
|
|
||||||
* @return
|
|
||||||
* @throws InvalidKeyException
|
|
||||||
* @throws NoSuchAlgorithmException
|
|
||||||
* @throws UnsupportedEncodingException
|
|
||||||
* @throws SignatureException
|
|
||||||
*/
|
|
||||||
public String getToken(String method, String orderId, String body) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException, SignatureException {
|
|
||||||
String nonceStr = WXPayUtil.generateNonceStr();
|
|
||||||
long timestamp = System.currentTimeMillis() / NumberConstant.THOUSAND; // 生成时间戳
|
|
||||||
|
|
||||||
String parameter = method + "\n"
|
|
||||||
+ REFUNDS_URi + orderId + "\n"
|
|
||||||
+ timestamp + "\n"
|
|
||||||
+ nonceStr + "\n"
|
|
||||||
+ body + "\n";
|
|
||||||
|
|
||||||
// 对参数进行加密
|
|
||||||
byte[] bytes = parameter.getBytes(String.valueOf(StandardCharsets.UTF_8));
|
|
||||||
Signature sign = Signature.getInstance("SHA256withRSA");
|
|
||||||
PrivateKey privateKey = PemUtil.loadPrivateKeyFromString(wechatConfig.getKeyPath()); // privateKeyPath是商户证书密钥的位置apiclient_key.pem
|
|
||||||
sign.initSign(privateKey); // 商户密钥文件路径
|
|
||||||
sign.update(bytes);
|
|
||||||
String signature = Base64.getEncoder().encodeToString(sign.sign());
|
|
||||||
|
|
||||||
// 获取token
|
|
||||||
String token = "mchid=\"" + wechatConfig.getMchId() + "\"," // 商户号
|
|
||||||
+ "nonce_str=\"" + nonceStr + "\","
|
|
||||||
+ "timestamp=\"" + timestamp + "\","
|
|
||||||
+ "serial_no=\"" + wechatConfig.getMchSerialNo() + "\"," // merchantSerialNumber是微信支付中申请的证书序列号
|
|
||||||
+ "signature=\"" + signature + "\"";
|
|
||||||
|
|
||||||
return REFUNDS_SCHEMA + token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
|
|
||||||
*/
|
|
||||||
private static class Holder {
|
|
||||||
private static volatile Config instance;
|
|
||||||
|
|
||||||
static void init(WechatConfig wechatConfig) {
|
|
||||||
instance = new RSAAutoCertificateConfig.Builder()
|
|
||||||
.merchantId(wechatConfig.getMchId())
|
|
||||||
.privateKey(wechatConfig.getKeyPath())
|
|
||||||
.merchantSerialNumber(wechatConfig.getMchSerialNo())
|
|
||||||
.apiV3Key(wechatConfig.getApiV3())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Config getInstance(WechatConfig wechatConfig) {
|
|
||||||
if (Holder.instance == null) {
|
|
||||||
synchronized (Holder.class) {
|
|
||||||
if (Holder.instance == null) {
|
|
||||||
Holder.init(wechatConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Holder.instance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,13 @@ import com.ycwl.basic.model.pc.order.entity.OrderEntity;
|
|||||||
import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO;
|
import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO;
|
||||||
import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO;
|
import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO;
|
||||||
import com.ycwl.basic.model.pc.order.req.OrderUpdateReq;
|
import com.ycwl.basic.model.pc.order.req.OrderUpdateReq;
|
||||||
import com.ycwl.basic.model.pc.order.req.OrderAddReq;
|
|
||||||
import com.ycwl.basic.model.pc.order.req.OrderReqQuery;
|
import com.ycwl.basic.model.pc.order.req.OrderReqQuery;
|
||||||
import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO;
|
import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO;
|
||||||
import com.ycwl.basic.model.pc.order.resp.OrderRespVO;
|
import com.ycwl.basic.model.pc.order.resp.OrderRespVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author:longbinbin
|
* @Author:longbinbin
|
||||||
@ -63,7 +62,7 @@ public interface OrderService {
|
|||||||
|
|
||||||
ApiResponse<PageInfo<OrderRespVO>> refundPageQuery(OrderReqQuery query);
|
ApiResponse<PageInfo<OrderRespVO>> refundPageQuery(OrderReqQuery query);
|
||||||
|
|
||||||
ApiResponse<WxPayRespVO> createOrder(Long userId, CreateOrderReqVO orderAddReq) throws Exception;
|
ApiResponse<Map<String, Object>> createOrder(Long userId, CreateOrderReqVO orderAddReq) throws Exception;
|
||||||
|
|
||||||
ApiResponse<WxPayRespVO> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception;
|
ApiResponse<Map<String, Object>> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -19,4 +19,6 @@ public interface PriceConfigService extends IService<PriceConfigEntity> {
|
|||||||
void fillGoodsName(List<PriceConfigRespVO> result);
|
void fillGoodsName(List<PriceConfigRespVO> result);
|
||||||
|
|
||||||
void fillGoodsName(PriceConfigRespVO config);
|
void fillGoodsName(PriceConfigRespVO config);
|
||||||
|
|
||||||
|
void updateStatus(Integer id);
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
|||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||||
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||||
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
|
|
||||||
@ -36,5 +37,11 @@ public interface ScenicService {
|
|||||||
|
|
||||||
IStorageAdapter getScenicStorageAdapter(Long scenicId);
|
IStorageAdapter getScenicStorageAdapter(Long scenicId);
|
||||||
|
|
||||||
|
IStorageAdapter getScenicTmpStorageAdapter(Long scenicId);
|
||||||
|
|
||||||
|
IStorageAdapter getScenicLocalStorageAdapter(Long scenicId);
|
||||||
|
|
||||||
IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId);
|
IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId);
|
||||||
|
|
||||||
|
IPayAdapter getScenicPayAdapter(Long scenicId);
|
||||||
}
|
}
|
||||||
|
@ -136,14 +136,7 @@ public class FaceServiceImpl implements FaceService {
|
|||||||
String faceUrl = adapter.uploadFile(file, filePath, fileName);
|
String faceUrl = adapter.uploadFile(file, filePath, fileName);
|
||||||
Long newFaceId = SnowFlakeUtil.getLongId();
|
Long newFaceId = SnowFlakeUtil.getLongId();
|
||||||
Long oldFaceId = null;
|
Long oldFaceId = null;
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId);
|
||||||
IFaceBodyAdapter faceBodyAdapter;
|
|
||||||
if (scenicConfig != null && scenicConfig.getFaceType() != null) {
|
|
||||||
faceBodyAdapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
|
|
||||||
faceBodyAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
|
|
||||||
} else {
|
|
||||||
faceBodyAdapter = FaceBodyFactory.use();
|
|
||||||
}
|
|
||||||
faceService.assureFaceDb(faceBodyAdapter, USER_FACE_DB_NAME+scenicId);
|
faceService.assureFaceDb(faceBodyAdapter, USER_FACE_DB_NAME+scenicId);
|
||||||
SearchFaceRespVo userDbSearchResult = faceService.searchFace(faceBodyAdapter, USER_FACE_DB_NAME+scenicId, faceUrl, "判断是否为用户上传过的人脸");
|
SearchFaceRespVo userDbSearchResult = faceService.searchFace(faceBodyAdapter, USER_FACE_DB_NAME+scenicId, faceUrl, "判断是否为用户上传过的人脸");
|
||||||
float strictScore = 0.6F;
|
float strictScore = 0.6F;
|
||||||
@ -225,13 +218,7 @@ public class FaceServiceImpl implements FaceService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
|
||||||
IFaceBodyAdapter faceBodyAdapter;
|
IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(face.getScenicId());
|
||||||
if (scenicConfig != null && scenicConfig.getFaceType() != null) {
|
|
||||||
faceBodyAdapter = FaceBodyFactory.getAdapter(scenicConfig.getFaceType());
|
|
||||||
faceBodyAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getFaceConfigJson(), Map.class));
|
|
||||||
} else {
|
|
||||||
faceBodyAdapter = FaceBodyFactory.use();
|
|
||||||
}
|
|
||||||
SearchFaceRespVo scenicDbSearchResult = faceService.searchFace(faceBodyAdapter, String.valueOf(face.getScenicId()), face.getFaceUrl(), "人脸识别");
|
SearchFaceRespVo scenicDbSearchResult = faceService.searchFace(faceBodyAdapter, String.valueOf(face.getScenicId()), face.getFaceUrl(), "人脸识别");
|
||||||
if (scenicDbSearchResult == null) {
|
if (scenicDbSearchResult == null) {
|
||||||
throw new BaseException("人脸识别失败,请换一张试试把~");
|
throw new BaseException("人脸识别失败,请换一张试试把~");
|
||||||
@ -244,7 +231,10 @@ public class FaceServiceImpl implements FaceService {
|
|||||||
FaceSampleEntity faceSample = faceRepository.getFaceSample(resultItem);
|
FaceSampleEntity faceSample = faceRepository.getFaceSample(resultItem);
|
||||||
if (faceSample != null) {
|
if (faceSample != null) {
|
||||||
// 以这个结果为人脸库的匹配结果
|
// 以这个结果为人脸库的匹配结果
|
||||||
scenicDbSearchResult = faceService.searchFace(faceBodyAdapter, String.valueOf(face.getScenicId()), faceSample.getFaceUrl(), "人脸补救措施1");
|
SearchFaceRespVo tmpResult = faceService.searchFace(faceBodyAdapter, String.valueOf(face.getScenicId()), faceSample.getFaceUrl(), "人脸补救措施1");
|
||||||
|
if (tmpResult != null && tmpResult.getSampleListIds() != null && !tmpResult.getSampleListIds().isEmpty()) {
|
||||||
|
scenicDbSearchResult = tmpResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
|||||||
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
|
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
|
||||||
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
|
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
|
||||||
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
import com.ycwl.basic.model.wx.WXPayOrderReqVO;
|
||||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
|
||||||
import com.ycwl.basic.repository.FaceRepository;
|
import com.ycwl.basic.repository.FaceRepository;
|
||||||
import com.ycwl.basic.repository.PriceRepository;
|
import com.ycwl.basic.repository.PriceRepository;
|
||||||
import com.ycwl.basic.repository.VideoRepository;
|
import com.ycwl.basic.repository.VideoRepository;
|
||||||
@ -52,7 +51,9 @@ import java.math.BigDecimal;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -167,11 +168,12 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 发起支付
|
* 发起支付
|
||||||
* @param order 订单
|
*
|
||||||
|
* @param order 订单
|
||||||
* @param orderItems 商品详情
|
* @param orderItems 商品详情
|
||||||
* @return 支付请求结果
|
* @return 支付请求结果
|
||||||
*/
|
*/
|
||||||
private WxPayRespVO initiatePayment(OrderEntity order, List<OrderItemEntity> orderItems) throws Exception {
|
private Map<String, Object> initiatePayment(OrderEntity order, List<OrderItemEntity> orderItems) throws Exception {
|
||||||
WXPayOrderReqVO wxPayOrderReqVO = new WXPayOrderReqVO();
|
WXPayOrderReqVO wxPayOrderReqVO = new WXPayOrderReqVO();
|
||||||
String goodsName = null;
|
String goodsName = null;
|
||||||
if (orderItems.size() > 1) {
|
if (orderItems.size() > 1) {
|
||||||
@ -186,12 +188,6 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
goodsName = "景区照片包";
|
goodsName = "景区照片包";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
// 0元支付
|
|
||||||
WxPayRespVO wxPayRespVO = new WxPayRespVO();
|
|
||||||
wxPayRespVO.setNeedPay(false);
|
|
||||||
return wxPayRespVO;
|
|
||||||
}
|
|
||||||
wxPayOrderReqVO.setOpenId(order.getOpenId())
|
wxPayOrderReqVO.setOpenId(order.getOpenId())
|
||||||
.setMemberId(order.getMemberId())
|
.setMemberId(order.getMemberId())
|
||||||
.setOrderSn(order.getId())
|
.setOrderSn(order.getId())
|
||||||
@ -199,7 +195,7 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
.setGoodsName(goodsName)
|
.setGoodsName(goodsName)
|
||||||
.setDescription(goodsName);
|
.setDescription(goodsName);
|
||||||
|
|
||||||
return wxPayService.createOrder(wxPayOrderReqVO);
|
return wxPayService.createOrder(order.getScenicId(), wxPayOrderReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -360,7 +356,7 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ApiResponse<WxPayRespVO> createOrder(Long userId, CreateOrderReqVO createOrderReqVO) throws Exception {
|
public ApiResponse<Map<String, Object>> createOrder(Long userId, CreateOrderReqVO createOrderReqVO) throws Exception {
|
||||||
IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId());
|
IsBuyRespVO isBuy = orderBiz.isBuy(userId, createOrderReqVO.getScenicId(), createOrderReqVO.getGoodsType(), createOrderReqVO.getGoodsId());
|
||||||
if (isBuy.isBuy()) {
|
if (isBuy.isBuy()) {
|
||||||
return ApiResponse.fail("您已购买此内容,无需重复购买!");
|
return ApiResponse.fail("您已购买此内容,无需重复购买!");
|
||||||
@ -442,16 +438,18 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
}
|
}
|
||||||
if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
|
if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
orderBiz.paidOrder(order.getId());
|
orderBiz.paidOrder(order.getId());
|
||||||
return ApiResponse.success(new WxPayRespVO());
|
HashMap<String, Object> data = new HashMap<>();
|
||||||
|
data.put("needPay", false);
|
||||||
|
return ApiResponse.success(data);
|
||||||
} else {
|
} else {
|
||||||
WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems);
|
Map<String, Object> wxPayRespVO = initiatePayment(order, orderItems);
|
||||||
return ApiResponse.success(wxPayRespVO);
|
return ApiResponse.success(wxPayRespVO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ApiResponse<WxPayRespVO> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception {
|
public ApiResponse<Map<String, Object>> createBatchOrder(Long userId, CreateBatchOrderReqVO batchOrderReqVO) throws Exception {
|
||||||
PriceConfigEntity priceConfig = priceRepository.getPriceConfigByScenicTypeGoods(batchOrderReqVO.getScenicId(), batchOrderReqVO.getType(), batchOrderReqVO.getGoodsId());
|
PriceConfigEntity priceConfig = priceRepository.getPriceConfigByScenicTypeGoods(batchOrderReqVO.getScenicId(), batchOrderReqVO.getType(), batchOrderReqVO.getGoodsId());
|
||||||
if (priceConfig == null) {
|
if (priceConfig == null) {
|
||||||
return ApiResponse.fail("该套餐暂未开放购买");
|
return ApiResponse.fail("该套餐暂未开放购买");
|
||||||
@ -504,9 +502,11 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
}
|
}
|
||||||
if (order.getPayPrice().equals(BigDecimal.ZERO)) {
|
if (order.getPayPrice().equals(BigDecimal.ZERO)) {
|
||||||
orderBiz.paidOrder(order.getId());
|
orderBiz.paidOrder(order.getId());
|
||||||
return ApiResponse.success(new WxPayRespVO());
|
HashMap<String, Object> data = new HashMap<>();
|
||||||
|
data.put("needPay", false);
|
||||||
|
return ApiResponse.success(data);
|
||||||
} else {
|
} else {
|
||||||
WxPayRespVO wxPayRespVO = initiatePayment(order, orderItems);
|
Map<String, Object> wxPayRespVO = initiatePayment(order, orderItems);
|
||||||
return ApiResponse.success(wxPayRespVO);
|
return ApiResponse.success(wxPayRespVO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,4 +74,9 @@ public class PriceConfigServiceImpl extends ServiceImpl<PriceConfigMapper, Price
|
|||||||
item.setGoodsNames(StringUtils.join(goodsNames, ","));
|
item.setGoodsNames(StringUtils.join(goodsNames, ","));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStatus(Integer id) {
|
||||||
|
baseMapper.updateStatus(id);
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,11 +12,14 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
|||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicAddOrUpdateReq;
|
||||||
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||||
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||||
|
import com.ycwl.basic.pay.PayFactory;
|
||||||
|
import com.ycwl.basic.pay.adapter.IPayAdapter;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
import com.ycwl.basic.service.pc.ScenicService;
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
import com.ycwl.basic.service.task.TaskFaceService;
|
import com.ycwl.basic.service.task.TaskFaceService;
|
||||||
import com.ycwl.basic.storage.StorageFactory;
|
import com.ycwl.basic.storage.StorageFactory;
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
|
import com.ycwl.basic.storage.exceptions.StorageUnsupportedException;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -105,6 +108,7 @@ public class ScenicServiceImpl implements ScenicService {
|
|||||||
scenicRepository.clearCache(id);
|
scenicRepository.clearCache(id);
|
||||||
scenicFaceBodyAdapterMap.remove(id);
|
scenicFaceBodyAdapterMap.remove(id);
|
||||||
scenicStorageAdapterMap.remove(id);
|
scenicStorageAdapterMap.remove(id);
|
||||||
|
scenicPayAdapterMap.remove(id);
|
||||||
return ApiResponse.success(true);
|
return ApiResponse.success(true);
|
||||||
}else {
|
}else {
|
||||||
return ApiResponse.fail("景区删除失败");
|
return ApiResponse.fail("景区删除失败");
|
||||||
@ -197,6 +201,9 @@ public class ScenicServiceImpl implements ScenicService {
|
|||||||
scenicRepository.clearCache(config.getScenicId());
|
scenicRepository.clearCache(config.getScenicId());
|
||||||
scenicFaceBodyAdapterMap.remove(config.getScenicId());
|
scenicFaceBodyAdapterMap.remove(config.getScenicId());
|
||||||
scenicStorageAdapterMap.remove(config.getScenicId());
|
scenicStorageAdapterMap.remove(config.getScenicId());
|
||||||
|
scenicTmpStorageAdapterMap.remove(config.getScenicId());
|
||||||
|
scenicLocalStorageAdapterMap.remove(config.getScenicId());
|
||||||
|
scenicPayAdapterMap.remove(config.getScenicId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -207,14 +214,57 @@ public class ScenicServiceImpl implements ScenicService {
|
|||||||
IStorageAdapter adapter;
|
IStorageAdapter adapter;
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
try {
|
||||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||||
|
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||||
|
} catch (StorageUnsupportedException ignored) {
|
||||||
|
return StorageFactory.use("video");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
adapter = StorageFactory.use("video");
|
adapter = StorageFactory.use("video");
|
||||||
}
|
}
|
||||||
return adapter;
|
return adapter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private static final Map<Long, IStorageAdapter> scenicTmpStorageAdapterMap = new ConcurrentHashMap<>();
|
||||||
|
@Override
|
||||||
|
public IStorageAdapter getScenicTmpStorageAdapter(Long scenicId) {
|
||||||
|
return scenicTmpStorageAdapterMap.computeIfAbsent(scenicId, (key) -> {
|
||||||
|
IStorageAdapter adapter;
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
|
if (scenicConfig != null && scenicConfig.getTmpStoreType() != null) {
|
||||||
|
try {
|
||||||
|
adapter = StorageFactory.get(scenicConfig.getTmpStoreType());
|
||||||
|
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getTmpStoreConfigJson(), Map.class));
|
||||||
|
} catch (StorageUnsupportedException ignored) {
|
||||||
|
return getScenicStorageAdapter(scenicId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getScenicStorageAdapter(scenicId);
|
||||||
|
}
|
||||||
|
return adapter;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private static final Map<Long, IStorageAdapter> scenicLocalStorageAdapterMap = new ConcurrentHashMap<>();
|
||||||
|
@Override
|
||||||
|
public IStorageAdapter getScenicLocalStorageAdapter(Long scenicId) {
|
||||||
|
return scenicLocalStorageAdapterMap.computeIfAbsent(scenicId, (key) -> {
|
||||||
|
IStorageAdapter adapter;
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
|
if (scenicConfig != null && scenicConfig.getLocalStoreType() != null) {
|
||||||
|
try {
|
||||||
|
adapter = StorageFactory.get(scenicConfig.getLocalStoreType());
|
||||||
|
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getLocalStoreConfigJson(), Map.class));
|
||||||
|
} catch (StorageUnsupportedException ignored) {
|
||||||
|
return getScenicStorageAdapter(scenicId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getScenicStorageAdapter(scenicId);
|
||||||
|
}
|
||||||
|
return adapter;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static final Map<Long, IFaceBodyAdapter> scenicFaceBodyAdapterMap = new ConcurrentHashMap<>();
|
private static final Map<Long, IFaceBodyAdapter> scenicFaceBodyAdapterMap = new ConcurrentHashMap<>();
|
||||||
@Override
|
@Override
|
||||||
public IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId) {
|
public IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId) {
|
||||||
@ -230,4 +280,20 @@ public class ScenicServiceImpl implements ScenicService {
|
|||||||
return adapter;
|
return adapter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Map<Long, IPayAdapter> scenicPayAdapterMap = new ConcurrentHashMap<>();
|
||||||
|
@Override
|
||||||
|
public IPayAdapter getScenicPayAdapter(Long scenicId) {
|
||||||
|
return scenicPayAdapterMap.computeIfAbsent(scenicId, (key) -> {
|
||||||
|
IPayAdapter adapter;
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
|
if (scenicConfig != null && scenicConfig.getPayType() != null) {
|
||||||
|
adapter = PayFactory.getAdapter(scenicConfig.getPayType());
|
||||||
|
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getPayConfigJson(), Map.class));
|
||||||
|
} else {
|
||||||
|
adapter = PayFactory.use();
|
||||||
|
}
|
||||||
|
return adapter;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,12 @@ import com.ycwl.basic.service.pc.SourceService;
|
|||||||
import com.ycwl.basic.task.VideoPieceGetter;
|
import com.ycwl.basic.task.VideoPieceGetter;
|
||||||
import com.ycwl.basic.utils.ApiResponse;
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -32,18 +35,63 @@ public class SourceServiceImpl implements SourceService {
|
|||||||
public ApiResponse<PageInfo<SourceRespVO>> pageQuery(SourceReqQuery sourceReqQuery) {
|
public ApiResponse<PageInfo<SourceRespVO>> pageQuery(SourceReqQuery sourceReqQuery) {
|
||||||
PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
|
PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
|
||||||
List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
|
List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
|
||||||
|
list.forEach(sourceRespVO -> {
|
||||||
|
if (sourceRespVO.getVideoUrl() != null) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||||
|
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||||
|
// 内网地址,需要代理
|
||||||
|
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||||
|
} else {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
|
PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
|
||||||
return ApiResponse.success(pageInfo);
|
return ApiResponse.success(pageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<List<SourceRespVO>> list(SourceReqQuery sourceReqQuery) {
|
public ApiResponse<List<SourceRespVO>> list(SourceReqQuery sourceReqQuery) {
|
||||||
return ApiResponse.success(sourceMapper.list(sourceReqQuery));
|
List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
|
||||||
|
list.forEach(sourceRespVO -> {
|
||||||
|
if (sourceRespVO.getVideoUrl() != null) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||||
|
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||||
|
// 内网地址,需要代理
|
||||||
|
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||||
|
} else {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return ApiResponse.success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<SourceRespVO> getById(Long id, Long userId) {
|
public ApiResponse<SourceRespVO> getById(Long id, Long userId) {
|
||||||
return ApiResponse.success(sourceMapper.userGetById(id, userId));
|
SourceRespVO sourceRespVO = sourceMapper.userGetById(id, userId);
|
||||||
|
if (sourceRespVO.getVideoUrl() != null) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||||
|
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||||
|
// 内网地址,需要代理
|
||||||
|
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||||
|
} else {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ApiResponse.success(sourceRespVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,8 +10,6 @@ public interface TaskFaceService {
|
|||||||
|
|
||||||
SearchFaceRespVo searchFace(IFaceBodyAdapter adapter, String dbName, String faceUrl, String reason);
|
SearchFaceRespVo searchFace(IFaceBodyAdapter adapter, String dbName, String faceUrl, String reason);
|
||||||
|
|
||||||
String uploadFile(MultipartFile file, Long userId);
|
|
||||||
|
|
||||||
boolean deleteFaceSample(Long scenicId, String dbName, String entityId);
|
boolean deleteFaceSample(Long scenicId, String dbName, String entityId);
|
||||||
|
|
||||||
boolean assureFaceDb(IFaceBodyAdapter faceBodyAdapter, String dbName);
|
boolean assureFaceDb(IFaceBodyAdapter faceBodyAdapter, String dbName);
|
||||||
|
@ -3,8 +3,6 @@ package com.ycwl.basic.service.task.impl;
|
|||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesRequest;
|
|
||||||
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse;
|
|
||||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
||||||
import com.ycwl.basic.biz.OrderBiz;
|
import com.ycwl.basic.biz.OrderBiz;
|
||||||
import com.ycwl.basic.constant.FaceConstant;
|
import com.ycwl.basic.constant.FaceConstant;
|
||||||
@ -17,7 +15,6 @@ import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
|
|||||||
import com.ycwl.basic.mapper.FaceDetectLogMapper;
|
import com.ycwl.basic.mapper.FaceDetectLogMapper;
|
||||||
import com.ycwl.basic.mapper.FaceMapper;
|
import com.ycwl.basic.mapper.FaceMapper;
|
||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.ScenicMapper;
|
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||||
@ -27,7 +24,6 @@ import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
|||||||
import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog;
|
import com.ycwl.basic.model.pc.faceDetectLog.entity.FaceDetectLog;
|
||||||
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
import com.ycwl.basic.model.pc.faceDetectLog.resp.MatchLocalRecord;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||||
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
|
||||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||||
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
|
||||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||||
@ -42,8 +38,6 @@ import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
|||||||
import com.ycwl.basic.storage.utils.StorageUtil;
|
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||||
import com.ycwl.basic.task.VideoPieceGetter;
|
import com.ycwl.basic.task.VideoPieceGetter;
|
||||||
import com.ycwl.basic.utils.DateUtils;
|
import com.ycwl.basic.utils.DateUtils;
|
||||||
import com.ycwl.basic.utils.ratelimiter.FixedRateLimiter;
|
|
||||||
import com.ycwl.basic.utils.ratelimiter.IRateLimiter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -55,18 +49,13 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
|
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
|
||||||
@ -239,30 +228,27 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
List<FaceSampleEntity> allFaceSampleList = new ArrayList<>();
|
List<FaceSampleEntity> allFaceSampleList = new ArrayList<>();
|
||||||
if (StringUtils.isNumeric(dbName)) { // 景区
|
if (StringUtils.isNumeric(dbName)) { // 景区
|
||||||
allFaceSampleList = faceSampleMapper.listByIds(allFaceSampleIds);
|
allFaceSampleList = faceSampleMapper.listByIds(allFaceSampleIds);
|
||||||
Long firstFaceSampleId = acceptFaceSampleIds.get(0);
|
if (!acceptFaceSampleIds.isEmpty()) {
|
||||||
Optional<FaceSampleEntity> firstFaceSample = allFaceSampleList.stream().filter(faceSample -> faceSample.getId().equals(firstFaceSampleId)).findAny();
|
Long firstFaceSampleId = acceptFaceSampleIds.get(0);
|
||||||
if (firstFaceSample.isPresent()) {
|
Optional<FaceSampleEntity> firstFaceSample = allFaceSampleList.stream().filter(faceSample -> faceSample.getId().equals(firstFaceSampleId)).findAny();
|
||||||
if (tourMinutes > 0) {
|
if (firstFaceSample.isPresent()) {
|
||||||
List<FaceSampleEntity> acceptFaceSampleList = faceSampleMapper.listByIds(acceptFaceSampleIds);
|
if (tourMinutes > 0) {
|
||||||
Date startDate = DateUtil.offsetMinute(firstFaceSample.get().getCreateAt(), -tourMinutes/2);
|
List<FaceSampleEntity> acceptFaceSampleList = faceSampleMapper.listByIds(acceptFaceSampleIds);
|
||||||
Date endDate = DateUtil.offsetMinute(firstFaceSample.get().getCreateAt(), tourMinutes/2);
|
Date startDate = DateUtil.offsetMinute(firstFaceSample.get().getCreateAt(), -tourMinutes/2);
|
||||||
acceptFaceSampleIds = acceptFaceSampleList.stream()
|
Date endDate = DateUtil.offsetMinute(firstFaceSample.get().getCreateAt(), tourMinutes/2);
|
||||||
.filter(faceSample -> faceSample.getCreateAt().after(startDate) && faceSample.getCreateAt().before(endDate))
|
acceptFaceSampleIds = acceptFaceSampleList.stream()
|
||||||
.map(FaceSampleEntity::getId)
|
.filter(faceSample -> faceSample.getCreateAt().after(startDate) && faceSample.getCreateAt().before(endDate))
|
||||||
.collect(Collectors.toList());
|
.map(FaceSampleEntity::getId)
|
||||||
log.info("时间范围逻辑:最高匹配:{},时间范围需要在:{}~{}间", firstFaceSample, startDate, endDate);
|
.collect(Collectors.toList());
|
||||||
|
log.info("时间范围逻辑:最高匹配:{},时间范围需要在:{}~{}间", firstFaceSample, startDate, endDate);
|
||||||
|
} else {
|
||||||
|
log.info("时间范围逻辑:景区未限制");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("时间范围逻辑:景区未限制");
|
log.info("时间范围逻辑:最高匹配ID:{},未找到", firstFaceSampleId);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.info("时间范围逻辑:最高匹配ID:{},未找到", firstFaceSampleId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (acceptFaceSampleIds.isEmpty()) {
|
|
||||||
respVo.setFirstMatchRate(0f);
|
|
||||||
respVo.setSampleListIds(Collections.emptyList());
|
|
||||||
return respVo;
|
|
||||||
}
|
|
||||||
List<MatchLocalRecord> collect = new ArrayList<>();
|
List<MatchLocalRecord> collect = new ArrayList<>();
|
||||||
for (SearchFaceResultItem item : records) {
|
for (SearchFaceResultItem item : records) {
|
||||||
MatchLocalRecord record = new MatchLocalRecord();
|
MatchLocalRecord record = new MatchLocalRecord();
|
||||||
@ -286,6 +272,11 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
record.setMatched(item.getScore() > _threshold);
|
record.setMatched(item.getScore() > _threshold);
|
||||||
collect.add(record);
|
collect.add(record);
|
||||||
}
|
}
|
||||||
|
if (acceptFaceSampleIds.isEmpty()) {
|
||||||
|
respVo.setFirstMatchRate(0f);
|
||||||
|
respVo.setSampleListIds(Collections.emptyList());
|
||||||
|
return respVo;
|
||||||
|
}
|
||||||
logEntity.setMatchLocalRecord(JSONObject.toJSONString(collect));
|
logEntity.setMatchLocalRecord(JSONObject.toJSONString(collect));
|
||||||
respVo.setFirstMatchRate(response.getFirstMatchRate());
|
respVo.setFirstMatchRate(response.getFirstMatchRate());
|
||||||
respVo.setSampleListIds(acceptFaceSampleIds);
|
respVo.setSampleListIds(acceptFaceSampleIds);
|
||||||
@ -298,30 +289,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String uploadFile(MultipartFile file, Long userId) {
|
|
||||||
if (file.isEmpty()) {
|
|
||||||
throw new RuntimeException("文件不存在!");
|
|
||||||
}
|
|
||||||
String originalFilename = file.getOriginalFilename();
|
|
||||||
//获取文件名后缀
|
|
||||||
String suffix = originalFilename.split("\\.")[1];
|
|
||||||
if ("Jpeg".equals(suffix)) {
|
|
||||||
suffix = "jpg";
|
|
||||||
}
|
|
||||||
//文件储存路径
|
|
||||||
String filePath = StorageUtil.joinPath("user-faces", DateUtils.format(new Date(),"yyyy-MM-dd"));
|
|
||||||
// 生成文件名
|
|
||||||
String fileName= userId + "." + suffix;
|
|
||||||
IStorageAdapter adapter = StorageFactory.use("faces");
|
|
||||||
try {
|
|
||||||
return adapter.uploadFile(file.getInputStream(), filePath, fileName);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("文件上传失败!", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean deleteFaceSample(Long scenicId, String dbName, String entityId) {
|
public boolean deleteFaceSample(Long scenicId, String dbName, String entityId) {
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||||
@ -368,22 +335,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
|||||||
return redisTemplate.delete(FaceConstant.FACE_DB_NAME_PFX + "*");
|
return redisTemplate.delete(FaceConstant.FACE_DB_NAME_PFX + "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final String DATE_FORMAT="yyyyMMddHHmmss";
|
|
||||||
|
|
||||||
public static String generateEntityId(FaceSampleEntity entity) {
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
|
||||||
Random random = new Random();
|
|
||||||
int randomNumber = random.nextInt(900) + 100;
|
|
||||||
return entity.getDeviceId().toString() + "_" + sdf.format(entity.getCreateAt()) + randomNumber;
|
|
||||||
}
|
|
||||||
public static String generateEntityId(FaceSampleRespVO entity) {
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
|
||||||
Random random = new Random();
|
|
||||||
int randomNumber = random.nextInt(900) + 100;
|
|
||||||
return entity.getDeviceId().toString() + "_" + sdf.format(entity.getCreateAt()) + randomNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFaceUrl(Long faceId) {
|
public String getFaceUrl(Long faceId) {
|
||||||
if (faceId == null) {
|
if (faceId == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -58,6 +58,7 @@ import com.ycwl.basic.storage.utils.StorageUtil;
|
|||||||
import com.ycwl.basic.task.VideoPieceGetter;
|
import com.ycwl.basic.task.VideoPieceGetter;
|
||||||
import com.ycwl.basic.repository.TemplateRepository;
|
import com.ycwl.basic.repository.TemplateRepository;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
|
import com.ycwl.basic.utils.VideoReUploader;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -117,8 +118,6 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private VideoRepository videoRepository;
|
private VideoRepository videoRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private OrderRepository orderRepository;
|
|
||||||
@Autowired
|
|
||||||
private ScenicService scenicService;
|
private ScenicService scenicService;
|
||||||
|
|
||||||
private final ReentrantLock lock = new ReentrantLock();
|
private final ReentrantLock lock = new ReentrantLock();
|
||||||
@ -126,7 +125,8 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
private TaskStatusBiz taskStatusBiz;
|
private TaskStatusBiz taskStatusBiz;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(8, 1024, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1024));
|
@Autowired
|
||||||
|
private VideoReUploader videoReUploader;
|
||||||
|
|
||||||
|
|
||||||
private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
|
private RenderWorkerEntity getWorker(@NonNull WorkerAuthReqVo req) {
|
||||||
@ -191,7 +191,7 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
try {
|
try {
|
||||||
List<TaskRespVO> taskList;
|
List<TaskRespVO> taskList;
|
||||||
if (worker.getScenicOnly() != null) {
|
if (worker.getScenicOnly() != null) {
|
||||||
taskList = taskMapper.selectNotRunningByScenicId(worker.getScenicOnly());
|
taskList = taskMapper.selectNotRunningByScenicList(worker.getScenicOnly());
|
||||||
} else {
|
} else {
|
||||||
taskList = taskMapper.selectNotRunning();
|
taskList = taskMapper.selectNotRunning();
|
||||||
}
|
}
|
||||||
@ -590,9 +590,10 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
videoMapper.add(video);
|
videoMapper.add(video);
|
||||||
}
|
}
|
||||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId());
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(task.getScenicId());
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
|
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(task.getScenicId());
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
|
||||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||||
|
videoReUploader.addVideoTask(task.getVideoUrl(), video.getId());
|
||||||
int isBuy = 0;
|
int isBuy = 0;
|
||||||
FaceEntity face = faceRepository.getFace(task.getFaceId());
|
FaceEntity face = faceRepository.getFace(task.getFaceId());
|
||||||
if (face != null) {
|
if (face != null) {
|
||||||
@ -619,9 +620,9 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
videoMapper.updateRelationWhenTaskSuccess(taskId, video.getId(), isBuy);
|
videoMapper.updateRelationWhenTaskSuccess(taskId, video.getId(), isBuy);
|
||||||
executor.execute(() -> {
|
new Thread(() -> {
|
||||||
sendVideoGeneratedServiceNotification(taskId);
|
sendVideoGeneratedServiceNotification(taskId);
|
||||||
});
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -649,7 +650,7 @@ public class TaskTaskServiceImpl implements TaskService {
|
|||||||
if (task == null) {
|
if (task == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(task.getScenicId());
|
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(task.getScenicId());
|
||||||
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
|
String filename = StorageUtil.joinPath(StorageConstant.VLOG_PATH, task.getId() + "_" + task.getScenicId() + ".mp4");
|
||||||
if (StringUtils.isBlank(task.getVideoUrl())) {
|
if (StringUtils.isBlank(task.getVideoUrl())) {
|
||||||
// 生成
|
// 生成
|
||||||
|
7
src/main/java/com/ycwl/basic/stats/biz/StatsBiz.java
Normal file
7
src/main/java/com/ycwl/basic/stats/biz/StatsBiz.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.ycwl.basic.stats.biz;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class StatsBiz {
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.ycwl.basic.stats.controller;
|
||||||
|
|
||||||
|
import com.ycwl.basic.annotation.IgnoreToken;
|
||||||
|
import com.ycwl.basic.stats.dto.AddTraceReq;
|
||||||
|
import com.ycwl.basic.stats.service.StatsService;
|
||||||
|
import com.ycwl.basic.stats.util.StatsUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
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 javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/trace/v1")
|
||||||
|
public class TraceController {
|
||||||
|
@Autowired
|
||||||
|
private StatsService statsService;
|
||||||
|
@IgnoreToken
|
||||||
|
@PostMapping("/start")
|
||||||
|
public void startTrace(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
String traceId = request.getHeader("traceId");
|
||||||
|
if (traceId == null || traceId.isEmpty()) {
|
||||||
|
traceId = StatsUtil.createUuid();
|
||||||
|
response.setHeader("Set-TraceId", traceId);
|
||||||
|
}
|
||||||
|
statsService.addStats(traceId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@IgnoreToken
|
||||||
|
@PostMapping("/add")
|
||||||
|
public void addTrace(HttpServletRequest request, HttpServletResponse response, @RequestBody AddTraceReq req) {
|
||||||
|
String traceId = request.getHeader("traceId");
|
||||||
|
if (traceId == null || traceId.isEmpty()) {
|
||||||
|
traceId = StatsUtil.createUuid();
|
||||||
|
response.setHeader("Set-TraceId", traceId);
|
||||||
|
}
|
||||||
|
statsService.addRecord(traceId, req.getAction(), req.getIdentifier(), req.getParams());
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/com/ycwl/basic/stats/dto/AddTraceReq.java
Normal file
10
src/main/java/com/ycwl/basic/stats/dto/AddTraceReq.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.ycwl.basic.stats.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AddTraceReq {
|
||||||
|
private String action;
|
||||||
|
private String identifier;
|
||||||
|
private String params;
|
||||||
|
}
|
18
src/main/java/com/ycwl/basic/stats/entity/StatsEntity.java
Normal file
18
src/main/java/com/ycwl/basic/stats/entity/StatsEntity.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package com.ycwl.basic.stats.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("t_stats")
|
||||||
|
public class StatsEntity {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String traceId;
|
||||||
|
private Long memberId;
|
||||||
|
private Date createTime;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.ycwl.basic.stats.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("t_stats_record")
|
||||||
|
public class StatsRecordEntity {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String traceId;
|
||||||
|
private String action;
|
||||||
|
private String identifier;
|
||||||
|
private String params;
|
||||||
|
private Date createTime;
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.ycwl.basic.stats.interceptor;
|
||||||
|
|
||||||
|
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||||
|
import com.ycwl.basic.constant.BaseContextHandler;
|
||||||
|
import com.ycwl.basic.stats.service.StatsService;
|
||||||
|
import com.ycwl.basic.stats.util.StatsUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class StatsInterceptor implements HandlerInterceptor {
|
||||||
|
@Autowired
|
||||||
|
private StatsService statsService;
|
||||||
|
|
||||||
|
// 在请求处理前执行
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
if (!(handler instanceof HandlerMethod)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||||
|
request.setAttribute("startTime", System.currentTimeMillis());
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
String method = request.getMethod();
|
||||||
|
String traceId = request.getHeader("traceId");
|
||||||
|
if (StringUtils.isEmpty(traceId)) {
|
||||||
|
return true;
|
||||||
|
// traceId = StatsUtil.createUuid();
|
||||||
|
// response.setHeader("Set-TraceId", traceId);
|
||||||
|
// statsService.addStats(traceId, null);
|
||||||
|
}
|
||||||
|
if (handlerMethod.getMethodAnnotation(IgnoreLogReq.class) == null) {
|
||||||
|
statsService.addRecord(traceId, "REQUEST",method + " " + requestURI, null);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(BaseContextHandler.getUserId())) {
|
||||||
|
statsService.updateStats(traceId, Long.valueOf(BaseContextHandler.getUserId()));
|
||||||
|
}
|
||||||
|
// 返回 true 继续后续流程,false 终止请求
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 控制器方法执行后,渲染视图前
|
||||||
|
@Override
|
||||||
|
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求完全完成后执行(无论是否异常)
|
||||||
|
@Override
|
||||||
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||||
|
// long startTime = (Long) request.getAttribute("startTime");
|
||||||
|
// long endTime = System.currentTimeMillis();
|
||||||
|
// System.out.println("【AfterCompletion】请求结束,耗时:" + (endTime - startTime) + "ms");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.stats.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ycwl.basic.stats.entity.StatsEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface StatsMapper extends BaseMapper<StatsEntity> {
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.stats.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.ycwl.basic.stats.entity.StatsRecordEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface StatsRecordMapper extends BaseMapper<StatsRecordEntity> {
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.stats.service;
|
||||||
|
|
||||||
|
public interface StatsService {
|
||||||
|
void addStats(String traceId, Long memberId);
|
||||||
|
|
||||||
|
void updateStats(String traceId, Long memberId);
|
||||||
|
|
||||||
|
void addRecord(String traceId, String action, String identifier, String params);
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.ycwl.basic.stats.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.ycwl.basic.stats.entity.StatsEntity;
|
||||||
|
import com.ycwl.basic.stats.entity.StatsRecordEntity;
|
||||||
|
import com.ycwl.basic.stats.mapper.StatsMapper;
|
||||||
|
import com.ycwl.basic.stats.mapper.StatsRecordMapper;
|
||||||
|
import com.ycwl.basic.stats.service.StatsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class StatsServiceImpl implements StatsService {
|
||||||
|
@Autowired
|
||||||
|
private StatsMapper statsMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StatsRecordMapper statsRecordMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addStats(String traceId, Long memberId) {
|
||||||
|
StatsEntity entity = new StatsEntity();
|
||||||
|
entity.setTraceId(traceId);
|
||||||
|
entity.setMemberId(memberId);
|
||||||
|
entity.setCreateTime(new Date());
|
||||||
|
statsMapper.insert(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStats(String traceId, Long memberId) {
|
||||||
|
StatsEntity entity = new StatsEntity();
|
||||||
|
entity.setMemberId(memberId);
|
||||||
|
LambdaQueryWrapper<StatsEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(StatsEntity::getTraceId, traceId);
|
||||||
|
statsMapper.update(entity, queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRecord(String traceId, String action, String identifier, String params) {
|
||||||
|
StatsRecordEntity entity = new StatsRecordEntity();
|
||||||
|
entity.setTraceId(traceId);
|
||||||
|
entity.setAction(action);
|
||||||
|
entity.setIdentifier(identifier);
|
||||||
|
entity.setParams(params);
|
||||||
|
entity.setCreateTime(new Date());
|
||||||
|
statsRecordMapper.insert(entity);
|
||||||
|
}
|
||||||
|
}
|
9
src/main/java/com/ycwl/basic/stats/util/StatsUtil.java
Normal file
9
src/main/java/com/ycwl/basic/stats/util/StatsUtil.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.stats.util;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class StatsUtil {
|
||||||
|
public static String createUuid() {
|
||||||
|
return UUID.randomUUID().toString().replace("-", "");
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.storage.adapters;
|
package com.ycwl.basic.storage.adapters;
|
||||||
|
|
||||||
import com.ycwl.basic.storage.exceptions.UploadFileFailedException;
|
import com.ycwl.basic.storage.exceptions.UploadFileFailedException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -9,16 +10,17 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public abstract class AStorageAdapter implements IStorageAdapter {
|
public abstract class AStorageAdapter implements IStorageAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String uploadFile(File file, String ...path) {
|
public String uploadFile(String contentType, File file, String ...path) {
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = new FileInputStream(file);
|
InputStream inputStream = new FileInputStream(file);
|
||||||
return uploadFile(inputStream, path);
|
return uploadFile(contentType, inputStream, path);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
throw new UploadFileFailedException("文件不存在");
|
throw new UploadFileFailedException("文件不存在");
|
||||||
}
|
}
|
||||||
@ -31,8 +33,9 @@ public abstract class AStorageAdapter implements IStorageAdapter {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
InputStream inputStream = file.getInputStream();
|
InputStream inputStream = file.getInputStream();
|
||||||
return uploadFile(inputStream, path);
|
return uploadFile(file.getContentType(), inputStream, path);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
log.warn("文件上传失败", e);
|
||||||
throw new UploadFileFailedException("文件上传失败");
|
throw new UploadFileFailedException("文件上传失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ final public class AliOssAdapter extends AStorageAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String uploadFile(InputStream inputStream, String ...path) {
|
public String uploadFile(String contentType, InputStream inputStream, String ...path) {
|
||||||
if (inputStream == null) {
|
if (inputStream == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -71,6 +71,9 @@ final public class AliOssAdapter extends AStorageAdapter {
|
|||||||
OSS ossClient = wrapper.getOSSClient();
|
OSS ossClient = wrapper.getOSSClient();
|
||||||
ObjectMetadata metadata = new ObjectMetadata();
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
metadata.setContentLength(inputStream.available());
|
metadata.setContentLength(inputStream.available());
|
||||||
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
|
metadata.setContentType(contentType);
|
||||||
|
}
|
||||||
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream);
|
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream);
|
||||||
ossClient.putObject(putObjectRequest);
|
ossClient.putObject(putObjectRequest);
|
||||||
return getUrl(path);
|
return getUrl(path);
|
||||||
|
@ -55,7 +55,7 @@ public class AwsOssAdapter extends AStorageAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String uploadFile(InputStream inputStream, String... path) {
|
public String uploadFile(String contentType, InputStream inputStream, String... path) {
|
||||||
if (inputStream == null) {
|
if (inputStream == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -64,6 +64,9 @@ public class AwsOssAdapter extends AStorageAdapter {
|
|||||||
AmazonS3Client s3Client = wrapper.getS3Client();
|
AmazonS3Client s3Client = wrapper.getS3Client();
|
||||||
ObjectMetadata metadata = new ObjectMetadata();
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
metadata.setContentLength(inputStream.available());
|
metadata.setContentLength(inputStream.available());
|
||||||
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
|
metadata.setContentType(contentType);
|
||||||
|
}
|
||||||
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream, metadata);
|
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream, metadata);
|
||||||
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead); // 设置访问权限,让所有用户都允许访问
|
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead); // 设置访问权限,让所有用户都允许访问
|
||||||
s3Client.putObject(putObjectRequest);
|
s3Client.putObject(putObjectRequest);
|
||||||
|
@ -14,8 +14,8 @@ import java.util.Map;
|
|||||||
public interface IStorageAdapter {
|
public interface IStorageAdapter {
|
||||||
void loadConfig(Map<String, String> config);
|
void loadConfig(Map<String, String> config);
|
||||||
void setConfig(StorageConfig config);
|
void setConfig(StorageConfig config);
|
||||||
String uploadFile(InputStream inputStream, String ...path);
|
String uploadFile(String contentType, InputStream inputStream, String ...path);
|
||||||
String uploadFile(File file, String ...path);
|
String uploadFile(String contentType, File file, String ...path);
|
||||||
String uploadFile(MultipartFile file, String ...path);
|
String uploadFile(MultipartFile file, String ...path);
|
||||||
boolean deleteFile(String ...path);
|
boolean deleteFile(String ...path);
|
||||||
String getUrl(String ...path);
|
String getUrl(String ...path);
|
||||||
|
@ -22,7 +22,7 @@ public class LocalStorageAdapter extends AStorageAdapter{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String uploadFile(InputStream inputStream, String... path) {
|
public String uploadFile(String contentType, InputStream inputStream, String... path) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,15 @@ package com.ycwl.basic.storage.entity;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class StorageFileObject {
|
public class StorageFileObject {
|
||||||
private String path;
|
private String path;
|
||||||
private String name;
|
private String name;
|
||||||
private Long size;
|
private Long size;
|
||||||
private Object rawObject;
|
private Object rawObject;
|
||||||
|
private Date modifyTime;
|
||||||
|
|
||||||
public String getFullPath() {
|
public String getFullPath() {
|
||||||
return path + "/" + name;
|
return path + "/" + name;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.ycwl.basic.task;
|
package com.ycwl.basic.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUnit;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.ycwl.basic.constant.StorageConstant;
|
import com.ycwl.basic.constant.StorageConstant;
|
||||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||||
@ -37,7 +38,6 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
|
import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME;
|
||||||
import static com.ycwl.basic.service.task.impl.TaskFaceServiceImpl.generateEntityId;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@ -79,7 +79,7 @@ public class FaceCleaner {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
faceSampleList.forEach(faceSample -> {
|
faceSampleList.forEach(faceSample -> {
|
||||||
boolean success = adapter.deleteFace(String.valueOf(scenic.getId()), generateEntityId(faceSample));
|
boolean success = adapter.deleteFace(String.valueOf(scenic.getId()), faceSample.getId().toString());
|
||||||
if (success) {
|
if (success) {
|
||||||
log.info("当前景区{},人脸样本ID{},删除成功", scenic.getId(), faceSample.getId());
|
log.info("当前景区{},人脸样本ID{},删除成功", scenic.getId(), faceSample.getId());
|
||||||
faceSampleMapper.deleteById(faceSample.getId());
|
faceSampleMapper.deleteById(faceSample.getId());
|
||||||
@ -140,7 +140,7 @@ public class FaceCleaner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 3 * * ?")
|
@Scheduled(cron = "0 15 3 * * ?")
|
||||||
public void deleteNotBuyVideos(){
|
public void deleteNotBuyVideos(){
|
||||||
ScenicReqQuery scenicQuery = new ScenicReqQuery();
|
ScenicReqQuery scenicQuery = new ScenicReqQuery();
|
||||||
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
|
List<ScenicRespVO> scenicList = scenicMapper.list(scenicQuery);
|
||||||
@ -212,6 +212,12 @@ public class FaceCleaner {
|
|||||||
IStorageAdapter adapter = StorageFactory.use("faces");
|
IStorageAdapter adapter = StorageFactory.use("faces");
|
||||||
List<StorageFileObject> fileObjectList = adapter.listDir("user-face");
|
List<StorageFileObject> fileObjectList = adapter.listDir("user-face");
|
||||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||||
|
if (fileObject.getModifyTime() != null) {
|
||||||
|
// 如果是一天以内修改的,则跳过
|
||||||
|
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(faceSampleRespVOS.parallelStream().noneMatch(faceSampleRespVO -> faceSampleRespVO.getFaceUrl().contains(fileObject.getFullPath()))){
|
if(faceSampleRespVOS.parallelStream().noneMatch(faceSampleRespVO -> faceSampleRespVO.getFaceUrl().contains(fileObject.getFullPath()))){
|
||||||
log.info("删除人脸文件:{}", fileObject);
|
log.info("删除人脸文件:{}", fileObject);
|
||||||
adapter.deleteFile(fileObject.getFullPath());
|
adapter.deleteFile(fileObject.getFullPath());
|
||||||
@ -226,6 +232,12 @@ public class FaceCleaner {
|
|||||||
log.info("开始清理视频文件");
|
log.info("开始清理视频文件");
|
||||||
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VIDEO_PIECE_PATH);
|
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VIDEO_PIECE_PATH);
|
||||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||||
|
if (fileObject.getModifyTime() != null) {
|
||||||
|
// 如果是一天以内修改的,则跳过
|
||||||
|
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
||||||
log.info("删除文件:{}", fileObject);
|
log.info("删除文件:{}", fileObject);
|
||||||
adapter.deleteFile(fileObject.getFullPath());
|
adapter.deleteFile(fileObject.getFullPath());
|
||||||
@ -236,6 +248,12 @@ public class FaceCleaner {
|
|||||||
log.info("开始清理图片文件");
|
log.info("开始清理图片文件");
|
||||||
fileObjectList = adapter.listDir(StorageConstant.PHOTO_PATH);
|
fileObjectList = adapter.listDir(StorageConstant.PHOTO_PATH);
|
||||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||||
|
if (fileObject.getModifyTime() != null) {
|
||||||
|
// 如果是一天以内修改的,则跳过
|
||||||
|
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getUrl())).noneMatch(videoRespVO -> videoRespVO.getUrl().contains(fileObject.getFullPath()))){
|
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getUrl())).noneMatch(videoRespVO -> videoRespVO.getUrl().contains(fileObject.getFullPath()))){
|
||||||
log.info("删除文件:{}", fileObject);
|
log.info("删除文件:{}", fileObject);
|
||||||
adapter.deleteFile(fileObject.getFullPath());
|
adapter.deleteFile(fileObject.getFullPath());
|
||||||
@ -253,6 +271,12 @@ public class FaceCleaner {
|
|||||||
log.info("开始清理视频文件");
|
log.info("开始清理视频文件");
|
||||||
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VLOG_PATH);
|
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VLOG_PATH);
|
||||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||||
|
if (fileObject.getModifyTime() != null) {
|
||||||
|
// 如果是一天以内修改的,则跳过
|
||||||
|
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
||||||
log.info("删除文件:{}", fileObject);
|
log.info("删除文件:{}", fileObject);
|
||||||
adapter.deleteFile(fileObject.getFullPath());
|
adapter.deleteFile(fileObject.getFullPath());
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package com.ycwl.basic.task;
|
package com.ycwl.basic.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||||
import com.ycwl.basic.biz.OrderBiz;
|
import com.ycwl.basic.biz.OrderBiz;
|
||||||
import com.ycwl.basic.biz.TaskStatusBiz;
|
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||||
|
import com.ycwl.basic.constant.StorageConstant;
|
||||||
import com.ycwl.basic.device.DeviceFactory;
|
import com.ycwl.basic.device.DeviceFactory;
|
||||||
import com.ycwl.basic.device.entity.common.FileObject;
|
import com.ycwl.basic.device.entity.common.FileObject;
|
||||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||||
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
|
||||||
import com.ycwl.basic.repository.DeviceRepository;
|
import com.ycwl.basic.repository.DeviceRepository;
|
||||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||||
import com.ycwl.basic.mapper.SourceMapper;
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
@ -19,9 +20,9 @@ import com.ycwl.basic.repository.TemplateRepository;
|
|||||||
import com.ycwl.basic.storage.StorageFactory;
|
import com.ycwl.basic.storage.StorageFactory;
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||||
|
import com.ycwl.basic.utils.VideoReUploader;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
@ -41,6 +42,7 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -63,6 +65,8 @@ public class VideoPieceGetter {
|
|||||||
private TemplateRepository templateRepository;
|
private TemplateRepository templateRepository;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TaskStatusBiz taskStatusBiz;
|
private TaskStatusBiz taskStatusBiz;
|
||||||
|
@Autowired
|
||||||
|
private VideoReUploader videoReUploader;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class Task {
|
public static class Task {
|
||||||
@ -118,7 +122,13 @@ public class VideoPieceGetter {
|
|||||||
// taskStatusBiz.setFaceCutStatus(task.faceId, 0);
|
// taskStatusBiz.setFaceCutStatus(task.faceId, 0);
|
||||||
// }
|
// }
|
||||||
AtomicBoolean invoke = new AtomicBoolean(false);
|
AtomicBoolean invoke = new AtomicBoolean(false);
|
||||||
final ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 512, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(512));
|
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||||
|
.setNamePrefix("VPG-" + task.faceId + "-t")
|
||||||
|
.build();
|
||||||
|
final ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 512, 0L, TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue<>(512),
|
||||||
|
threadFactory
|
||||||
|
);
|
||||||
List<String> currentPlaceholder = new ArrayList<>();
|
List<String> currentPlaceholder = new ArrayList<>();
|
||||||
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
List<FaceSampleEntity> list = faceSampleMapper.listByIds(task.getFaceSampleIds());
|
||||||
Map<Long, Long> pairDeviceMap = new ConcurrentHashMap<>();
|
Map<Long, Long> pairDeviceMap = new ConcurrentHashMap<>();
|
||||||
@ -277,7 +287,7 @@ public class VideoPieceGetter {
|
|||||||
}
|
}
|
||||||
log.info("视频裁切成功");
|
log.info("视频裁切成功");
|
||||||
IStorageAdapter adapter = StorageFactory.use("assets");
|
IStorageAdapter adapter = StorageFactory.use("assets");
|
||||||
url = adapter.uploadFile(outFile, "video-source", outFile.getName());
|
url = adapter.uploadFile("video/mp4", outFile, StorageConstant.VIDEO_PIECE_PATH, outFile.getName());
|
||||||
// 上传成功后删除文件
|
// 上传成功后删除文件
|
||||||
outFile.delete();
|
outFile.delete();
|
||||||
}
|
}
|
||||||
@ -312,6 +322,7 @@ public class VideoPieceGetter {
|
|||||||
sourceMapper.addRelation(videoSource);
|
sourceMapper.addRelation(videoSource);
|
||||||
}
|
}
|
||||||
sourceMapper.add(sourceEntity);
|
sourceMapper.add(sourceEntity);
|
||||||
|
videoReUploader.addTask(sourceEntity.getVideoUrl(), sourceEntity.getId());
|
||||||
} else {
|
} else {
|
||||||
// 有原视频
|
// 有原视频
|
||||||
if (task.memberId != null && task.faceId != null) {
|
if (task.memberId != null && task.faceId != null) {
|
||||||
|
@ -15,6 +15,7 @@ import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
|||||||
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
import com.ycwl.basic.model.task.resp.SearchFaceRespVo;
|
||||||
import com.ycwl.basic.repository.ScenicRepository;
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
import com.ycwl.basic.repository.TemplateRepository;
|
import com.ycwl.basic.repository.TemplateRepository;
|
||||||
|
import com.ycwl.basic.service.pc.FaceService;
|
||||||
import com.ycwl.basic.service.task.TaskFaceService;
|
import com.ycwl.basic.service.task.TaskFaceService;
|
||||||
import com.ycwl.basic.service.task.impl.TaskTaskServiceImpl;
|
import com.ycwl.basic.service.task.impl.TaskTaskServiceImpl;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -47,8 +48,8 @@ public class VideoTaskGenerator {
|
|||||||
private ScenicMapper scenicMapper;
|
private ScenicMapper scenicMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScenicRepository scenicRepository;
|
private ScenicRepository scenicRepository;
|
||||||
|
@Autowired
|
||||||
// TODO: 可配置,现在赶时间暂时写死
|
private FaceService faceService;
|
||||||
|
|
||||||
@Scheduled(cron = "0 0 * * * *")
|
@Scheduled(cron = "0 0 * * * *")
|
||||||
public void generateVideoTask() {
|
public void generateVideoTask() {
|
||||||
@ -84,7 +85,7 @@ public class VideoTaskGenerator {
|
|||||||
query.setEndTime(DateUtil.endOfDay(new Date()));
|
query.setEndTime(DateUtil.endOfDay(new Date()));
|
||||||
List<FaceRespVO> list = faceMapper.list(query);
|
List<FaceRespVO> list = faceMapper.list(query);
|
||||||
list.stream().parallel().forEach(face -> {
|
list.stream().parallel().forEach(face -> {
|
||||||
taskFaceService.searchFace(face.getId());
|
faceService.matchFaceId(face.getId(), false);
|
||||||
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
if (Integer.valueOf(3).equals(scenicConfig.getBookRoutine())) {
|
||||||
// 全部生成
|
// 全部生成
|
||||||
contentList.forEach(content -> {
|
contentList.forEach(content -> {
|
||||||
|
@ -1,202 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @date 2022年06月02日 13:40
|
|
||||||
* 自定义的BigDecimal计算工具类
|
|
||||||
*/
|
|
||||||
public class CustomBigDecimalUtils {
|
|
||||||
|
|
||||||
public static final BigDecimal HUNDRED_BIG_DECIMAL = new BigDecimal("100");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 除法
|
|
||||||
*
|
|
||||||
* @param divisor 除数
|
|
||||||
* @param dividend 被除数
|
|
||||||
* @param scale 保留的小数位数
|
|
||||||
* @param roundingMode 舍入模式:比如四舍五入
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:43
|
|
||||||
*/
|
|
||||||
public static BigDecimal divide(BigDecimal divisor,
|
|
||||||
BigDecimal dividend,
|
|
||||||
int scale,
|
|
||||||
RoundingMode roundingMode) {
|
|
||||||
if (divisor == null || dividend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Double.compare(divisor.doubleValue(), BigDecimal.ZERO.doubleValue()) == 0 ||
|
|
||||||
Double.compare(dividend.doubleValue(), BigDecimal.ZERO.doubleValue()) == 0) {
|
|
||||||
return BigDecimal.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return divisor.divide(dividend, scale, roundingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 除法
|
|
||||||
*
|
|
||||||
* @param divisor 除数
|
|
||||||
* @param dividend 被除数
|
|
||||||
* @param scale 保留的小数位数
|
|
||||||
* @param roundingMode 舍入模式:比如四舍五入
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:43
|
|
||||||
*/
|
|
||||||
public static BigDecimal divide(Integer divisor,
|
|
||||||
Integer dividend,
|
|
||||||
int scale,
|
|
||||||
RoundingMode roundingMode) {
|
|
||||||
if (divisor == null || dividend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (divisor == 0 || dividend == 0) {
|
|
||||||
return BigDecimal.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BigDecimal(divisor).divide(new BigDecimal(dividend), scale, roundingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 除法
|
|
||||||
*
|
|
||||||
* @param divisor 除数
|
|
||||||
* @param dividend 被除数
|
|
||||||
* @param scale 保留的小数位数
|
|
||||||
* @param roundingMode 舍入模式:比如四舍五入
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:43
|
|
||||||
*/
|
|
||||||
public static BigDecimal divide(Double divisor,
|
|
||||||
Double dividend,
|
|
||||||
int scale,
|
|
||||||
RoundingMode roundingMode) {
|
|
||||||
if (divisor == null || dividend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Double.compare(divisor, BigDecimal.ZERO.doubleValue()) == 0 ||
|
|
||||||
Double.compare(dividend, BigDecimal.ZERO.doubleValue()) == 0) {
|
|
||||||
return BigDecimal.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BigDecimal(String.valueOf(divisor)).divide(new BigDecimal(String.valueOf(dividend)),
|
|
||||||
scale, roundingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 除法
|
|
||||||
*
|
|
||||||
* @param divisor 除数
|
|
||||||
* @param dividend 被除数
|
|
||||||
* @param scale 保留的小数位数
|
|
||||||
* @param roundingMode 舍入模式:比如四舍五入
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:43
|
|
||||||
*/
|
|
||||||
public static BigDecimal divide(Double divisor,
|
|
||||||
Integer dividend,
|
|
||||||
int scale,
|
|
||||||
RoundingMode roundingMode) {
|
|
||||||
if (divisor == null || dividend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Double.compare(divisor, BigDecimal.ZERO.doubleValue()) == 0 ||
|
|
||||||
Double.compare(dividend, BigDecimal.ZERO.doubleValue()) == 0) {
|
|
||||||
return BigDecimal.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BigDecimal(String.valueOf(divisor)).divide(new BigDecimal(String.valueOf(dividend)),
|
|
||||||
scale, roundingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 减法
|
|
||||||
*
|
|
||||||
* @param subtraction 减数
|
|
||||||
* @param minuend 被减数
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:53
|
|
||||||
*/
|
|
||||||
public static BigDecimal subtract(BigDecimal subtraction,
|
|
||||||
BigDecimal minuend) {
|
|
||||||
if (subtraction == null || minuend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtraction.subtract(minuend);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 减法
|
|
||||||
*
|
|
||||||
* @param subtraction 减数
|
|
||||||
* @param minuend 被减数
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:53
|
|
||||||
*/
|
|
||||||
public static BigDecimal subtract(Double subtraction,
|
|
||||||
Double minuend) {
|
|
||||||
if (subtraction == null || minuend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BigDecimal(String.valueOf(subtraction)).subtract(new BigDecimal(String.valueOf(minuend)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 减法
|
|
||||||
*
|
|
||||||
* @param subtraction 减数
|
|
||||||
* @param minuend 被减数
|
|
||||||
* @return java.math.BigDecimal
|
|
||||||
* @date 2022/6/2 13:53
|
|
||||||
*/
|
|
||||||
public static BigDecimal subtract(BigDecimal subtraction,
|
|
||||||
Double minuend) {
|
|
||||||
if (subtraction == null || minuend == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtraction.subtract(new BigDecimal(minuend));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加法
|
|
||||||
* @date 2022/6/7 17:31
|
|
||||||
* @param addend 加数
|
|
||||||
* @param summand 被加数
|
|
||||||
* @return java.lang.Double
|
|
||||||
*/
|
|
||||||
public static Double add(Double addend,
|
|
||||||
Double summand) {
|
|
||||||
if (addend == null || summand == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BigDecimal(addend.toString()).add(new BigDecimal(summand.toString())).doubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加法
|
|
||||||
* @date 2022/6/7 17:31
|
|
||||||
* @param addend 加数
|
|
||||||
* @param summand 被加数
|
|
||||||
* @return java.lang.Double
|
|
||||||
*/
|
|
||||||
public static Double add(BigDecimal addend,
|
|
||||||
BigDecimal summand) {
|
|
||||||
if (addend == null || summand == null) {
|
|
||||||
throw new NullPointerException("传入的数据不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
return addend.add(summand).doubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
import org.apache.http.StatusLine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Http服务工具类
|
|
||||||
* @author songmingsong
|
|
||||||
*/
|
|
||||||
public class HttpServiceUtil {
|
|
||||||
/**
|
|
||||||
* 请求OK代码
|
|
||||||
*/
|
|
||||||
public static final int REQUEST_OK_CODE=200;
|
|
||||||
/**
|
|
||||||
* 无响应内容
|
|
||||||
*/
|
|
||||||
public static final String REQUEST_NO_RESULT="No_Result";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否响应成功
|
|
||||||
* @param status 响应状态
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public static boolean success(StatusLine status) {
|
|
||||||
return status.getStatusCode() == REQUEST_OK_CODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -45,8 +45,7 @@ public class ImageUtils {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getContentType() {
|
public String getContentType() {
|
||||||
// TODO - implementation depends on your requirements
|
return "";
|
||||||
return header.split(":")[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.BeanWrapper;
|
|
||||||
import org.springframework.beans.BeanWrapperImpl;
|
|
||||||
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @date 2022年07月14日 14:12
|
|
||||||
* 数据格式转换工具类
|
|
||||||
*/
|
|
||||||
public class ObjectConvertUtils {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ObjectConvertUtils.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 浅克隆
|
|
||||||
*
|
|
||||||
* @param source 原对象
|
|
||||||
* @param clazz 目标对象
|
|
||||||
* @return T
|
|
||||||
* @date 2022/4/6 13:45
|
|
||||||
*/
|
|
||||||
public static <T> T clone(Object source, Class<T> clazz) {
|
|
||||||
return clone(source, clazz, true);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @date 2022/7/18 16:36
|
|
||||||
* @param source 原对象
|
|
||||||
* @param clazz 目标对象
|
|
||||||
* @param whetherAssignNull 是否赋值空值:true是 false否
|
|
||||||
* @return T
|
|
||||||
*/
|
|
||||||
public static <T> T clone(Object source, Class<T> clazz, Boolean whetherAssignNull) {
|
|
||||||
T target;
|
|
||||||
|
|
||||||
if (source == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
target = clazz.newInstance();
|
|
||||||
if (whetherAssignNull) {
|
|
||||||
BeanUtils.copyProperties(source, target);
|
|
||||||
} else {
|
|
||||||
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("数据转换异常", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象与对象之间的数据转换
|
|
||||||
*
|
|
||||||
* @param source 转换的数据对象
|
|
||||||
* @param target 需要转换数据的对象
|
|
||||||
* @date 2022/7/14 17:24
|
|
||||||
*/
|
|
||||||
public static void clone(Object source, Object target) {
|
|
||||||
clone(source, target, true);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @date 2022/7/18 16:39
|
|
||||||
* @param source 转换的数据对象
|
|
||||||
* @param target 需要转换数据的对象
|
|
||||||
* @param whetherAssignNull 是否赋值空值:true是 false否
|
|
||||||
*/
|
|
||||||
public static void clone(Object source, Object target, Boolean whetherAssignNull) {
|
|
||||||
if (source == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (whetherAssignNull) {
|
|
||||||
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
|
|
||||||
} else {
|
|
||||||
BeanUtils.copyProperties(source, target);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("数据转换异常", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象与对象之间的数据转换
|
|
||||||
*
|
|
||||||
* @param source 转换的数据对象
|
|
||||||
* @param target 需要转换数据的对象
|
|
||||||
* @date 2022/7/15 9:11
|
|
||||||
*/
|
|
||||||
public static void cglibBeanCopierCloneObject(Object source, Object target) {
|
|
||||||
BeanCopierUtils.copyProperties(source, target);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 对象与对象之间的数据转换
|
|
||||||
*
|
|
||||||
* @param source 转换的数据对象
|
|
||||||
* @param target 需要转换数据的对象
|
|
||||||
* @date 2022/7/15 9:11
|
|
||||||
*/
|
|
||||||
public static <T> T cglibBeanCopierCloneObject(Object source, Class<T> target) {
|
|
||||||
T t;
|
|
||||||
try {
|
|
||||||
t = target.newInstance();
|
|
||||||
BeanCopierUtils.copyProperties(source, t);
|
|
||||||
} catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将list集合转换为传入的对象的数据集合
|
|
||||||
*
|
|
||||||
* @param sourceList 原数据集合
|
|
||||||
* @param clazz 需要转换的集合数据对象
|
|
||||||
* @return java.util.List<T>
|
|
||||||
* @date 2022/4/6 13:49
|
|
||||||
*/
|
|
||||||
public static <T> List<T> cloneList(List<?> sourceList, Class<T> clazz) {
|
|
||||||
return cloneList(sourceList, clazz, true);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @date 2022/7/18 16:41
|
|
||||||
* @param sourceList 原数据集合
|
|
||||||
* @param clazz 需要转换的集合数据对象
|
|
||||||
* @param whetherAssignNull 是否赋值空值:true是 false否
|
|
||||||
* @return java.util.List<T>
|
|
||||||
*/
|
|
||||||
public static <T> List<T> cloneList(List<?> sourceList, Class<T> clazz, Boolean whetherAssignNull) {
|
|
||||||
try {
|
|
||||||
List<T> targetList = new ArrayList<>(sourceList.size());
|
|
||||||
for (Object source : sourceList) {
|
|
||||||
if (whetherAssignNull) {
|
|
||||||
targetList.add(clone(source, clazz));
|
|
||||||
} else {
|
|
||||||
targetList.add(clone(source, clazz, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return targetList;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("数据转换异常", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取需要忽略的属性
|
|
||||||
*/
|
|
||||||
public static String[] getNullPropertyNames(Object source) {
|
|
||||||
final BeanWrapper src = new BeanWrapperImpl(source);
|
|
||||||
PropertyDescriptor[] pds = src.getPropertyDescriptors();
|
|
||||||
|
|
||||||
Set<String> emptyNames = new HashSet<>();
|
|
||||||
for (PropertyDescriptor pd : pds) {
|
|
||||||
Object srcValue = src.getPropertyValue(pd.getName());
|
|
||||||
// 此处判断可根据需求修改
|
|
||||||
if (srcValue == null) {
|
|
||||||
emptyNames.add(pd.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String[] result = new String[emptyNames.size()];
|
|
||||||
return emptyNames.toArray(result);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.redis.core.*;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @date 2022年08月08日 16:06
|
|
||||||
* redis缓存操作行为工具类
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class RedisCacheOperationUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* string类型的redis操作类
|
|
||||||
*/
|
|
||||||
private static StringRedisTemplate stringRedisTemplate;
|
|
||||||
/**
|
|
||||||
* 通用的redis操作类
|
|
||||||
*/
|
|
||||||
private static RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建string类型的操作对象
|
|
||||||
*/
|
|
||||||
public static BoundValueOperations<String, String> createValueOperations(String cacheKey) {
|
|
||||||
return stringRedisTemplate.boundValueOps(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 创建list类型的操作对象
|
|
||||||
*/
|
|
||||||
public static BoundListOperations<String, List<String>> createListOperations(String cacheKey) {
|
|
||||||
return redisTemplate.boundListOps(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 创建hash类型的操作对象
|
|
||||||
*/
|
|
||||||
public static BoundHashOperations createHashOperations(String cacheKey) {
|
|
||||||
return redisTemplate.boundHashOps(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 创建set类型的操作对象
|
|
||||||
*/
|
|
||||||
public static BoundSetOperations createSetOperations(String cacheKey) {
|
|
||||||
return redisTemplate.boundSetOps(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 创建zset类型的操作对象
|
|
||||||
*/
|
|
||||||
public static BoundZSetOperations createZSetOperations(String cacheKey) {
|
|
||||||
return redisTemplate.boundZSetOps(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 判断缓存key值是否存在
|
|
||||||
*/
|
|
||||||
public static Boolean hasKey(String cacheKey) {
|
|
||||||
return redisTemplate.hasKey(cacheKey);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 删除缓存的redis缓存key
|
|
||||||
*/
|
|
||||||
public static Boolean delete(String cacheKey) {
|
|
||||||
return redisTemplate.delete(cacheKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
|
|
||||||
RedisCacheOperationUtils.stringRedisTemplate = stringRedisTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public void setRedisTemplate(RedisTemplate redisTemplate) {
|
|
||||||
RedisCacheOperationUtils.redisTemplate = redisTemplate;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.http.config.Registry;
|
|
||||||
import org.apache.http.config.RegistryBuilder;
|
|
||||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
|
||||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
|
||||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSL工具类
|
|
||||||
*
|
|
||||||
* @author songmingsong
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class SslUtil {
|
|
||||||
/**
|
|
||||||
* 获取HtttpClient对象
|
|
||||||
*
|
|
||||||
* @return CloseableHttpClient
|
|
||||||
*/
|
|
||||||
public static CloseableHttpClient sslHttpClientBuild() {
|
|
||||||
Registry<ConnectionSocketFactory> socketFactoryRegistry =
|
|
||||||
RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
|
|
||||||
.register("https", trustAllHttpsCertificates()).build();
|
|
||||||
// 创建ConnectionManager,添加Connection配置信息
|
|
||||||
PoolingHttpClientConnectionManager connectionManager =
|
|
||||||
new PoolingHttpClientConnectionManager(socketFactoryRegistry);
|
|
||||||
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();
|
|
||||||
return httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 信任所有Http证书
|
|
||||||
*
|
|
||||||
* @return SSLConnectionSocketFactory
|
|
||||||
*/
|
|
||||||
private static SSLConnectionSocketFactory trustAllHttpsCertificates() {
|
|
||||||
SSLConnectionSocketFactory socketFactory = null;
|
|
||||||
TrustManager[] trustAllCerts = new TrustManager[1];
|
|
||||||
TrustManager tm = new X509TrustManager() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// 返回受信任的X509证书数组。
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// 该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。
|
|
||||||
// 在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
try {
|
|
||||||
if (chain!=null&&chain.length>0) {
|
|
||||||
chain[0].checkValidity();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("checkServerTrusted",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
// 该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,
|
|
||||||
// 因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
try {
|
|
||||||
if (chain!=null&&chain.length>0) {
|
|
||||||
chain[0].checkValidity();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("checkClientTrusted",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
trustAllCerts[0] = tm;
|
|
||||||
SSLContext sc = null;
|
|
||||||
try {
|
|
||||||
sc = SSLContext.getInstance("TLSv1.2");
|
|
||||||
sc.init(null, trustAllCerts, null);
|
|
||||||
socketFactory = new SSLConnectionSocketFactory(sc, NoopHostnameVerifier.INSTANCE);
|
|
||||||
// HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("trustAllHttpsCertificates", e);
|
|
||||||
}
|
|
||||||
return socketFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
149
src/main/java/com/ycwl/basic/utils/VideoReUploader.java
Normal file
149
src/main/java/com/ycwl/basic/utils/VideoReUploader.java
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package com.ycwl.basic.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import com.ycwl.basic.constant.StorageConstant;
|
||||||
|
import com.ycwl.basic.mapper.SourceMapper;
|
||||||
|
import com.ycwl.basic.mapper.VideoMapper;
|
||||||
|
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||||
|
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||||
|
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
|
||||||
|
import com.ycwl.basic.repository.ScenicRepository;
|
||||||
|
import com.ycwl.basic.repository.VideoRepository;
|
||||||
|
import com.ycwl.basic.repository.VideoTaskRepository;
|
||||||
|
import com.ycwl.basic.service.pc.ScenicService;
|
||||||
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
|
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||||
|
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class VideoReUploader {
|
||||||
|
private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||||
|
.setNamePrefix("Vid-ReUp-")
|
||||||
|
.build();
|
||||||
|
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(8, 1024, 0L, TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue<>(1024),
|
||||||
|
threadFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SourceMapper sourceMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScenicService scenicService;
|
||||||
|
@Autowired
|
||||||
|
private VideoMapper videoMapper;
|
||||||
|
@Autowired
|
||||||
|
private VideoRepository videoRepository;
|
||||||
|
@Autowired
|
||||||
|
private ScenicRepository scenicRepository;
|
||||||
|
|
||||||
|
public void addTask(String url, Long sourceId) {
|
||||||
|
SourceEntity entity = sourceMapper.getEntity(sourceId);
|
||||||
|
if (entity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entity.getScenicId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entity.getType() != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(entity.getScenicId());
|
||||||
|
if (scenicConfig == null || scenicConfig.getLocalStoreType() == null || scenicConfig.getLocalStoreConfigJson() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final String dstFilePath = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, entity.getId().toString() + ".mp4");
|
||||||
|
final IStorageAdapter adapter = scenicService.getScenicStorageAdapter(entity.getScenicId());
|
||||||
|
if (StringUtils.equals(url, adapter.getUrl(dstFilePath))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String tmpFilePath = UUID.randomUUID().toString();
|
||||||
|
executor.execute(() -> {
|
||||||
|
// 先下载,后上传
|
||||||
|
File dstFile = new File(tmpFilePath);
|
||||||
|
log.info("下载视频:{};sourceId:{}", url, sourceId);
|
||||||
|
long size = HttpUtil.downloadFile(url, dstFile);
|
||||||
|
log.info("下载视频完成:{};大小:{};sourceId:{}", url, size, sourceId);
|
||||||
|
try {
|
||||||
|
log.info("开始上传:{};sourceId:{}", dstFilePath, sourceId);
|
||||||
|
String newUrl = adapter.uploadFile("video/mp4", dstFile, dstFilePath);
|
||||||
|
log.info("上传成功:{};sourceId:{}", newUrl, sourceId);
|
||||||
|
SourceEntity updateEntity = new SourceEntity();
|
||||||
|
updateEntity.setId(sourceId);
|
||||||
|
updateEntity.setVideoUrl(newUrl);
|
||||||
|
sourceMapper.update(updateEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("上传失败:{};sourceId:{}", dstFilePath, sourceId, e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
dstFile.delete();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void addVideoTask(String url, Long videoId) {
|
||||||
|
VideoEntity entity = videoMapper.getEntity(videoId);
|
||||||
|
if (entity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entity.getScenicId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(entity.getScenicId());
|
||||||
|
if (scenicConfig == null || scenicConfig.getTmpStoreType() == null || scenicConfig.getTmpStoreConfigJson() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final String dstFilePath = StorageUtil.joinPath(StorageConstant.VLOG_PATH, entity.getTaskId() + "_" + entity.getScenicId() + ".mp4");
|
||||||
|
final IStorageAdapter adapter = scenicService.getScenicStorageAdapter(entity.getScenicId());
|
||||||
|
if (StringUtils.equals(url, adapter.getUrl(dstFilePath))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String tmpFilePath = UUID.randomUUID().toString();
|
||||||
|
executor.execute(() -> {
|
||||||
|
// 先下载,后上传
|
||||||
|
File dstFile = new File(tmpFilePath);
|
||||||
|
log.info("下载视频:{};videoId:{}", url, videoId);
|
||||||
|
long size = HttpUtil.downloadFile(url, dstFile);
|
||||||
|
log.info("下载视频完成:{};大小:{};videoId:{}", url, size, videoId);
|
||||||
|
try {
|
||||||
|
log.info("开始上传:{};videoId:{}", dstFilePath, videoId);
|
||||||
|
String newUrl = adapter.uploadFile("video/mp4", dstFile, dstFilePath);
|
||||||
|
adapter.setAcl(StorageAcl.PUBLIC_READ, dstFilePath);
|
||||||
|
log.info("上传成功:{};videoId:{}", newUrl, videoId);
|
||||||
|
VideoEntity updateEntity = new VideoEntity();
|
||||||
|
updateEntity.setId(videoId);
|
||||||
|
updateEntity.setVideoUrl(newUrl);
|
||||||
|
videoMapper.update(updateEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("上传失败:{};videoId:{}", dstFilePath, videoId, e);
|
||||||
|
} finally {
|
||||||
|
videoRepository.clearVideoCache(videoId);
|
||||||
|
try {
|
||||||
|
dstFile.delete();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
package com.ycwl.basic.utils;
|
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.util.XmlUtil;
|
|
||||||
import com.wechat.pay.java.core.util.PemUtil;
|
|
||||||
import org.springframework.util.Base64Utils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.*;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author: songmingsong
|
|
||||||
* @CreateTime: 2024-12-05
|
|
||||||
* @Description: 微信支付
|
|
||||||
* @Version: 1.0
|
|
||||||
*/
|
|
||||||
public class WXPayUtil {
|
|
||||||
|
|
||||||
private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
||||||
|
|
||||||
private static final Random RANDOM = new SecureRandom();
|
|
||||||
|
|
||||||
|
|
||||||
public static String getSign(String signatureStr,String privateKey) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IOException, URISyntaxException {
|
|
||||||
//replace 根据实际情况,不一定都需要
|
|
||||||
String replace = privateKey.replace("\\n", "\n");
|
|
||||||
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromString(replace);
|
|
||||||
Signature sign = Signature.getInstance("SHA256withRSA");
|
|
||||||
sign.initSign(merchantPrivateKey);
|
|
||||||
sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
|
||||||
return Base64Utils.encodeToString(sign.sign());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取随机字符串 Nonce Str
|
|
||||||
*
|
|
||||||
* @return String 随机字符串
|
|
||||||
*/
|
|
||||||
public static String generateNonceStr() {
|
|
||||||
char[] nonceChars = new char[32];
|
|
||||||
for (int index = 0; index < nonceChars.length; ++index) {
|
|
||||||
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
|
|
||||||
}
|
|
||||||
return new String(nonceChars);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<String, Object> xmlToMap(String xmlData) {
|
|
||||||
return XmlUtil.xmlToMap(xmlData);
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,26 +6,34 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class WxMpUtil {
|
public class WxMpUtil {
|
||||||
private static final String GET_WXA_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s";
|
private static final String GET_WXA_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s";
|
||||||
private static final String GET_URL_LICK_URL = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=%s";
|
private static final String GET_URL_LICK_URL = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=%s";
|
||||||
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||||
private static String ACCESS_TOKEN = "";
|
private static final Map<String, String> tokens = new ConcurrentHashMap<>();
|
||||||
private static Date expireTime = new Date();
|
private static final Map<String, Date> expireTimes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static String getAccessToken(String appId, String appSecret) {
|
private static String getAccessToken(String appId, String appSecret) {
|
||||||
if (ACCESS_TOKEN != null && !ACCESS_TOKEN.isEmpty()) {
|
if (expireTimes.containsKey(appId)) {
|
||||||
if (expireTime.getTime() > System.currentTimeMillis()) {
|
Date expireTime = expireTimes.get(appId);
|
||||||
return ACCESS_TOKEN;
|
if (expireTime.getTime() < System.currentTimeMillis()) {
|
||||||
|
tokens.remove(appId);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tokens.remove(appId);
|
||||||
}
|
}
|
||||||
String url = String.format(ACCESS_TOKEN_URL, appId, appSecret);
|
return tokens.computeIfAbsent(appId, (k) -> {
|
||||||
String response = HttpUtil.get(url);
|
String url = String.format(ACCESS_TOKEN_URL, appId, appSecret);
|
||||||
JSONObject jsonObject = JSONObject.parseObject(response);
|
String response = HttpUtil.get(url);
|
||||||
ACCESS_TOKEN = jsonObject.getString("access_token");
|
JSONObject jsonObject = JSONObject.parseObject(response);
|
||||||
expireTime = new Date(System.currentTimeMillis() + jsonObject.getInteger("expires_in") * 1000 / 2);
|
String token = jsonObject.getString("access_token");
|
||||||
return ACCESS_TOKEN;
|
Date expireTime = new Date(System.currentTimeMillis() + jsonObject.getInteger("expires_in") * 1000 / 2);
|
||||||
|
expireTimes.put(appId, expireTime);
|
||||||
|
return token;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateWXAQRCode(String appId, String appSecret, String envVersion, String path, String filePath) throws Exception {
|
public static void generateWXAQRCode(String appId, String appSecret, String envVersion, String path, String filePath) throws Exception {
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package com.ycwl.basic.xss;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
|
||||||
import org.apache.commons.text.StringEscapeUtils;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
public class XssJacksonDeserializer extends JsonDeserializer<String> {
|
|
||||||
@Override
|
|
||||||
public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
|
||||||
return StringEscapeUtils.escapeHtml4(jp.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package com.ycwl.basic.xss;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
||||||
import org.apache.commons.text.StringEscapeUtils;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class XssJacksonSerializer extends JsonSerializer<String>{
|
|
||||||
@Override
|
|
||||||
public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
|
|
||||||
jgen.writeString(StringEscapeUtils.escapeHtml4(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -49,60 +49,6 @@ mybatis-plus:
|
|||||||
# 指定使用的日志配置文件
|
# 指定使用的日志配置文件
|
||||||
logging:
|
logging:
|
||||||
config: classpath:logback-spring.xml
|
config: classpath:logback-spring.xml
|
||||||
# 微信小程序相关配置
|
|
||||||
wx:
|
|
||||||
# 公众号的appId
|
|
||||||
appId: fix
|
|
||||||
# 公众号的密钥
|
|
||||||
appSecret: fix
|
|
||||||
# 小程序的AppId
|
|
||||||
miniProgramAppId: wxe7ff26af70bfc37c
|
|
||||||
# 小程序的secret
|
|
||||||
miniProgramSecret: 5252fbbc68513bc77b7cc0052b9f9695
|
|
||||||
# 申请openid授权
|
|
||||||
grandType: authorization_code
|
|
||||||
# 推送模板
|
|
||||||
push:
|
|
||||||
templateId: 5b8vTm7kvwYubqDxb3dxBqFIhc3Swt5l7QHSK5r-ZRI
|
|
||||||
# 商户号
|
|
||||||
mchId: 1700540331
|
|
||||||
# 商户证书序列号
|
|
||||||
mchSerialNo: 2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0
|
|
||||||
# 支付回调接口地址
|
|
||||||
payNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/payNotify
|
|
||||||
# 退款回调接口地址
|
|
||||||
refundNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/refundNotify
|
|
||||||
# 商户API私钥路径
|
|
||||||
keyPath: "-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn
|
|
||||||
Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ
|
|
||||||
F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq
|
|
||||||
Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/
|
|
||||||
QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF
|
|
||||||
SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY
|
|
||||||
eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN
|
|
||||||
/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd
|
|
||||||
6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu
|
|
||||||
8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9
|
|
||||||
SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM
|
|
||||||
SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX
|
|
||||||
tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl
|
|
||||||
GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b
|
|
||||||
c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+
|
|
||||||
2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj
|
|
||||||
tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+
|
|
||||||
MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M
|
|
||||||
WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV
|
|
||||||
tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv
|
|
||||||
IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT
|
|
||||||
ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW
|
|
||||||
Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx
|
|
||||||
DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP
|
|
||||||
0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5
|
|
||||||
YfkdFNxtYLdVAwuylMoV3fKI
|
|
||||||
-----END PRIVATE KEY-----"
|
|
||||||
# 商户APIV3密钥
|
|
||||||
apiV3: ZHENTUAIzhentuaiZHENTUAIzhentuai
|
|
||||||
|
|
||||||
# 存储
|
# 存储
|
||||||
storage:
|
storage:
|
||||||
@ -168,7 +114,45 @@ facebody:
|
|||||||
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
||||||
accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c"
|
accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c"
|
||||||
region: "cn-shanghai"
|
region: "cn-shanghai"
|
||||||
|
#支付
|
||||||
|
pay:
|
||||||
|
default-use: zt
|
||||||
|
configs:
|
||||||
|
- name: zt
|
||||||
|
type: WX_MP_PAY
|
||||||
|
config:
|
||||||
|
merchantId: "1700540331"
|
||||||
|
appId: "wxe7ff26af70bfc37c"
|
||||||
|
privateKey: "-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn
|
||||||
|
Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ
|
||||||
|
F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq
|
||||||
|
Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/
|
||||||
|
QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF
|
||||||
|
SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY
|
||||||
|
eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN
|
||||||
|
/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd
|
||||||
|
6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu
|
||||||
|
8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9
|
||||||
|
SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM
|
||||||
|
SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX
|
||||||
|
tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl
|
||||||
|
GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b
|
||||||
|
c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+
|
||||||
|
2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj
|
||||||
|
tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+
|
||||||
|
MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M
|
||||||
|
WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV
|
||||||
|
tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv
|
||||||
|
IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT
|
||||||
|
ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW
|
||||||
|
Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx
|
||||||
|
DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP
|
||||||
|
0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5
|
||||||
|
YfkdFNxtYLdVAwuylMoV3fKI
|
||||||
|
-----END PRIVATE KEY-----"
|
||||||
|
serialNumber: "2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0"
|
||||||
|
apiV3Key: ZHENTUAIzhentuaiZHENTUAIzhentuai
|
||||||
notify:
|
notify:
|
||||||
defaultUse: ""
|
defaultUse: ""
|
||||||
configs:
|
configs:
|
||||||
|
@ -54,57 +54,6 @@ mybatis-plus:
|
|||||||
# 指定使用的日志配置文件
|
# 指定使用的日志配置文件
|
||||||
logging:
|
logging:
|
||||||
config: classpath:logback-spring-prod.xml
|
config: classpath:logback-spring-prod.xml
|
||||||
# 微信小程序相关配置
|
|
||||||
wx:
|
|
||||||
# 公众号的appId
|
|
||||||
appId: fix
|
|
||||||
# 公众号的密钥
|
|
||||||
appSecret: fix
|
|
||||||
# 小程序的AppId
|
|
||||||
miniProgramAppId: wxe7ff26af70bfc37c
|
|
||||||
# 小程序的secret
|
|
||||||
miniProgramSecret: 5252fbbc68513bc77b7cc0052b9f9695
|
|
||||||
# 申请openid授权
|
|
||||||
grandType: authorization_code
|
|
||||||
# 商户号
|
|
||||||
mchId: 1700540331
|
|
||||||
# 商户证书序列号
|
|
||||||
mchSerialNo: 2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0
|
|
||||||
# 支付回调接口地址
|
|
||||||
payNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/payNotify
|
|
||||||
# 退款回调接口地址
|
|
||||||
refundNotifyUrl: https://zhentuai.com/api/mobile/wx/pay/v1/refundNotify
|
|
||||||
# 商户API私钥路径
|
|
||||||
keyPath: "-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn
|
|
||||||
Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ
|
|
||||||
F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq
|
|
||||||
Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/
|
|
||||||
QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF
|
|
||||||
SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY
|
|
||||||
eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN
|
|
||||||
/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd
|
|
||||||
6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu
|
|
||||||
8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9
|
|
||||||
SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM
|
|
||||||
SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX
|
|
||||||
tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl
|
|
||||||
GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b
|
|
||||||
c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+
|
|
||||||
2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj
|
|
||||||
tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+
|
|
||||||
MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M
|
|
||||||
WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV
|
|
||||||
tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv
|
|
||||||
IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT
|
|
||||||
ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW
|
|
||||||
Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx
|
|
||||||
DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP
|
|
||||||
0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5
|
|
||||||
YfkdFNxtYLdVAwuylMoV3fKI
|
|
||||||
-----END PRIVATE KEY-----"
|
|
||||||
# 商户APIV3密钥
|
|
||||||
apiV3: ZHENTUAIzhentuaiZHENTUAIzhentuai
|
|
||||||
|
|
||||||
# 存储
|
# 存储
|
||||||
storage:
|
storage:
|
||||||
@ -171,7 +120,45 @@ facebody:
|
|||||||
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
||||||
accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c"
|
accessKeySecret: "ZCIP8aKx1jwX1wkeYIPQEDZ8fPtN1c"
|
||||||
region: "cn-shanghai"
|
region: "cn-shanghai"
|
||||||
|
#支付
|
||||||
|
pay:
|
||||||
|
default-use: zt
|
||||||
|
configs:
|
||||||
|
- name: zt
|
||||||
|
type: WX_MP_PAY
|
||||||
|
config:
|
||||||
|
merchantId: "1700540331"
|
||||||
|
appId: "wxe7ff26af70bfc37c"
|
||||||
|
privateKey: "-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHwDoab8iRX4vn
|
||||||
|
Ta3a+gh5Z3wcyTM3VkWhkAPJGNJhaNgzOBI9b4v1x+uSZ4To2uXhQE5hvcxWSfNZ
|
||||||
|
F7H6yp+6estADeZLpdXLBDBvPDOjEGhG7YUHJjWnFh5eY2Rtnx4/7x+xCsRS+Mtq
|
||||||
|
Mx6KMrb4UZYNIq14peTQgfICkDBdqnUIkFjDmChUy0LlsSFW8AyJIqrBec5VZWf/
|
||||||
|
QqsIBf9vsTVxrqlX+5owYZuPYoFOIQJFUW8dfU20qk//BxiDjPFZBLNa02aIEbNF
|
||||||
|
SXZE2TlKD7zD0Qv/w95Hf1V+a/cxP2B6LNtqwioIdHbU6Axu7uHkr0RSPXPsvOWY
|
||||||
|
eUIpGP4bAgMBAAECggEBALm34w3TYtKu2D/tfDh9gkWGTuHgu6q2nrTxVmOxnWEN
|
||||||
|
/v3YIzVVsfaJs2ACuZNaeqNsi7PaqNKNnSD3o/X+UHYsVy8t/THWdSl1sqapfYUd
|
||||||
|
6yYPDkEwaG/6Y6/0j1pQt+pPpNKRpSlTwqTx9HIfZvkHuhBqbokfDNhECUQS1bUu
|
||||||
|
8pmyALIkuXu38B/xCs/EH+Lp1N69IA0mwalT/2zi9ZJhGNg5OWBzNbkMKf2Tck+9
|
||||||
|
SnS6s+pAT6YxB9qYhg645H3dRKXdeSYbjI+uiIe/7cJvTxfQDLD/oDap2TJQH3iM
|
||||||
|
SVbSfNFbR1tH6PiYx9eXeElEg2QXEPztbf8NcUlGOGkCgYEA8PewLVzUdHD20KkX
|
||||||
|
tZP+JCvSTy2f0kPHTc3+BU+MOlG8uZzsK06efo+X5BGkMRj8P+MPp9rJQr5IJqJl
|
||||||
|
GpeA1XpF54v2DIcNcjrQHIJ9XWoWirZjMWRVn4D5laQTI+FEV8pyFfJJOLIgBe9b
|
||||||
|
c6hBHNnAB4Y6JZ/s+US4ymK4wQ0CgYEA1DZMcuyiUgjnprUsOIokpg8RxGLIvB5+
|
||||||
|
2FyCffa/CikMRU8bRtHdpJLguArrR9rEILU6fICPARdlCg8r0XMrvniiAaS3YlDj
|
||||||
|
tSxbfrrS6xySvVFdNusv/j3i5/76IedsSArJLeQpIZMZ3n6q/dmq4kbWh+bT/5z+
|
||||||
|
MVpjWixpYccCgYBtaEh5kDh2VgP6YYv+SZ+OVMc8Y/64vUV0sh6v0ppcsFf7/p/M
|
||||||
|
WfnkhNX2G3xtPmbpqvKkx9WxlCu2Pu2g0UERrF6o7wdcUMVuI/3xs92v2Ec72+vV
|
||||||
|
tTSbIzgvFTwLgnBBXA3IoSVVtKqNh0wCi1Zk/wkNYYhtJNu3odg1K/Wu0QKBgBOv
|
||||||
|
IbI7TucrGkm1Xm+0KKgal7xOqW4BqiRpmFUU0S2hFxlKuC3+g3+jfCK2KJLWsQCT
|
||||||
|
ruQjjKA+Skn/lEHuW+1kBSr/217MQALrJWWA8NWMJfRXmrzgXehIV0bLuOnyLHIW
|
||||||
|
Rgjys/oAShMATt4TFa29gmLCv4FjT5TGXJbdrby7AoGBAOqER71Vi90UV84sYLWx
|
||||||
|
DSW/3q5/QrndmeeaQALslA6sidnTZWqlhMsNPl8dfBKl6xnrCdcaeY5xk/xmVOqP
|
||||||
|
0KedJgT+IjLwY1yJ9QOBd02ejAY3qNlKt2NiSWv2GBY1cZxqhkHNaI/UWI9CAyH5
|
||||||
|
YfkdFNxtYLdVAwuylMoV3fKI
|
||||||
|
-----END PRIVATE KEY-----"
|
||||||
|
serialNumber: "2AD248A1D15F0056D6AEC20B4EEF53F3C32CBFF0"
|
||||||
|
apiV3Key: ZHENTUAIzhentuaiZHENTUAIzhentuai
|
||||||
# 通知到人
|
# 通知到人
|
||||||
notify:
|
notify:
|
||||||
defaultUse: "developer"
|
defaultUse: "developer"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user