Merge remote-tracking branch 'origin/wzj-main' into wzj-main
# Conflicts: # ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/VlogService.java # ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java # ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberService.java
This commit is contained in:
commit
1aebe07488
@ -14,6 +14,7 @@ import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -32,6 +33,9 @@ public class AppCommentController {
|
||||
private RedisOperator redis;
|
||||
@Autowired
|
||||
private MsgService msgService;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@ApiOperation("查询视频评论列表")
|
||||
@PostMapping("/vlogComments")
|
||||
public R<Page<CommentVO>> queryVlogComments(
|
||||
@ -66,7 +70,7 @@ public class AppCommentController {
|
||||
commentService.createComment(bo);
|
||||
|
||||
// 2) 短视频评论总数 +1(Redis 优先)
|
||||
redis.increment(BaseInfoProperties.REDIS_VLOG_COMMENT_COUNTS + ":" + bo.getVlogId(), 1);
|
||||
redisCache.zSetIncrement(BaseInfoProperties.REDIS_VLOG_COMMENT_COUNTS , bo.getVlogId(), 1);
|
||||
|
||||
// 3) 发送站内消息:根评论 -> 通知视频作者;回复评论 -> 通知被回复用户
|
||||
if ("0".equals(bo.getFatherCommentId())) {
|
||||
|
@ -6,6 +6,7 @@ import com.wzj.soopin.content.domain.bo.*;
|
||||
import com.wzj.soopin.content.domain.po.MyLikedVlog;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.service.IVlogPullService;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.content.service.VlogUploadService;
|
||||
import com.wzj.soopin.content.utils.PagedGridResult;
|
||||
@ -13,6 +14,7 @@ import com.wzj.soopin.content.utils.QcCloud;
|
||||
import com.wzj.soopin.content.utils.RedisOperator;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.core.domain.R;
|
||||
@ -22,6 +24,7 @@ import org.dromara.common.mq.domain.MQMessage;
|
||||
import org.dromara.common.mq.enums.MQMessageType;
|
||||
import org.dromara.common.mq.enums.MessageActionEnum;
|
||||
import org.dromara.common.mq.utils.MqUtil;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -38,34 +41,25 @@ import static com.wzj.soopin.content.domain.base.BaseInfoProperties.*;
|
||||
@Api(tags = "VlogController 短视频相关业务功能的接口")
|
||||
@RequestMapping("/app/vlog")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class AppVlogController {
|
||||
@Autowired
|
||||
private VlogService vlogService;
|
||||
@Autowired
|
||||
private QcCloud qcCloud;
|
||||
@Autowired
|
||||
private VlogUploadService vlogUploadService;
|
||||
@Autowired
|
||||
private final VlogService vlogService;
|
||||
private final QcCloud qcCloud;
|
||||
private final VlogUploadService vlogUploadService;
|
||||
public final RedisCache cache;
|
||||
|
||||
private final IVlogPullService pullService;
|
||||
|
||||
public RedisOperator redis;
|
||||
@Tag(name = "首页视频列表")
|
||||
@PostMapping("/indexList")
|
||||
public R<Page<IndexVlogVO>> indexList(@RequestBody IndexListBO bo, @RequestBody Page page) {
|
||||
|
||||
try{
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
bo.setUserId(String.valueOf(loginUser.getUserId()));
|
||||
}catch (Exception e){
|
||||
log.error("用户没登陆", e);
|
||||
}
|
||||
Page<IndexVlogVO> pages = vlogService.getIndexVlogList(bo, page);
|
||||
Page<IndexVlogVO> pages = pullService.page(page);
|
||||
return R.ok(pages);
|
||||
}
|
||||
|
||||
@GetMapping("/detail/{vlogId}")
|
||||
public R<Object> detail( @PathVariable String vlogId) {
|
||||
public R<Object> detail(@PathVariable String vlogId) {
|
||||
|
||||
return R.ok(vlogService.getVlogDetailById(vlogId));
|
||||
}
|
||||
@ -99,7 +93,7 @@ public class AppVlogController {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
bo.setMyId(String.valueOf(loginUser.getUserId()));
|
||||
Page<IndexVlogVO> pages = vlogService.getMyFollowVlogList( page);
|
||||
Page<IndexVlogVO> pages = vlogService.getMyFollowVlogList(page);
|
||||
return R.ok(pages);
|
||||
}
|
||||
|
||||
@ -111,9 +105,10 @@ public class AppVlogController {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
bo.setMyId(String.valueOf(loginUser.getUserId()));
|
||||
Page<IndexVlogVO> pages = vlogService.getMyFriendVlogList( page);
|
||||
Page<IndexVlogVO> pages = vlogService.getMyFriendVlogList(page);
|
||||
return R.ok(pages);
|
||||
}
|
||||
|
||||
@PostMapping("publish")
|
||||
public R<Void> publish(@RequestBody VlogBO vlogBO) throws Exception {
|
||||
|
||||
@ -126,12 +121,12 @@ public class AppVlogController {
|
||||
|
||||
|
||||
String url = vlogBO.getUrl();
|
||||
log.info("未审核视频地址:"+url);
|
||||
log.info("未审核视频地址:" + url);
|
||||
String fileName = url.substring(url.lastIndexOf("/") + 1);
|
||||
log.info("视频文件名称:"+fileName);
|
||||
log.info("开始上传腾讯云点播:"+fileName);
|
||||
log.info("视频文件名称:" + fileName);
|
||||
log.info("开始上传腾讯云点播:" + fileName);
|
||||
String fileId = qcCloud.uploadViaTempFile(fileName);
|
||||
log.info("视频发布ID:"+fileId);
|
||||
log.info("视频发布ID:" + fileId);
|
||||
vlogBO.setFileId(fileId);
|
||||
// 删除minio文件
|
||||
// MinIOUtils.removeFile(minIOConfig.getBucketName(),fileName);
|
||||
@ -142,6 +137,7 @@ public class AppVlogController {
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Tag(name = "我的公开视频列表")
|
||||
@PostMapping("/myPublicList")
|
||||
public R<Page<IndexVlogVO>> myPublicList(@RequestBody MyListBO bo, @RequestBody Page page) {
|
||||
@ -149,155 +145,51 @@ public class AppVlogController {
|
||||
return R.ok(pages);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Integer nacosConuts=0;
|
||||
|
||||
|
||||
@PostMapping("like")
|
||||
@PostMapping("/like")
|
||||
public R<Void> like(@RequestBody VlogBO vlogBO) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
|
||||
String userId = String.valueOf(loginUser.getUserId());
|
||||
String vlogId = vlogBO.getId();
|
||||
|
||||
|
||||
//获取vlog
|
||||
Vlog vlog = vlogService.getVlog(vlogId);
|
||||
if(vlog==null){
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
// 我点赞的视频,关联关系保存到数据库
|
||||
vlogService.userLikeVlog(userId, vlogId);
|
||||
|
||||
// 点赞后,视频和视频发布者的获赞都会 +1
|
||||
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlog.getMemberId(), 1);
|
||||
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
|
||||
// 我点赞的视频,需要在redis中保存关联关系
|
||||
redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");
|
||||
|
||||
log.info("nacosConuts="+nacosConuts);
|
||||
|
||||
String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
|
||||
Integer counts=0;
|
||||
if (StringUtils.isNotBlank(countsStr)){
|
||||
|
||||
counts=Integer.valueOf(countsStr);
|
||||
if (counts>=nacosConuts){
|
||||
|
||||
vlogService.flushCounts(vlogId, counts);
|
||||
}
|
||||
}
|
||||
if (userId != null && vlog.getMemberId() != null && !userId.equals(vlog.getMemberId())) {
|
||||
// 新版:使用模板类型编号和参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", userId);
|
||||
params.put("nickname", loginUser.getNickname());
|
||||
params.put("action", MessageActionEnum.INTERACTION_LIKE.name());
|
||||
params.put("toUserId",vlog.getMemberId());
|
||||
MQMessage message = MQMessage.builder()
|
||||
.messageType(MQMessageType.IM.name())
|
||||
.data(params)
|
||||
.source("member")
|
||||
.build();
|
||||
// 关注消息
|
||||
MqUtil.sendIMMessage(message);
|
||||
|
||||
}
|
||||
|
||||
vlogService.userLikeVlog(userId,vlogId );
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("unlike")
|
||||
public R<Void> unlike(@RequestBody Map<String, String> params) {
|
||||
|
||||
@PostMapping("/unlike")
|
||||
public R<Void> unlike(@RequestBody VlogBO vlogBO) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
|
||||
String userId = String.valueOf(loginUser.getUserId());
|
||||
String vlogId = params.get("vlogId");
|
||||
|
||||
//获取vlog
|
||||
Vlog vlog = vlogService.getVlog(vlogId);
|
||||
if(vlog==null){
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
|
||||
// 我取消点赞的视频,关联关系删除
|
||||
String vlogId = vlogBO.getId();
|
||||
vlogService.userUnLikeVlog(userId, vlogId);
|
||||
|
||||
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlog.getMemberId(), 1);
|
||||
redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
@GetMapping("/read")
|
||||
public R<Void> read(@RequestBody VlogBO vlogBO) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
vlogService.readVlog(loginUser.getUserId(), vlogBO.getId());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Tag(name = "手动触发缓存点赞最多视频")
|
||||
@PostMapping("/cacheTopLikedVlogs")
|
||||
public R<Void> cacheTopLikedVlogs(@RequestParam(defaultValue = "100") int limit) {
|
||||
try {
|
||||
vlogService.cacheTopLikedVlogs(limit);
|
||||
// vlogService.cacheTopLikedVlogs(limit);
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
log.error("手动触发缓存点赞最多视频失败", e);
|
||||
return R.fail("缓存失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(name = "获取缓存中的点赞最多视频")
|
||||
@GetMapping("/getTopLikedVlogs")
|
||||
public R<Object> getTopLikedVlogs(@RequestParam(defaultValue = "") String date,
|
||||
@RequestParam(defaultValue = "10") int pageSize,
|
||||
@RequestParam(defaultValue = "0") int pageNum) {
|
||||
try {
|
||||
String redisKey;
|
||||
if (StringUtils.isBlank(date)) {
|
||||
// 如果没有指定日期,使用今天的日期
|
||||
redisKey = "top_liked_vlogs:" + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} else {
|
||||
redisKey = "top_liked_vlogs:" + date;
|
||||
}
|
||||
|
||||
String cachedData = redis.get(redisKey);
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
|
||||
if (StringUtils.isNotBlank(cachedData)) {
|
||||
// 解析JSON数据
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<Map<String, Object>> vlogList = objectMapper.readValue(cachedData, new com.fasterxml.jackson.core.type.TypeReference<List<Map<String, Object>>>() {});
|
||||
|
||||
// 计算分页
|
||||
int startIndex = pageNum * pageSize;
|
||||
int endIndex = Math.min(startIndex + pageSize, vlogList.size());
|
||||
|
||||
if (startIndex < vlogList.size()) {
|
||||
// 从Redis缓存中获取指定页的数据
|
||||
resultList = vlogList.subList(startIndex, endIndex);
|
||||
log.info("从Redis缓存中获取了{}条视频数据", resultList.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 如果Redis中的数据不足,从数据库随机查询补充
|
||||
if (resultList.size() < pageSize) {
|
||||
int needMore = pageSize - resultList.size();
|
||||
log.info("Redis缓存数据不足,需要从数据库随机查询{}条视频", needMore);
|
||||
|
||||
// 从数据库随机查询视频
|
||||
List<Map<String, Object>> randomVlogs = vlogService.getRandomVlogs(needMore);
|
||||
resultList.addAll(randomVlogs);
|
||||
log.info("从数据库随机查询了{}条视频", randomVlogs.size());
|
||||
}
|
||||
|
||||
return R.ok(resultList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取缓存中的点赞最多视频失败", e);
|
||||
return R.fail("获取缓存失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,3 +254,12 @@ tencent:
|
||||
password: A1969bf8
|
||||
authentication-database: admin
|
||||
# replica-set-name: mongoreplset
|
||||
|
||||
easypay:
|
||||
api-path-prefix: https://d-phoenix-gap.easypay.com.cn:24443/yqt
|
||||
req-id: D01X66666667068
|
||||
mcht-code: 631000000003325
|
||||
wechat-mchid: 804474446
|
||||
easypay-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArgVerkGaSEQvZIOpLjeUoVpL0lSYLc04+txtPFtfm5r5XFbaNaf5Ahu0lziGEwWzrGONThSsnb3U9pqoY6BpqviN4h+Guw5oEdHr1T/eDkQD5urgQUaZA6lDoU9XC662r+0kpbKidvXIsK2CrShN+BF8HEJmRZuhglxh25OHWIWqQiUDjLZC+QJRZqUu9Uzy9RBBu7qa0f0xbqYl3hnYi+vH++SsyOavO2gUVQyKU5Kkt5ZJVpZFQvD3BXePgwJSpsvrjhj0hiYp2v6PScN9XHP1vXB4wtIYSFYwmVus1KkV/LfDzUm6zHjliHYTVl6lPMhveIVJlRIqInRZRHxg5QIDAQAB
|
||||
merRsaPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCc1mku1mtfTc1vZM9z3TkRMZ9SaKP+6MdoQhjDHB9vJUOuG2Jnegej4gtzcm8MVYomV1azJMtCbPq4PN9aHegH13JthvrUPR3nAKp8AUp9Fh47ded//snNyAf7C7o8xKN5e7n89ROwacCAL2QDno76ngXzQQVj1TxY9pBdekZ03ezuDk1sv/u4FBlW8kRyaVdqyl4FdvP+EEljDe8gGxRikLyb3cK1B6G7w2BXgM/svft5SOoiqStx2XvgHRrFRB5w96TdoKNH9yxHU2clMJiz+5cej1VL6OHZspuY3cnPyJtyS+weYjDT+COLLBUe9UwbOV15DXDNpBLd34W4GiqtAgMBAAECggEAYaVwmVOwSAblp7wJGScb16OggStbJ2MAe93jEt7Yh1eZGrY7/xbP2O3smTUfBHvhZlusRB7dWf8F3l0v5iiGhRNTT/PhCPEARAl7G3emS9jQe869kkgslq06ose7bQg0i3dH5cEkQAqnameXClXWyRxHshrCY1SonO7uFPUDFtD2Z9GHu6dOWkOHfX7UETHV5/NTSqvner5M2YNsV/5To87zrmaeeNyvu91JgJSYofTD8IcMyhxcswxB9F3ECP7nulLDdCV+9mvE9zO0i4mPBxYb++87J0pu35TN9OY+gpiCK3Ed0gDqvvkTiCQEFu6y7OiqsQwy03CE5hAwWZR2YQKBgQDdb6e7+FWJSr9fIknfvZPPtKmbEkMHP1RYnVo3pmuVm14Z3UmostiSBRPMfVjeOX0N82SONM9P+1v9SDgSK3pL8rlk9Hx6D5KI7uj2IMtTVt00pO31KtxDLmXfgapDbWHK1RGEn1PDrnKYy5yOKJ8n0Wgp4lVEPIBN6uIud0A9iQKBgQC1UXdhEXFETyqEYWb9OnWbBjiVIw3D2/qW5c+WQGsHYdMEImC/0oTWIH9fKd4Azf26JjZ9nQvs5VcijJP6BXbGPqir5NgGVkwCj33PoNg4dDgIVE4BYaSp//7B6jCi5QiRTzCSOmUSkZ5L1Kz4SNEDe9r0MpLhxrsAzmR9aEJ/BQKBgHI71Ks63F2cSwd39+ZNtYA0cj7Gd/+4IvooCs+kseGXKj9rkkFOKj2CEwmuLHdP7vyQcHKQOdbIFFegtxRgi5G8oPm8yq5pdC3iGhpHJr1SlYFACGYu+zxJJlLcYIqyVf2+V3A0hZDwYLwEZjpMKHbxJ6xbz6MJFyObJZ3U9TYJAoGANXoGjJF5Z501u/+CQZN5VjSagZnqGGcL3G+BLx5msrGua9y7zjeHyCOjjWyqtnAKsllM3vVvq/nkHiN6DVaJNmUKmFARSqUvG944TAFzZAsa75H1w8CJsT34ZDbvC0wjn7/MYoRohPZ/ynu6XCwVwUJJTJaR7ZcQVmeJCdezLQUCgYEAszix6V9oL80Clb1nMwIly6I78+pcFKyk82yXxvySb6XPJvgoasbz9xYIeKlPyy6r8Aj/ujz5GVtDtkE6n6bsjekCdnUKUY3uTvFAX+YGQkuZnaPoisELJFI2Hal22tNnJyCOYh//AGAiHYpHNUKD4hsKBb45MhK1xwvTHpuLkdc=
|
||||
backUrl: http://192.168.1.71:8080/easypay/trade/callback
|
||||
|
@ -375,6 +375,9 @@ wechat:
|
||||
transfer-notify-url: https://a94aeb5582c2.ngrok-free.app/no-auth/wechat/notify # 转账回调地址
|
||||
app-id: wxebcdaea31881caab # 应用ID
|
||||
secret: your_wechat_secret # 应用密钥
|
||||
mini-program:
|
||||
app-id: wx87a5db19138da60d
|
||||
secret: your_wechat_secret
|
||||
|
||||
http:
|
||||
client:
|
||||
|
@ -36,4 +36,21 @@ public interface GlobalConstants {
|
||||
* 会员 redis key
|
||||
*/
|
||||
String MEMBER_KEY = GLOBAL_REDIS_KEY + "member:";
|
||||
|
||||
/**
|
||||
* 视频 redis key
|
||||
*/
|
||||
String VLOG_KEY = GLOBAL_REDIS_KEY + "vlog:";
|
||||
|
||||
/**
|
||||
* 会员视频 redis key
|
||||
*/
|
||||
String GLOBAL_OFFSET = GLOBAL_REDIS_KEY + "offset:";
|
||||
|
||||
|
||||
/**
|
||||
* 热点视频 redis key
|
||||
*/
|
||||
String HOT_VLOG_TAG = "HOT";
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,10 @@
|
||||
<version>2.15.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-client</artifactId>
|
||||
<version>5.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -0,0 +1,37 @@
|
||||
package org.dromara.common.mq.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* 消息事件
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Getter
|
||||
public class VlogPushEvent extends ApplicationEvent {
|
||||
|
||||
private final String tag;
|
||||
private final String userIdStr;
|
||||
|
||||
/**
|
||||
* 使用 Long 类型用户 ID 创建消息事件
|
||||
*/
|
||||
public VlogPushEvent(Object source, String tag) {
|
||||
super(source);
|
||||
this.tag = tag;
|
||||
this.userIdStr = tag;
|
||||
}
|
||||
/**
|
||||
* 使用 Long 类型用户 ID 创建消息事件
|
||||
*/
|
||||
public VlogPushEvent(String tag) {
|
||||
super(tag);
|
||||
this.tag = tag;
|
||||
this.userIdStr = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,8 +1,13 @@
|
||||
package org.dromara.common.mq.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
|
||||
import org.apache.rocketmq.client.consumer.LitePullConsumer;
|
||||
import org.apache.rocketmq.client.producer.SendCallback;
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.mq.config.RocketMQConfig;
|
||||
@ -13,18 +18,40 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MqUtil implements ApplicationContextAware {
|
||||
private static final String NAME_SERVER_ADDR = "localhost:9876";
|
||||
private static final String CONSUMER_GROUP = "TEST_PULL_GROUP";
|
||||
private static final String TOPIC = "TEST_TOPIC";
|
||||
private static RocketMQTemplate template;
|
||||
|
||||
private static Map<String, LitePullConsumer> consumerMap = new ConcurrentHashMap<>();
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
template = applicationContext.getBean(RocketMQTemplate.class);
|
||||
}
|
||||
|
||||
public void init() throws Exception {
|
||||
// 1. 创建消费者实例,指定消费者组
|
||||
DefaultLitePullConsumer consumer = new DefaultLitePullConsumer("YOUR_PULL_CONSUMER_GROUP");
|
||||
|
||||
consumer.setNamesrvAddr("localhost:9876"); // 替换为您的NameServer地址
|
||||
consumer.subscribe("YOUR_TOPIC", "*");
|
||||
consumer.start();
|
||||
// 3. 设置从何处开始消费(首次启动时)
|
||||
//consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
|
||||
// 4. 订阅主题和Tag
|
||||
consumer.subscribe("YOUR_TOPIC", "*"); // 使用*消费所有Tag
|
||||
// 5. 启动消费者
|
||||
consumer.start();
|
||||
System.out.println("LitePullConsumer 启动成功");
|
||||
}
|
||||
|
||||
//
|
||||
public static void sendMessage(String topic, MQMessage message) {
|
||||
public static void sendMessage(String destination, MQMessage message) {
|
||||
if (template == null) {
|
||||
log.error("RocketMQTemplate未初始化,无法发送消息");
|
||||
return;
|
||||
@ -32,10 +59,10 @@ public class MqUtil implements ApplicationContextAware {
|
||||
|
||||
try {
|
||||
String jsonMessage = JsonUtils.toJsonString(message);
|
||||
template.convertAndSend(topic, jsonMessage);
|
||||
log.info("发送消息到RocketMQ成功,topic: {}, message: {}", topic, jsonMessage);
|
||||
template.convertAndSend(destination, jsonMessage);
|
||||
log.info("发送消息到RocketMQ成功,topic: {}, message: {}", destination, jsonMessage);
|
||||
} catch (Exception e) {
|
||||
log.error("发送消息到RocketMQ失败,topic: {}, message: {}", topic, message, e);
|
||||
log.error("发送消息到RocketMQ失败,topic: {}, message: {}", destination, message, e);
|
||||
}
|
||||
}
|
||||
public static void sendIMMessage( MQMessage message) {
|
||||
@ -97,5 +124,4 @@ public class MqUtil implements ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,212 @@
|
||||
package org.dromara.common.mq.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
|
||||
import org.apache.rocketmq.client.consumer.PullResult;
|
||||
import org.apache.rocketmq.client.consumer.PullStatus;
|
||||
import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;
|
||||
import org.apache.rocketmq.client.exception.MQBrokerException;
|
||||
import org.apache.rocketmq.client.exception.MQClientException;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
import org.apache.rocketmq.common.message.MessageQueue;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingException;
|
||||
import org.apache.rocketmq.remoting.protocol.heartbeat.MessageModel;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 带超时自动销毁功能的用户级RocketMQ消费者管理器
|
||||
* 支持按用户隔离消费者,并自动清理超时未活动的实例
|
||||
*/
|
||||
@Component
|
||||
public class UserRocketMQConsumerManager {
|
||||
// 全局NameServer地址
|
||||
private String namesrvAddr="192.168.1.65:9876";
|
||||
|
||||
// 超时时间(毫秒),默认30分钟
|
||||
private long timeoutMillis = 30 * 60 * 1000;
|
||||
|
||||
// 定时检查间隔(毫秒),默认5分钟
|
||||
private long checkIntervalMillis = 5 * 60 * 1000;
|
||||
|
||||
// 存储用户与消费者的映射(线程安全)
|
||||
private final Map<String, UserConsumerContext> userConsumerMap = new ConcurrentHashMap<>();
|
||||
|
||||
// 定时任务执行器,用于检测超时消费者
|
||||
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
private final String consumerGroup="user_consumer_group";
|
||||
private final String topic="MEMBER_VLOG_MSG";
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 为指定用户创建消费者实例
|
||||
* @param userId 用户唯一标识
|
||||
* @param consumerGroup 该用户的消费组
|
||||
* @param topic 消费的主题
|
||||
* @return 是否创建成功
|
||||
*/
|
||||
public boolean createConsumer(String userId, String consumerGroup, String topic) throws MQClientException {
|
||||
validateUserId(userId);
|
||||
|
||||
// 若用户已存在消费者,更新活动时间并返回
|
||||
if (userConsumerMap.containsKey(userId)) {
|
||||
UserConsumerContext context = userConsumerMap.get(userId);
|
||||
context.lastActiveTime = System.currentTimeMillis();
|
||||
System.out.println("用户[" + userId + "]的消费者已存在,更新活动时间");
|
||||
return false;
|
||||
}
|
||||
System.setProperty("rocketmq.namesrv.addr", namesrvAddr);
|
||||
// 创建消费者
|
||||
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(consumerGroup);
|
||||
consumer.setMessageModel(MessageModel.CLUSTERING);
|
||||
consumer.setAllocateMessageQueueStrategy(new AllocateMessageQueueAveragely());
|
||||
consumer.start();
|
||||
|
||||
|
||||
// 初始化该用户的偏移量存储
|
||||
redisCache.zSetAdd(GlobalConstants.GLOBAL_OFFSET+userId,userId,0);
|
||||
|
||||
// 存储用户消费者上下文
|
||||
UserConsumerContext context = new UserConsumerContext(
|
||||
consumer,
|
||||
consumerGroup,
|
||||
topic,
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
userConsumerMap.put(userId, context);
|
||||
System.out.println("用户[" + userId + "]的消费者创建成功,消费组: " + consumerGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为指定用户拉取消息(会更新活动时间)
|
||||
* @param userId 用户唯一标识
|
||||
* @param batchSize 每次拉取数量
|
||||
* @return 拉取到的消息列表
|
||||
*/
|
||||
public List<MessageExt> pullUserMessages(String userId , int batchSize)
|
||||
throws MQClientException, InterruptedException, MQBrokerException, RemotingException {
|
||||
validateUserId(userId);
|
||||
UserConsumerContext context = getUserConsumerContext(userId);
|
||||
|
||||
// 更新最后活动时间
|
||||
context.lastActiveTime = System.currentTimeMillis();
|
||||
|
||||
// 获取用户的消息队列
|
||||
Set<MessageQueue> mqs = context.consumer.fetchSubscribeMessageQueues(context.topic);
|
||||
List<MessageExt> allMessages = new ArrayList<>();
|
||||
|
||||
int current=0;
|
||||
// 拉取所有队列的消息
|
||||
for (MessageQueue mq : mqs) {
|
||||
PullResult result = pullSingleQueueMessage(userId, context.consumer, mq , batchSize-current);
|
||||
if (result.getPullStatus() == PullStatus.FOUND) {
|
||||
allMessages.addAll(result.getMsgFoundList());
|
||||
// 更新用户的偏移量
|
||||
updateUserOffset(userId, mq, result.getNextBeginOffset());
|
||||
redisCache.zSetAdd(GlobalConstants.GLOBAL_OFFSET+userId,mq.getQueueId()+"",result.getNextBeginOffset());
|
||||
current+=result.getMsgFoundList().size();
|
||||
if(current==batchSize){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return allMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户的消费者上下文
|
||||
*/
|
||||
private UserConsumerContext getUserConsumerContext(String userId) throws MQClientException {
|
||||
UserConsumerContext context = userConsumerMap.get(userId);
|
||||
if (context == null) {
|
||||
createConsumer(userId, consumerGroup,topic);
|
||||
}
|
||||
return userConsumerMap.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取单个队列的消息
|
||||
*/
|
||||
private PullResult pullSingleQueueMessage(String userId, DefaultMQPullConsumer consumer,
|
||||
MessageQueue mq, int batchSize)
|
||||
throws MQClientException, MQBrokerException, RemotingException, InterruptedException {
|
||||
// 获取该用户在该队列的偏移量
|
||||
Double offset = getUserQueueOffset(userId, mq);
|
||||
if(offset==null){
|
||||
offset=0.0;
|
||||
}
|
||||
return consumer.pull(mq, userId, offset.longValue(), batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户在指定队列的消费偏移量
|
||||
*/
|
||||
private Double getUserQueueOffset(String userId, MessageQueue mq) {
|
||||
return redisCache.zSetScore(GlobalConstants.GLOBAL_OFFSET+userId,mq.getQueueId()+"") ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户在指定队列的消费偏移量
|
||||
*/
|
||||
private void updateUserOffset(String userId, MessageQueue mq, long offset) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前所有用户的消费者列表
|
||||
*/
|
||||
public Set<String> getRegisteredUserIds() {
|
||||
return userConsumerMap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户ID
|
||||
*/
|
||||
private void validateUserId(String userId) {
|
||||
if (userId == null || userId.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("用户ID不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户消费者上下文(存储消费者实例及活动时间)
|
||||
*/
|
||||
private static class UserConsumerContext {
|
||||
DefaultMQPullConsumer consumer;
|
||||
String consumerGroup;
|
||||
String topic;
|
||||
long createTime; // 创建时间
|
||||
long lastActiveTime; // 最后活动时间(拉取消息时间)
|
||||
|
||||
public UserConsumerContext(DefaultMQPullConsumer consumer, String consumerGroup,
|
||||
String topic, long createTime) {
|
||||
this.consumer = consumer;
|
||||
this.consumerGroup = consumerGroup;
|
||||
this.topic = topic;
|
||||
this.createTime = createTime;
|
||||
this.lastActiveTime = createTime; // 初始活动时间=创建时间
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.sql.ShardingKey;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -121,7 +122,7 @@ public class RedisCache
|
||||
* 获得缓存的list对象
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @return 缓存键值对应的数据
|
||||
* * @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> List<T> getCacheList(final String key)
|
||||
{
|
||||
@ -230,4 +231,98 @@ public class RedisCache
|
||||
}
|
||||
|
||||
|
||||
//zeset类型的增删改查
|
||||
/**
|
||||
* 新增zset
|
||||
* @param key
|
||||
* @param value
|
||||
* @param score
|
||||
*/
|
||||
public void zSetAdd(String key, String value, double score) {
|
||||
redisTemplate.opsForZSet().add(key, value, score);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询zset
|
||||
* @param key
|
||||
* @param start
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
public Set<String> zSetRange(String key, long start, long end) {
|
||||
return redisTemplate.opsForZSet().range(key, start, end);
|
||||
}
|
||||
/**
|
||||
* 删除zset
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void zSetRemove(String key, String value) {
|
||||
redisTemplate.opsForZSet().remove(key, value);
|
||||
}
|
||||
/**
|
||||
* 查询zset分数
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Double zSetScore(String key, String value) {
|
||||
return redisTemplate.opsForZSet().score(key, value);
|
||||
}
|
||||
/**
|
||||
* 查询zset长度
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Long zSetSize(String key) {
|
||||
return redisTemplate.opsForZSet().size(key);
|
||||
}
|
||||
/**
|
||||
* 查询zset排名
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Long zSetRank(String key, String value) {
|
||||
return redisTemplate.opsForZSet().rank(key, value);
|
||||
}
|
||||
/**
|
||||
* 排行榜
|
||||
* @param key
|
||||
* @param start
|
||||
* @param end
|
||||
* @return
|
||||
*/
|
||||
public Set<String> zSetReverseRange(String key, long start, long end) {
|
||||
return redisTemplate.opsForZSet().reverseRange(key, start, end);
|
||||
}
|
||||
/**
|
||||
* 增加增量
|
||||
* @param key
|
||||
* @param value
|
||||
* @param delta
|
||||
*/
|
||||
public void zSetIncrement(String key, String value, double delta) {
|
||||
redisTemplate.opsForZSet().incrementScore(key, value, delta);
|
||||
}
|
||||
/**
|
||||
* 减少数量
|
||||
* @param key
|
||||
* @param value
|
||||
* @param delta
|
||||
*/
|
||||
public void zSetDecrement(String key, String value, double delta) {
|
||||
redisTemplate.opsForZSet().incrementScore(key, value, -delta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否有这个成员
|
||||
* @param key
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public boolean zSetHasMember(String key, String value) {
|
||||
return redisTemplate.opsForZSet().rank(key, value) != null;
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,7 @@ import org.redisson.api.*;
|
||||
import org.redisson.api.options.KeysScanOptions;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -581,4 +578,6 @@ public class RedisUtils {
|
||||
RKeys rKeys = CLIENT.getKeys();
|
||||
return rKeys.countExists(key) > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -65,11 +65,16 @@ public class LoginHelper {
|
||||
*/
|
||||
@SuppressWarnings("unchecked cast")
|
||||
public static <T extends LoginUser> T getLoginUser() {
|
||||
SaSession session = StpUtil.getTokenSession();
|
||||
if (ObjectUtil.isNull(session)) {
|
||||
try {
|
||||
SaSession session = StpUtil.getTokenSession();
|
||||
if (ObjectUtil.isNull(session)) {
|
||||
return null;
|
||||
}
|
||||
return (T) session.get(LOGIN_USER_KEY);
|
||||
}catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
return (T) session.get(LOGIN_USER_KEY);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ import java.util.List;
|
||||
*/
|
||||
@Tag(name = "文章分类管理")
|
||||
@RestController
|
||||
@RequestMapping("/content/article/category")
|
||||
@RequestMapping("/cms/article/category")
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleCategoryController {
|
||||
|
||||
|
@ -27,7 +27,7 @@ import java.util.List;
|
||||
*/
|
||||
@Tag(name = "内容管理")
|
||||
@RestController
|
||||
@RequestMapping("/content/article")
|
||||
@RequestMapping("/cms/article")
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleController {
|
||||
|
||||
|
@ -3,8 +3,12 @@ package com.wzj.soopin.content.controller;
|
||||
|
||||
|
||||
import com.wzj.soopin.content.domain.base.BaseInfoProperties;
|
||||
import com.wzj.soopin.content.domain.bo.VlogBO;
|
||||
import com.wzj.soopin.content.domain.bo.*;
|
||||
import com.wzj.soopin.content.domain.po.Article;
|
||||
import com.wzj.soopin.content.domain.vo.ArticleVO;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.enums.YesOrNo;
|
||||
import com.wzj.soopin.content.service.IVlogPushService;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.content.service.VlogUploadService;
|
||||
@ -20,9 +24,6 @@ import com.wzj.soopin.content.utils.RedisOperator;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import com.wzj.soopin.content.domain.bo.IndexListBO;
|
||||
import com.wzj.soopin.content.domain.bo.MyListBO;
|
||||
import com.wzj.soopin.content.domain.bo.SimpleListBO;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -33,7 +34,7 @@ import java.util.ArrayList;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "VlogController 短视频相关业务功能的接口")
|
||||
@RequestMapping("/vlog")
|
||||
@RequestMapping("/cms/vlog")
|
||||
@RestController
|
||||
|
||||
public class VlogController extends BaseInfoProperties {
|
||||
@ -45,8 +46,15 @@ public class VlogController extends BaseInfoProperties {
|
||||
private VlogUploadService vlogUploadService;
|
||||
@Autowired
|
||||
public RedisOperator redis;
|
||||
|
||||
@PostMapping("vodCallBack")
|
||||
@Autowired
|
||||
private IVlogPushService vlogPushService;
|
||||
@Tag(name = "查询列表")
|
||||
@PostMapping("/page")
|
||||
public R<IPage<IndexVlogVO>> page(@RequestBody VlogBO bo, @RequestBody Page page) {
|
||||
Page<IndexVlogVO> pages = vlogService.getIndexVlogList(bo ,page);
|
||||
return R.ok(pages);
|
||||
}
|
||||
@PostMapping("/vodCallBack")
|
||||
public R<Void> vodCallBack(@RequestBody Map<String, Object> callbackData) {
|
||||
try {
|
||||
// 解析回调事件类型
|
||||
@ -160,7 +168,7 @@ public class VlogController extends BaseInfoProperties {
|
||||
|
||||
|
||||
|
||||
@PostMapping("changeVlogStatus")
|
||||
@PostMapping("/changeVlogStatus")
|
||||
public R<Void> changeVlogStatus(@RequestParam String userId,
|
||||
@RequestParam String vlogId,
|
||||
@RequestParam Integer status) {
|
||||
@ -168,7 +176,7 @@ public class VlogController extends BaseInfoProperties {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("changeToPrivate")
|
||||
@PostMapping("/changeToPrivate")
|
||||
public R<Void> changeToPrivate(@RequestParam String userId,
|
||||
@RequestParam String vlogId) {
|
||||
vlogService.changeToPrivateOrPublic(userId,
|
||||
@ -177,7 +185,7 @@ public class VlogController extends BaseInfoProperties {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("changeToPublic")
|
||||
@PostMapping("/changeToPublic")
|
||||
public R<Void> changeToPublic(@RequestParam String userId,
|
||||
@RequestParam String vlogId) {
|
||||
vlogService.changeToPrivateOrPublic(userId,
|
||||
@ -186,15 +194,13 @@ public class VlogController extends BaseInfoProperties {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping("totalLikedCounts")
|
||||
@PostMapping("/totalLikedCounts")
|
||||
public R<Integer> totalLikedCounts(@RequestParam String vlogId) {
|
||||
return R.ok(vlogService.getVlogBeLikedCounts(vlogId));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/push")
|
||||
public R pushMember(@RequestParam int count,@RequestParam String tag) {
|
||||
return R.ok(vlogPushService.pushVlogToMq(count,tag));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import com.wzj.soopin.content.enums.MessageEnum;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "管理端-评论管理接口")
|
||||
@RequestMapping("/comment")
|
||||
@RequestMapping("/cms/comment")
|
||||
@RestController
|
||||
public class CommentController extends BaseController {
|
||||
|
||||
|
@ -24,7 +24,7 @@ import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "管理端-视频")
|
||||
@RequestMapping("/video")
|
||||
@RequestMapping("/cms/video")
|
||||
@RestController
|
||||
public class VlogUploadController extends BaseInfoProperties {
|
||||
|
||||
@ -43,217 +43,6 @@ public class VlogUploadController extends BaseInfoProperties {
|
||||
@Autowired
|
||||
private IFansService fansService;
|
||||
|
||||
@ApiOperation("获取腾讯云点播视频列表")
|
||||
@PostMapping("/list")
|
||||
public R<IPage<Map<String, Object>>> getVodList(@RequestBody VlogBO vlogBO) {
|
||||
try {
|
||||
// 验证分页参数
|
||||
if (vlogBO.getCurrent() < 1) {
|
||||
vlogBO.setCurrent(1L);
|
||||
}
|
||||
if (vlogBO.getSize() < 1 || vlogBO.getSize() > 50) {
|
||||
vlogBO.setSize(10L);
|
||||
}
|
||||
|
||||
// 如果有模糊查询条件、时间区间条件,或者有排序条件,则只查询数据库
|
||||
if (StringUtils.isNotBlank(vlogBO.getMobile())
|
||||
|| StringUtils.isNotBlank(vlogBO.getNickname())
|
||||
|| StringUtils.isNotBlank(vlogBO.getTitleQuery())
|
||||
|| vlogBO.getStartTime() != null
|
||||
|| vlogBO.getEndTime() != null
|
||||
|| vlogBO.getStatus() != null
|
||||
|| StringUtils.isNotBlank(vlogBO.getColumn())) {
|
||||
|
||||
// 创建分页对象
|
||||
Page<Map<String, Object>> page = new Page<>(vlogBO.getCurrent(), vlogBO.getSize());
|
||||
|
||||
// 调用服务层方法进行查询
|
||||
IPage<Map<String, Object>> result = vlogService.getVlogListByMobile(page, vlogBO);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
// 否则查询腾讯云点播
|
||||
// 验证密钥配置
|
||||
String secretId = tencentCloudUtil.getSecretId();
|
||||
String secretKey = tencentCloudUtil.getSecretKey();
|
||||
if (secretId == null || secretId.isEmpty() || secretKey == null || secretKey.isEmpty()) {
|
||||
log.error("腾讯云密钥未配置");
|
||||
return R.fail("腾讯云密钥未配置");
|
||||
}
|
||||
|
||||
// 计算实际的offset
|
||||
long offset = (long) ((vlogBO.getCurrent() - 1) * vlogBO.getSize());
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
// 打印分页参数
|
||||
log.info("分页参数 - 当前页码: {}, 每页记录数: {}, 偏移量: {}", vlogBO.getCurrent(), vlogBO.getSize(), offset);
|
||||
|
||||
// 创建请求对象
|
||||
SearchMediaRequest req = new SearchMediaRequest();
|
||||
|
||||
// 设置分页参数
|
||||
req.setOffset(offset);
|
||||
req.setLimit(vlogBO.getSize());
|
||||
|
||||
// 设置排序
|
||||
SortBy sort = new SortBy();
|
||||
sort.setField("CreateTime");
|
||||
sort.setOrder("Desc");
|
||||
req.setSort(sort);
|
||||
|
||||
// 调用腾讯云API获取视频列表
|
||||
log.info("开始调用腾讯云 SearchMedia API");
|
||||
SearchMediaResponse resp = vlogUploadService.searchMedia(req);
|
||||
log.info("腾讯云 SearchMedia API 调用成功,总记录数: {}", resp.getTotalCount());
|
||||
|
||||
// 处理响应结果
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("total", resp.getTotalCount());
|
||||
result.put("current", vlogBO.getCurrent());
|
||||
result.put("size", vlogBO.getSize());
|
||||
result.put("pages", (resp.getTotalCount() + vlogBO.getSize() - 1) / vlogBO.getSize()); // 总页数
|
||||
|
||||
// 批量获取所有视频的统计信息,避免重复查询
|
||||
Map<String, String> fileIdToVlogIdMap = new HashMap<>();
|
||||
List<String> allVlogIds = new ArrayList<>();
|
||||
|
||||
if (resp.getMediaInfoSet() != null) {
|
||||
for (MediaInfo mediaInfo : resp.getMediaInfoSet()) {
|
||||
String fileId = mediaInfo.getFileId();
|
||||
Map<String, Object> statistics = vlogService.getVlogStatistics(fileId);
|
||||
String vlogId = (String) statistics.get("vlogId");
|
||||
if (StringUtils.isNotBlank(vlogId)) {
|
||||
fileIdToVlogIdMap.put(fileId, vlogId);
|
||||
allVlogIds.add(vlogId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取所有点赞数据
|
||||
Map<String, Integer> vlogLikeCounts = new HashMap<>();
|
||||
Map<String, Integer> vlogCommentCounts = new HashMap<>();
|
||||
long totalLikeCounts = 0;
|
||||
long totalCommentCounts = 0;
|
||||
|
||||
if (!allVlogIds.isEmpty()) {
|
||||
// 批量获取所有点赞键
|
||||
String likePattern = REDIS_USER_LIKE_VLOG + ":*";
|
||||
Collection<String> allLikeKeys = RedisUtils.keys(likePattern);
|
||||
|
||||
if (allLikeKeys != null && !allLikeKeys.isEmpty()) {
|
||||
// 逐个获取点赞值(由于RedisUtils没有批量方法)
|
||||
Map<String, String> likeKeyValueMap = new HashMap<>();
|
||||
for (String likeKey : allLikeKeys) {
|
||||
String likeValue = RedisUtils.getCacheObject(likeKey);
|
||||
if ("1".equals(likeValue)) {
|
||||
likeKeyValueMap.put(likeKey, likeValue);
|
||||
}
|
||||
}
|
||||
|
||||
// 按vlogId分组统计点赞数
|
||||
for (String vlogId : allVlogIds) {
|
||||
int likeCount = 0;
|
||||
for (String likeKey : likeKeyValueMap.keySet()) {
|
||||
if (likeKey.endsWith(":" + vlogId)) {
|
||||
likeCount++;
|
||||
}
|
||||
}
|
||||
vlogLikeCounts.put(vlogId, likeCount);
|
||||
totalLikeCounts += likeCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取所有评论数
|
||||
for (String vlogId : allVlogIds) {
|
||||
String commentKey = REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId;
|
||||
String commentCountsStr = RedisUtils.getCacheObject(commentKey);
|
||||
int commentCount = 0;
|
||||
if (StringUtils.isNotBlank(commentCountsStr)) {
|
||||
try {
|
||||
commentCount = Integer.valueOf(commentCountsStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的评论数格式错误: {}", vlogId, commentCountsStr);
|
||||
}
|
||||
}
|
||||
vlogCommentCounts.put(vlogId, commentCount);
|
||||
totalCommentCounts += commentCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 将总的点赞数和评论数添加到结果中
|
||||
result.put("totalLikeCounts", totalLikeCounts);
|
||||
result.put("totalCommentCounts", totalCommentCounts);
|
||||
|
||||
List<Map<String, Object>> mediaList = new ArrayList<>();
|
||||
if (resp.getMediaInfoSet() != null) {
|
||||
for (MediaInfo mediaInfo : resp.getMediaInfoSet()) {
|
||||
Map<String, Object> mediaMap = new HashMap<>();
|
||||
// 基础信息
|
||||
MediaBasicInfo basicInfo = mediaInfo.getBasicInfo();
|
||||
mediaMap.put("fileId", mediaInfo.getFileId());
|
||||
mediaMap.put("name", basicInfo.getName());
|
||||
mediaMap.put("description", basicInfo.getDescription());
|
||||
mediaMap.put("createTime", basicInfo.getCreateTime());
|
||||
mediaMap.put("updateTime", basicInfo.getUpdateTime());
|
||||
mediaMap.put("expireTime", basicInfo.getExpireTime());
|
||||
mediaMap.put("classId", basicInfo.getClassId());
|
||||
mediaMap.put("className", basicInfo.getClassName());
|
||||
mediaMap.put("classPath", basicInfo.getClassPath());
|
||||
mediaMap.put("coverUrl", basicInfo.getCoverUrl());
|
||||
mediaMap.put("type", basicInfo.getType());
|
||||
mediaMap.put("mediaUrl", basicInfo.getMediaUrl());
|
||||
mediaMap.put("status", basicInfo.getStatus());
|
||||
mediaMap.put("storageRegion", basicInfo.getStorageRegion());
|
||||
mediaMap.put("category", basicInfo.getCategory());
|
||||
mediaMap.put("storageClass", basicInfo.getStorageClass());
|
||||
mediaMap.put("tagSet", basicInfo.getTagSet());
|
||||
|
||||
// 获取视频统计信息
|
||||
Map<String, Object> statistics = vlogService.getVlogStatistics(mediaInfo.getFileId());
|
||||
mediaMap.putAll(statistics);
|
||||
|
||||
// 从statistics中获取vlogId,用于Redis查询
|
||||
String vlogId = (String) statistics.get("vlogId");
|
||||
log.info("处理视频 fileId: {}, vlogId: {}", mediaInfo.getFileId(), vlogId);
|
||||
|
||||
// 使用批量获取的数据,避免重复查询Redis
|
||||
int videoLikeCounts = 0;
|
||||
int videoCommentCounts = 0;
|
||||
if (StringUtils.isNotBlank(vlogId)) {
|
||||
videoLikeCounts = vlogLikeCounts.getOrDefault(vlogId, 0);
|
||||
videoCommentCounts = vlogCommentCounts.getOrDefault(vlogId, 0);
|
||||
}
|
||||
mediaMap.put("likeCounts", videoLikeCounts);
|
||||
mediaMap.put("commentCounts", videoCommentCounts);
|
||||
|
||||
// 获取视频上传者信息
|
||||
Map<String, String> uploaderInfo = vlogService.getVlogUploaderInfo(mediaInfo.getFileId());
|
||||
if (uploaderInfo != null) {
|
||||
mediaMap.put("nickname", uploaderInfo.get("name"));
|
||||
mediaMap.put("mobile", uploaderInfo.get("phone"));
|
||||
}
|
||||
|
||||
mediaList.add(mediaMap);
|
||||
}
|
||||
}
|
||||
result.put("records", mediaList);
|
||||
|
||||
// 构建Page对象
|
||||
Page<Map<String, Object>> page = new Page<>();
|
||||
page.setCurrent(vlogBO.getCurrent());
|
||||
page.setSize(vlogBO.getSize());
|
||||
page.setTotal(resp.getTotalCount());
|
||||
page.setRecords(mediaList);
|
||||
|
||||
return R.ok(page);
|
||||
} catch (Exception e) {
|
||||
log.error("获取视频列表失败", e);
|
||||
return R.fail("获取视频列表失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频审核接口
|
||||
*/
|
||||
|
@ -4,13 +4,14 @@ package com.wzj.soopin.content.domain.base;
|
||||
|
||||
import com.wzj.soopin.content.utils.PagedGridResult;
|
||||
import com.wzj.soopin.content.utils.RedisOperator;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BaseInfoProperties {
|
||||
|
||||
public RedisOperator redis;
|
||||
public RedisCache redis;
|
||||
|
||||
public static final Integer COMMON_START_PAGE = 1;
|
||||
public static final Integer COMMON_START_PAGE_ZERO = 0;
|
||||
|
@ -12,6 +12,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.core.domain.BaseBO;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ -64,6 +65,12 @@ public class VlogBO extends BaseBO {
|
||||
@ApiModelProperty("创建时间范围-结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
private List<String> blockVd;
|
||||
|
||||
private List<String> blockUser;
|
||||
|
||||
private List<String> ids;
|
||||
|
||||
@Override
|
||||
public LambdaQueryWrapper<Vlog> toWrapper() {
|
||||
LambdaQueryWrapper<Vlog> wrapper = new LambdaQueryWrapper<>();
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.wzj.soopin.content.event;
|
||||
|
||||
import com.wzj.soopin.content.service.IVlogPushService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.mq.domain.VlogPushEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class VlogPushEventListener {
|
||||
private final IVlogPushService vlogPushService;
|
||||
@EventListener
|
||||
public void handleNeedPushVlogEvent(VlogPushEvent event) {
|
||||
log.info("收到需要推送的视频事件,用户ID:{}", event.getUserIdStr());
|
||||
vlogPushService.pushVlogToMq(100, event.getTag());
|
||||
}
|
||||
}
|
@ -168,4 +168,8 @@ public interface VlogMapper extends BaseMapper<Vlog> {
|
||||
"ORDER BY RAND() " +
|
||||
"LIMIT #{limit}")
|
||||
List<Map<String, Object>> selectRandomVlogs(@Param("limit") int limit);
|
||||
|
||||
|
||||
IPage<String> getVlogForUser(Page<IndexVlogVO> page, @Param("memberId") Long memberId);
|
||||
int readVlog(@Param("memberId") Long memberId, @Param("vlogId") String vlogId);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.wzj.soopin.content.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.wzj.soopin.content.domain.bo.VlogBO;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.domain.vo.VlogerVO;
|
||||
@ -16,9 +17,9 @@ import java.util.Map;
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
public interface VlogMapperCustom extends BaseMapperPlus<Vlog, VlogerVO> {
|
||||
|
||||
List<IndexVlogVO> getIndexVlogList(@Param("paramMap") Map<String, Object> map);
|
||||
List<IndexVlogVO> getIndexVlogList(@Param("bo") VlogBO bo);
|
||||
|
||||
Page<IndexVlogVO> getIndexVlogList(@Param("paramMap") Map<String, Object> map, Page<IndexVlogVO> page);
|
||||
Page<IndexVlogVO> getIndexVlogList(@Param("bo") VlogBO bo, Page<IndexVlogVO> page);
|
||||
|
||||
List<IndexVlogVO> getVlogDetailById(@Param("paramMap") Map<String, Object> map);
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.wzj.soopin.content.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.tencentcloudapi.vod.v20180717.models.SearchMediaRequest;
|
||||
import com.tencentcloudapi.vod.v20180717.models.SearchMediaResponse;
|
||||
import com.wzj.soopin.content.domain.bo.VlogBO;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
|
||||
public interface IVlogPullService {
|
||||
|
||||
/**
|
||||
* 从视频库中拉取视频
|
||||
*/
|
||||
Page<IndexVlogVO> page(Page<IndexVlogVO> page);
|
||||
|
||||
|
||||
void pullVlog(VlogBO vlogBO);
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.wzj.soopin.content.service;
|
||||
|
||||
/**
|
||||
* 视频推送服务
|
||||
* @author wqx
|
||||
* @date 2023-12-20
|
||||
*/
|
||||
public interface IVlogPushService {
|
||||
boolean cacheTopLikedVlogs(int limit) ;
|
||||
|
||||
boolean pushVlogToMq(int count,String tag);
|
||||
}
|
@ -2,6 +2,7 @@ package com.wzj.soopin.content.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.wzj.soopin.content.domain.bo.*;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
@ -10,7 +11,7 @@ import com.wzj.soopin.content.utils.PagedGridResult;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface VlogService {
|
||||
public interface VlogService extends IService<Vlog> {
|
||||
/**
|
||||
* 修改视频首帧图
|
||||
*/
|
||||
@ -115,10 +116,6 @@ public interface VlogService {
|
||||
*/
|
||||
List<Map<String, Object>> getLikedUsers(String vlogId);
|
||||
|
||||
/**
|
||||
* 获取视频点赞数
|
||||
*/
|
||||
int getLikeCounts(String vlogId);
|
||||
|
||||
/**
|
||||
* 获取视频上传者信息
|
||||
@ -135,11 +132,6 @@ public interface VlogService {
|
||||
*/
|
||||
IPage<Map<String, Object>> getVlogListByMobile(Page<Map<String, Object>> page, VlogBO vlogBO);
|
||||
|
||||
/**
|
||||
* 查询点赞最多的视频列表并存储到Redis
|
||||
* @param limit 查询数量限制
|
||||
*/
|
||||
void cacheTopLikedVlogs(int limit);
|
||||
|
||||
/**
|
||||
* 随机查询视频列表
|
||||
@ -148,8 +140,15 @@ public interface VlogService {
|
||||
*/
|
||||
List<Map<String, Object>> getRandomVlogs(int limit);
|
||||
|
||||
IPage<String> getVlogForUser(Page<IndexVlogVO> page, Long memberId);
|
||||
int readVlog(Long memberId, String vlogId);
|
||||
|
||||
List<IndexVlogVO> getIndexVlogList(VlogBO bo);
|
||||
Page<IndexVlogVO> getIndexVlogList(VlogBO bo,Page page);
|
||||
|
||||
/**
|
||||
* 首页搜索/搜索的vlog列表
|
||||
*/
|
||||
Page<IndexVlogVO> getIndexSearchVlogList(SearchBO bo, Page page);
|
||||
|
||||
}
|
||||
|
@ -26,13 +26,6 @@ public interface VlogUploadService {
|
||||
// */
|
||||
// Map<String, Object> getTaskStatus(String taskId) throws Exception;
|
||||
|
||||
/**
|
||||
* 搜索媒体文件
|
||||
*
|
||||
* @param req 搜索请求
|
||||
* @return 搜索响应
|
||||
*/
|
||||
SearchMediaResponse searchMedia(SearchMediaRequest req);
|
||||
|
||||
// 新增:视频审核
|
||||
void auditVlog(String vlogId, Integer status, String reason);
|
||||
|
@ -80,7 +80,7 @@ public class MsgServiceImpl extends BaseInfoProperties implements MsgService {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
String relationship = redis.get(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + msg.getToUserId() + ":" + msg.getFromUserId());
|
||||
String relationship = redis.getCacheObject(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + msg.getToUserId() + ":" + msg.getFromUserId());
|
||||
if (StringUtils.isNotBlank(relationship) && relationship.equalsIgnoreCase("1")) {
|
||||
map.put("isFriend", true);
|
||||
} else {
|
||||
|
@ -0,0 +1,393 @@
|
||||
package com.wzj.soopin.content.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||
import com.tencentcloudapi.vod.v20180717.VodClient;
|
||||
import com.tencentcloudapi.vod.v20180717.models.*;
|
||||
import com.wzj.soopin.content.domain.bo.VlogBO;
|
||||
import com.wzj.soopin.content.service.IVlogPullService;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.content.utils.TencentCloudUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.rocketmq.common.message.MessageExt;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.domain.model.LoginUser;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.mq.domain.MQMessage;
|
||||
import org.dromara.common.mq.domain.VlogPushEvent;
|
||||
import org.dromara.common.mq.utils.UserRocketMQConsumerManager;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_USER_LIKE_VLOG;
|
||||
import static com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_COMMENT_COUNTS;
|
||||
import static org.dromara.common.core.constant.GlobalConstants.HOT_VLOG_TAG;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class VlogPullServiceImpl implements IVlogPullService {
|
||||
|
||||
private final UserRocketMQConsumerManager mqConsumerManager;
|
||||
private final VlogService vlogService;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final TencentCloudUtil tencentCloudUtil;
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> page(Page<IndexVlogVO> page) {
|
||||
|
||||
List<MessageExt> messageExts = new ArrayList<>();
|
||||
|
||||
try {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
messageExts = mqConsumerManager.pullUserMessages(HOT_VLOG_TAG, (int) page.getSize());
|
||||
} else {
|
||||
messageExts = mqConsumerManager.pullUserMessages(loginUser.getUserId() + "", (int) page.getSize());
|
||||
|
||||
}
|
||||
List<String> ids = messageExts.stream().map(messageExt -> {
|
||||
MQMessage mqMessage = JsonUtils.parseObject(messageExt.getBody(), MQMessage.class);
|
||||
return mqMessage.getData().toString();
|
||||
}).collect(Collectors.toList());
|
||||
VlogBO vlogBO = new VlogBO();
|
||||
if (ids.size() > 0) {
|
||||
|
||||
vlogBO.setIds(ids);
|
||||
List<IndexVlogVO> vlogVOList = vlogService.getIndexVlogList(vlogBO);
|
||||
return page.setRecords(vlogVOList);
|
||||
} else {
|
||||
if (loginUser != null) {
|
||||
eventPublisher.publishEvent(new VlogPushEvent(loginUser.getUserId() + ""));
|
||||
|
||||
} else {
|
||||
eventPublisher.publishEvent(new VlogPushEvent(HOT_VLOG_TAG));
|
||||
}
|
||||
//发出事件
|
||||
//先临时取10条数据
|
||||
Page<IndexVlogVO> indexVlogVOPage = vlogService.getIndexVlogList(vlogBO, page);
|
||||
//直接获取数据库数据,并要求push类推送数据
|
||||
return indexVlogVOPage;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("拉取视频失败", e);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pullVlog(VlogBO vlogBO) {
|
||||
try {
|
||||
// 验证分页参数
|
||||
if (vlogBO.getCurrent() < 1) {
|
||||
vlogBO.setCurrent(1L);
|
||||
}
|
||||
if (vlogBO.getSize() < 1 || vlogBO.getSize() > 50) {
|
||||
vlogBO.setSize(10L);
|
||||
}
|
||||
|
||||
// 如果有模糊查询条件、时间区间条件,或者有排序条件,则只查询数据库
|
||||
if (StringUtils.isNotBlank(vlogBO.getMobile())
|
||||
|| StringUtils.isNotBlank(vlogBO.getNickname())
|
||||
|| StringUtils.isNotBlank(vlogBO.getTitleQuery())
|
||||
|| vlogBO.getStartTime() != null
|
||||
|| vlogBO.getEndTime() != null
|
||||
|| vlogBO.getStatus() != null
|
||||
|| StringUtils.isNotBlank(vlogBO.getColumn())) {
|
||||
|
||||
// 创建分页对象
|
||||
Page<Map<String, Object>> page = new Page<>(vlogBO.getCurrent(), vlogBO.getSize());
|
||||
|
||||
// 调用服务层方法进行查询
|
||||
IPage<Map<String, Object>> result = vlogService.getVlogListByMobile(page, vlogBO);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 否则查询腾讯云点播
|
||||
// 验证密钥配置
|
||||
String secretId = tencentCloudUtil.getSecretId();
|
||||
String secretKey = tencentCloudUtil.getSecretKey();
|
||||
if (secretId == null || secretId.isEmpty() || secretKey == null || secretKey.isEmpty()) {
|
||||
log.error("腾讯云密钥未配置");
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算实际的offset
|
||||
long offset = (long) ((vlogBO.getCurrent() - 1) * vlogBO.getSize());
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
// 打印分页参数
|
||||
log.info("分页参数 - 当前页码: {}, 每页记录数: {}, 偏移量: {}", vlogBO.getCurrent(), vlogBO.getSize(), offset);
|
||||
|
||||
// 创建请求对象
|
||||
SearchMediaRequest req = new SearchMediaRequest();
|
||||
|
||||
// 设置分页参数
|
||||
req.setOffset(offset);
|
||||
req.setLimit(vlogBO.getSize());
|
||||
|
||||
// 设置排序
|
||||
SortBy sort = new SortBy();
|
||||
sort.setField("CreateTime");
|
||||
sort.setOrder("Desc");
|
||||
req.setSort(sort);
|
||||
|
||||
// 调用腾讯云API获取视频列表
|
||||
log.info("开始调用腾讯云 SearchMedia API");
|
||||
SearchMediaResponse resp = searchMedia(req);
|
||||
log.info("腾讯云 SearchMedia API 调用成功,总记录数: {}", resp.getTotalCount());
|
||||
|
||||
// 处理响应结果
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("total", resp.getTotalCount());
|
||||
result.put("current", vlogBO.getCurrent());
|
||||
result.put("size", vlogBO.getSize());
|
||||
result.put("pages", (resp.getTotalCount() + vlogBO.getSize() - 1) / vlogBO.getSize()); // 总页数
|
||||
|
||||
// 批量获取所有视频的统计信息,避免重复查询
|
||||
Map<String, String> fileIdToVlogIdMap = new HashMap<>();
|
||||
List<String> allVlogIds = new ArrayList<>();
|
||||
|
||||
if (resp.getMediaInfoSet() != null) {
|
||||
for (MediaInfo mediaInfo : resp.getMediaInfoSet()) {
|
||||
String fileId = mediaInfo.getFileId();
|
||||
Map<String, Object> statistics = vlogService.getVlogStatistics(fileId);
|
||||
String vlogId = (String) statistics.get("vlogId");
|
||||
if (StringUtils.isNotBlank(vlogId)) {
|
||||
fileIdToVlogIdMap.put(fileId, vlogId);
|
||||
allVlogIds.add(vlogId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取所有点赞数据
|
||||
Map<String, Integer> vlogLikeCounts = new HashMap<>();
|
||||
Map<String, Integer> vlogCommentCounts = new HashMap<>();
|
||||
long totalLikeCounts = 0;
|
||||
long totalCommentCounts = 0;
|
||||
|
||||
if (!allVlogIds.isEmpty()) {
|
||||
// 批量获取所有点赞键
|
||||
String likePattern = REDIS_USER_LIKE_VLOG + ":*";
|
||||
Collection<String> allLikeKeys = RedisUtils.keys(likePattern);
|
||||
|
||||
if (allLikeKeys != null && !allLikeKeys.isEmpty()) {
|
||||
// 逐个获取点赞值(由于RedisUtils没有批量方法)
|
||||
Map<String, String> likeKeyValueMap = new HashMap<>();
|
||||
for (String likeKey : allLikeKeys) {
|
||||
String likeValue = RedisUtils.getCacheObject(likeKey);
|
||||
if ("1".equals(likeValue)) {
|
||||
likeKeyValueMap.put(likeKey, likeValue);
|
||||
}
|
||||
}
|
||||
|
||||
// 按vlogId分组统计点赞数
|
||||
for (String vlogId : allVlogIds) {
|
||||
int likeCount = 0;
|
||||
for (String likeKey : likeKeyValueMap.keySet()) {
|
||||
if (likeKey.endsWith(":" + vlogId)) {
|
||||
likeCount++;
|
||||
}
|
||||
}
|
||||
vlogLikeCounts.put(vlogId, likeCount);
|
||||
totalLikeCounts += likeCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取所有评论数
|
||||
for (String vlogId : allVlogIds) {
|
||||
String commentKey = REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId;
|
||||
String commentCountsStr = RedisUtils.getCacheObject(commentKey);
|
||||
int commentCount = 0;
|
||||
if (StringUtils.isNotBlank(commentCountsStr)) {
|
||||
try {
|
||||
commentCount = Integer.valueOf(commentCountsStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的评论数格式错误: {}", vlogId, commentCountsStr);
|
||||
}
|
||||
}
|
||||
vlogCommentCounts.put(vlogId, commentCount);
|
||||
totalCommentCounts += commentCount;
|
||||
}
|
||||
}
|
||||
|
||||
// 将总的点赞数和评论数添加到结果中
|
||||
result.put("totalLikeCounts", totalLikeCounts);
|
||||
result.put("totalCommentCounts", totalCommentCounts);
|
||||
|
||||
List<Map<String, Object>> mediaList = new ArrayList<>();
|
||||
if (resp.getMediaInfoSet() != null) {
|
||||
for (MediaInfo mediaInfo : resp.getMediaInfoSet()) {
|
||||
Map<String, Object> mediaMap = new HashMap<>();
|
||||
// 基础信息
|
||||
MediaBasicInfo basicInfo = mediaInfo.getBasicInfo();
|
||||
mediaMap.put("fileId", mediaInfo.getFileId());
|
||||
mediaMap.put("name", basicInfo.getName());
|
||||
mediaMap.put("description", basicInfo.getDescription());
|
||||
mediaMap.put("createTime", basicInfo.getCreateTime());
|
||||
mediaMap.put("updateTime", basicInfo.getUpdateTime());
|
||||
mediaMap.put("expireTime", basicInfo.getExpireTime());
|
||||
mediaMap.put("classId", basicInfo.getClassId());
|
||||
mediaMap.put("className", basicInfo.getClassName());
|
||||
mediaMap.put("classPath", basicInfo.getClassPath());
|
||||
mediaMap.put("coverUrl", basicInfo.getCoverUrl());
|
||||
mediaMap.put("type", basicInfo.getType());
|
||||
mediaMap.put("mediaUrl", basicInfo.getMediaUrl());
|
||||
mediaMap.put("status", basicInfo.getStatus());
|
||||
mediaMap.put("storageRegion", basicInfo.getStorageRegion());
|
||||
mediaMap.put("category", basicInfo.getCategory());
|
||||
mediaMap.put("storageClass", basicInfo.getStorageClass());
|
||||
mediaMap.put("tagSet", basicInfo.getTagSet());
|
||||
|
||||
// 获取视频统计信息
|
||||
Map<String, Object> statistics = vlogService.getVlogStatistics(mediaInfo.getFileId());
|
||||
mediaMap.putAll(statistics);
|
||||
|
||||
// 从statistics中获取vlogId,用于Redis查询
|
||||
String vlogId = (String) statistics.get("vlogId");
|
||||
log.info("处理视频 fileId: {}, vlogId: {}", mediaInfo.getFileId(), vlogId);
|
||||
|
||||
// 使用批量获取的数据,避免重复查询Redis
|
||||
int videoLikeCounts = 0;
|
||||
int videoCommentCounts = 0;
|
||||
if (StringUtils.isNotBlank(vlogId)) {
|
||||
videoLikeCounts = vlogLikeCounts.getOrDefault(vlogId, 0);
|
||||
videoCommentCounts = vlogCommentCounts.getOrDefault(vlogId, 0);
|
||||
}
|
||||
mediaMap.put("likeCounts", videoLikeCounts);
|
||||
mediaMap.put("commentCounts", videoCommentCounts);
|
||||
|
||||
// 获取视频上传者信息
|
||||
Map<String, String> uploaderInfo = vlogService.getVlogUploaderInfo(mediaInfo.getFileId());
|
||||
if (uploaderInfo != null) {
|
||||
mediaMap.put("nickname", uploaderInfo.get("name"));
|
||||
mediaMap.put("mobile", uploaderInfo.get("phone"));
|
||||
}
|
||||
|
||||
mediaList.add(mediaMap);
|
||||
}
|
||||
}
|
||||
result.put("records", mediaList);
|
||||
}catch (Exception e){
|
||||
log.error("拉取视频失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public SearchMediaResponse searchMedia(SearchMediaRequest req) {
|
||||
try {
|
||||
// 获取VOD客户端实例
|
||||
VodClient client = tencentCloudUtil.getVodClient();
|
||||
|
||||
// 设置默认值
|
||||
if (req.getOffset() == null) {
|
||||
req.setOffset(0L);
|
||||
}
|
||||
if (req.getLimit() == null) {
|
||||
req.setLimit(10L);
|
||||
}
|
||||
|
||||
// 添加日志,打印请求参数
|
||||
// log.info("SearchMediaRequest 请求参数: {}", req.toJsonString());
|
||||
|
||||
// 添加调试信息
|
||||
log.info("请求时间戳: {}", System.currentTimeMillis());
|
||||
log.info("请求参数详情 - Offset: {}, Limit: {}, Sort: {}, Filters: {}",
|
||||
req.getOffset(),
|
||||
req.getLimit(),
|
||||
// req.getSort() != null ? req.getSort().toJsonString() : "null",
|
||||
req.getFilters() != null ? String.join(",", req.getFilters()) : "null");
|
||||
|
||||
// 验证请求参数
|
||||
validateSearchRequest(req);
|
||||
|
||||
SearchMediaResponse response = client.SearchMedia(req);
|
||||
log.info("SearchMedia API 调用成功,返回结果数: {}", response.getTotalCount());
|
||||
return response;
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("搜索媒体文件失败: {}", e.getMessage(), e);
|
||||
// 添加更详细的错误信息
|
||||
if (e.getMessage().contains("signature")) {
|
||||
log.error("签名验证失败,请检查:\n1. 密钥是否正确\n2. 服务器时间是否准确\n3. 时区设置是否正确");
|
||||
} else if (e.getMessage().contains("InvalidParameterValue")) {
|
||||
log.error("参数值错误,请检查:\n1. 分页参数 Offset 和 Limit 是否有效\n2. 搜索条件是否合法\n3. 排序参数是否正确");
|
||||
} else if (e.getMessage().contains("UnauthorizedOperation")) {
|
||||
log.error("未授权操作,请检查:\n1. 密钥是否有权限\n2. 应用 ID 是否正确\n3. 是否开通了点播服务");
|
||||
}
|
||||
throw new RuntimeException("搜索媒体文件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 验证搜索请求参数
|
||||
*/
|
||||
private void validateSearchRequest(SearchMediaRequest req) {
|
||||
// 验证分页参数
|
||||
if (req.getOffset() < 0) {
|
||||
throw new IllegalArgumentException("Offset 不能小于 0");
|
||||
}
|
||||
if (req.getLimit() < 1 || req.getLimit() > 50) {
|
||||
throw new IllegalArgumentException("Limit 必须在 1-50 之间");
|
||||
}
|
||||
if (req.getOffset() + req.getLimit() > 5000) {
|
||||
throw new IllegalArgumentException("Offset + Limit 不能超过 5000");
|
||||
}
|
||||
|
||||
// 验证搜索条件
|
||||
if (req.getFileIds() != null && req.getFileIds().length > 10) {
|
||||
throw new IllegalArgumentException("FileIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getNames() != null && req.getNames().length > 10) {
|
||||
throw new IllegalArgumentException("Names 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getNamePrefixes() != null && req.getNamePrefixes().length > 10) {
|
||||
throw new IllegalArgumentException("NamePrefixes 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getDescriptions() != null && req.getDescriptions().length > 10) {
|
||||
throw new IllegalArgumentException("Descriptions 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getClassIds() != null && req.getClassIds().length > 10) {
|
||||
throw new IllegalArgumentException("ClassIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getTags() != null && req.getTags().length > 16) {
|
||||
throw new IllegalArgumentException("Tags 数组长度不能超过 16");
|
||||
}
|
||||
if (req.getSourceTypes() != null && req.getSourceTypes().length > 10) {
|
||||
throw new IllegalArgumentException("SourceTypes 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getStreamIds() != null && req.getStreamIds().length > 10) {
|
||||
throw new IllegalArgumentException("StreamIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getStorageRegions() != null && req.getStorageRegions().length > 20) {
|
||||
throw new IllegalArgumentException("StorageRegions 数组长度不能超过 20");
|
||||
}
|
||||
// if (req.getMediaTypes() != null && req.getMediaTypes().length > 10) {
|
||||
// throw new IllegalArgumentException("MediaTypes 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getStatus() != null && req.getStatus().length > 10) {
|
||||
// throw new IllegalArgumentException("Status 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getReviewResults() != null && req.getReviewResults().length > 10) {
|
||||
// throw new IllegalArgumentException("ReviewResults 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getTrtcSdkAppIds() != null && req.getTrtcSdkAppIds().length > 10) {
|
||||
// throw new IllegalArgumentException("TrtcSdkAppIds 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getTrtcRoomIds() != null && req.getTrtcRoomIds().length > 10) {
|
||||
// throw new IllegalArgumentException("TrtcRoomIds 数组长度不能超过 10");
|
||||
// }
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.wzj.soopin.content.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.service.IVlogPushService;
|
||||
import com.wzj.soopin.content.service.VlogService;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.mq.domain.MQMessage;
|
||||
import org.dromara.common.mq.utils.MqUtil;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS;
|
||||
import static org.dromara.common.core.constant.GlobalConstants.HOT_VLOG_TAG;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class VlogPushServiceImpl implements IVlogPushService {
|
||||
|
||||
private final RedisCache redisCache;
|
||||
private final VlogService vlogService;
|
||||
|
||||
private final IMemberService memberService;
|
||||
|
||||
@Override
|
||||
public boolean cacheTopLikedVlogs(int limit ) {
|
||||
try {
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("缓存点赞最多视频到Redis失败", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pushVlogToMq(int count,String tag ) {
|
||||
|
||||
if(tag.equals(HOT_VLOG_TAG)){
|
||||
// 1. 获取 ZSet 中所有成员(按分数升序排列)
|
||||
// 这里我们只关心成员(member),不关心分数(score),所以使用 range(key, start, end)
|
||||
log.info("开始查询点赞最多的{}条视频", count);
|
||||
Set<String> rankSet = redisCache.zSetRange(REDIS_VLOG_BE_LIKED_COUNTS, 0, count);
|
||||
if (rankSet == null ||rankSet.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if(rankSet!=null&&rankSet.size()<count){
|
||||
//从数据库中获取差量数据
|
||||
Page<Vlog> vlogPage = new Page<>(1, count-rankSet.size());
|
||||
vlogPage = vlogService.page(vlogPage, new LambdaQueryWrapper<Vlog>()
|
||||
.orderByDesc(Vlog::getLikeCounts));
|
||||
Set<String> vlogIds = vlogPage.getRecords().stream().map(vlog -> vlog.getId()).collect(Collectors.toSet());
|
||||
rankSet.addAll(vlogIds);
|
||||
}
|
||||
// 3. 将 Set 转换为 List 以便打乱顺序
|
||||
List<String> vlogList = new ArrayList<>(rankSet);
|
||||
|
||||
// 4. 使用 Collections.shuffle 打乱 List 的顺序
|
||||
Collections.shuffle(vlogList);
|
||||
vlogList.stream().forEach(vlogId -> {
|
||||
|
||||
//将数据发送的mq的热点数据队列
|
||||
MQMessage message = MQMessage.builder()
|
||||
.topic("MEMBER_VLOG_MSG")
|
||||
.tag(HOT_VLOG_TAG)
|
||||
.messageType("json")
|
||||
.data(vlogId)
|
||||
.source("vlog_service")
|
||||
.sendTime(LocalDateTime.now())
|
||||
.build();
|
||||
MqUtil.sendMessage("MEMBER_VLOG_MSG",HOT_VLOG_TAG, message);
|
||||
});
|
||||
|
||||
}else{
|
||||
Member member = memberService.getById(tag);
|
||||
String cityCode = member.getCity();
|
||||
IPage<String> vlogPage=vlogService.getVlogForUser(new Page<>(1, 100), Long.parseLong(tag));
|
||||
if(CollectionUtils.isEmpty(vlogPage.getRecords())){
|
||||
return false;
|
||||
}
|
||||
vlogPage.getRecords().stream().forEach(vlogId -> {
|
||||
//将数据发送的mq的热点数据队列
|
||||
MQMessage message = MQMessage.builder()
|
||||
.topic("MEMBER_VLOG_MSG")
|
||||
.tag(tag)
|
||||
.messageType("json")
|
||||
.data(vlogId)
|
||||
.source("vlog_service")
|
||||
.sendTime(LocalDateTime.now())
|
||||
.build();
|
||||
MqUtil.sendMessage("MEMBER_VLOG_MSG"+":"+tag, message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -13,6 +14,7 @@ import com.wzj.soopin.content.domain.bo.*;
|
||||
import com.wzj.soopin.content.domain.po.MyLikedVlog;
|
||||
import com.wzj.soopin.content.domain.po.Vlog;
|
||||
import com.wzj.soopin.content.domain.po.Users;
|
||||
import com.wzj.soopin.content.domain.vo.VlogerVO;
|
||||
import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.content.domain.vo.IndexVlogVO;
|
||||
import com.wzj.soopin.content.enums.YesOrNo;
|
||||
@ -32,12 +34,22 @@ import com.wzj.soopin.content.utils.TencentCloudUtil;
|
||||
import com.wzj.soopin.member.service.IFansService;
|
||||
import com.wzj.soopin.content.convert.VlogConvert;
|
||||
import com.wzj.soopin.member.service.IMemberService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.core.constant.GlobalConstants;
|
||||
import org.dromara.common.core.domain.model.LoginUser;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.mq.domain.MQMessage;
|
||||
import org.dromara.common.mq.enums.MQMessageType;
|
||||
import org.dromara.common.mq.enums.MessageActionEnum;
|
||||
import org.dromara.common.mq.utils.MqUtil;
|
||||
import org.dromara.common.mq.utils.UserRocketMQConsumerManager;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
@ -49,36 +61,27 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.wzj.soopin.content.domain.base.BaseInfoProperties.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
@AllArgsConstructor
|
||||
public class VlogServiceImpl extends ServiceImpl<VlogMapper, Vlog> implements VlogService {
|
||||
|
||||
private final VlogMapper vlogMapper;
|
||||
private final VlogMapperCustom vlogMapperCustom;
|
||||
private final MyLikedVlogMapper myLikedVlogMapper;
|
||||
private final IFansService fansService;
|
||||
private final MsgService msgService;
|
||||
private final Sid sid;
|
||||
private final CommentMapper commentMapper;
|
||||
private final MemberMapper memberMapper;
|
||||
private final RedisCache cache;
|
||||
private final RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private VlogMapper vlogMapper;
|
||||
@Autowired
|
||||
private VlogMapperCustom vlogMapperCustom;
|
||||
@Autowired
|
||||
private MyLikedVlogMapper myLikedVlogMapper;
|
||||
@Autowired
|
||||
private IFansService fansService;
|
||||
@Autowired
|
||||
private MsgService msgService;
|
||||
@Autowired
|
||||
private Sid sid;
|
||||
@Autowired
|
||||
private CommentMapper commentMapper;
|
||||
@Autowired
|
||||
private RedisOperator redis;
|
||||
@Autowired
|
||||
private TencentCloudUtil tencentCloudUtil;
|
||||
@Autowired
|
||||
private UsersMapper usersMapper;
|
||||
@Autowired
|
||||
private MemberMapper memberMapper;
|
||||
@Autowired
|
||||
private IMemberService memberService;
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateVlogStatus(String fileId, Integer status, String reason) {
|
||||
@ -138,157 +141,40 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
vlogMapper.insert(vlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getIndexVlogList(IndexListBO bo, Page page) {
|
||||
String userId = bo.getMemberId();
|
||||
String search = bo.getSearch();
|
||||
String cityCode = bo.getCityCode();
|
||||
String status = bo.getStatus();
|
||||
int current = (int) page.getCurrent();
|
||||
int size = (int) page.getSize();
|
||||
Page<Vlog> pageParam = new Page<>(current, size);
|
||||
LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.isNotBlank(search)) {
|
||||
queryWrapper.like(Vlog::getTitle, search);
|
||||
}
|
||||
if (StringUtils.isNotBlank(cityCode)) {
|
||||
queryWrapper.eq(Vlog::getCityCode, cityCode);
|
||||
}
|
||||
if (StringUtils.isNotBlank(status)) {
|
||||
queryWrapper.eq(Vlog::getStatus, status);
|
||||
}
|
||||
// 去掉黑名单的视频
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_VIDEO_BLOCK + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
List<String> blockVdList = new ArrayList<>();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> reports = redis.lrange(redisKey, 0, -1);
|
||||
for (String report : reports) {
|
||||
try {
|
||||
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
|
||||
String vlogId = (String) reportMap.get("vlogId");
|
||||
blockVdList.add(vlogId);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!blockVdList.isEmpty()) {
|
||||
queryWrapper.notIn(Vlog::getId, blockVdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 去掉黑名单的用户
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_USER_BLOCK + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
List<String> blockUserList = new ArrayList<>();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> reports = redis.lrange(redisKey, 0, -1);
|
||||
for (String report : reports) {
|
||||
try {
|
||||
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
|
||||
String memberId = (String) reportMap.get("MemberId");
|
||||
blockUserList.add(memberId);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
if (!blockUserList.isEmpty()) {
|
||||
queryWrapper.notIn(Vlog::getMemberId, blockUserList);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 去掉已读的视频
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
String redisKey = REDIS_USER_READ_VLOG + ":" + userId;
|
||||
if (redis.keyIsExist(redisKey)) {
|
||||
List<String> readVlogList = new ArrayList<>();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> reports = redis.lrange(redisKey, 0, -1);
|
||||
for (String report : reports) {
|
||||
try {
|
||||
Map<String, Object> reportMap = objectMapper.readValue(report, new TypeReference<Map<String, Object>>() {});
|
||||
String memberId = (String) reportMap.get("MemberId");
|
||||
readVlogList.add(memberId);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
if (!readVlogList.isEmpty()) {
|
||||
queryWrapper.notIn(Vlog::getMemberId, readVlogList);
|
||||
}
|
||||
}
|
||||
}
|
||||
Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
|
||||
List<Vlog> vlogList = vlogPage.getRecords();
|
||||
List<IndexVlogVO> voList = vlogList.stream().map(v -> {
|
||||
IndexVlogVO vo = MapstructUtils.convert(v, IndexVlogVO.class);
|
||||
if (StringUtils.isNotBlank(userId)) {
|
||||
vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(userId, v.getMemberId()));
|
||||
vo.setDoILikeThisVlog(doILikeVlog(userId, v.getId()));
|
||||
}
|
||||
vo.setLikeCounts(getVlogBeLikedCounts(v.getId()));
|
||||
vo.setCommentsCounts(getVlogComment(v.getId()));
|
||||
MemberVO m =memberService.getMemberInfo(vo.getMemberId());
|
||||
if (m != null) {
|
||||
vo.setAvatar(m.getAvatar());
|
||||
vo.setNickname(m.getNickname());
|
||||
}
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
|
||||
// 封装分页结果
|
||||
Page<IndexVlogVO> gridResult = new Page<IndexVlogVO>();
|
||||
gridResult.setRecords(voList); // 当前页数据列表
|
||||
gridResult.setCurrent(current); // 当前页码
|
||||
gridResult.setTotal(vlogPage.getTotal()); // 总记录数
|
||||
gridResult.setSize(vlogPage.getPages()); // 总页数
|
||||
|
||||
|
||||
return gridResult;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getVlogBeLikedCounts(String vlogId) {
|
||||
String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
|
||||
if (StringUtils.isBlank(countsStr)) {
|
||||
countsStr = "0";
|
||||
}
|
||||
return Integer.valueOf(countsStr);
|
||||
Double count = cache.zSetScore(REDIS_VLOG_BE_LIKED_COUNTS, vlogId);
|
||||
|
||||
return count==null?0:count.intValue();
|
||||
}
|
||||
|
||||
private Integer getVlogComment(String vlogId) {
|
||||
String countsStr = redis.get(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
|
||||
if (StringUtils.isBlank(countsStr)) {
|
||||
countsStr = "0";
|
||||
}
|
||||
return Integer.valueOf(countsStr);
|
||||
Double count = cache.zSetScore(REDIS_VLOG_COMMENT_COUNTS, vlogId);
|
||||
return count==null?0:count.intValue();
|
||||
}
|
||||
|
||||
private boolean doILikeVlog(String myId, String vlogId) {
|
||||
String doILike = redis.get(REDIS_USER_LIKE_VLOG + ":" + myId + ":" + vlogId);
|
||||
private boolean doILikeVlog(String myId, String vlogId) {
|
||||
String doILike = cache.getCacheObject(REDIS_USER_LIKE_VLOG + ":" + myId + ":" + vlogId);
|
||||
return StringUtils.isNotBlank(doILike) && doILike.equalsIgnoreCase("1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexVlogVO getVlogDetailById( String vlogId) {
|
||||
@Cacheable(cacheNames = GlobalConstants.VLOG_KEY, key = "#vlogId")
|
||||
public IndexVlogVO getVlogDetailById(String vlogId) {
|
||||
Vlog vlog = vlogMapper.selectById(vlogId);
|
||||
if (vlog == null) {
|
||||
return null;
|
||||
}
|
||||
IndexVlogVO vo = MapstructUtils.convert(vlog, IndexVlogVO.class);
|
||||
//获取用户信息
|
||||
try{
|
||||
try {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
if (loginUser != null) {
|
||||
vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(loginUser.getUserId()+"", vlog.getMemberId()));
|
||||
vo.setDoILikeThisVlog(doILikeVlog(loginUser.getUserId()+"", vlogId));
|
||||
vo.setDoIFollowVloger(fansService.queryDoIFollowVloger(loginUser.getUserId() + "", vlog.getMemberId()));
|
||||
vo.setDoILikeThisVlog(doILikeVlog(loginUser.getUserId() + "", vlogId));
|
||||
}
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
@ -307,6 +193,8 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
|
||||
@CacheEvict(value = GlobalConstants.VLOG_KEY, key = "#vlogId")
|
||||
public void changeToPrivateOrPublic(String userId, String vlogId, Integer yesOrNo) {
|
||||
LambdaUpdateWrapper<Vlog> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(Vlog::getId, vlogId)
|
||||
@ -317,6 +205,7 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
@CacheEvict(value = GlobalConstants.VLOG_KEY, key = "#vlogId")
|
||||
public void changeVlogStatus(String userId, String vlogId, Integer status) {
|
||||
LambdaUpdateWrapper<Vlog> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(Vlog::getId, vlogId)
|
||||
@ -332,17 +221,17 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
Page<Vlog> pageParam = new Page<>(current, size);
|
||||
LambdaQueryWrapper<Vlog> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
if(bo.getUserId()==null){
|
||||
LoginUser user= LoginHelper.getLoginUser();
|
||||
if(user==null){
|
||||
if (bo.getUserId() == null) {
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
if (user == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
queryWrapper.eq(Vlog::getMemberId, user.getUserId());
|
||||
}else{
|
||||
} else {
|
||||
queryWrapper.eq(Vlog::getMemberId, bo.getUserId());
|
||||
|
||||
}
|
||||
queryWrapper.eq(bo.getPrivateFlag()!=null,Vlog::getIsPrivate, bo.getPrivateFlag());
|
||||
queryWrapper.eq(bo.getPrivateFlag() != null, Vlog::getIsPrivate, bo.getPrivateFlag());
|
||||
Page<Vlog> vlogPage = vlogMapper.selectPage(pageParam, queryWrapper);
|
||||
List<Vlog> vlogList = vlogPage.getRecords();
|
||||
|
||||
@ -380,7 +269,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
@CacheEvict(value = GlobalConstants.VLOG_KEY, key = "#vlogId")
|
||||
public void userLikeVlog(String userId, String vlogId) {
|
||||
//获取vlog
|
||||
Vlog vlog = this.getVlog(vlogId);
|
||||
if (vlog == null) {
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
// 我点赞的视频,关联关系保存到数据库
|
||||
|
||||
String rid = sid.nextShort();
|
||||
MyLikedVlog likedVlog = new MyLikedVlog();
|
||||
likedVlog.setId(rid);
|
||||
@ -388,36 +285,32 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
likedVlog.setUserId(userId);
|
||||
myLikedVlogMapper.insert(likedVlog);
|
||||
|
||||
// 我喜欢的视频总数累加
|
||||
redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + userId, 1);
|
||||
// 视频被喜欢的总数累加
|
||||
redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
// 保存用户和视频的喜欢关系
|
||||
redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");
|
||||
// 点赞后,视频和视频发布者的获赞都会 +1
|
||||
cache.zSetIncrement(REDIS_VLOGER_BE_LIKED_COUNTS, vlog.getMemberId(), 1);
|
||||
cache.zSetIncrement(REDIS_VLOG_BE_LIKED_COUNTS, vlogId, 1);
|
||||
|
||||
// 发送点赞通知
|
||||
Vlog vlog = vlogMapper.selectById(vlogId);
|
||||
if (vlog != null) {
|
||||
String vlogerId = vlog.getMemberId();
|
||||
if (!userId.equals(vlogerId)) {
|
||||
// Long templateId = 1938491299175723009L;
|
||||
// SysMessageTemplateVo template = templateService.selectTemplateById(templateId);
|
||||
// if (template != null) {
|
||||
// // 查询点赞用户昵称
|
||||
// Member liker = memberMapper.selectById(userId);
|
||||
// String likerNickname = liker != null && liker.getNickname() != null ? liker.getNickname() : "";
|
||||
//
|
||||
// String content = template.getTemplateContent()
|
||||
// .replace("${videoTitle}", vlog.getTitle() == null ? "" : vlog.getTitle())
|
||||
// .replace("${liker}", userId)
|
||||
// .replace("${likerNickname}", likerNickname);
|
||||
// SysMessageBo messageBo = new SysMessageBo();
|
||||
// messageBo.setTitle(template.getTitle());
|
||||
// messageBo.setContent(content);
|
||||
// messageBo.setSenderId(Long.valueOf(userId));
|
||||
// sysMessageService.sendMessageToUser(messageBo, Long.valueOf(vlogerId));
|
||||
// }
|
||||
}
|
||||
// 我点赞的视频,需要在redis中保存关联关系
|
||||
cache.setCacheObject(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");
|
||||
Double count = cache.zSetScore(REDIS_VLOG_BE_LIKED_COUNTS, vlogId);
|
||||
if (count > 0) {
|
||||
//更新数据库的点赞数
|
||||
this.flushCounts(vlogId, count.intValue());
|
||||
}
|
||||
//发送消息
|
||||
if (userId != null && vlog.getMemberId() != null && !userId.equals(vlog.getMemberId())) {
|
||||
// 新版:使用模板类型编号和参数
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("userId", userId);
|
||||
params.put("nickname", LoginHelper.getLoginUser().getNickname());
|
||||
params.put("action", MessageActionEnum.INTERACTION_LIKE.name());
|
||||
params.put("toUserId", vlog.getMemberId());
|
||||
MQMessage message = MQMessage.builder()
|
||||
.messageType(MQMessageType.IM.name())
|
||||
.data(params)
|
||||
.source("member")
|
||||
.build();
|
||||
// 关注消息
|
||||
MqUtil.sendIMMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,61 +330,71 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
@CacheEvict(value = GlobalConstants.VLOG_KEY, key = "#vlogId")
|
||||
public void userUnLikeVlog(String userId, String vlogId) {
|
||||
LambdaQueryWrapper<MyLikedVlog> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(MyLikedVlog::getUserId, userId)
|
||||
.eq(MyLikedVlog::getVlogId, vlogId);
|
||||
myLikedVlogMapper.delete(queryWrapper);
|
||||
|
||||
// 我喜欢的视频总数累减
|
||||
redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + userId, 1);
|
||||
// 视频被喜欢的总数累减
|
||||
redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
|
||||
// 删除用户和视频的喜欢关系
|
||||
redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
|
||||
//获取vlog
|
||||
Vlog vlog = this.getVlog(vlogId);
|
||||
if (vlog == null) {
|
||||
throw new ServiceException("视频不存在");
|
||||
}
|
||||
|
||||
// 我取消点赞的视频,关联关系删除
|
||||
this.userUnLikeVlog(userId, vlogId);
|
||||
|
||||
cache.zSetDecrement(REDIS_VLOGER_BE_LIKED_COUNTS, vlog.getMemberId(), 1);
|
||||
cache.zSetDecrement(REDIS_VLOG_BE_LIKED_COUNTS, vlogId, 1);
|
||||
cache.deleteObject(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
|
||||
|
||||
|
||||
Double count = cache.zSetScore(REDIS_VLOG_BE_LIKED_COUNTS, vlogId);
|
||||
if (count > 0) {
|
||||
//更新数据库的点赞数
|
||||
this.flushCounts(vlogId, count.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getMyLikedVlogList( Page page) {
|
||||
public Page<IndexVlogVO> getMyLikedVlogList(Page page) {
|
||||
|
||||
LoginUser user= LoginHelper.getLoginUser();
|
||||
if(user==null){
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
if (user == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("myId", user.getUserId());
|
||||
Page<IndexVlogVO> likedPage = vlogMapperCustom.getMyLikedVlogList(map,page);
|
||||
Page<IndexVlogVO> likedPage = vlogMapperCustom.getMyLikedVlogList(map, page);
|
||||
|
||||
likedPage.getRecords().stream().forEach(
|
||||
liked -> {
|
||||
liked.setDoIFollowVloger(true);
|
||||
liked.setDoILikeThisVlog(true);
|
||||
likedPage.getRecords().stream().forEach(
|
||||
liked -> {
|
||||
liked.setDoIFollowVloger(true);
|
||||
liked.setDoILikeThisVlog(true);
|
||||
});
|
||||
return likedPage;
|
||||
return likedPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getMyFollowVlogList(Page page) {
|
||||
LoginUser user= LoginHelper.getLoginUser();
|
||||
if(user==null){
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
if (user == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("myId", user.getUserId());
|
||||
Page<IndexVlogVO> voPage = vlogMapperCustom.getMyFollowVlogList(map,page);
|
||||
Page<IndexVlogVO> voPage = vlogMapperCustom.getMyFollowVlogList(map, page);
|
||||
|
||||
return voPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getMyFriendVlogList( Page page) {
|
||||
LoginUser user= LoginHelper.getLoginUser();
|
||||
if(user==null){
|
||||
public Page<IndexVlogVO> getMyFriendVlogList(Page page) {
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
if (user == null) {
|
||||
throw new ServiceException("用户未登录");
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("myId", user.getUserId());
|
||||
Page<IndexVlogVO> voPage = vlogMapperCustom.getMyFriendVlogList(map,page);
|
||||
Page<IndexVlogVO> voPage = vlogMapperCustom.getMyFriendVlogList(map, page);
|
||||
|
||||
return voPage;
|
||||
}
|
||||
@ -512,15 +415,15 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
if (vlog != null) {
|
||||
result.put("vlogId", vlog.getId());
|
||||
result.put("title", vlog.getTitle());
|
||||
result.put("width",vlog.getWidth());
|
||||
result.put("height",vlog.getHeight());
|
||||
result.put("reason",vlog.getReason());
|
||||
result.put("width", vlog.getWidth());
|
||||
result.put("height", vlog.getHeight());
|
||||
result.put("reason", vlog.getReason());
|
||||
|
||||
// 注意:点赞数和评论数现在在控制器中直接从Redis获取
|
||||
// 这里不再统计,避免重复计算
|
||||
|
||||
// 获取粉丝数量:优先 Redis,无则 MySQL
|
||||
String fansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + vlog.getMemberId());
|
||||
String fansCountsStr = cache.getCacheObject(REDIS_MY_FANS_COUNTS + ":" + vlog.getMemberId());
|
||||
Integer fansCounts = 0;
|
||||
if (StringUtils.isNotBlank(fansCountsStr)) {
|
||||
fansCounts = Integer.valueOf(fansCountsStr);
|
||||
@ -560,22 +463,14 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
result.put("comments", comments);
|
||||
|
||||
// 从Redis获取点赞数
|
||||
String likeCountsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlog.getId());
|
||||
Integer likeCounts = 0;
|
||||
if (StringUtils.isNotBlank(likeCountsStr)) {
|
||||
try {
|
||||
likeCounts = Integer.valueOf(likeCountsStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的点赞数格式错误: {}", vlog.getId(), likeCountsStr);
|
||||
likeCounts = 0;
|
||||
}
|
||||
}
|
||||
int likeCounts = getVlogBeLikedCounts(vlog.getId());
|
||||
|
||||
result.put("likeCounts", likeCounts);
|
||||
result.put("vlogId", vlog.getId());
|
||||
|
||||
List<Map<String, Object>> likedUsers = myLikedVlogMapper.selectLikedUsersByVlogId(vlog.getId());
|
||||
result.put("likedUsers", likedUsers);
|
||||
result.put("vlog",vo);
|
||||
result.put("vlog", vo);
|
||||
|
||||
// 添加粉丝列表
|
||||
// Page<FansVO> fansPage = fansService.queryMyFans(vlog.getVlogerId(), 0, 10);
|
||||
@ -608,20 +503,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
return myLikedVlogMapper.selectLikedUsersByVlogId(vlogId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLikeCounts(String vlogId) {
|
||||
// 从Redis获取点赞数
|
||||
String likeCountsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
|
||||
if (StringUtils.isNotBlank(likeCountsStr)) {
|
||||
try {
|
||||
return Integer.valueOf(likeCountsStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的点赞数格式错误: {}", vlogId, likeCountsStr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getVlogUploaderInfo(String fileId) {
|
||||
@ -699,77 +580,6 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
return vlogMapper.selectVlogListWithAggregatedData(page, vlogBO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cacheTopLikedVlogs(int limit) {
|
||||
try {
|
||||
log.info("开始查询点赞最多的{}条视频", limit);
|
||||
|
||||
// 查询所有公开的视频列表
|
||||
List<Map<String, Object>> allVlogs = vlogMapper.selectAllPublicVlogs();
|
||||
|
||||
if (allVlogs != null && !allVlogs.isEmpty()) {
|
||||
// 从Redis获取每个视频的点赞数量
|
||||
List<Map<String, Object>> vlogsWithLikeCounts = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> vlog : allVlogs) {
|
||||
String vlogId = vlog.get("id").toString();
|
||||
String redisLikeKey = REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId;
|
||||
String likeCountStr = redis.get(redisLikeKey);
|
||||
|
||||
// 获取Redis中的点赞数,如果没有则使用数据库中的默认值
|
||||
int likeCount = 0;
|
||||
if (likeCountStr != null && !likeCountStr.isEmpty()) {
|
||||
try {
|
||||
likeCount = Integer.parseInt(likeCountStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("Redis中视频{}的点赞数格式错误: {}", vlogId, likeCountStr);
|
||||
likeCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加Redis中的点赞数到视频信息中
|
||||
vlog.put("redis_like_count", likeCount);
|
||||
vlogsWithLikeCounts.add(vlog);
|
||||
}
|
||||
|
||||
// 先打乱顺序
|
||||
Collections.shuffle(vlogsWithLikeCounts);
|
||||
|
||||
// 按Redis中的点赞数排序,获取前limit个
|
||||
vlogsWithLikeCounts.sort((v1, v2) -> {
|
||||
int count1 = (Integer) v1.get("redis_like_count");
|
||||
int count2 = (Integer) v2.get("redis_like_count");
|
||||
return Integer.compare(count2, count1); // 降序排列
|
||||
});
|
||||
|
||||
// 取前limit个
|
||||
List<Map<String, Object>> topLikedVlogs = vlogsWithLikeCounts.stream()
|
||||
.limit(limit)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!topLikedVlogs.isEmpty()) {
|
||||
// 将结果存储到Redis中,使用JSON格式
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
// 注册JavaTimeModule以支持LocalDateTime序列化
|
||||
objectMapper.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
|
||||
objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
String jsonData = objectMapper.writeValueAsString(topLikedVlogs);
|
||||
|
||||
// 存储到Redis,设置24小时过期时间
|
||||
String redisKey = "top_liked_vlogs:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
redis.set(redisKey, jsonData, 24 * 60 * 60); // 24小时过期
|
||||
|
||||
log.info("成功缓存{}条点赞最多的视频到Redis,key: {}", topLikedVlogs.size(), redisKey);
|
||||
} else {
|
||||
log.warn("未查询到点赞最多的视频数据");
|
||||
}
|
||||
} else {
|
||||
log.warn("未查询到公开的视频数据");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("缓存点赞最多视频到Redis失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getRandomVlogs(int limit) {
|
||||
@ -784,6 +594,49 @@ public class VlogServiceImpl extends BaseInfoProperties implements VlogService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<String> getVlogForUser(Page<IndexVlogVO> page, Long memberId) {
|
||||
return baseMapper.getVlogForUser(page, memberId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int readVlog(Long memberId, String vlogId) {
|
||||
//加入已读缓存列表,数量为1
|
||||
if (!redisCache.zSetHasMember("vlog:read:" + memberId, vlogId)) {
|
||||
redisCache.zSetAdd("vlog:read:" + memberId, vlogId, 1);
|
||||
} else {
|
||||
redisCache.zSetIncrement("vlog:read:" + memberId, vlogId, 1);
|
||||
}
|
||||
return baseMapper.readVlog(memberId, vlogId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IndexVlogVO> getIndexVlogList(VlogBO bo) {
|
||||
List<IndexVlogVO> indexVlogVOPage = vlogMapperCustom.getIndexVlogList(bo);
|
||||
fillRedisColumn(indexVlogVOPage );
|
||||
return indexVlogVOPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getIndexVlogList(VlogBO bo, Page page) {
|
||||
Page<IndexVlogVO> indexVlogVOPage = vlogMapperCustom.getIndexVlogList(bo,page);
|
||||
fillRedisColumn(indexVlogVOPage.getRecords());
|
||||
return indexVlogVOPage;
|
||||
}
|
||||
|
||||
private void fillRedisColumn(List<IndexVlogVO> vlogList) {
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
vlogList.parallelStream().forEach(vlog -> {
|
||||
if (user != null) {
|
||||
vlog.setDoIFollowVloger(fansService.queryDoIFollowVloger(user.getUserId() + "", vlog.getMemberId()));
|
||||
vlog.setDoILikeThisVlog(doILikeVlog(user.getUserId() + "", vlog.getId()));
|
||||
}
|
||||
vlog.setLikeCounts(getVlogBeLikedCounts(vlog.getId()));
|
||||
vlog.setCommentsCounts(getVlogComment(vlog.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<IndexVlogVO> getIndexSearchVlogList(SearchBO bo, Page page) {
|
||||
String userId = bo.getUserId();
|
||||
|
@ -14,6 +14,7 @@ import com.wzj.soopin.content.utils.TencentCloudUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -36,7 +37,7 @@ public class VlogUploadServiceImpl implements VlogUploadService {
|
||||
@Autowired
|
||||
private com.wzj.soopin.content.service.CommentService commentService;
|
||||
@Autowired
|
||||
private com.wzj.soopin.content.utils.RedisOperator redis;
|
||||
private RedisCache redisCache;
|
||||
@Autowired
|
||||
private com.wzj.soopin.content.mapper.VlogMapperCustom vlogMapperCustom;
|
||||
|
||||
@ -48,110 +49,8 @@ public class VlogUploadServiceImpl implements VlogUploadService {
|
||||
// return client.PullUpload(req);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public SearchMediaResponse searchMedia(SearchMediaRequest req) {
|
||||
try {
|
||||
// 获取VOD客户端实例
|
||||
VodClient client = tencentCloudUtil.getVodClient();
|
||||
|
||||
// 设置默认值
|
||||
if (req.getOffset() == null) {
|
||||
req.setOffset(0L);
|
||||
}
|
||||
if (req.getLimit() == null) {
|
||||
req.setLimit(10L);
|
||||
}
|
||||
|
||||
// 添加日志,打印请求参数
|
||||
// log.info("SearchMediaRequest 请求参数: {}", req.toJsonString());
|
||||
|
||||
// 添加调试信息
|
||||
log.info("请求时间戳: {}", System.currentTimeMillis());
|
||||
log.info("请求参数详情 - Offset: {}, Limit: {}, Sort: {}, Filters: {}",
|
||||
req.getOffset(),
|
||||
req.getLimit(),
|
||||
// req.getSort() != null ? req.getSort().toJsonString() : "null",
|
||||
req.getFilters() != null ? String.join(",", req.getFilters()) : "null");
|
||||
|
||||
// 验证请求参数
|
||||
validateSearchRequest(req);
|
||||
|
||||
SearchMediaResponse response = client.SearchMedia(req);
|
||||
log.info("SearchMedia API 调用成功,返回结果数: {}", response.getTotalCount());
|
||||
return response;
|
||||
} catch (TencentCloudSDKException e) {
|
||||
log.error("搜索媒体文件失败: {}", e.getMessage(), e);
|
||||
// 添加更详细的错误信息
|
||||
if (e.getMessage().contains("signature")) {
|
||||
log.error("签名验证失败,请检查:\n1. 密钥是否正确\n2. 服务器时间是否准确\n3. 时区设置是否正确");
|
||||
} else if (e.getMessage().contains("InvalidParameterValue")) {
|
||||
log.error("参数值错误,请检查:\n1. 分页参数 Offset 和 Limit 是否有效\n2. 搜索条件是否合法\n3. 排序参数是否正确");
|
||||
} else if (e.getMessage().contains("UnauthorizedOperation")) {
|
||||
log.error("未授权操作,请检查:\n1. 密钥是否有权限\n2. 应用 ID 是否正确\n3. 是否开通了点播服务");
|
||||
}
|
||||
throw new RuntimeException("搜索媒体文件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证搜索请求参数
|
||||
*/
|
||||
private void validateSearchRequest(SearchMediaRequest req) {
|
||||
// 验证分页参数
|
||||
if (req.getOffset() < 0) {
|
||||
throw new IllegalArgumentException("Offset 不能小于 0");
|
||||
}
|
||||
if (req.getLimit() < 1 || req.getLimit() > 50) {
|
||||
throw new IllegalArgumentException("Limit 必须在 1-50 之间");
|
||||
}
|
||||
if (req.getOffset() + req.getLimit() > 5000) {
|
||||
throw new IllegalArgumentException("Offset + Limit 不能超过 5000");
|
||||
}
|
||||
|
||||
// 验证搜索条件
|
||||
if (req.getFileIds() != null && req.getFileIds().length > 10) {
|
||||
throw new IllegalArgumentException("FileIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getNames() != null && req.getNames().length > 10) {
|
||||
throw new IllegalArgumentException("Names 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getNamePrefixes() != null && req.getNamePrefixes().length > 10) {
|
||||
throw new IllegalArgumentException("NamePrefixes 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getDescriptions() != null && req.getDescriptions().length > 10) {
|
||||
throw new IllegalArgumentException("Descriptions 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getClassIds() != null && req.getClassIds().length > 10) {
|
||||
throw new IllegalArgumentException("ClassIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getTags() != null && req.getTags().length > 16) {
|
||||
throw new IllegalArgumentException("Tags 数组长度不能超过 16");
|
||||
}
|
||||
if (req.getSourceTypes() != null && req.getSourceTypes().length > 10) {
|
||||
throw new IllegalArgumentException("SourceTypes 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getStreamIds() != null && req.getStreamIds().length > 10) {
|
||||
throw new IllegalArgumentException("StreamIds 数组长度不能超过 10");
|
||||
}
|
||||
if (req.getStorageRegions() != null && req.getStorageRegions().length > 20) {
|
||||
throw new IllegalArgumentException("StorageRegions 数组长度不能超过 20");
|
||||
}
|
||||
// if (req.getMediaTypes() != null && req.getMediaTypes().length > 10) {
|
||||
// throw new IllegalArgumentException("MediaTypes 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getStatus() != null && req.getStatus().length > 10) {
|
||||
// throw new IllegalArgumentException("Status 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getReviewResults() != null && req.getReviewResults().length > 10) {
|
||||
// throw new IllegalArgumentException("ReviewResults 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getTrtcSdkAppIds() != null && req.getTrtcSdkAppIds().length > 10) {
|
||||
// throw new IllegalArgumentException("TrtcSdkAppIds 数组长度不能超过 10");
|
||||
// }
|
||||
// if (req.getTrtcRoomIds() != null && req.getTrtcRoomIds().length > 10) {
|
||||
// throw new IllegalArgumentException("TrtcRoomIds 数组长度不能超过 10");
|
||||
// }
|
||||
}
|
||||
|
||||
// 视频审核
|
||||
@Override
|
||||
@ -301,26 +200,11 @@ public class VlogUploadServiceImpl implements VlogUploadService {
|
||||
}
|
||||
|
||||
// 2. 点赞数量:优先 Redis,无则 MySQL
|
||||
String likeCountsStr = redis.get(com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
|
||||
int likeCounts;
|
||||
if (likeCountsStr != null) {
|
||||
likeCounts = Integer.parseInt(likeCountsStr);
|
||||
} else if (vlog != null && vlog.getLikeCounts() != null) {
|
||||
likeCounts = vlog.getLikeCounts();
|
||||
} else {
|
||||
likeCounts = 0;
|
||||
}
|
||||
int likeCounts=redisCache.zSetScore(com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS , vlogId).intValue();
|
||||
|
||||
// 3. 评论数量:优先 Redis,无则 MySQL
|
||||
String commentCountsStr = redis.get(com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
|
||||
int commentCounts;
|
||||
if (commentCountsStr != null) {
|
||||
commentCounts = Integer.parseInt(commentCountsStr);
|
||||
} else if (vlog != null && vlog.getCommentsCounts() != null) {
|
||||
commentCounts = vlog.getCommentsCounts();
|
||||
} else {
|
||||
commentCounts = 0;
|
||||
}
|
||||
int commentCounts=redisCache.zSetScore(com.wzj.soopin.content.domain.base.BaseInfoProperties.REDIS_VLOG_COMMENT_COUNTS , vlogId).intValue();
|
||||
|
||||
|
||||
// 4. 评论内容:只查 MySQL
|
||||
List<com.wzj.soopin.content.domain.vo.CommentVO> commentList = new ArrayList<>();
|
||||
|
@ -27,7 +27,7 @@ public class VlogScheduledTask {
|
||||
public void jobExecute() {
|
||||
log.info("开始执行定时任务:查询点赞最多的100条视频并存储到Redis");
|
||||
try {
|
||||
vlogService.cacheTopLikedVlogs(100);
|
||||
// vlogService.cacheTopLikedVlogs(100);
|
||||
log.info("定时任务执行完成:成功缓存点赞最多的100条视频到Redis");
|
||||
} catch (Exception e) {
|
||||
log.error("定时任务执行失败:缓存点赞最多视频到Redis时发生异常", e);
|
||||
|
@ -24,286 +24,286 @@ public class RedisOperator {
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
// Key(键),简单的key-value操作
|
||||
|
||||
/**
|
||||
* 判断key是否存在
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public boolean keyIsExist(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long ttl(String key) {
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:expire 设置过期时间,单位秒
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public void expire(String key, long timeout) {
|
||||
redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:increment key,增加key一次
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long increment(String key, long delta) {
|
||||
return redisTemplate.opsForValue().increment(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 累加,使用hash
|
||||
*/
|
||||
public long incrementHash(String name, String key, long delta) {
|
||||
return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 累减,使用hash
|
||||
*/
|
||||
public long decrementHash(String name, String key, long delta) {
|
||||
delta = delta * (-1);
|
||||
return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash 设置value
|
||||
*/
|
||||
public void setHashValue(String name, String key, String value) {
|
||||
redisTemplate.opsForHash().put(name, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash 获得value
|
||||
*/
|
||||
public String getHashValue(String name, String key) {
|
||||
return (String)redisTemplate.opsForHash().get(name, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:decrement key,减少key一次
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public long decrement(String key, long delta) {
|
||||
return redisTemplate.opsForValue().decrement(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key
|
||||
*/
|
||||
public Set<String> keys(String pattern) {
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:DEL key,删除一个key
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void del(String key) {
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
// String(字符串)
|
||||
|
||||
/**
|
||||
* 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void set(String key, String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param timeout
|
||||
* (以秒为单位)
|
||||
*/
|
||||
public void set(String key, String value, long timeout) {
|
||||
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果key不存在,则设置,如果存在,则报错
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setnx60s(String key, String value) {
|
||||
redisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果key不存在,则设置,如果存在,则报错
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setnx(String key, String value) {
|
||||
redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:GET key,返回 key所关联的字符串值。
|
||||
*
|
||||
* @param key
|
||||
* @return value
|
||||
*/
|
||||
public String get(String key) {
|
||||
return (String)redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询,对应mget
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public List<String> mget(List<String> keys) {
|
||||
return redisTemplate.opsForValue().multiGet(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询,管道pipeline
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public List<Object> batchGet(List<String> keys) {
|
||||
|
||||
// nginx -> keepalive
|
||||
// redis -> pipeline
|
||||
|
||||
List<Object> result = redisTemplate.executePipelined(new RedisCallback<String>() {
|
||||
@Override
|
||||
public String doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
StringRedisConnection src = (StringRedisConnection)connection;
|
||||
|
||||
for (String k : keys) {
|
||||
src.get(k);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Hash(哈希表)
|
||||
|
||||
/**
|
||||
* 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value
|
||||
*
|
||||
* @param key
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
public void hset(String key, String field, Object value) {
|
||||
redisTemplate.opsForHash().put(key, field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HGET key field,返回哈希表 key中给定域 field的值
|
||||
*
|
||||
* @param key
|
||||
* @param field
|
||||
* @return
|
||||
*/
|
||||
public String hget(String key, String field) {
|
||||
return (String) redisTemplate.opsForHash().get(key, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
|
||||
*
|
||||
* @param key
|
||||
* @param fields
|
||||
*/
|
||||
public void hdel(String key, Object... fields) {
|
||||
redisTemplate.opsForHash().delete(key, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Map<Object, Object> hgetall(String key) {
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
// List(列表)
|
||||
|
||||
/**
|
||||
* 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return 执行 LPUSH命令后,列表的长度。
|
||||
*/
|
||||
public long lpush(String key, String value) {
|
||||
return redisTemplate.opsForList().leftPush(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:LPOP key,移除并返回列表 key的头元素。
|
||||
*
|
||||
* @param key
|
||||
* @return 列表key的头元素。
|
||||
*/
|
||||
public String lpop(String key) {
|
||||
return (String)redisTemplate.opsForList().leftPop(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @return 执行 LPUSH命令后,列表的长度。
|
||||
*/
|
||||
public long rpush(String key, String value) {
|
||||
return redisTemplate.opsForList().rightPush(key, value);
|
||||
}
|
||||
// List(列表)
|
||||
/**
|
||||
* 实现命令:LRANGE key start stop,返回列表key中指定区间内的元素
|
||||
*
|
||||
* @param key Redis key
|
||||
* @param start 开始索引
|
||||
* @param stop 结束索引
|
||||
* @return 返回指定区间的元素
|
||||
*/
|
||||
public List<String> lrange(String key, long start, long stop) {
|
||||
return redisTemplate.opsForList().range(key, start, stop);
|
||||
}
|
||||
/**
|
||||
* 实现命令:LREM key count value,移除列表中与 value 相等的元素
|
||||
*
|
||||
* @param key Redis key
|
||||
* @param count 删除的数量(正数表示从头部开始删除,负数从尾部,0表示删除全部匹配项)
|
||||
* @param value 要删除的元素值
|
||||
* @return 被删除的元素个数
|
||||
*/
|
||||
public Long lrem(String key, long count, Object value) {
|
||||
return redisTemplate.opsForList().remove(key, count, value);
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * 判断key是否存在
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public boolean keyIsExist(String key) {
|
||||
// return redisTemplate.hasKey(key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。
|
||||
// *
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public long ttl(String key) {
|
||||
// return redisTemplate.getExpire(key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:expire 设置过期时间,单位秒
|
||||
// *
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public void expire(String key, long timeout) {
|
||||
// redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:increment key,增加key一次
|
||||
// *
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public long increment(String key, long delta) {
|
||||
// return redisTemplate.opsForValue().increment(key, delta);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 累加,使用hash
|
||||
// */
|
||||
// public long incrementHash(String name, String key, long delta) {
|
||||
// return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 累减,使用hash
|
||||
// */
|
||||
// public long decrementHash(String name, String key, long delta) {
|
||||
// delta = delta * (-1);
|
||||
// return redisTemplate.opsForHash().increment(name, key, delta);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * hash 设置value
|
||||
// */
|
||||
// public void setHashValue(String name, String key, String value) {
|
||||
// redisTemplate.opsForHash().put(name, key, value);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * hash 获得value
|
||||
// */
|
||||
// public String getHashValue(String name, String key) {
|
||||
// return (String)redisTemplate.opsForHash().get(name, key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:decrement key,减少key一次
|
||||
// *
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public long decrement(String key, long delta) {
|
||||
// return redisTemplate.opsForValue().decrement(key, delta);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key
|
||||
// */
|
||||
// public Set<String> keys(String pattern) {
|
||||
// return redisTemplate.keys(pattern);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:DEL key,删除一个key
|
||||
// *
|
||||
// * @param key
|
||||
// */
|
||||
// public void del(String key) {
|
||||
// redisTemplate.delete(key);
|
||||
// }
|
||||
//
|
||||
// // String(字符串)
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key)
|
||||
// *
|
||||
// * @param key
|
||||
// * @param value
|
||||
// */
|
||||
// public void set(String key, String value) {
|
||||
// redisTemplate.opsForValue().set(key, value);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
|
||||
// *
|
||||
// * @param key
|
||||
// * @param value
|
||||
// * @param timeout
|
||||
// * (以秒为单位)
|
||||
// */
|
||||
// public void set(String key, String value, long timeout) {
|
||||
// redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 如果key不存在,则设置,如果存在,则报错
|
||||
// * @param key
|
||||
// * @param value
|
||||
// */
|
||||
// public void setnx60s(String key, String value) {
|
||||
// redisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 如果key不存在,则设置,如果存在,则报错
|
||||
// * @param key
|
||||
// * @param value
|
||||
// */
|
||||
// public void setnx(String key, String value) {
|
||||
// redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:GET key,返回 key所关联的字符串值。
|
||||
// *
|
||||
// * @param key
|
||||
// * @return value
|
||||
// */
|
||||
// public String get(String key) {
|
||||
// return (String)redisTemplate.opsForValue().get(key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 批量查询,对应mget
|
||||
// * @param keys
|
||||
// * @return
|
||||
// */
|
||||
// public List<String> mget(List<String> keys) {
|
||||
// return redisTemplate.opsForValue().multiGet(keys);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 批量查询,管道pipeline
|
||||
// * @param keys
|
||||
// * @return
|
||||
// */
|
||||
// public List<Object> batchGet(List<String> keys) {
|
||||
//
|
||||
//// nginx -> keepalive
|
||||
//// redis -> pipeline
|
||||
//
|
||||
// List<Object> result = redisTemplate.executePipelined(new RedisCallback<String>() {
|
||||
// @Override
|
||||
// public String doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
// StringRedisConnection src = (StringRedisConnection)connection;
|
||||
//
|
||||
// for (String k : keys) {
|
||||
// src.get(k);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Hash(哈希表)
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value
|
||||
// *
|
||||
// * @param key
|
||||
// * @param field
|
||||
// * @param value
|
||||
// */
|
||||
// public void hset(String key, String field, Object value) {
|
||||
// redisTemplate.opsForHash().put(key, field, value);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:HGET key field,返回哈希表 key中给定域 field的值
|
||||
// *
|
||||
// * @param key
|
||||
// * @param field
|
||||
// * @return
|
||||
// */
|
||||
// public String hget(String key, String field) {
|
||||
// return (String) redisTemplate.opsForHash().get(key, field);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
|
||||
// *
|
||||
// * @param key
|
||||
// * @param fields
|
||||
// */
|
||||
// public void hdel(String key, Object... fields) {
|
||||
// redisTemplate.opsForHash().delete(key, fields);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。
|
||||
// *
|
||||
// * @param key
|
||||
// * @return
|
||||
// */
|
||||
// public Map<Object, Object> hgetall(String key) {
|
||||
// return redisTemplate.opsForHash().entries(key);
|
||||
// }
|
||||
//
|
||||
// // List(列表)
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头
|
||||
// *
|
||||
// * @param key
|
||||
// * @param value
|
||||
// * @return 执行 LPUSH命令后,列表的长度。
|
||||
// */
|
||||
// public long lpush(String key, String value) {
|
||||
// return redisTemplate.opsForList().leftPush(key, value);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:LPOP key,移除并返回列表 key的头元素。
|
||||
// *
|
||||
// * @param key
|
||||
// * @return 列表key的头元素。
|
||||
// */
|
||||
// public String lpop(String key) {
|
||||
// return (String)redisTemplate.opsForList().leftPop(key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。
|
||||
// *
|
||||
// * @param key
|
||||
// * @param value
|
||||
// * @return 执行 LPUSH命令后,列表的长度。
|
||||
// */
|
||||
// public long rpush(String key, String value) {
|
||||
// return redisTemplate.opsForList().rightPush(key, value);
|
||||
// }
|
||||
// // List(列表)
|
||||
// /**
|
||||
// * 实现命令:LRANGE key start stop,返回列表key中指定区间内的元素
|
||||
// *
|
||||
// * @param key Redis key
|
||||
// * @param start 开始索引
|
||||
// * @param stop 结束索引
|
||||
// * @return 返回指定区间的元素
|
||||
// */
|
||||
// public List<String> lrange(String key, long start, long stop) {
|
||||
// return redisTemplate.opsForList().range(key, start, stop);
|
||||
// }
|
||||
// /**
|
||||
// * 实现命令:LREM key count value,移除列表中与 value 相等的元素
|
||||
// *
|
||||
// * @param key Redis key
|
||||
// * @param count 删除的数量(正数表示从头部开始删除,负数从尾部,0表示删除全部匹配项)
|
||||
// * @param value 要删除的元素值
|
||||
// * @return 被删除的元素个数
|
||||
// */
|
||||
// public Long lrem(String key, long count, Object value) {
|
||||
// return redisTemplate.opsForList().remove(key, count, value);
|
||||
// }
|
||||
}
|
||||
|
@ -282,5 +282,27 @@
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<select id="getVlogForUser" resultType="java.lang.String">
|
||||
SELECT
|
||||
v.id
|
||||
FROM
|
||||
cont_vlog v
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM cms_vlog_member m
|
||||
WHERE m.vlog_id = v.id AND m.member_id = ${memberId}
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM ums_block b
|
||||
WHERE b.block_member_id = v.id AND b.member_id = ${memberId}
|
||||
)
|
||||
ORDER BY
|
||||
v.create_time DESC
|
||||
|
||||
</select>
|
||||
|
||||
<update id="readVlog">
|
||||
insert into cms_vlog_member (vlog_id, member_id,status) values (#{vlogId}, #{memberId},1)
|
||||
</update>
|
||||
</mapper>
|
||||
|
||||
|
@ -32,32 +32,38 @@
|
||||
WHERE
|
||||
v.is_private = 0
|
||||
<choose>
|
||||
<when test="paramMap.status != null and paramMap.status!=''">
|
||||
AND v.status = #{paramMap.status}
|
||||
<when test="bo.status != null and bo.status!=''">
|
||||
AND v.status = #{bo.status}
|
||||
</when>
|
||||
<otherwise>
|
||||
AND v.status = 1
|
||||
</otherwise>
|
||||
</choose>
|
||||
AND v.first_frame_img IS NOT NULL
|
||||
<if test="paramMap.cityCode != null and paramMap.cityCode != ''">
|
||||
AND v.city_code = #{paramMap.cityCode}
|
||||
<if test="bo.cityCode != null and bo.cityCode != ''">
|
||||
AND v.city_code = #{bo.cityCode}
|
||||
</if>
|
||||
<if test="paramMap.search != null and paramMap.search != ''">
|
||||
AND v.title like '%${paramMap.search}%'
|
||||
<if test="bo.title != null and bo.title != ''">
|
||||
AND v.title like '%${bo.title}%'
|
||||
</if>
|
||||
<if test="paramMap.blockVd != null and paramMap.blockVd.size() > 0">
|
||||
<if test="bo.blockVd != null and bo.blockVd.size() > 0">
|
||||
AND v.id NOT IN
|
||||
<foreach collection="paramMap.blockVd" item="vlogId" open="(" separator="," close=")">
|
||||
<foreach collection="bo.blockVd" item="vlogId" open="(" separator="," close=")">
|
||||
#{vlogId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="paramMap.blockUser != null and paramMap.blockUser.size() > 0">
|
||||
<if test="bo.blockUser != null and bo.blockUser.size() > 0">
|
||||
AND v.member_id NOT IN
|
||||
<foreach collection="paramMap.blockUser" item="memberId" open="(" separator="," close=")">
|
||||
<foreach collection="bo.blockUser" item="memberId" open="(" separator="," close=")">
|
||||
#{memberId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="bo.ids != null and bo.ids.size() > 0">
|
||||
AND v.id IN
|
||||
<foreach collection="bo.ids" item="vlogId" open="(" separator="," close=")">
|
||||
#{vlogId}
|
||||
</foreach>
|
||||
</if>
|
||||
ORDER BY
|
||||
v.create_time
|
||||
DESC
|
||||
|
@ -45,7 +45,7 @@ public class Feedback extends BaseAudit {
|
||||
|
||||
|
||||
@Schema(description ="反馈对象ID")
|
||||
private Long aimId;
|
||||
private String aimId;
|
||||
|
||||
@Schema(description ="反馈对象类型 1 会员 2 群组 3 评论 4 视频 5 聊天" )
|
||||
private Integer aimType;
|
||||
|
@ -46,7 +46,7 @@ public class FeedbackVO {
|
||||
|
||||
@Schema(description ="反馈对象ID")
|
||||
@Excel(name = "反馈对象ID")
|
||||
private Long aimId;
|
||||
private String aimId;
|
||||
|
||||
@Schema(description ="反馈对象类型 1 会员 2 群组 3 评论 4 视频 5 聊天" )
|
||||
private BaseAudit aimObject;
|
||||
|
@ -73,6 +73,9 @@ public interface IMemberService extends IService<Member> {
|
||||
|
||||
String updateWechat(MemberBO bo);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 不带租户的获取会员信息
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.wzj.soopin.order.domain.entity.OrderItem;
|
||||
import com.wzj.soopin.order.mapper.OrderItemMapper;
|
||||
import com.wzj.soopin.order.service.OrderItemService;
|
||||
import org.dromara.common.redis.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -15,6 +16,8 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
@ -28,7 +31,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem> implements OrderItemService {
|
||||
|
||||
@Autowired
|
||||
private RedisOperator redis;
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
public List<OrderItem> findByOrderId(Long orderId) {
|
||||
@ -54,7 +57,7 @@ public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem
|
||||
|
||||
// 存储到Redis,设置24小时过期时间
|
||||
String redisKey = "top_trading_products:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
redis.set(redisKey, jsonData, 24 * 60 * 60); // 24小时过期
|
||||
redisCache.setCacheObject(redisKey, jsonData, 24 * 60 * 60, TimeUnit.SECONDS); // 24小时过期
|
||||
|
||||
log.info("成功缓存{}个交易量最多的商品到Redis,key: {}", topTradingProducts.size(), redisKey);
|
||||
} else {
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.wzj.soopin.transaction.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "easypay")
|
||||
public class EasypayConfig {
|
||||
|
||||
/**
|
||||
* 易生接口请求地址前缀
|
||||
*/
|
||||
private String apiPathPrefix;
|
||||
|
||||
/**
|
||||
* 易生分配的机构号
|
||||
*/
|
||||
private String reqId;
|
||||
|
||||
/**
|
||||
* 易生分配的商户号
|
||||
*/
|
||||
private String mchtCode;
|
||||
|
||||
/**
|
||||
* 微信子商户号
|
||||
*/
|
||||
private String wechatMchid;
|
||||
|
||||
/**
|
||||
* 易生公钥
|
||||
*/
|
||||
private String easypayPublicKey;
|
||||
|
||||
/**
|
||||
* 商户私钥
|
||||
*/
|
||||
private String merRsaPrivateKey;
|
||||
|
||||
/**
|
||||
* 易生异步回调通知地址
|
||||
*/
|
||||
private String backUrl;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.wzj.soopin.transaction.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "wechat.mini-program")
|
||||
public class WechatMiniProgramConfig {
|
||||
|
||||
private String appId;
|
||||
|
||||
private String secret;
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.wzj.soopin.transaction.constans;
|
||||
|
||||
/**
|
||||
* 易生接口涉及常量
|
||||
*/
|
||||
public interface EasypayConstants {
|
||||
|
||||
/**
|
||||
* 请求方类型.1:商户;2:拓展机构。 默认是1
|
||||
* 1商户模式下,reqId即为商户号mchtCode
|
||||
* 2机构模式下,reqId即为拓展机构编号
|
||||
*/
|
||||
public static final String REQ_TYPE = "2";
|
||||
|
||||
/**
|
||||
* 生成订单前缀
|
||||
*/
|
||||
public static final String TRACE_PREFIX = "wzj";
|
||||
|
||||
/**
|
||||
* 支付订单超时时长,单位:秒
|
||||
*/
|
||||
public static final Long TRACE_TIMEOUT = 180L;
|
||||
|
||||
|
||||
/**
|
||||
* 通讯返回码-成功
|
||||
*/
|
||||
public static final String RSP_HEADER_OK = "000000";
|
||||
|
||||
/**
|
||||
* 业务返回码-成功
|
||||
*/
|
||||
public static final String RSP_BODY_RESP_OK = "000000";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-交易成功
|
||||
*/
|
||||
public static final String RSP_BODY_TRANS_OK = "0";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-交易部分成功
|
||||
*/
|
||||
public static final String RSP_BODY_TRANS_PARTIALLY_OK = "1";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-支付成功待发货
|
||||
*/
|
||||
public static final String RSP_BODY_TRANS_OK_WETCAT = "2";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-支付中,需查询或接收通知获取最终状态
|
||||
*/
|
||||
public static final String RSP_BODY_TRANS_PROCESSING = "9";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-交易失败
|
||||
*/
|
||||
public static final String RSP_BODY_TRANS_FAIL = "X";
|
||||
|
||||
/**
|
||||
* 交易状态返回码-已退款
|
||||
*/
|
||||
public static final String RSP_BODY_REFUND_OK = "R";
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.wzj.soopin.transaction.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import com.wzj.soopin.transaction.domain.bo.PaymentBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.EasyPayRequest;
|
||||
import com.wzj.soopin.transaction.domain.vo.EasypayPrePayVO;
|
||||
import com.wzj.soopin.transaction.service.IEasypayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
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 java.rmi.ServerException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 易生支付结果通知回调
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/easypay")
|
||||
@RequiredArgsConstructor
|
||||
public class EasypayCallbackController {
|
||||
|
||||
private final IEasypayService easypayService;
|
||||
|
||||
/**
|
||||
* 处理易生支付结果通知回调
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@SaIgnore
|
||||
@Log(title = "易生支付结果通知回调", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/trade/callback")
|
||||
public Map tradeCallback(@RequestBody EasyPayRequest request) {
|
||||
easypayService.handlerTradeCallback(request);
|
||||
HashMap<Object, Object> map = new HashMap<>();
|
||||
map.put("code", "000000");
|
||||
map.put("msg", "Success");
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试发起支付
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@SaIgnore
|
||||
@Log(title = "测试发起支付", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/test/trade")
|
||||
public R<EasypayPrePayVO> testTrade(@RequestBody PaymentBO paymentBO) throws ServerException {
|
||||
EasypayPrePayVO easypayPrePayVO = easypayService.payment(paymentBO);
|
||||
return R.ok(easypayPrePayVO);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
@ -20,7 +21,6 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -179,6 +179,22 @@ public class WxPayController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过小程序的授权码获取用户的openid
|
||||
*
|
||||
* @param code 授权码
|
||||
* @return 包含openid的响应对象
|
||||
*/
|
||||
@Tag(name = "获取用户openid")
|
||||
@GetMapping("/openid2")
|
||||
@Parameters({
|
||||
@Parameter(name = "code", description = "授权码", required = true, in = ParameterIn.QUERY)
|
||||
})
|
||||
public R<WxAuthResponse> getOpenIdByMiniProgramCode(@RequestParam String code) {
|
||||
WxAuthResponse response = wxAuthService.getOpenIdByMiniProgramCode(code);
|
||||
return R.ok(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
package com.wzj.soopin.transaction.domain.bo;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.PayType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 支付请求参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class PaymentBO {
|
||||
|
||||
private String memberId;
|
||||
|
||||
private String goodsId;
|
||||
|
||||
/**
|
||||
* 订单标题,对应支付宝订单里的 “商品说明”,微信订单里的“商品”
|
||||
*/
|
||||
private String orderSub;
|
||||
/**
|
||||
* 订单描述
|
||||
*/
|
||||
private String orderDes;
|
||||
/**
|
||||
* 订单金额,单位分,最小1
|
||||
*/
|
||||
private long transAmount;
|
||||
/**
|
||||
* 支付方式
|
||||
*/
|
||||
private PayType payType;
|
||||
|
||||
/**
|
||||
* 支付宝业务参数:买家的支付宝唯一用户号
|
||||
*/
|
||||
private String buyerId;
|
||||
|
||||
/**
|
||||
* 微信业务参数:微信用户子标识
|
||||
*/
|
||||
private String subOpenId;
|
||||
|
||||
// ============银联业务参数 start ==============
|
||||
/**
|
||||
* 交易类型
|
||||
*/
|
||||
private String transType;
|
||||
/**
|
||||
* 授权码
|
||||
*/
|
||||
private String userAuthCode;
|
||||
/**
|
||||
* 用户标识,对应旧系统的payerId
|
||||
*/
|
||||
private String userId;
|
||||
/**
|
||||
* 地区信息,7位,1-3为国家代码,境内业务统一为“156”,4-7位为地区码,采用《银联卡跨行业务地区代码标准》。境外商户受理的二维码业务,地区代码用全0 填充。 点击
|
||||
* [地区码](https://www.yuque.com/pandans/ws1g9s/loa46fu6isbvoksz#n3L1v)
|
||||
* <p>
|
||||
* 例:上海市——上海市——浦东新区 则传 1562904
|
||||
*/
|
||||
private String areaInfo;
|
||||
/**
|
||||
* 支付有效时间,允许对一个订单进行支付的最长相对时间,单位为秒。
|
||||
*/
|
||||
private String paymentValidTime;
|
||||
/**
|
||||
* 二维码,payType=UnionPayJsapi、UnionPayJsMini时必填。
|
||||
* 二维码表示的数据,内容为特定格式的URL或TLV。其中境内二维码采用URL格式,境外二维码采用TLV格式。见附录F21.
|
||||
*/
|
||||
private String qrCode;
|
||||
/**
|
||||
* 二维码类型,payType=UnionPayJsapi、UnionPayJsMini时必填。
|
||||
*/
|
||||
private String qrCodeType;
|
||||
/**
|
||||
* 支付方式,payType=UnionPayJsMini时必填
|
||||
*/
|
||||
private String payChannel;
|
||||
/**
|
||||
* 微信分配的公众账号ID,payType=UnionPayJsMini时必填,上送调起云闪付微信小程序的微信APPID
|
||||
*/
|
||||
private String appid;
|
||||
/**
|
||||
* 银联支付标识,payType=UnionPayJsMini时必填,固定上送MicroMessenger
|
||||
*/
|
||||
private String appUpIdentifier;
|
||||
// ============银联业务参数 end ==============
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 易企通接口请求实体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class EasyPayRequest {
|
||||
|
||||
private EasyPayRequestHeader reqHeader;
|
||||
|
||||
private Object reqBody;
|
||||
|
||||
private String reqSign;
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 易企通接口请求头
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class EasyPayRequestHeader {
|
||||
|
||||
//请求时间,当前时间:yyyyMMddHHmmss
|
||||
private String transTime;
|
||||
|
||||
//业务交易码
|
||||
private String transCode;
|
||||
|
||||
// 请求流水号
|
||||
private String transSequence;
|
||||
|
||||
// 密钥Id,商户号、机构号等
|
||||
private String reqId;
|
||||
|
||||
//请求方类型,1:商户;2:拓展机构。 默认是1. 1商户模式下,reqId即为商户号mchtCode,2机构模式下,reqId即为拓展机构编号
|
||||
private String reqType;
|
||||
|
||||
//证书Id,多证书情况下需要。支持同一个reqId下有多证书
|
||||
private String certificateId;
|
||||
|
||||
//易生证书Id,多证书情况下需要,为空时使用默认证书
|
||||
private String easyPayCertificateId;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 易企通接口响应实体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class EasyPayResponse {
|
||||
|
||||
private EasyPayResponseHeader rspHeader;
|
||||
|
||||
private Object rspBody;
|
||||
|
||||
private String rspSign;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* 易企通接口响应头
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class EasyPayResponseHeader {
|
||||
|
||||
// 应答码 000000-成功,其他失败
|
||||
private String rspCode;
|
||||
|
||||
// 应答消息,错误信息
|
||||
private String rspInfo;
|
||||
|
||||
//业务交易码, 同请求
|
||||
private String transCode;
|
||||
|
||||
// 请求流水号,同请求
|
||||
private String transSequence;
|
||||
|
||||
//易生证书Id,多证书情况下需要,为空时使用默认证书
|
||||
private String easyPayCertificateId;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class PayInfo {
|
||||
|
||||
/**
|
||||
* 业务场景,建议上线前与产品经理确认
|
||||
* 微信订单发货业务时必填,送值说明参见2.业务指引/2.15微信订单发货
|
||||
* 建议上线前与产品经理确认
|
||||
*/
|
||||
private String bizScen;
|
||||
/**
|
||||
* 业务类型
|
||||
* 微信订单发货业务时必填,送值说明参见2.业务指引/2.15微信订单发货
|
||||
* 建议上线前与产品经理确认
|
||||
*/
|
||||
private String bizType;
|
||||
/**
|
||||
* 支付方式
|
||||
* @See com.wzj.soopin.transaction.enums.easypay.PayType
|
||||
*/
|
||||
private String payType;
|
||||
/**
|
||||
* 产品代码,yqt
|
||||
*/
|
||||
private String productCode;
|
||||
/**
|
||||
* 业务日期,yyyyMMdd
|
||||
*/
|
||||
private String transDate;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class ReqInfo {
|
||||
|
||||
/**
|
||||
* 商户号,合作商户号,易生提供
|
||||
*/
|
||||
private String mchtCode;
|
||||
/**
|
||||
* 终端号,商户入网成功后可获得,客户根据自己情况选择上送,如需通过商服平台查询交易,则建议上送易生提供
|
||||
*/
|
||||
private String termCode;
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 返回码信息,规则详见F.1
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RespStateInfo {
|
||||
|
||||
/**
|
||||
* 渠道返回码
|
||||
*/
|
||||
private String appendRetCode;
|
||||
/**
|
||||
* 渠道返回码描述
|
||||
*/
|
||||
private String appendRetMsg;
|
||||
/**
|
||||
* 易生状态码
|
||||
*/
|
||||
private String respCode;
|
||||
/**
|
||||
* 易生状态码描述
|
||||
*/
|
||||
private String respDesc;
|
||||
/**
|
||||
* 交易状态码
|
||||
*/
|
||||
private String transState;
|
||||
/**
|
||||
* 交易状态码描述
|
||||
*/
|
||||
private String transStatusDesc;
|
||||
}
|
@ -0,0 +1,251 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付宝业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class AliBizParam {
|
||||
|
||||
/**
|
||||
* ali:商品详情列表,订单包含的商品列表信息,json格式。
|
||||
*/
|
||||
private List<AliGoodsDetail> aliGoodsDetail;
|
||||
/**
|
||||
* 商户机具终端信息
|
||||
*/
|
||||
private Map<String, Map<String, Object>> aliTerminalParams;
|
||||
/**
|
||||
* ali:商户传入业务信息,用于安全/营销等参数直传场景, json
|
||||
*/
|
||||
private String businessParams;
|
||||
/**
|
||||
* 买家的支付宝唯一用户号,[点击查看获取userId](https://opendocs.alipay.com/open/02xtl7)
|
||||
*/
|
||||
private String buyerId;
|
||||
/**
|
||||
* 买家支付宝账号
|
||||
*/
|
||||
private String buyerLogonId;
|
||||
/**
|
||||
* ali:禁用支付渠道,逗号分隔
|
||||
* https://docs.open.alipay.com/common/wifww7,多个渠道以逗号分割,如同时禁用信用支付类型和积分,则disable_pay_channels="credit_group,point"https://docs.open.alipay.com/common/wifww7
|
||||
*/
|
||||
private String disablePayChannels;
|
||||
/**
|
||||
* 可打折金额
|
||||
*/
|
||||
private String discountableAmount;
|
||||
/** * 扩展参数,可传支付宝能力使用分期付款信息,格式为json字符串; * 1)信用卡分期格式: * { "fq_num" : "3" , "fq_seller_percent" : "0", "fq_channels " : "alipayfq_cc"} * 2)花呗分期格式: * { "hb_fq_num" : "3" , "hb_fq_seller_percent" : "0" } */
|
||||
private String extendParams;
|
||||
/**
|
||||
* 实名支付信息
|
||||
*/
|
||||
private AliBizParamIdentity identity;
|
||||
/**
|
||||
* 商户操作员编号
|
||||
*/
|
||||
private String operatorId;
|
||||
/**
|
||||
* 描述分账信息
|
||||
*/
|
||||
private RoyaltyInfo royaltyInfo;
|
||||
/**
|
||||
* 卖家id
|
||||
*/
|
||||
private String sellerId;
|
||||
/**
|
||||
* 商户门店编号
|
||||
*/
|
||||
private String storeId;
|
||||
/**
|
||||
* 间联商户信息体
|
||||
*/
|
||||
private SubMerchant subMerchant;
|
||||
/**
|
||||
* 不可打折金额
|
||||
*/
|
||||
private String unDiscountableAmount;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class AliGoodsDetail {
|
||||
|
||||
/**
|
||||
* 支付宝定义的统一商品编号
|
||||
*/
|
||||
private String alipayGoodsId;
|
||||
/**
|
||||
* 商品描述信息
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 商品类目树,从商品类目根节点到叶子节点的类目id组成,类目id值使用|分割
|
||||
*/
|
||||
private String categoriesTree;
|
||||
/**
|
||||
* 商品类目
|
||||
*/
|
||||
private String goodsCategory;
|
||||
/**
|
||||
* 商品的编号
|
||||
*/
|
||||
private String goodsId;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String goodsName;
|
||||
/**
|
||||
* 商品单价,单位:元
|
||||
*/
|
||||
private Double price;
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
private Long quantity;
|
||||
/**
|
||||
* 商品的展示地址
|
||||
*/
|
||||
private String showUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实名支付信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class AliBizParamIdentity {
|
||||
|
||||
/**
|
||||
* 证件号
|
||||
*/
|
||||
private String certNo;
|
||||
/**
|
||||
* 证件类型,身份证: IDENTITY_CARD、 护照: PASSPORT 、 军 官 证 : OFFICER_CARD 、 士 兵 证 : SOLDIER_CARD、户口本:
|
||||
* HOKOU 等。 注: need_check_info=T 时 该参数才有 IDENTITY_CARD28 效
|
||||
*/
|
||||
private String certType;
|
||||
/**
|
||||
* 数字信封,见2.4
|
||||
*/
|
||||
private String dgtlEnvlp;
|
||||
/**
|
||||
* 是否强制校验付款人身份信息 ,T:强制校验, F:不强制
|
||||
*/
|
||||
private String fixBuyer;
|
||||
/**
|
||||
* 允许的最小买家年龄,买家年龄必须大于等于所传数值,买家年龄必须大 于等于所传数值 注: 1. need_check_info=T 时该参数才有效 2. min_age
|
||||
* 为整数,必须大于等于 0
|
||||
*/
|
||||
private Long minAge;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 是否强制校验身份信息,T:强制校验, F:不强制
|
||||
*/
|
||||
private String needCheckInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述分账信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RoyaltyInfo {
|
||||
|
||||
/**
|
||||
* 分账明细的信息
|
||||
*/
|
||||
private List<RoyaltyDetailInfo> royaltyDetailInfos;
|
||||
/**
|
||||
* 分账类型卖家的分账类型
|
||||
*/
|
||||
private String royaltyType;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RoyaltyDetailInfo {
|
||||
|
||||
/**
|
||||
* 分账的金额
|
||||
*/
|
||||
private long amount;
|
||||
/**
|
||||
* 分账的比例
|
||||
*/
|
||||
private String amountPercentage;
|
||||
/**
|
||||
* 分账批次号
|
||||
*/
|
||||
private String batchNo;
|
||||
/**
|
||||
* 分账描述信息
|
||||
*/
|
||||
private String desc;
|
||||
/**
|
||||
* 商户分账的外部关联号
|
||||
*/
|
||||
private String outRelationId;
|
||||
/**
|
||||
* 分账序列号
|
||||
*/
|
||||
private String serialNo;
|
||||
/**
|
||||
* 如果转入账号类型为 userId,本参 数为接受分账金额的支付宝账号对应的支付宝唯一用户号
|
||||
*/
|
||||
private String transIn;
|
||||
/**
|
||||
* 接受分账金额的账户类型
|
||||
*/
|
||||
private String transInType;
|
||||
/**
|
||||
* 如果转出账号类型为 userId,本参数为要分账的支付宝账号对应的 支付宝唯一用户号
|
||||
*/
|
||||
private String transOut;
|
||||
/**
|
||||
* 要分账的账户类型
|
||||
*/
|
||||
private String transOutType;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class SubMerchant {
|
||||
|
||||
/**
|
||||
* 间连受理商户的支付宝商户编号,间连受理商户的支付宝商户编号
|
||||
*/
|
||||
private String merchantId;
|
||||
/**
|
||||
* 商户id类型,商户id类型
|
||||
*/
|
||||
private String merchantType;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* JSAPI支付接口请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class JsApiReqBody {
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private JsapiReqOrderInfo reqOrderInfo;
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 支付宝业务参数
|
||||
*/
|
||||
private @Nullable AliBizParam aliBizParam;
|
||||
/**
|
||||
* 微信业务参数
|
||||
*/
|
||||
private @Nullable WxBizParam wxBizParam;
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
private @Nullable QrBizParam qrBizParam;
|
||||
/**
|
||||
* toC营销信息,一笔交易请求中支持最多上送5条toC营销活动信息
|
||||
*/
|
||||
private @Nullable List<MarketingOrder> marketingOrders;
|
||||
/**
|
||||
* toB营销信息,1、一笔交易请求中仅可上送一个toB营销活动。
|
||||
* 2、如上送toB营销活动,则不再命中后台配置的手续费营销活动。
|
||||
* 3、活动业务说明见【2.7】。
|
||||
*/
|
||||
private @Nullable List<Promo> promos;
|
||||
/**
|
||||
* 清算信息,三个标识互斥,三个标识互斥,最多仅能其中一个送是(非0)。
|
||||
* 合单支付时,主单清算标识(本字段)不起作用,以各子单的清算标识为准。
|
||||
*/
|
||||
private SettleParamInfo settleParamInfo;
|
||||
/**
|
||||
* 分账信息
|
||||
*/
|
||||
private @Nullable SeparateInfo separateInfo;
|
||||
/**
|
||||
* 合单信息
|
||||
*/
|
||||
private @Nullable List<MergeOrder> mergeOrders;
|
||||
/**
|
||||
* 合规信息
|
||||
*/
|
||||
private RiskData riskData;
|
||||
/**
|
||||
* 其他信息
|
||||
*/
|
||||
private @Nullable OtherParamInfo otherParamInfo;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class JsapiReqOrderInfo {
|
||||
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String backUrl;
|
||||
/**
|
||||
* 订单描述
|
||||
*/
|
||||
private String orderDes;
|
||||
/**
|
||||
* 订单标题,对应支付宝订单里的 “商品说明”,微信订单里的“商品”
|
||||
*/
|
||||
private String orderSub;
|
||||
/**
|
||||
* 请求方自定义信息,不作处理
|
||||
*/
|
||||
private String orgInfo;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号,同一日下商户号下唯一
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 订单超时时间,单位秒,例如3分钟送180
|
||||
*/
|
||||
private String timeout;
|
||||
/**
|
||||
* 订单金额,单位分,最小1
|
||||
*/
|
||||
private long transAmount;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账信息,子单支持分账
|
||||
*
|
||||
* 合单子单分账信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class JsapiSeparateInfo {
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
private String mchtCode;
|
||||
/**
|
||||
* 分账批次号,分账批次流水号
|
||||
*/
|
||||
private String separaBatchTrace;
|
||||
/**
|
||||
* 分账单信息列表
|
||||
*/
|
||||
private List<SeparateInfo.SeparateOrderDetailList> separateOrderDetailList;
|
||||
/**
|
||||
* 商户终端号
|
||||
*/
|
||||
private String termCode;
|
||||
/**
|
||||
* 同批次分账金额合计,单位分,取值范围:1-10000000000
|
||||
*/
|
||||
private long transSumAmt;
|
||||
/**
|
||||
* 同批次分账笔数,取值范围:1-10000000000
|
||||
*/
|
||||
private long transSumCount;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class MarketingOrder {
|
||||
/**
|
||||
* 活动ID
|
||||
*/
|
||||
private Double activityId;
|
||||
/**
|
||||
* 营销金额币种,默认CNY
|
||||
*/
|
||||
private String marketingCurrency;
|
||||
/**
|
||||
* 收银单营销请求扩展信息
|
||||
*/
|
||||
private Map<String, Object> marketingExtInfo;
|
||||
/**
|
||||
* 营销金额,单位分
|
||||
*/
|
||||
private double marketingTransAmount;
|
||||
/**
|
||||
* 商户号,与reqInfo中保持一致
|
||||
*/
|
||||
private String mchtCode;
|
||||
/**
|
||||
* 营销报名ID
|
||||
*/
|
||||
private Double registrationId;
|
||||
/**
|
||||
* 商户终端号,非必填,如上送需与reqInfo中保持一致
|
||||
*/
|
||||
private String termCode;
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.DelaySettleFlag;
|
||||
import com.wzj.soopin.transaction.enums.easypay.PatnerSettleFlag;
|
||||
import com.wzj.soopin.transaction.enums.easypay.SplitSettleFlag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class MergeOrder {
|
||||
|
||||
/**
|
||||
* 代理结算模式
|
||||
*/
|
||||
private String agentStlmMode;
|
||||
/**
|
||||
* 币种
|
||||
*/
|
||||
private String currency;
|
||||
/**
|
||||
* 请求方自定义信息
|
||||
*/
|
||||
private String customInfo;
|
||||
/**
|
||||
* 延时结算标识
|
||||
*/
|
||||
private DelaySettleFlag delaySettleFlag;
|
||||
/**
|
||||
* 下游手续费, 单位分
|
||||
*/
|
||||
private Double handlingFee;
|
||||
/**
|
||||
* 下游机构商户唯一标识
|
||||
*/
|
||||
private String orgSmerCode;
|
||||
/**
|
||||
* 小商户终端号
|
||||
*/
|
||||
private String orgSterminalCode;
|
||||
/**
|
||||
* 特殊计费
|
||||
*/
|
||||
private String otherFee;
|
||||
/**
|
||||
* D0标识,0: 非D0交易,即按进件商户开通功能结算周期结算
|
||||
* 1: D0交易,商户需开通了D0,且此字段送1时,会d0到账
|
||||
* 默认值0
|
||||
*/
|
||||
private PatnerSettleFlag patnerSettleFlag;
|
||||
/**
|
||||
* 分账信息,子单支持分账
|
||||
*/
|
||||
private JsapiSeparateInfo separateInfo;
|
||||
/**
|
||||
* 小商户号
|
||||
*/
|
||||
private String smallMchtCode;
|
||||
/**
|
||||
* 分账标识,与主单分账标识互斥,不能同时上送1
|
||||
*/
|
||||
private SplitSettleFlag splitSettleFlag;
|
||||
/**
|
||||
* 子单商户号,子单商户号
|
||||
*/
|
||||
private String subMchtCode;
|
||||
/**
|
||||
* 商户子单流水号
|
||||
*/
|
||||
private String subOrgTrace;
|
||||
/**
|
||||
* 子单商户终端号
|
||||
*/
|
||||
private String subTermCode;
|
||||
/**
|
||||
* 子单商户订单金额,单位分
|
||||
*/
|
||||
private double transAmount;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 其他信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class OtherParamInfo {
|
||||
|
||||
/**
|
||||
* 请求方自定义信息
|
||||
*/
|
||||
private String customInfo;
|
||||
/**
|
||||
* 下游手续费
|
||||
*/
|
||||
private Double handlingFee;
|
||||
/**
|
||||
* 下游机构商户唯一标识
|
||||
*/
|
||||
private String orgSmerCode;
|
||||
/**
|
||||
* 小商户终端号
|
||||
*/
|
||||
private String orgSterminalCode;
|
||||
/**
|
||||
* 特殊计费
|
||||
*/
|
||||
private List<Specialfee> otherFee;
|
||||
/**
|
||||
* 所属项目
|
||||
*/
|
||||
private String projectId;
|
||||
/**
|
||||
* 小商户号
|
||||
*/
|
||||
private String smallMchtCode;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Promo {
|
||||
|
||||
/**
|
||||
* 营销活动ID
|
||||
*/
|
||||
private String promoCode;
|
||||
/**
|
||||
* 营销金额,单位分,必须小于等于交易应收手续费金额。
|
||||
*/
|
||||
private String promoFeeAmount;
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.IDCheckIn;
|
||||
import com.wzj.soopin.transaction.enums.easypay.LimitCreditPay;
|
||||
import com.wzj.soopin.transaction.enums.easypay.PayChannel;
|
||||
import com.wzj.soopin.transaction.enums.easypay.QrCodeType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class QrBizParam {
|
||||
|
||||
/**
|
||||
* AcqAddnData
|
||||
*/
|
||||
private AcqAddnData acqAddnData;
|
||||
/**
|
||||
* 微信分配的公众账号ID,payType=UnionPayJsMini时必填,上送调起云闪付微信小程序的微信APPID
|
||||
*/
|
||||
private String appid;
|
||||
/**
|
||||
* 银联支付标识,payType=UnionPayJsMini时必填,固定上送MicroMessenger
|
||||
*/
|
||||
private String appUpIdentifier;
|
||||
/**
|
||||
* 地区信息,7位,1-3为国家代码,境内业务统一为“156”,4-7位为地区码,采用《银联卡跨行业务地区代码标准》。境外商户受理的二维码业务,地区代码用全0 填充。 点击
|
||||
* [地区码](https://www.yuque.com/pandans/ws1g9s/loa46fu6isbvoksz#n3L1v)
|
||||
* <p>
|
||||
* 例:上海市——上海市——浦东新区 则传 1562904
|
||||
*/
|
||||
private String areaInfo;
|
||||
/**
|
||||
* 优惠码
|
||||
*/
|
||||
private String discountCode;
|
||||
/**
|
||||
* 前台失败通知地址,与frontUrl同时出现。
|
||||
* APP侧未成功完成支付时调
|
||||
* 用,银联将通过GET方式访问
|
||||
* 本地址,银联将在frontFailUrl
|
||||
* 后附加付款中止原因码,原因
|
||||
* 码error_code取值如下:
|
||||
* 01 - APP付款失败
|
||||
* 91 - 用户取消支付
|
||||
*/
|
||||
private String frontFailUrl;
|
||||
/**
|
||||
* 前台通知地址
|
||||
*/
|
||||
private String frontUrl;
|
||||
/**
|
||||
* 实名支付验证标识
|
||||
*/
|
||||
private IDCheckIn idCheckIn;
|
||||
/**
|
||||
* 实名支付验证地址,当idCheckIn 取值为“1”时出现
|
||||
*/
|
||||
private String idCheckUrl;
|
||||
/**
|
||||
* UnionIdentity
|
||||
*/
|
||||
private QrBizParamIdentity identity;
|
||||
/**
|
||||
* 禁用支付渠道
|
||||
*/
|
||||
private LimitCreditPay limitCreditPay;
|
||||
/**
|
||||
* 商户交易索引,若商户必须使用自身交易索引,且无法使用orderNo作为交易主键发起撤销、退货交易时出现。
|
||||
*/
|
||||
private String merTransIndex;
|
||||
/**
|
||||
* 是否支持发票
|
||||
*/
|
||||
private String needReceipt;
|
||||
/**
|
||||
* 支付方式,payType=UnionPayJsMini时必填
|
||||
*/
|
||||
private PayChannel payChannel;
|
||||
/**
|
||||
* PayeeInfo
|
||||
*/
|
||||
private PayeeInfo payeeInfo;
|
||||
/**
|
||||
* 支付有效时间,允许对一个订单进行支付的最长相对时间,单位为秒。
|
||||
*/
|
||||
private long paymentValidTime;
|
||||
/**
|
||||
* 银联服务商信息,json格式,参数值示例如下:
|
||||
* <p>
|
||||
* {"pnrOrderId":"1220250321034502483875104", "pidSct" :"lj8352@da099%ldang", "tradeScene"
|
||||
* :"1"}
|
||||
*/
|
||||
private String pidInfo;
|
||||
/**
|
||||
* 二维码,payType=UnionPayJsapi、UnionPayJsMini时必填。
|
||||
* 二维码表示的数据,内容为特定格式的URL或TLV。其中境内二维码采用URL格式,境外二维码采用TLV格式。见附录F21.
|
||||
*/
|
||||
private String qrCode;
|
||||
/**
|
||||
* 二维码类型,payType=UnionPayJsapi、UnionPayJsMini时必填。
|
||||
*/
|
||||
private QrCodeType qrCodeType;
|
||||
/**
|
||||
* 银联服务商机构标识码,这是银联的渠道商号,类似微信渠道商号24006513
|
||||
*/
|
||||
private String qrPnrInsIdCd;
|
||||
/**
|
||||
* 请求方自定义域
|
||||
*/
|
||||
private String reqReserved;
|
||||
/**
|
||||
* 交易类型,参考
|
||||
* [附录F1.2](https://apifox.com/apidoc/shared/9758ecc8-2c38-4ec6-914f-b09be6f563bc/doc-5524664)
|
||||
*/
|
||||
private String transType;
|
||||
/**
|
||||
* 授权码
|
||||
*/
|
||||
private String userAuthCode;
|
||||
/**
|
||||
* 用户标识,对应旧系统的payerId
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
|
||||
/**
|
||||
* AcqAddnData
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class AcqAddnData {
|
||||
/**
|
||||
* 自定义数据
|
||||
*/
|
||||
private String customData;
|
||||
/**
|
||||
* 商品信息,商品明细内容
|
||||
*/
|
||||
private List<GoodsInfo> goodsInfos;
|
||||
/**
|
||||
* QrOrderInfo
|
||||
*/
|
||||
private OrderInfo orderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* QrGoodsInfo,白条支付下,如涉及贴息信息,可在本参数下上送信息,参数说明详见F22
|
||||
*/
|
||||
@Data
|
||||
public static class GoodsInfo {
|
||||
/**
|
||||
* 商品简述信息
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 商品类目树
|
||||
*/
|
||||
private String categoriesTree;
|
||||
/**
|
||||
* 商品类目
|
||||
*/
|
||||
private String goodsCategory;
|
||||
/**
|
||||
* 商品编号
|
||||
*/
|
||||
private String goodsId;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String goodsName;
|
||||
/**
|
||||
* 商品单价
|
||||
*/
|
||||
private long price;
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
private long quantity;
|
||||
/**
|
||||
* 商品的展示地址
|
||||
*/
|
||||
private String showUrl;
|
||||
/**
|
||||
* 支付宝定义的统一商品编号
|
||||
* 第三方商品编号
|
||||
*/
|
||||
private String thirdGoodsId;
|
||||
}
|
||||
|
||||
/**
|
||||
* QrOrderInfo
|
||||
*/
|
||||
@Data
|
||||
public static class OrderInfo {
|
||||
/**
|
||||
* 附件信息
|
||||
* <p>
|
||||
* 如需京东白条支付,可在此参数下上送白条相应参数,详细参数见附录F22
|
||||
*/
|
||||
private String addnInfo;
|
||||
/**
|
||||
* 可优惠金额
|
||||
*/
|
||||
private String dctAmount;
|
||||
/**
|
||||
* 订单描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 订单标题
|
||||
*/
|
||||
private String title;
|
||||
}
|
||||
|
||||
/**
|
||||
* UnionIdentity
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class QrBizParamIdentity {
|
||||
/**
|
||||
* 证件号
|
||||
*/
|
||||
private String certNo;
|
||||
/**
|
||||
* 证件类型
|
||||
*/
|
||||
private String certType;
|
||||
/**
|
||||
* 数字信封
|
||||
*/
|
||||
private String dgtlEnvlp;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 证件姓名
|
||||
*/
|
||||
private String name;
|
||||
}
|
||||
|
||||
/**
|
||||
* PayeeInfo
|
||||
*/
|
||||
@lombok.Data
|
||||
public static class PayeeInfo {
|
||||
/**
|
||||
* 商户类别
|
||||
*/
|
||||
private String mchtMccCode;
|
||||
/**
|
||||
* 商户英文名称
|
||||
*/
|
||||
private String nameEng;
|
||||
/**
|
||||
* 收款方账号
|
||||
*/
|
||||
private String payeeAcctNo;
|
||||
/**
|
||||
* 账号类型
|
||||
*/
|
||||
private String payeeAcctType;
|
||||
/**
|
||||
* 二级商户代码
|
||||
*/
|
||||
private String subMchtCode;
|
||||
/**
|
||||
* 二级商户名称
|
||||
*/
|
||||
private String subMchtName;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 合规信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RiskData {
|
||||
|
||||
/**
|
||||
* 用户ip
|
||||
*/
|
||||
private String customerIp;
|
||||
/**
|
||||
* 终端信息
|
||||
*/
|
||||
private TerminalInfo terminalInfo;
|
||||
|
||||
/**
|
||||
* 终端信息
|
||||
*/
|
||||
@Data
|
||||
public static class TerminalInfo {
|
||||
/**
|
||||
* 终端版本号
|
||||
*/
|
||||
private String appVersion;
|
||||
/**
|
||||
* 终端位置地区编码
|
||||
*/
|
||||
private String areaNo;
|
||||
/**
|
||||
* 终端位置国家编码
|
||||
*/
|
||||
private String ctryNo;
|
||||
/**
|
||||
* 加密随机数
|
||||
*/
|
||||
private String encryptRandNum;
|
||||
/**
|
||||
* ICCID,SIM卡卡号
|
||||
*/
|
||||
private String iccId;
|
||||
/**
|
||||
* 基站编号 1
|
||||
*/
|
||||
private String lbsNum1;
|
||||
/**
|
||||
* 基站编号 2
|
||||
*/
|
||||
private String lbsNum2;
|
||||
/**
|
||||
* 基站编号 3
|
||||
*/
|
||||
private String lbsNum3;
|
||||
/**
|
||||
* 基站信号 1
|
||||
*/
|
||||
private String lbsSignal1;
|
||||
/**
|
||||
* 基站信号 2
|
||||
*/
|
||||
private String lbsSignal2;
|
||||
/**
|
||||
* 基站信号 3
|
||||
*/
|
||||
private String lbsSignal3;
|
||||
/**
|
||||
* 终端实时经纬度信息
|
||||
*/
|
||||
private String location;
|
||||
/**
|
||||
* 位置区域码 1
|
||||
*/
|
||||
private String locationCd1;
|
||||
/**
|
||||
* 位置区域码 2
|
||||
*/
|
||||
private String locationCd2;
|
||||
/**
|
||||
* 位置区域码 3
|
||||
*/
|
||||
private String locationCd3;
|
||||
/**
|
||||
* 基站信息,移动国家代码
|
||||
*/
|
||||
private String mobileCountryCd;
|
||||
/**
|
||||
* 基站信息,移动网络号码
|
||||
*/
|
||||
private String mobileNetNum;
|
||||
/**
|
||||
* 网络授权
|
||||
*/
|
||||
private String networkLicense;
|
||||
/**
|
||||
* 密钥文本
|
||||
*/
|
||||
private String secretText;
|
||||
/**
|
||||
* 终端序列号
|
||||
*/
|
||||
private String serialNum;
|
||||
/**
|
||||
* 电信基站信号
|
||||
*/
|
||||
private String telecomLbs;
|
||||
/**
|
||||
* 电信网络识别码
|
||||
*/
|
||||
private String telecomNetId;
|
||||
/**
|
||||
* 电信系统识别码
|
||||
*/
|
||||
private String telecomSysId;
|
||||
/**
|
||||
* 终端编号
|
||||
*/
|
||||
private String terminalId;
|
||||
/**
|
||||
* 终端IP,终端信息非必填,但如果送了终端信息,则terminalIp必填
|
||||
*/
|
||||
private String terminalIp;
|
||||
/**
|
||||
* 终端类型
|
||||
*/
|
||||
private String terminalType;
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.DelaySettleFlag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateInfo {
|
||||
|
||||
/**
|
||||
* 分账商户号,即发起分账方,分账资金来源方
|
||||
*/
|
||||
private String oriSeparateMchtCode;
|
||||
/**
|
||||
* 分账流水号,商户号下唯一
|
||||
*/
|
||||
private String separaBatchTrace;
|
||||
/**
|
||||
* 分账订单明细
|
||||
*/
|
||||
private List<SeparateOrderDetailList> separateOrderDetailList;
|
||||
/**
|
||||
* 分账订单总金额,单位分
|
||||
*/
|
||||
private long transSumAmt;
|
||||
/**
|
||||
* 分账订单总笔数
|
||||
*/
|
||||
private long transSumCount;
|
||||
|
||||
/**
|
||||
* 分账订单明细
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class SeparateOrderDetailList {
|
||||
|
||||
/**
|
||||
* 分账订单标题
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 分账D0标识,D0需提前开通
|
||||
*/
|
||||
private DelaySettleFlag isD0;
|
||||
/**
|
||||
* 分账收款方商户号,可以商户号或分账接收方编号
|
||||
*/
|
||||
private String receiveMchtCode;
|
||||
/**
|
||||
* 分账手续费承担本金金额,金额和比例2选1必填
|
||||
*/
|
||||
private Long sepaFeeAmount;
|
||||
/**
|
||||
* 分账手续费承担本金比例,金额和比例2选1必填,30代表30%,仅可上送整数
|
||||
*/
|
||||
private Long sepaFeeRatio;
|
||||
/**
|
||||
* 分账子单流水号
|
||||
*/
|
||||
private String separateTrade;
|
||||
/**
|
||||
* 分账比例,分账金额和分账比例2选一必填,30代表30%,仅可上送整数
|
||||
*/
|
||||
private Long sepaRatio;
|
||||
/**
|
||||
* 分账金额,分账金额和分账比例2选一必填,单位分
|
||||
*/
|
||||
private Long sepaTransAmount;
|
||||
/**
|
||||
* 分账订单描述
|
||||
*/
|
||||
private String subject;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.DelaySettleFlag;
|
||||
import com.wzj.soopin.transaction.enums.easypay.PatnerSettleFlag;
|
||||
import com.wzj.soopin.transaction.enums.easypay.SplitSettleFlag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 清算信息,三个标识互斥,三个标识互斥,最多仅能其中一个送是(非0)。
|
||||
* 合单支付时,主单清算标识(本字段)不起作用,以各子单的清算标识为准。
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SettleParamInfo {
|
||||
/**
|
||||
* 延时结算标识
|
||||
* {@link DelaySettleFlag}
|
||||
*/
|
||||
private String delaySettleFlag;
|
||||
/**
|
||||
* D0标识
|
||||
* {@link PatnerSettleFlag}
|
||||
*/
|
||||
private String patnerSettleFlag;
|
||||
/**
|
||||
* 分账标识
|
||||
* {@link SplitSettleFlag}
|
||||
*/
|
||||
private String splitSettleFlag;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.SpecialTag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Specialfee {
|
||||
|
||||
/**
|
||||
* 费用金额,单位分
|
||||
*/
|
||||
private long feeAmount;
|
||||
/**
|
||||
* 费用类型
|
||||
*/
|
||||
private SpecialTag specialTag;
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.WxLimitPay;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 微信业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class WxBizParam {
|
||||
|
||||
/**
|
||||
* 微信分配的公众账号ID,微信分配的公众账号ID(企业号corpid即为此appid)
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
*/
|
||||
private String attach;
|
||||
/**
|
||||
* 单品优惠功能字段
|
||||
*/
|
||||
private Detail detail;
|
||||
/**
|
||||
* 订单优惠标记,用于区分订单是否可以享受优惠,字段内容在微信后台配置券时进行设置
|
||||
*/
|
||||
private String goodsTag;
|
||||
/**
|
||||
* 实名信息
|
||||
*/
|
||||
private WxBizParamIdentity identity;
|
||||
/**
|
||||
* 是否支持发票
|
||||
*/
|
||||
private Boolean needReceip;
|
||||
/**
|
||||
* 用户标识
|
||||
*/
|
||||
private String openId;
|
||||
/**
|
||||
* 商品描述
|
||||
*/
|
||||
private String orderBody;
|
||||
/**
|
||||
* 微信场景信息,该字段用于上报场景信息,目前支持上报实际门店信息。该字段为JSON对象数据,对象格式为{"store_info":{"id": "门店ID","name":
|
||||
* "名称","area_code": "编码","address": "地址" }}
|
||||
*/
|
||||
private SceneInfo sceneInfo;
|
||||
/**
|
||||
* 微信分配的子商户公众账号ID
|
||||
*/
|
||||
private String subAppid;
|
||||
/**
|
||||
* 用户子标识,[点击查看获取openid](https://pay.weixin.qq.com/doc/v3/partner/4012081935)
|
||||
*/
|
||||
private String subOpenId;
|
||||
/**
|
||||
* 交易限制支付类型
|
||||
*/
|
||||
private WxLimitPay wxLimitPay;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 单品优惠功能字段
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class Detail {
|
||||
/**
|
||||
* 订单原价,1.商户侧一张小票订单可能被分多次支付,订单原价用于记录整张小票的交易金额。<br />2.当订单原价与支付金额不相等,则不享受优惠。<br
|
||||
* />3.该字段主要用于防止同一张小票分多次支付,以享受多次优惠的情况,正常支付订单不必上传此参数。
|
||||
*/
|
||||
private Long costPrice;
|
||||
/**
|
||||
* 单品列表,单品信息,使用Json数组格式提交
|
||||
*/
|
||||
private List<GoodsDetail> goodsDetail;
|
||||
/**
|
||||
* 商家小票ID,商家小票ID
|
||||
*/
|
||||
private String receiptid;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class GoodsDetail {
|
||||
/**
|
||||
* 商品编码,由半角的大小写字母、数字、中划线、下划线中的一种或几种组成
|
||||
*/
|
||||
private String goodsid;
|
||||
/**
|
||||
* 商品名称,商品的实际名称
|
||||
*/
|
||||
private String goodsName;
|
||||
/**
|
||||
* 商品单价,单位为:分。如果商户有优惠,需传输商户优惠后的单价(例如:用户对一笔100元的订单使用了商场发的优惠券100-50,则活动商品的单价应为原单价-50)
|
||||
*/
|
||||
private Long price;
|
||||
/**
|
||||
* 商品数量,用户购买的数量
|
||||
*/
|
||||
private Long quantity;
|
||||
/**
|
||||
* 微信侧商品编码,微信支付定义的统一商品编号(没有可不传)
|
||||
*/
|
||||
private String wxpayGoodsid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实名信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class WxBizParamIdentity {
|
||||
/**
|
||||
* 证件号
|
||||
*/
|
||||
private String certNo;
|
||||
/**
|
||||
* 证件类型
|
||||
*/
|
||||
private String certType;
|
||||
/**
|
||||
* 数字信封
|
||||
*/
|
||||
private String dgtlEnvlp;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信场景信息,该字段用于上报场景信息,目前支持上报实际门店信息。该字段为JSON对象数据,对象格式为{"store_info":{"id": "门店ID","name":
|
||||
* "名称","area_code": "编码","address": "地址" }}
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class SceneInfo {
|
||||
/**
|
||||
* 商户端设备号,商户端设备号
|
||||
*/
|
||||
private String deviceid;
|
||||
/**
|
||||
* 用户的客户端IP,用户的客户端IP
|
||||
*/
|
||||
private String payerClientip;
|
||||
/**
|
||||
* 门店信息,门店信息
|
||||
*/
|
||||
private StoreInfo storeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店信息,门店信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class StoreInfo {
|
||||
/**
|
||||
* 门店详细地址,门店详细地址
|
||||
*/
|
||||
private String address;
|
||||
/**
|
||||
* 门店所在地行政区划码,门店所在地行政区划码
|
||||
*/
|
||||
private String areaCode;
|
||||
/**
|
||||
* 门店唯一标识,门店唯一标识
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 门店名称,门店名称
|
||||
*/
|
||||
private String name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* ali业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class AliRespParamInfo {
|
||||
|
||||
/**
|
||||
* 调起支付宝支付参数,调起支付宝支付参考
|
||||
* [附录F.15](https://apifox.com/apidoc/shared/9758ecc8-2c38-4ec6-914f-b09be6f563bc/doc-5662571)
|
||||
*/
|
||||
private String tradeNo;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* JSAPI支付接口响应
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class JsApiRespBody {
|
||||
|
||||
/**
|
||||
* 返回码信息,规则详见F.1
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private JsapiRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* ali业务参数
|
||||
*/
|
||||
private AliRespParamInfo aliRespParamInfo;
|
||||
/**
|
||||
* wx业务参数
|
||||
*/
|
||||
private WxJsApiRespParamInfoVO wxRespParamInfo;
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
private QrJsApiRespParamInfoVO qrRespParamInfo;
|
||||
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.AddCalcType;
|
||||
import com.wzj.soopin.transaction.enums.easypay.BillingCycle;
|
||||
import com.wzj.soopin.transaction.enums.easypay.CardType;
|
||||
import com.wzj.soopin.transaction.enums.easypay.FeeType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class JsapiRespOrderInfo {
|
||||
/**
|
||||
* 商户费率信息
|
||||
*/
|
||||
private Empty mchtRateList;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 易生订单号,易生生成后上送渠道的订单号
|
||||
*/
|
||||
private String outTrace;
|
||||
/**
|
||||
* 渠道订单号,渠道生成返回给易生的订单号,例如微信、支付宝订单号
|
||||
*/
|
||||
private String pcTrace;
|
||||
/**
|
||||
* 产品订单号,易生系统内流转的订单号求易生的流水号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 交易金额,单位分
|
||||
*/
|
||||
private Long transAmount;
|
||||
/**
|
||||
* 银联订单号
|
||||
*/
|
||||
private String unTrace;
|
||||
|
||||
/**
|
||||
* 商户费率信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
private static class Empty {
|
||||
|
||||
/**
|
||||
* 附加手续费计算方式
|
||||
*/
|
||||
private AddCalcType addCalcType;
|
||||
/**
|
||||
* 附加手续费值,单位:分
|
||||
*/
|
||||
private String addCalcVal;
|
||||
/**
|
||||
* 交易金额最高值,单位:分
|
||||
*/
|
||||
private String amtHighLt;
|
||||
/**
|
||||
* 交易金额最低值,单位:分
|
||||
*/
|
||||
private String amtLowLt;
|
||||
/**
|
||||
* 结算周期
|
||||
*/
|
||||
private BillingCycle billingCycle;
|
||||
/**
|
||||
* 手续费计算方式
|
||||
*/
|
||||
private AddCalcType calcType;
|
||||
/**
|
||||
* 手续费费率值,按笔单位为分;按比例为百万比
|
||||
*/
|
||||
private String calcVal;
|
||||
/**
|
||||
* 卡机构编号,见F.10
|
||||
*/
|
||||
private String cardIssuerCode;
|
||||
/**
|
||||
* 卡类型
|
||||
*/
|
||||
private CardType cardType;
|
||||
/**
|
||||
* 生效时间
|
||||
*/
|
||||
private String effDatetime;
|
||||
/**
|
||||
* 失效时间
|
||||
*/
|
||||
private String expDatetime;
|
||||
/**
|
||||
* 手续费处理模式
|
||||
*/
|
||||
private String feeCalcMode;
|
||||
/**
|
||||
* 手续费最高值,单位:分
|
||||
*/
|
||||
private String feeHighLimit;
|
||||
/**
|
||||
* feeId
|
||||
*/
|
||||
private String feeId;
|
||||
/**
|
||||
* 手续费承担机构
|
||||
*/
|
||||
private String feeInst;
|
||||
/**
|
||||
* 手续费最低值,单位:分
|
||||
*/
|
||||
private String feeLowLimit;
|
||||
/**
|
||||
* 手续费费用类型
|
||||
*/
|
||||
private AddCalcType feeMode;
|
||||
/**
|
||||
* 手续费处理模式
|
||||
*/
|
||||
private FeeType feeType;
|
||||
/**
|
||||
* 分期期数
|
||||
*/
|
||||
private String instalNum;
|
||||
/**
|
||||
* 是否需求配置费率
|
||||
*/
|
||||
private String isNeedConfigFee;
|
||||
/**
|
||||
* 是否允许退货
|
||||
*/
|
||||
private AddCalcType isRefundFee;
|
||||
/**
|
||||
* 优先级
|
||||
*/
|
||||
private String levelOrder;
|
||||
/**
|
||||
* 内部商户号
|
||||
*/
|
||||
private String mchtCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class QrJsApiRespParamInfoVO {
|
||||
|
||||
/**
|
||||
* 云闪付支付调用凭证,payType=UnionPayJsMini时,需要用此参数拼接跳转至云微小程序,具体跳转方法见F.17.
|
||||
*/
|
||||
private String qrRedirectUrl;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.jsapi.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* wx业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class WxJsApiRespParamInfoVO {
|
||||
/**
|
||||
* 调起微信支付参数,调起微信支付调起参考
|
||||
* [附录F.15](https://apifox.com/apidoc/shared/9758ecc8-2c38-4ec6-914f-b09be6f563bc/doc-5662571)
|
||||
*/
|
||||
private String wcPayData;
|
||||
|
||||
/**
|
||||
* 预支付交易会话标识
|
||||
*/
|
||||
private String prepayId;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AT交易退货请求扩展信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class QrCodeRefundExt {
|
||||
/**
|
||||
* 退款货币种类
|
||||
*/
|
||||
private String currency;
|
||||
/**
|
||||
* 商品详情列表
|
||||
*/
|
||||
private List<GoodsDetail> goodsDetail;
|
||||
/**
|
||||
* 商户的操作员编号
|
||||
*/
|
||||
private String operatorId;
|
||||
/**
|
||||
* 查询选项
|
||||
*/
|
||||
private List<String> queryOption;
|
||||
/**
|
||||
* 退款原因
|
||||
*/
|
||||
private String refundReason;
|
||||
/**
|
||||
* 商户的门店编号
|
||||
*/
|
||||
private String storeCode;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class GoodsDetail {
|
||||
/**
|
||||
* 支付宝定义的统一商品编号
|
||||
*/
|
||||
private String alipayGoodsid;
|
||||
/**
|
||||
* 商品描述信息
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 商品类目树
|
||||
*/
|
||||
private String categoriesTree;
|
||||
/**
|
||||
* 商品类目
|
||||
*/
|
||||
private String goodsCategory;
|
||||
/**
|
||||
* 商品的编号
|
||||
*/
|
||||
private String goodsid;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String goodsName;
|
||||
/**
|
||||
* 商品单价(单位:元)
|
||||
*/
|
||||
private Double price;
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
private Long quantity;
|
||||
/**
|
||||
* 商品的展示地址
|
||||
*/
|
||||
private String showurl;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 发起退款请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundApplyReqBody {
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private RefundReqOrderInfo reqOrderInfo;
|
||||
/**
|
||||
* AT交易退货请求扩展信息
|
||||
*/
|
||||
private QrCodeRefundExt qrCodeRefundExt;
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundReqOrderInfo {
|
||||
/**
|
||||
* 下游手续费
|
||||
*/
|
||||
private Double handlingFee;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原商户订单号,传的是支付交易的orgTrace,代表要退哪笔支付交易, 可以是主单订单号和子单订单号
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 原订单outTrace,oriOrgTrace与oriOutTrace二选一必填
|
||||
*/
|
||||
private String oriOutTrace;
|
||||
/**
|
||||
* 原业务日期,原交易业务日期,格式:yyyyMMdd
|
||||
*/
|
||||
private String oriTransDate;
|
||||
/**
|
||||
* 退款金额,单位分 separate
|
||||
*/
|
||||
private long refundAmount;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.SettleRespParamInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 发起退款响应体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundApplyRespBody {
|
||||
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private RefundRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息,详见
|
||||
* [附录F.1](https://apifox.com/apidoc/shared/9758ecc8-2c38-4ec6-914f-b09be6f563bc/doc-5523713)
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
/**
|
||||
* 清算信息
|
||||
*/
|
||||
private SettleRespParamInfo settleRespParamInfo;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundRespOrderInfo {
|
||||
/**
|
||||
* 请求方自定义信息
|
||||
*/
|
||||
private String orgInfo;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原商户订单号
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 原易生订单号
|
||||
*/
|
||||
private String oriOutTrace;
|
||||
/**
|
||||
* 易生订单号,易生生成后上送渠道的订单号
|
||||
*/
|
||||
private String outTrace;
|
||||
/**
|
||||
* 渠道订单号,渠道生成返回给易生的订单号,例如微信、支付宝订单号
|
||||
*/
|
||||
private String pcTrace;
|
||||
/**
|
||||
* 产品订单号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 退货金额,单位分
|
||||
*/
|
||||
private Long refundAmount;
|
||||
/**
|
||||
* 银联订单号
|
||||
*/
|
||||
private String unTrace;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.refund.query.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req.RefundReqOrderInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 退款查询请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundQueryReqBody {
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private RefundReqOrderInfo reqOrderInfo;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 发起分账请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateApplyReqBody {
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private SeparateReqOrderInfo reqOrderInfo;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req.SeparateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateReqOrderInfo {
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
private String backUrl;
|
||||
/**
|
||||
* 原商户交易的orgTrace,需要对哪笔交易进行分账,就传那笔交易的orgTrace。就是支付交易的orgTrace
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 原商户交易日期
|
||||
*/
|
||||
private String oriTransDate;
|
||||
/**
|
||||
* 营销信息,仅支持ToB营销活动
|
||||
*/
|
||||
private List<PromoList> promoList;
|
||||
/**
|
||||
* 分账总单流水号,分账批次号,自定义,要唯一
|
||||
*/
|
||||
private String separateBatchTrace;
|
||||
/**
|
||||
* 分账子单明细,可送多条
|
||||
*/
|
||||
private List<SeparateInfo.SeparateOrderDetailList> separateOrderDetailList;
|
||||
/**
|
||||
* 分账订单总金额,单位分
|
||||
*/
|
||||
private long transSumAmt;
|
||||
/**
|
||||
* 分账订单总笔数
|
||||
*/
|
||||
private long transSumCount;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class PromoList {
|
||||
/**
|
||||
* 营销ID
|
||||
*/
|
||||
private String promoCode;
|
||||
/**
|
||||
* 营销手续费金额
|
||||
*/
|
||||
private long promoFeeAmount;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 发起分账响应体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateApplyRespBody {
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private SeparateRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.DelaySettleFlag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateRespInfoList {
|
||||
/**
|
||||
* 分账单标题
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 分账D0标识
|
||||
*/
|
||||
private DelaySettleFlag isD0;
|
||||
/**
|
||||
* 分账收款方商户号
|
||||
*/
|
||||
private String receiveMchtCode;
|
||||
/**
|
||||
* 当前分账单已退款金额总计
|
||||
*/
|
||||
private Long refundAmountSum;
|
||||
/**
|
||||
* 分账手续费承担本金金额
|
||||
*/
|
||||
private Long sepaFeeAmount;
|
||||
/**
|
||||
* 分账手续费承担本金比例
|
||||
*/
|
||||
private Long sepaFeeRatio;
|
||||
/**
|
||||
* 分账平台应结金额
|
||||
*/
|
||||
private Long sepaPlatStlmAmount;
|
||||
/**
|
||||
* 分账单流水号,同一日期内唯一,否则会因流水号重复而失败
|
||||
*/
|
||||
private String separateTrade;
|
||||
/**
|
||||
* 分账比例
|
||||
*/
|
||||
private Long sepaRatio;
|
||||
/**
|
||||
* 分账单状态,(处理中、成功、失败、已退款)
|
||||
*/
|
||||
private String sepaStatus;
|
||||
/**
|
||||
* 分账单状态说明
|
||||
*/
|
||||
private String sepaStatusDesc;
|
||||
/**
|
||||
* 分账实际结算金额
|
||||
*/
|
||||
private Long sepaStlmAmount;
|
||||
/**
|
||||
* 分账金额,单位分
|
||||
*/
|
||||
private Long sepaTransAmount;
|
||||
/**
|
||||
* 分账订单描述
|
||||
*/
|
||||
private String subject;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateRespOrderInfo {
|
||||
|
||||
/**
|
||||
* 同批次分账笔数
|
||||
*/
|
||||
private Long batchNum;
|
||||
/**
|
||||
* 同批次分账金额合计
|
||||
*/
|
||||
private Long batchTransAmount;
|
||||
/**
|
||||
* 原商户交易的orgTrace
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 产品订单号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 分账商户批次号,同一日期内唯一,否则会因为流水号重复失败
|
||||
*/
|
||||
private String separateBatchTrace;
|
||||
/**
|
||||
* 分账单信息列表
|
||||
*/
|
||||
private List<SeparateRespInfoList> separateRespInfoList;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.cancel.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CancelReqOrderInfo {
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原分账总单流水
|
||||
*/
|
||||
private String oriSeparateBatchTrace;
|
||||
/**
|
||||
* 原分账子单流水号
|
||||
*/
|
||||
private String oriSeparateTrade;
|
||||
/**
|
||||
* 原业务日期
|
||||
*/
|
||||
private String oriTransDate;
|
||||
/**
|
||||
* 回退金额
|
||||
*/
|
||||
private long refundAmount;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.cancel.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账回退请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateCancelReqBody {
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private CancelReqOrderInfo reqOrderInfo;
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.cancel.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CancelRespOrderInfo {
|
||||
/**
|
||||
* 同批次分账笔数
|
||||
*/
|
||||
private Long batchNum;
|
||||
/**
|
||||
* 同批次分账金额合计
|
||||
*/
|
||||
private Long batchTransAmount;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号,每次都要唯一
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原商户订单号
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 产品订单号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 原分账批次号,原分账总单流水号
|
||||
*/
|
||||
private String separateBatchTrace;
|
||||
/**
|
||||
* 分账单信息列表
|
||||
*/
|
||||
private List<SeparateRespInfoList> separateRespInfoList;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class SeparateRespInfoList {
|
||||
/**
|
||||
* 分账订单标题,请求方上送
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 分账-秒到标识(1:是 0:否)
|
||||
*/
|
||||
private String isD0;
|
||||
/**
|
||||
* 分账收款方商户号,请求方上送
|
||||
*/
|
||||
private String receiveMchtCode;
|
||||
/**
|
||||
* 当前分账单已退款金额总计
|
||||
*/
|
||||
private Long refundAmountSum;
|
||||
/**
|
||||
* 分账手续费承担金额(金额和比例都支持传,2选1),根据资产单金额来算比例,请求方上送
|
||||
*/
|
||||
private Long sepaFeeAmount;
|
||||
/**
|
||||
* 分账手续费承担比例(金额和比例都支持传,2选1),30代表百万分之30,请求方上送
|
||||
*/
|
||||
private Long sepaFeeRatio;
|
||||
/**
|
||||
* 分账平台应结金额
|
||||
*/
|
||||
private Long sepaPlatStlmAmount;
|
||||
/**
|
||||
* 分账单商户订单号,请求方上送
|
||||
*/
|
||||
private String separateTrade;
|
||||
/**
|
||||
* 分账比例,请求方上送
|
||||
*/
|
||||
private Long sepaRatio;
|
||||
/**
|
||||
* 分账单状态(处理中、成功、失败、已退款)
|
||||
*/
|
||||
private String sepaStatus;
|
||||
/**
|
||||
* 分账单状态说明
|
||||
*/
|
||||
private String sepaStatusDesc;
|
||||
/**
|
||||
* 分账实际结算金额
|
||||
*/
|
||||
private Long sepaStlmAmount;
|
||||
/**
|
||||
* 分账金额,请求方上送
|
||||
*/
|
||||
private Long sepaTransAmount;
|
||||
/**
|
||||
* 分账订单描述,请求方上送
|
||||
*/
|
||||
private String subject;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.cancel.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账回退响应体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateCancelRespBody {
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private CancelRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.query.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CancelQueryReqOrderInfo {
|
||||
/**
|
||||
* 原分账批次流水separateBatchTrace,原分账总单流水号
|
||||
*/
|
||||
private String oriSeparateBatchTrace;
|
||||
/**
|
||||
* 原请求分账日期
|
||||
*/
|
||||
private String oriTransDate;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.query.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账查询请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateQueryReqBody {
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private CancelQueryReqOrderInfo reqOrderInfo;
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.query.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.enums.easypay.SepaStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class CancelQueryRespOrderInfo {
|
||||
/**
|
||||
* 同批次分账笔数
|
||||
*/
|
||||
private Long batchNum;
|
||||
/**
|
||||
* 同批次分账金额合计
|
||||
*/
|
||||
private Long batchTransAmount;
|
||||
/**
|
||||
* 分账总单流水号
|
||||
*/
|
||||
private String oriSeparateBatchTrace;
|
||||
/**
|
||||
* 产品订单号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 分账单信息列表
|
||||
*/
|
||||
private List<SeparateRespInfoList> separateRespInfoList;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class SeparateRespInfoList {
|
||||
/**
|
||||
* 分账订单标题
|
||||
*/
|
||||
private String body;
|
||||
/**
|
||||
* 分账D0标识
|
||||
*/
|
||||
private String isD0;
|
||||
/**
|
||||
* 分账收款方商户号
|
||||
*/
|
||||
private String receiveMchtCode;
|
||||
/**
|
||||
* 当前分账单已退款金额总计
|
||||
*/
|
||||
private Long refundAmountSum;
|
||||
/**
|
||||
* 分账手续费承担本金金额
|
||||
*/
|
||||
private Long sepaFeeAmount;
|
||||
/**
|
||||
* 分账手续费承担本金比例
|
||||
*/
|
||||
private Long sepaFeeRatio;
|
||||
/**
|
||||
* 分账平台应结金额
|
||||
*/
|
||||
private Long sepaPlatStlmAmount;
|
||||
/**
|
||||
* 分账单商户订单号
|
||||
*/
|
||||
private String separateTrade;
|
||||
/**
|
||||
* 分账比例
|
||||
*/
|
||||
private Long sepaRatio;
|
||||
/**
|
||||
* 分账单状态,(处理中、成功、失败、已退款)
|
||||
*/
|
||||
private SepaStatus sepaStatus;
|
||||
/**
|
||||
* 分账单状态说明
|
||||
*/
|
||||
private String sepaStatusDesc;
|
||||
/**
|
||||
* 分账实际结算金额
|
||||
*/
|
||||
private Long sepaStlmAmount;
|
||||
/**
|
||||
* 分账金额
|
||||
*/
|
||||
private Long sepaTransAmount;
|
||||
/**
|
||||
* 分账订单描述
|
||||
*/
|
||||
private String subject;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.query.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 查询分账响应体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateQueryRespBody {
|
||||
/**
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private CancelQueryRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.notice.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req.Promo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易结果通知请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TradeNoticeReqBody {
|
||||
/**
|
||||
* ali业务参数
|
||||
*/
|
||||
private AliQueryRespParamInfoVO aliRespParamInfo;
|
||||
/**
|
||||
* toC营销信息
|
||||
*/
|
||||
private List<MarketingParamInfo> marketingRespParamInfoList;
|
||||
/**
|
||||
* toB营销信息
|
||||
*/
|
||||
private List<Promo> promos;
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
private QrRespParamInfoVO qrRespParamInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private TradeQueryRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息,规则详见F.1
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
/**
|
||||
* 风险控制信息
|
||||
*/
|
||||
private RiskInfo riskParamInfo;
|
||||
/**
|
||||
* 清算信息
|
||||
*/
|
||||
private SettleRespParamInfo settleRespParamInfo;
|
||||
/**
|
||||
* wx业务参数
|
||||
*/
|
||||
private WxQueryRespParamInfoVO wxRespParamInfo;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 交易查询请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TradeQueryReqBody {
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private ReqOrderInfo reqOrderInfo;
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class ReqOrderInfo {
|
||||
/**
|
||||
* 商户订单号,要唯一,代表本次请求
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原商户交易的orgTrace,需要查询哪笔交易,就传那笔交易的orgTrace
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
/**
|
||||
* 原订单outTrace,oriOrgTrace与oriOutTrace二选一必填
|
||||
*/
|
||||
private String oriOutTrace;
|
||||
/**
|
||||
* 原商户交易日期,yyyyMMdd
|
||||
*/
|
||||
private String oriTransDate;
|
||||
}
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class AliQueryRespParamInfoVO {
|
||||
/**
|
||||
* 支付宝店铺编号 支付宝支付能力出现
|
||||
*/
|
||||
private String alipayStoreId;
|
||||
/**
|
||||
* 买家的支付宝唯一用户号
|
||||
*/
|
||||
private String buyerId;
|
||||
/**
|
||||
* 买方登录ID
|
||||
*/
|
||||
private String buyerLogonId;
|
||||
/**
|
||||
* 费率活动标识
|
||||
*/
|
||||
private String chargeFlags;
|
||||
/**
|
||||
* 支付货币类型 默认人民 币: CNY,网联微信&银联微信,必填;网联支付宝&银联支付宝,选填,币种
|
||||
*/
|
||||
private String currency;
|
||||
private AliDiscountsInfoVO discountsInfo;
|
||||
/**
|
||||
* 交易额外信息 网联支付宝渠道出现 特殊场景下与支付宝约定返回。 json字符串
|
||||
*/
|
||||
private String extInfos;
|
||||
private List<FundBillVO> fundBillList;
|
||||
private HbFqPayInfo hbFqPayInfo;
|
||||
/**
|
||||
* 行业特殊信息 支付宝能力出现( 例如在医保卡 支付业务中, 向用户返回医疗信息)
|
||||
*/
|
||||
private String industrySepcDetail;
|
||||
/**
|
||||
* 结算币种兑换标价币种汇率
|
||||
*/
|
||||
private String settleTransRate;
|
||||
/**
|
||||
* 商户门店编号 支付宝支付能力出现
|
||||
*/
|
||||
private String storeId;
|
||||
/**
|
||||
* 发生支付交易的商户门店名称
|
||||
*/
|
||||
private String storeName;
|
||||
/**
|
||||
* 商户机具终端编号 银联支付宝支付能力出现
|
||||
*/
|
||||
private String terminalId;
|
||||
/**
|
||||
* 标价币种兑换支付币种汇率
|
||||
*/
|
||||
private String transPayRate;
|
||||
/**
|
||||
* 买家名称 银联支付宝支付能力出现
|
||||
*/
|
||||
private String userName;
|
||||
/**
|
||||
* 买家用户类型
|
||||
*/
|
||||
private String userType;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class AliDiscountsInfoVO {
|
||||
|
||||
/**
|
||||
* 商家优惠金额
|
||||
*/
|
||||
private Long mchtDiscountAmount;
|
||||
/**
|
||||
* 平台优惠金额
|
||||
*/
|
||||
private Long platDiscountAmount;
|
||||
/**
|
||||
* 优惠信息
|
||||
*/
|
||||
private List<AliDiscountsDetailVO> promotionDetail;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class FundBillVO {
|
||||
/**
|
||||
* 该支付工具类型所使用的金额
|
||||
*/
|
||||
private Long amount;
|
||||
/**
|
||||
* 银行卡支付时的银行代码
|
||||
*/
|
||||
private String bankCode;
|
||||
/**
|
||||
* 交易使用的资金渠道
|
||||
*/
|
||||
private String fundChannel;
|
||||
/**
|
||||
* 渠道所使用的资金类型
|
||||
*/
|
||||
private String fundType;
|
||||
/**
|
||||
* 渠道实际付款金额
|
||||
*/
|
||||
private Long realAmount;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class HbFqPayInfo {
|
||||
/**
|
||||
* 分期金额
|
||||
*/
|
||||
private Long fqAmount;
|
||||
/**
|
||||
* 花呗分期数
|
||||
*/
|
||||
private Long hbFqNum;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class AliDiscountsDetailVO {
|
||||
/**
|
||||
* 活动ID
|
||||
*/
|
||||
private String activityId;
|
||||
/**
|
||||
* 优惠券面额
|
||||
*/
|
||||
private Long amount;
|
||||
/**
|
||||
* 优惠券备注信息
|
||||
*/
|
||||
private String memo;
|
||||
/**
|
||||
* 商户出资
|
||||
*/
|
||||
private Long merchantContribute;
|
||||
/**
|
||||
* 优惠名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 其他出资方出资金额
|
||||
*/
|
||||
private Long otherContribute;
|
||||
/**
|
||||
* 其他出资
|
||||
*/
|
||||
private List<OtherContribute> otherContributeDetails;
|
||||
/**
|
||||
* 券ID
|
||||
*/
|
||||
private String promotionId;
|
||||
/**
|
||||
* 如果使用的这张券是用户购买的,则该字段代表用户在购买这张券时平台优惠的金额
|
||||
*/
|
||||
private Long purchaseAntContribute;
|
||||
/**
|
||||
* 如果使用的这张券是用户购买的,则该字段代表用户在购买这张券时用户实际付款的金额
|
||||
*/
|
||||
private Long purchaseBuyerContribute;
|
||||
/**
|
||||
* 如果使用的这张券是用户购买的,则该字段代表用户在购买这张券时商户优惠的金额
|
||||
*/
|
||||
private Long purchaseMerchanCcontribute;
|
||||
/**
|
||||
* 优惠类型
|
||||
*/
|
||||
private String type;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class OtherContribute {
|
||||
/**
|
||||
* 出资金额
|
||||
*/
|
||||
private Long contributeAmount;
|
||||
/**
|
||||
* 出资类型
|
||||
*/
|
||||
private String contributeType;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 营销单返回
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class MarketingParamInfo {
|
||||
/**
|
||||
* 活动id
|
||||
*/
|
||||
private Double activityId;
|
||||
/**
|
||||
* 营销币种
|
||||
*/
|
||||
private String currency;
|
||||
/**
|
||||
* 营销业务场景码
|
||||
*/
|
||||
private String marketingBusinessSceneCode;
|
||||
/**
|
||||
* 营销支付能力编号
|
||||
*/
|
||||
private String marketingPayAbilityCode;
|
||||
/**
|
||||
* 营销支付方式编号
|
||||
*/
|
||||
private String marketingPayMethodCode;
|
||||
/**
|
||||
* 营销报名id
|
||||
*/
|
||||
private Double registrationId;
|
||||
/**
|
||||
* 收银台营销请求扩展信息
|
||||
*/
|
||||
private Map<String, Map<String, Object>> respMarketingExtInfo;
|
||||
/**
|
||||
* 营销金额
|
||||
*/
|
||||
private Double transAmount;
|
||||
private String upOrderNo;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 子单返回信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class MergeOrderSubRespList {
|
||||
|
||||
/**
|
||||
* 订单币种,默认CNY
|
||||
*/
|
||||
private String currency;
|
||||
/**
|
||||
* 延时结算标识
|
||||
*/
|
||||
private String delaySettleFlag;
|
||||
/**
|
||||
* 秒到标识
|
||||
*/
|
||||
private String patnerSettleFlag;
|
||||
/**
|
||||
* 分账标识
|
||||
*/
|
||||
private String splitSettleFlag;
|
||||
/**
|
||||
* 子单请求流水号
|
||||
*/
|
||||
private String subOrgTrace;
|
||||
/**
|
||||
* 订单金额
|
||||
*/
|
||||
private String transAmount;
|
||||
/**
|
||||
* 交易状态码
|
||||
*/
|
||||
private String transState;
|
||||
/**
|
||||
* 交易状态说明
|
||||
*/
|
||||
private String transStatusDesc;
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class QrRespParamInfoVO {
|
||||
|
||||
private List<QrDiscountsDetailVO> discountsInfo;
|
||||
/**
|
||||
* QrPayerInfoInner
|
||||
*/
|
||||
private QrPayerInfo qrPayerInfo;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class QrDiscountsDetailVO {
|
||||
/**
|
||||
* 活动id
|
||||
*/
|
||||
private String activityId;
|
||||
/**
|
||||
* 附件信息
|
||||
*/
|
||||
private String addnInfo;
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private Long amount;
|
||||
/**
|
||||
* 项目发行,发行优惠活动的平台或机构,取值如下:
|
||||
* 银联卡券平台:固定填写KQPT
|
||||
* 付款方:填写8 位付款方机构代码
|
||||
*/
|
||||
private String issuerId;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 营销活动id
|
||||
*/
|
||||
private String promotionId;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private String type;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class QrPayerInfo {
|
||||
/**
|
||||
* 卡号
|
||||
*/
|
||||
private String accNo;
|
||||
/**
|
||||
* 账户类型
|
||||
*/
|
||||
private String acctClass;
|
||||
/**
|
||||
* 卡属性,01 – 借记卡
|
||||
* 02 – 贷记卡(含准贷记卡)
|
||||
*/
|
||||
private String cardAttr;
|
||||
/**
|
||||
* 证件号码,可选
|
||||
* 取证件号后6 位数字,
|
||||
* 再左补0 到与原证件号
|
||||
* 相同长度
|
||||
*/
|
||||
private String certifId;
|
||||
/**
|
||||
* 证件类型
|
||||
*/
|
||||
private String certifTp;
|
||||
/**
|
||||
* cvn2
|
||||
*/
|
||||
private String cvn2;
|
||||
/**
|
||||
* 卡有效期
|
||||
*/
|
||||
private String expired;
|
||||
/**
|
||||
* 付款方机构代码,代表付款方机构。
|
||||
*/
|
||||
private String issCode;
|
||||
/**
|
||||
* 手机号,必选
|
||||
* 银行卡预留手机号码,
|
||||
* 11 位,不包括+86 等信
|
||||
* 息。银联将根据综合情
|
||||
* 况决定是否送发卡行
|
||||
* 验证
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 付款银行信息
|
||||
*/
|
||||
private String payerBankInfo;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 风险控制信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RiskInfo {
|
||||
|
||||
/**
|
||||
* 终端IP
|
||||
* 绑卡设备(付款 APP)所在的公网 IP,可用于
|
||||
* 定位所属地区,不是 wifi 连接时的局域网 IP。
|
||||
* 局域网 IP 包括:
|
||||
* A 类:10.0.0.0-10.255.255.255
|
||||
* B 类:172.16.0.0-172.31.255.255
|
||||
* C 类:192.168.0.0-192.168.255.255
|
||||
*/
|
||||
private String terminalIp;
|
||||
/**
|
||||
* 终端位置 (付款 APP)设备 GPS 位置,格式为纬度/经度, +表示北纬、东经,-表示南纬、西经
|
||||
*/
|
||||
private String terminalLocation;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 清算信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SettleRespParamInfo {
|
||||
/**
|
||||
* 延迟结算标识,(1:是 0:否)
|
||||
*/
|
||||
private String delaySettleFlag;
|
||||
/**
|
||||
* D0标识,(1:是 0:否)
|
||||
*/
|
||||
private String patnerSettleFlag;
|
||||
/**
|
||||
* 分账标识,(1:交易后分账 2:交易中分账 0:非分账交易)
|
||||
*/
|
||||
private String splitSettleFlag;
|
||||
/**
|
||||
* 手续费金额
|
||||
*/
|
||||
private Long fee;
|
||||
/**
|
||||
* 清算金额,含手续费的金额
|
||||
*/
|
||||
private Long settleAmt;
|
||||
/**
|
||||
* 结算金额,单位分.扣除手续费后的金额
|
||||
*/
|
||||
private Long finalAmt;
|
||||
/**
|
||||
* 支付完成/清算 日期,yyMMdd
|
||||
*/
|
||||
private String settleDate;
|
||||
/**
|
||||
* 支付完成/清算时间,HHMMSS
|
||||
*/
|
||||
private String settleTime;
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.jsapi.req.Promo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易查询响应
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TradeQueryRespBody {
|
||||
/**
|
||||
* ali业务参数
|
||||
*/
|
||||
private AliQueryRespParamInfoVO aliRespParamInfo;
|
||||
/**
|
||||
* toC营销信息
|
||||
*/
|
||||
private List<MarketingParamInfo> marketingRespParamInfoList;
|
||||
/**
|
||||
* 子单返回信息
|
||||
*/
|
||||
private MergeOrderSubRespList mergeOrderSubRespList;
|
||||
/**
|
||||
* toB营销信息
|
||||
*/
|
||||
private List<Promo> promos;
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
private QrRespParamInfoVO qrRespParamInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private TradeQueryRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息,规则详见F.1
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
/**
|
||||
* 风险控制信息
|
||||
*/
|
||||
private RiskInfo riskParamInfo;
|
||||
/**
|
||||
* 清算信息
|
||||
*/
|
||||
private SettleRespParamInfo settleRespParamInfo;
|
||||
/**
|
||||
* wx业务参数
|
||||
*/
|
||||
private WxQueryRespParamInfoVO wxRespParamInfo;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TradeQueryRespOrderInfo {
|
||||
|
||||
/**
|
||||
* 付款卡类型,详见F.9
|
||||
*/
|
||||
private String cardType;
|
||||
/**
|
||||
* 支付完成日期
|
||||
*/
|
||||
private String dateEnd;
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 易生订单号,易生生成后上送渠道的订单号
|
||||
*/
|
||||
private String outTrace;
|
||||
/**
|
||||
* 实际付款金额,用户实付金额,与订单是否参与渠道优惠活动有关。比如当订单发起金额1000,参加渠道用户减免100,实际付款金额为900。
|
||||
*/
|
||||
private Long payAmount;
|
||||
/**
|
||||
* 渠道订单号,渠道生成返回给易生的订单号,例如微信、支付宝订单号
|
||||
*/
|
||||
private String pcTrace;
|
||||
/**
|
||||
* 产品订单号
|
||||
*/
|
||||
private String productTrace;
|
||||
/**
|
||||
* 已退款金额总额
|
||||
*/
|
||||
private Long refundAmountSum;
|
||||
/**
|
||||
* 已分账金额总额
|
||||
*/
|
||||
private Long separateAmountSum;
|
||||
/**
|
||||
* 应结订单金额,上游渠道清算金额,与订单是否参与上游渠道优惠活动有关。
|
||||
* 1、假如一笔微信订单1000,参与了微信的满减1000-100,比如由银行出资,微信会按1000给我们结算,这个应结金额=1000。
|
||||
* 2、假如一笔微信订单1000,由商户自己在微信那边配了营销活动,且配的是从商户的结算款扣除营销款,这时候微信按900来款,应结金额=900
|
||||
*/
|
||||
private Long stlmAmount;
|
||||
/**
|
||||
* 已结算金额总额
|
||||
*/
|
||||
private Long stlmAmountSum;
|
||||
/**
|
||||
* 支付完成/清算时间
|
||||
*/
|
||||
private String timeEnd;
|
||||
/**
|
||||
* 交易金额
|
||||
*/
|
||||
private Long transAmount;
|
||||
/**
|
||||
* 银联订单号,银联生成并返回给易生的订单号
|
||||
*/
|
||||
private String unTrace;
|
||||
/**
|
||||
* 用户唯一编码
|
||||
*/
|
||||
private String userId;
|
||||
}
|
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