添加订单相关能力
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
package org.jiayunet.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.pojo.dto.memberProduct.CreateOrderDto;
|
||||||
|
import org.jiayunet.pojo.dto.memberProduct.OrderDetailDto;
|
||||||
|
import org.jiayunet.pojo.param.memberProduct.CreateOrderParam;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
import org.jiayunet.service.MemberProductService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员商品接口
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/member/product")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MemberProductController {
|
||||||
|
|
||||||
|
private final MemberProductService memberProductService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public List<MemberProduct> list() {
|
||||||
|
return memberProductService.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建订单
|
||||||
|
*/
|
||||||
|
@PostMapping("/createOrder")
|
||||||
|
public CreateOrderDto createOrder(@Validated @RequestBody CreateOrderParam param) {
|
||||||
|
return memberProductService.createOrder(param.getProductId(), param.getPayChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询订单详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/orderDetail")
|
||||||
|
public OrderDetailDto orderDetail(@RequestParam Long orderId) {
|
||||||
|
return memberProductService.orderDetail(orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.jiayunet.controller;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.jiayunet.pojo.dto.memberStatus.FuncStockDto;
|
||||||
|
import org.jiayunet.pojo.dto.memberStatus.MemberStatusDto;
|
||||||
|
import org.jiayunet.service.MemberStatusService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员状态接口
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/member")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MemberStatusController {
|
||||||
|
|
||||||
|
private final MemberStatusService memberStatusService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员状态
|
||||||
|
*/
|
||||||
|
@GetMapping("/status")
|
||||||
|
public MemberStatusDto status() {
|
||||||
|
return memberStatusService.status();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询功能权限库存
|
||||||
|
*/
|
||||||
|
@GetMapping("/funcStock")
|
||||||
|
public FuncStockDto funcStock(@RequestParam String funcCode) {
|
||||||
|
return memberStatusService.funcStock(funcCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.jiayunet.pojo.dto.memberProduct;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建订单返回
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateOrderDto {
|
||||||
|
|
||||||
|
/** 订单ID,用于轮询状态 */
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
/** 微信支付二维码链接 */
|
||||||
|
private String codeUrl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.jiayunet.pojo.dto.memberProduct;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单详情返回
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OrderDetailDto {
|
||||||
|
|
||||||
|
/** 订单ID */
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
/** 订单编号 */
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
/** 商品名称 */
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
/** 实付金额(分) */
|
||||||
|
private Integer payAmount;
|
||||||
|
|
||||||
|
/** 订单状态 0=待支付 1=已支付 2=已退款 3=已关闭 */
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/** 支付渠道 1=微信 2=支付宝 */
|
||||||
|
private Integer payChannel;
|
||||||
|
|
||||||
|
/** 支付时间 */
|
||||||
|
private Instant payTime;
|
||||||
|
|
||||||
|
/** 下单时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package org.jiayunet.pojo.dto.memberStatus;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能权限库存返回
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FuncStockDto {
|
||||||
|
|
||||||
|
/** 功能编码 */
|
||||||
|
private String funcCode;
|
||||||
|
|
||||||
|
/** 功能名称 */
|
||||||
|
private String funcName;
|
||||||
|
|
||||||
|
/** 每日免费次数 */
|
||||||
|
private Integer dailyFreeCount;
|
||||||
|
|
||||||
|
/** 今日已用次数 */
|
||||||
|
private Integer todayUsed;
|
||||||
|
|
||||||
|
/** 今日免费剩余次数 */
|
||||||
|
private Integer freeRemain;
|
||||||
|
|
||||||
|
/** 0=不限次 1=限次 */
|
||||||
|
private Integer countLimit;
|
||||||
|
|
||||||
|
/** 付费剩余次数,countLimit=0时为null */
|
||||||
|
private Integer remainCount;
|
||||||
|
|
||||||
|
/** 0=不限时 1=限时 */
|
||||||
|
private Integer timeLimit;
|
||||||
|
|
||||||
|
/** 权限过期时间,timeLimit=0时为null */
|
||||||
|
private Instant expireTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.jiayunet.pojo.dto.memberStatus;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员状态返回
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MemberStatusDto {
|
||||||
|
|
||||||
|
/** 是否是会员 */
|
||||||
|
private Boolean isMember;
|
||||||
|
|
||||||
|
/** 到期时间 */
|
||||||
|
private Instant expireTime;
|
||||||
|
|
||||||
|
/** 首次开通时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/** 最近续费时间 */
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.jiayunet.pojo.param.memberProduct;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建会员订单入参
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CreateOrderParam {
|
||||||
|
|
||||||
|
/** 商品ID */
|
||||||
|
@NotNull(message = "商品ID不能为空")
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
/** 支付渠道 1=微信 2=支付宝 */
|
||||||
|
@NotNull(message = "支付渠道不能为空")
|
||||||
|
private Integer payChannel;
|
||||||
|
}
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
package org.jiayunet.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
|
||||||
|
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.exception.BusinessException;
|
||||||
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
|
import org.jiayunet.mapper.MemberOrderMapper;
|
||||||
|
import org.jiayunet.mapper.MemberProductMapper;
|
||||||
|
import org.jiayunet.mapper.PayWechatFlowMapper;
|
||||||
|
import org.jiayunet.pojo.dto.memberProduct.CreateOrderDto;
|
||||||
|
import org.jiayunet.pojo.dto.memberProduct.OrderDetailDto;
|
||||||
|
import org.jiayunet.pojo.po.MemberOrder;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
import org.jiayunet.pojo.po.PayWechatFlow;
|
||||||
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
|
import org.jiayunet.wxPay.WxNativePayAbility;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员商品服务
|
||||||
|
* <p>依赖:WxNativePayAbility(微信Native支付下单)</p>
|
||||||
|
* <p>使用表:bg_member_product(查询商品)、bg_member_order(创建/查询订单)、bg_pay_wechat_flow(创建支付流水)</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class MemberProductService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberProductMapper memberProductMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberOrderMapper memberOrderMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PayWechatFlowMapper payWechatFlowMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WxNativePayAbility wxNativePayAbility;
|
||||||
|
|
||||||
|
@Value("${wx_pay.merchant_id:}")
|
||||||
|
private String merchantId;
|
||||||
|
|
||||||
|
@Value("${app.wx.app_id:}")
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品列表
|
||||||
|
* <p>查询上架商品,按sort_order排序</p>
|
||||||
|
*/
|
||||||
|
public List<MemberProduct> list() {
|
||||||
|
return memberProductMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<MemberProduct>()
|
||||||
|
.eq(MemberProduct::getStatus, 1)
|
||||||
|
.orderByAsc(MemberProduct::getSortOrder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建订单
|
||||||
|
* <p>1. 校验商品存在且上架 2. 创建订单 3. 生成orderNo 4. 创建支付流水 5. 调支付渠道下单拿codeUrl</p>
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public CreateOrderDto createOrder(Long productId, Integer payChannel) {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
|
||||||
|
// 1. 查商品,校验存在且上架
|
||||||
|
MemberProduct product = memberProductMapper.selectById(productId);
|
||||||
|
if (product == null || product.getStatus() != 1) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "商品不存在或已下架");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 创建订单
|
||||||
|
MemberOrder order = new MemberOrder();
|
||||||
|
order.setUserId(userId);
|
||||||
|
order.setProductId(productId);
|
||||||
|
order.setPayAmount(product.getPrice());
|
||||||
|
order.setPayChannel(payChannel);
|
||||||
|
order.setStatus(0);
|
||||||
|
memberOrderMapper.insert(order);
|
||||||
|
|
||||||
|
// 3. 生成orderNo
|
||||||
|
String orderNo = "OP" + order.getId();
|
||||||
|
order.setOrderNo(orderNo);
|
||||||
|
memberOrderMapper.update(null, new LambdaUpdateWrapper<MemberOrder>()
|
||||||
|
.eq(MemberOrder::getId, order.getId())
|
||||||
|
.set(MemberOrder::getOrderNo, orderNo));
|
||||||
|
|
||||||
|
// 4. 调支付渠道下单,拿二维码URL
|
||||||
|
String codeUrl;
|
||||||
|
if (payChannel == 1) {
|
||||||
|
// 微信Native支付
|
||||||
|
codeUrl = prepayWechat(orderNo, product);
|
||||||
|
} else {
|
||||||
|
// TODO 支付宝当面付
|
||||||
|
codeUrl = prepayAlipay(orderNo, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 返回
|
||||||
|
CreateOrderDto dto = new CreateOrderDto();
|
||||||
|
dto.setOrderId(order.getId());
|
||||||
|
dto.setCodeUrl(codeUrl);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信Native支付下单
|
||||||
|
*/
|
||||||
|
private String prepayWechat(String orderNo, MemberProduct product) {
|
||||||
|
// 创建微信支付流水
|
||||||
|
PayWechatFlow flow = new PayWechatFlow();
|
||||||
|
flow.setOrderType("member");
|
||||||
|
flow.setOrderNo(orderNo);
|
||||||
|
flow.setTotal(product.getPrice());
|
||||||
|
flow.setStatus(0);
|
||||||
|
payWechatFlowMapper.insert(flow);
|
||||||
|
|
||||||
|
// 调微信Native下单
|
||||||
|
PrepayRequest request = new PrepayRequest();
|
||||||
|
request.setAppid(appId);
|
||||||
|
request.setMchid(merchantId);
|
||||||
|
request.setDescription(product.getProductName());
|
||||||
|
request.setOutTradeNo(orderNo);
|
||||||
|
Amount amount = new Amount();
|
||||||
|
amount.setTotal(product.getPrice());
|
||||||
|
request.setAmount(amount);
|
||||||
|
|
||||||
|
return wxNativePayAbility.prepay(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付宝当面付下单
|
||||||
|
* TODO 接入支付宝当面付SDK,返回二维码URL
|
||||||
|
*/
|
||||||
|
private String prepayAlipay(String orderNo, MemberProduct product) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "支付宝支付暂未开放");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询订单详情
|
||||||
|
* <p>查询订单信息,关联商品名称</p>
|
||||||
|
*/
|
||||||
|
public OrderDetailDto orderDetail(Long orderId) {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
|
||||||
|
MemberOrder order = memberOrderMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<MemberOrder>()
|
||||||
|
.eq(MemberOrder::getId, orderId)
|
||||||
|
.eq(MemberOrder::getUserId, userId)
|
||||||
|
);
|
||||||
|
Assert.notNull(order, "订单不存在");
|
||||||
|
|
||||||
|
MemberProduct product = memberProductMapper.selectById(order.getProductId());
|
||||||
|
|
||||||
|
OrderDetailDto dto = new OrderDetailDto();
|
||||||
|
dto.setOrderId(order.getId());
|
||||||
|
dto.setOrderNo(order.getOrderNo());
|
||||||
|
dto.setProductName(product != null ? product.getProductName() : null);
|
||||||
|
dto.setPayAmount(order.getPayAmount());
|
||||||
|
dto.setStatus(order.getStatus());
|
||||||
|
dto.setPayChannel(order.getPayChannel());
|
||||||
|
dto.setPayTime(order.getPayTime());
|
||||||
|
dto.setCreateTime(order.getCreateTime());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package org.jiayunet.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.exception.BusinessException;
|
||||||
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
|
import org.jiayunet.mapper.FuncPermissionMapper;
|
||||||
|
import org.jiayunet.mapper.MemberUserMapper;
|
||||||
|
import org.jiayunet.mapper.UserFuncPermissionStockMapper;
|
||||||
|
import org.jiayunet.mapper.UserFuncUsageLogMapper;
|
||||||
|
import org.jiayunet.pojo.dto.memberStatus.FuncStockDto;
|
||||||
|
import org.jiayunet.pojo.dto.memberStatus.MemberStatusDto;
|
||||||
|
import org.jiayunet.pojo.po.FuncPermission;
|
||||||
|
import org.jiayunet.pojo.po.MemberUser;
|
||||||
|
import org.jiayunet.pojo.po.UserFuncPermissionStock;
|
||||||
|
import org.jiayunet.pojo.po.UserFuncUsageLog;
|
||||||
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员状态查询服务
|
||||||
|
* <p>依赖:FuncPermissionMapper、UserFuncPermissionStockMapper、UserFuncUsageLogMapper、MemberUserMapper</p>
|
||||||
|
* <p>使用表:bg_member_user(查询会员状态)、bg_func_permission(查询功能定义)、bg_user_func_permission_stock(查询库存)、bg_user_func_usage_log(统计今日使用)</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class MemberStatusService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberUserMapper memberUserMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FuncPermissionMapper funcPermissionMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserFuncPermissionStockMapper userFuncPermissionStockMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserFuncUsageLogMapper userFuncUsageLogMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员状态
|
||||||
|
* <p>查询当前用户的会员记录,判断是否在有效期内</p>
|
||||||
|
*/
|
||||||
|
public MemberStatusDto status() {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
|
||||||
|
MemberUser memberUser = memberUserMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getUserId, userId)
|
||||||
|
);
|
||||||
|
|
||||||
|
MemberStatusDto dto = new MemberStatusDto();
|
||||||
|
if (memberUser == null) {
|
||||||
|
dto.setIsMember(false);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.setIsMember(memberUser.getExpireTime().isAfter(Instant.now()));
|
||||||
|
dto.setExpireTime(memberUser.getExpireTime());
|
||||||
|
dto.setCreateTime(memberUser.getCreateTime());
|
||||||
|
dto.setUpdateTime(memberUser.getUpdateTime());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询功能权限库存
|
||||||
|
* <p>1. 查功能定义 2. 统计今日已用次数 3. 查付费库存 4. 组装返回</p>
|
||||||
|
*/
|
||||||
|
public FuncStockDto funcStock(String funcCode) {
|
||||||
|
Long userId = UserSecurityTool.getUserId();
|
||||||
|
|
||||||
|
// 1. 查功能定义
|
||||||
|
FuncPermission funcPermission = funcPermissionMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<FuncPermission>()
|
||||||
|
.eq(FuncPermission::getFuncCode, funcCode)
|
||||||
|
.eq(FuncPermission::getStatus, 1)
|
||||||
|
);
|
||||||
|
if (funcPermission == null) {
|
||||||
|
throw new BusinessException(BusinessExpCodeEnum.UNKNOWN_ERROR, "功能不存在或未启用");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 统计今日已用次数
|
||||||
|
Instant todayStart = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
Long todayUsed = userFuncUsageLogMapper.selectCount(
|
||||||
|
new LambdaQueryWrapper<UserFuncUsageLog>()
|
||||||
|
.eq(UserFuncUsageLog::getUserId, userId)
|
||||||
|
.eq(UserFuncUsageLog::getFuncCode, funcCode)
|
||||||
|
.ge(UserFuncUsageLog::getCreateTime, todayStart)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. 查付费库存
|
||||||
|
UserFuncPermissionStock stock = userFuncPermissionStockMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<UserFuncPermissionStock>()
|
||||||
|
.eq(UserFuncPermissionStock::getUserId, userId)
|
||||||
|
.eq(UserFuncPermissionStock::getFuncCode, funcCode)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4. 组装返回
|
||||||
|
int dailyFreeCount = funcPermission.getDailyFreeCount() == null ? 0 : funcPermission.getDailyFreeCount();
|
||||||
|
int used = todayUsed.intValue();
|
||||||
|
int freeRemain = Math.max(0, dailyFreeCount - used);
|
||||||
|
|
||||||
|
FuncStockDto dto = new FuncStockDto();
|
||||||
|
dto.setFuncCode(funcCode);
|
||||||
|
dto.setFuncName(funcPermission.getFuncName());
|
||||||
|
dto.setDailyFreeCount(dailyFreeCount);
|
||||||
|
dto.setTodayUsed(used);
|
||||||
|
dto.setFreeRemain(freeRemain);
|
||||||
|
|
||||||
|
if (stock != null) {
|
||||||
|
dto.setCountLimit(stock.getCountLimit());
|
||||||
|
dto.setRemainCount(stock.getRemainCount());
|
||||||
|
dto.setTimeLimit(stock.getTimeLimit());
|
||||||
|
dto.setExpireTime(stock.getExpireTime());
|
||||||
|
} else {
|
||||||
|
dto.setCountLimit(null);
|
||||||
|
dto.setRemainCount(null);
|
||||||
|
dto.setTimeLimit(null);
|
||||||
|
dto.setExpireTime(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.MemberFuncItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员-功能权限配置 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface MemberFuncItemMapper extends CommonMapper<MemberFuncItem> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.MemberOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员订单 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface MemberOrderMapper extends CommonMapper<MemberOrder> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.MemberProduct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员商品 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface MemberProductMapper extends CommonMapper<MemberProduct> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.MemberRouteItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员-菜单权限配置 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface MemberRouteItemMapper extends CommonMapper<MemberRouteItem> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.MemberUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户会员状态 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface MemberUserMapper extends CommonMapper<MemberUser> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.jiayunet.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.jiayunet.pojo.po.PayWechatFlow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付流水 Mapper
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface PayWechatFlowMapper extends CommonMapper<PayWechatFlow> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员-功能权限配置表(bg_member_func_item)
|
||||||
|
* <p>全局配置,定义会员包含哪些功能权限及次数限制</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_member_func_item")
|
||||||
|
public class MemberFuncItem {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 功能权限编码,关联 bg_func_permission.func_code */
|
||||||
|
private String funcCode;
|
||||||
|
|
||||||
|
/** 0=不限次 1=限次 */
|
||||||
|
private Integer countLimit;
|
||||||
|
|
||||||
|
/** 发放次数,countLimit=1时有值 */
|
||||||
|
private Integer addCount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员订单表(bg_member_order)
|
||||||
|
* <p>记录用户购买会员商品的订单信息</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_member_order")
|
||||||
|
public class MemberOrder {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 订单编号,"OP" + id */
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
/** 下单用户 */
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/** 关联 bg_member_product.id */
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
/** 实付金额(分) */
|
||||||
|
private Integer payAmount;
|
||||||
|
|
||||||
|
/** 支付渠道 1=微信 2=支付宝 */
|
||||||
|
private Integer payChannel;
|
||||||
|
|
||||||
|
/** 订单状态 0=待支付 1=已支付 2=已退款 3=已关闭 */
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/** 支付时间 */
|
||||||
|
private Instant payTime;
|
||||||
|
|
||||||
|
/** 退款时间(预留) */
|
||||||
|
private Instant refundTime;
|
||||||
|
|
||||||
|
/** 退款金额(分,预留) */
|
||||||
|
private Integer refundAmount;
|
||||||
|
|
||||||
|
/** 下单时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员商品表(bg_member_product)
|
||||||
|
* <p>定义会员套餐的名称、价格、时长等商业属性</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_member_product")
|
||||||
|
public class MemberProduct {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 商品名称 */
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
/** 标签,如"限时优惠"、"最划算" */
|
||||||
|
private String tag;
|
||||||
|
|
||||||
|
/** 主推标识 0=否 1=是 */
|
||||||
|
private Integer isFeatured;
|
||||||
|
|
||||||
|
/** 购买按钮文字,如"立即开通" */
|
||||||
|
private String buyButtonText;
|
||||||
|
|
||||||
|
/** 实付价格(分) */
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
/** 划线价(分) */
|
||||||
|
private Integer originalPrice;
|
||||||
|
|
||||||
|
/** 折算月价(分) */
|
||||||
|
private Integer monthlyPrice;
|
||||||
|
|
||||||
|
/** 有效天数 */
|
||||||
|
private Integer durationDays;
|
||||||
|
|
||||||
|
/** 排序,越小越靠前 */
|
||||||
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
/** 状态 0=下架 1=上架 */
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
private Instant updateTime;
|
||||||
|
|
||||||
|
/** 逻辑删除 0=正常 非0=已删除 */
|
||||||
|
@TableLogic(value = "0", delval = "new()")
|
||||||
|
private Long isDelete;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员-菜单权限配置表(bg_member_route_item)
|
||||||
|
* <p>全局配置,定义会员解锁哪些菜单</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_member_route_item")
|
||||||
|
public class MemberRouteItem {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 路由菜单ID,关联 bg_route_menu.id */
|
||||||
|
private Long routeId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户会员状态表(bg_member_user)
|
||||||
|
* <p>记录用户的会员到期时间,用于展示会员状态</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_member_user")
|
||||||
|
public class MemberUser {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 用户ID */
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/** 会员到期时间 */
|
||||||
|
private Instant expireTime;
|
||||||
|
|
||||||
|
/** 首次开通时间 */
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/** 最近续费时间 */
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package org.jiayunet.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付流水表(bg_pay_wechat_flow)
|
||||||
|
* <p>记录微信支付的下单和回调信息</p>
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "bg_pay_wechat_flow")
|
||||||
|
public class PayWechatFlow {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 订单类型,member=会员订单,后续可扩展其他业务类型 */
|
||||||
|
private String orderType;
|
||||||
|
|
||||||
|
/** 商户订单号,对应微信 out_trade_no,关联业务订单表 */
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
/** 微信支付订单号,支付成功后由回调返回 */
|
||||||
|
private String transactionId;
|
||||||
|
|
||||||
|
/** 订单金额(分),对应微信 amount.total */
|
||||||
|
private Integer total;
|
||||||
|
|
||||||
|
/** 流水状态 0=待支付 1=已支付 2=已关闭 */
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/** 支付成功时间,系统收到成功回调的时间 */
|
||||||
|
private Instant successTime;
|
||||||
|
|
||||||
|
/** 回调解密后的原始JSON完整数据,用于问题排查 */
|
||||||
|
private String notifyData;
|
||||||
|
|
||||||
|
/** 记录创建时间(下单时写入) */
|
||||||
|
private Instant createTime;
|
||||||
|
|
||||||
|
/** 记录更新时间(回调时更新) */
|
||||||
|
private Instant updateTime;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user