diff --git a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/DateUtils.java b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/DateUtils.java
index a34c2a5..f84a53a 100644
--- a/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/DateUtils.java
+++ b/bnyer-common/bnyer-common-core/src/main/java/com/bnyer/common/core/utils/DateUtils.java
@@ -8,7 +8,9 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
+import java.util.Calendar;
import java.util.Date;
+
import org.apache.commons.lang3.time.DateFormatUtils;
/**
@@ -176,4 +178,22 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
+
+ /**
+ * 给指定日期添加指定添加的天数 返回添加后的天数
+ *
+ * @param d 指定的日期
+ * @param day 指定添加的天数
+ * @return 添加后的天数
+ */
+ public static Date getDateAfter(Date d, int day) {
+ Calendar now = Calendar.getInstance();
+ now.setTime(d);
+ now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
+ return now.getTime();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(getDateAfter(new Date(), 365));
+ }
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/AlipayConfig.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/AlipayConfig.java
index 09928e0..ea0d7b1 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/AlipayConfig.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/config/AlipayConfig.java
@@ -27,6 +27,9 @@ public class AlipayConfig{
@Value("${alipay.privateKey}")
private String privateKey;
+ @Value("${alipay.publicKey}")
+ private String publicKey;
+
@Value("${alipay.certPath}")
private String certPath;
@@ -35,4 +38,17 @@ public class AlipayConfig{
@Value("${alipay.rootPath}")
private String rootPath;
+
+ @Value("${alipay.notifyUrl}")
+ private String notifyUrl;
+
+ @Value("${alipay.returnUrl}")
+ private String returnUrl;
+
+ @Value("${alipay.signType}")
+ private String signType;
+
+ @Value("${alipay.charset}")
+ private String charset;
+
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java
index e5c7bd3..ea07ae0 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/RedisKeyConstant.java
@@ -101,4 +101,9 @@ public class RedisKeyConstant {
* 艺术家上传键
*/
public static final String CREATOR_UPLOAD_KEY="bnyer.img.creator.upload:";
+
+ /**
+ * 用户会员vip锁键
+ */
+ public static final String PAY_USER_VIP_LOCK_KEY = "bnyer.img.userVip.lock:";
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipOrderStatusConstant.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipOrderStatusConstant.java
new file mode 100644
index 0000000..1a09232
--- /dev/null
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipOrderStatusConstant.java
@@ -0,0 +1,29 @@
+package com.bnyer.img.constants;
+
+/**
+ * 用户会员vip支付常量
+ * @author chengkun
+ * @date 2022/4/21 18:12
+ */
+public class UserVipOrderStatusConstant {
+
+ /**
+ * 待支付
+ */
+ public static final String UN_PAY = "0";
+
+ /**
+ * 已支付
+ */
+ public static final String PAYED = "1";
+
+ /**
+ * 支付失败
+ */
+ public static final String PAY_FAIL = "2";
+
+ /**
+ * 支付失败
+ */
+ public static final String PAY_EXCEPTION = "3";
+}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipTypeConstant.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipTypeConstant.java
new file mode 100644
index 0000000..fd0fa76
--- /dev/null
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/constants/UserVipTypeConstant.java
@@ -0,0 +1,24 @@
+package com.bnyer.img.constants;
+
+/**
+ * 用户会员vip常量
+ * @author chengkun
+ * @date 2022/4/21 18:12
+ */
+public class UserVipTypeConstant {
+
+ /**
+ * 月卡
+ */
+ public static final String MONTH_CARD = "0";
+
+ /**
+ * 季卡
+ */
+ public static final String SEASON_CARD = "1";
+
+ /**
+ * 年卡
+ */
+ public static final String YEAR_CARD = "2";
+}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/FhMiniController.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/FhMiniController.java
index 86182b0..c3c653d 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/FhMiniController.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/FhMiniController.java
@@ -64,6 +64,12 @@ public class FhMiniController extends BaseController {
@Autowired
private BzDataService bzDataService;
+ @Autowired
+ private UserVipService userVipService;
+
+ @Autowired
+ private UserVipRecordService userVipRecordService;
+
//@TokenCheck
@ApiOperation(value="查询banner列表")
@GetMapping(value = "/listBanner")
@@ -290,4 +296,24 @@ public class FhMiniController extends BaseController {
}
return AjaxResult.error();
}
+
+ //@TokenCheck
+ @ApiOperation(value="获取用户会员vip列表")
+ @GetMapping(value = "/queryUserVipList")
+ public AjaxResult queryUserVipList(){
+ return AjaxResult.success(userVipService.queryFront());
+ }
+
+ //@TokenCheck
+ @ApiOperation(value="支付购买用户会员vip")
+ @PostMapping(value = "/payUserVip")
+ public AjaxResult payUserVip(@Validated @RequestBody @ApiParam("购买会员vip对象") PayUserVipDto dto){
+ log.debug("【微信图文小程序】支付购买用户会员vip参数为:{}", JSON.toJSONString(dto));
+ boolean b = userVipRecordService.payUserVip(dto);
+ if(b){
+ return AjaxResult.success("购买支付成功!");
+ }else{
+ return AjaxResult.error("购买支付失败!");
+ }
+ }
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java
index 026a4d9..fd0ee53 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/TiktokMiniController.java
@@ -65,6 +65,9 @@ public class TiktokMiniController extends BaseController {
@Autowired
private BzDataService bzDataService;
+ @Autowired
+ private UserVipService userVipService;
+
//@TokenCheck
@ApiOperation(value="查询banner列表")
@GetMapping(value = "/listBanner")
@@ -293,4 +296,11 @@ public class TiktokMiniController extends BaseController {
}
return AjaxResult.error();
}
+
+ //@TokenCheck
+ @ApiOperation(value="获取用户会员vip列表")
+ @GetMapping(value = "/queryUserVipList")
+ public AjaxResult queryUserVipList(){
+ return AjaxResult.success(userVipService.queryFront());
+ }
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/WxMiniController.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/WxMiniController.java
index 47dfb91..32841ce 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/WxMiniController.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/controller/WxMiniController.java
@@ -64,6 +64,12 @@ public class WxMiniController extends BaseController {
@Autowired
private BzDataService bzDataService;
+ @Autowired
+ private UserVipService userVipService;
+
+ @Autowired
+ private UserVipRecordService userVipRecordService;
+
//@TokenCheck
@ApiOperation(value="查询banner列表")
@GetMapping(value = "/listBanner")
@@ -290,4 +296,24 @@ public class WxMiniController extends BaseController {
}
return AjaxResult.error();
}
+
+ //@TokenCheck
+ @ApiOperation(value="获取用户会员vip列表")
+ @GetMapping(value = "/queryUserVipList")
+ public AjaxResult queryUserVipList(){
+ return AjaxResult.success(userVipService.queryFront());
+ }
+
+ //@TokenCheck
+ @ApiOperation(value="支付购买用户会员vip")
+ @PostMapping(value = "/payUserVip")
+ public AjaxResult payUserVip(@Validated @RequestBody @ApiParam("购买会员vip对象") PayUserVipDto dto){
+ log.debug("【微信图文小程序】支付购买用户会员vip参数为:{}", JSON.toJSONString(dto));
+ boolean b = userVipRecordService.payUserVip(dto);
+ if(b){
+ return AjaxResult.success("购买支付成功!");
+ }else{
+ return AjaxResult.error("购买支付失败!");
+ }
+ }
}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/domain/UserVipRecord.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/domain/UserVipRecord.java
index 3b542ca..ce81907 100644
--- a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/domain/UserVipRecord.java
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/domain/UserVipRecord.java
@@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
+import java.math.BigDecimal;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -29,6 +31,13 @@ public class UserVipRecord extends BaseDomain {
@ApiModelProperty(value="主键id")
private Long id;
+ /**
+ * 订单id
+ */
+ @TableField(value = "order_id")
+ @ApiModelProperty(value="订单id")
+ private String orderId;
+
/**
* 用户手机号
*/
@@ -47,6 +56,7 @@ public class UserVipRecord extends BaseDomain {
* 开始时间
*/
@TableField(value = "start_time")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value="开始时间")
private Date startTime;
@@ -54,8 +64,30 @@ public class UserVipRecord extends BaseDomain {
* 到期时间
*/
@TableField(value = "end_time")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value="到期时间")
private Date endTime;
+ /**
+ * 支付金额
+ */
+ @TableField(value = "price")
+ @ApiModelProperty(value="支付金额")
+ private BigDecimal price;
+
+ /**
+ * vip类型状态(0->月卡;1->季卡;2->年卡)
+ */
+ @TableField(value = "type")
+ @ApiModelProperty(value="vip类型状态(0->月卡;1->季卡;2->年卡)")
+ private String type;
+
+ /**
+ * 支付状态(0->待支付;1->已支付;2->支付失败;3->支付异常)
+ */
+ @TableField(value = "status")
+ @ApiModelProperty(value="支付状态(0->待支付;1->已支付;2->支付失败;3->支付异常)")
+ private String status;
+
private static final long serialVersionUID = 1L;
-}
\ No newline at end of file
+}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/PayUserVipDto.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/PayUserVipDto.java
new file mode 100644
index 0000000..fe3d6c2
--- /dev/null
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/dto/PayUserVipDto.java
@@ -0,0 +1,33 @@
+package com.bnyer.img.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+
+@Getter
+@Setter
+@ApiModel("用户会员vip支付接收类")
+public class PayUserVipDto implements Serializable {
+
+ @NotBlank(message = "手机号不能为空!")
+ @ApiModelProperty(value="手机号")
+ private String phone;
+
+ @NotNull(message = "用户vipId不能为空!")
+ @ApiModelProperty(value="用户vip表id")
+ private Long userVipId;
+
+ @NotBlank(message = "vip类型状态不能为空!")
+ @ApiModelProperty(value="vip类型状态(0->月卡;1->季卡;2->年卡)")
+ private String type;
+
+ @NotBlank(message = "支付金额不能为空!")
+ @ApiModelProperty(value="支付金额")
+ private String price;
+}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/UserVipRecordService.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/UserVipRecordService.java
new file mode 100644
index 0000000..b00305f
--- /dev/null
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/UserVipRecordService.java
@@ -0,0 +1,15 @@
+package com.bnyer.img.service;
+
+import com.bnyer.img.domain.UserVipRecord;
+import com.bnyer.img.dto.PayUserVipDto;
+
+public interface UserVipRecordService {
+
+
+ /**
+ * 下单并支付会员vip
+ * @param param 用户vip参数对象
+ * @return -
+ */
+ boolean payUserVip(PayUserVipDto param);
+}
diff --git a/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/UserVipServiceRecordImpl.java b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/UserVipServiceRecordImpl.java
new file mode 100644
index 0000000..c03585c
--- /dev/null
+++ b/bnyer-services/bnyer-img/src/main/java/com/bnyer/img/service/impl/UserVipServiceRecordImpl.java
@@ -0,0 +1,98 @@
+package com.bnyer.img.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.bnyer.common.core.exception.ServiceException;
+import com.bnyer.common.core.utils.DateUtils;
+import com.bnyer.common.core.utils.StringUtils;
+import com.bnyer.common.core.utils.uuid.IdUtils;
+import com.bnyer.common.redis.service.RedissonService;
+import com.bnyer.img.constants.RedisKeyConstant;
+import com.bnyer.img.constants.UserVipOrderStatusConstant;
+import com.bnyer.img.constants.UserVipTypeConstant;
+import com.bnyer.img.domain.UserVip;
+import com.bnyer.img.domain.UserVipRecord;
+import com.bnyer.img.dto.PayUserVipDto;
+import com.bnyer.img.dto.UserVipPageDto;
+import com.bnyer.img.mapper.UserVipMapper;
+import com.bnyer.img.mapper.UserVipRecordMapper;
+import com.bnyer.img.service.UserVipRecordService;
+import com.bnyer.img.service.UserVipService;
+import com.bnyer.img.vo.UserVipVo;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Service
+@Slf4j
+public class UserVipServiceRecordImpl implements UserVipRecordService {
+
+ @Autowired
+ private UserVipRecordMapper userVipRecordMapper;
+
+ @Autowired
+ private RedissonService redissonService;
+
+
+ @Override
+ public boolean payUserVip(PayUserVipDto param) {
+ UserVipRecord userVipRecord = new UserVipRecord();
+ //生成订单id
+ userVipRecord.setOrderId(IdUtil.getSnowflakeNextIdStr());
+ //获取分布式锁
+ RLock lock = redissonService.getRLock(RedisKeyConstant.PAY_USER_VIP_LOCK_KEY + userVipRecord.getOrderId());
+ try{
+ if(lock.tryLock(500, 10000, TimeUnit.MILLISECONDS)){
+ //调用支付
+
+ //保存订单
+ userVipRecord.setCreateTime(new Date());
+ userVipRecord.setUpdateTime(new Date());
+ userVipRecord.setPrice(new BigDecimal(param.getPrice()));
+ userVipRecord.setStatus(UserVipOrderStatusConstant.UN_PAY);
+ userVipRecord.setIsShow("1");
+ Date startTime = new Date();
+ userVipRecord.setStartTime(startTime);
+ if(userVipRecord.getType().equals(UserVipTypeConstant.MONTH_CARD)){
+ //计算月卡(30天)的结束时间
+ userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 30));
+ }else if(userVipRecord.getType().equals(UserVipTypeConstant.SEASON_CARD)){
+ //结算季卡(90天)的结束时间
+ userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 90));
+ }else{
+ //计算年卡(365天)的结束时间
+ userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 365));
+ }
+ }else{
+ userVipRecord.setStatus(UserVipOrderStatusConstant.PAY_EXCEPTION);
+ log.error("用户会员vip支付异常,锁被占用!");
+ throw new ServiceException("系统繁忙,请稍候重试!");
+ }
+ }catch (Exception e){
+ userVipRecord.setStatus(UserVipOrderStatusConstant.PAY_FAIL);
+ log.error("用户会员vip支付失败!错误原因为【{}】",e.getMessage());
+ throw new ServiceException("系统繁忙,请勿重复操作!");
+ }finally {
+ int insert = userVipRecordMapper.insert(userVipRecord);
+ if(insert > 0){
+ return true;
+ }
+ //释放锁
+ if(lock.isHeldByCurrentThread()){
+ lock.unlock();
+ log.info("用户会员vip支付操作执行完毕,释放锁成功!");
+ }
+ }
+ return false;
+ }
+}
diff --git a/bnyer-services/bnyer-img/src/main/resources/com/bnyer/img/mapper/UserVipRecordMapper.xml b/bnyer-services/bnyer-img/src/main/resources/com/bnyer/img/mapper/UserVipRecordMapper.xml
index d5a7036..b98c13d 100644
--- a/bnyer-services/bnyer-img/src/main/resources/com/bnyer/img/mapper/UserVipRecordMapper.xml
+++ b/bnyer-services/bnyer-img/src/main/resources/com/bnyer/img/mapper/UserVipRecordMapper.xml
@@ -5,10 +5,14 @@
+
+
+
+
@@ -16,7 +20,7 @@
- id, phone, user_vip_id, start_time, end_time, is_show, create_time, update_time,
+ id,order_id, phone,price,status, user_vip_id, start_time, end_time,type, is_show, create_time, update_time,
sort
-
\ No newline at end of file
+