13 changed files with 341 additions and 3 deletions
@ -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"; |
|||
} |
|||
@ -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"; |
|||
} |
|||
@ -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; |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue