版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/danruoshui315/article/details/81567919
本人按照微信的红包实现的功能,首先红包分为个人红包和群红包,群红包又分为随机红包和定额红包,红包超时24小时未领取剩余的金额会退回到发红包的人的账户。发红包的过程分为以下几步:创建红包、获取红包信息、领红包、红包领取记录、红包发送记录信息等,根据公司需求稍微有所差异:
以下是countroller层,只列出最关键的几个接口:
@RestController
@RequestMapping(method = RequestMethod.POST)
@Slf4j
@Api(value = "红包接口", tags = { "红包操作接口" })
public class RedPacketController {
@Autowired
private LocaleMessageSourceService msService;
@Autowired
private MemberService memberService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedPacketService redPacketService;
@Autowired
private MemberWalletService memberWalletService;
@RequestMapping(value = "/createRedPacket")
public MessageResult createRedPacket(String name, String unit, BigDecimal quantity, BigDecimal amount,
Integer type,Integer redPacketType, Long drawNo, String jyPassword,
@ApiIgnore @SessionAttribute(SESSION_MEMBER) AuthMember user) throws Exception {
//入参非空验证
ValidateUtil.hasText(name, 500, msService.getMessage("NAME_IS_NOT_EMPTY"));
ValidateUtil.hasText(unit, 500, msService.getMessage("UNIT_IS_NOT_EMPTY"));
ValidateUtil.notNull(quantity, 500, msService.getMessage("QUANTITY_IS_NOT_EMPTY"));
ValidateUtil.notNull(amount, 500, msService.getMessage("AMOUNT_IS_NOT_EMPTY"));
ValidateUtil.notNull(redPacketType, 500, msService.getMessage("REDPACKET_TYPE_IS_NOT_EMPTY"));
ValidateUtil.notNull(drawNo, 500, msService.getMessage("DRAW_NO_IS_NOT_EMPTY"));
ValidateUtil.hasText(jyPassword, 500, msService.getMessage("TRANSFER_PASSWORD_IS_NOT_EMPTY"));
//调用创建红包的方法
return redPacketService.createRedPacket(name, unit, quantity, amount,type, redPacketType, drawNo, jyPassword, user.getId());
}
public MessageResult getRedPacket(Long id, @ApiIgnore @SessionAttribute(SESSION_MEMBER) AuthMember user) throws BusinessValidationException {
// 1 检查参数
ValidateUtil.notNull(id, 500, msService.getMessage("REDPACKET_ID_IS_NOT_EMPTY"));
// 业务处理
RedPacket redPacket = redPacketService.findRedPacketById(id);
RedPacketInfo info = RedPacketInfo.toRedPacketInfo(redPacket);
Member member = memberService.findOne(user.getId());
info.setAvatar(member.getAvatar());
info.setJid(member.getJid());
info.setNickname(member.getNickname());
MessageResult result = MessageResult.success();
result.setData(info);
return result;
}
@Transactional(rollbackFor = Exception.class)
public MessageResult drawRedPacket(Long id, @ApiIgnore @SessionAttribute(SESSION_MEMBER) AuthMember user) throws BusinessValidationException {
// 1. 检查参数
ValidateUtil.notNull(id, 500, msService.getMessage("REDPACKET_ID_IS_NOT_EMPTY"));
// 业务实现:Redis方式:
//return redPacketService.drawRedPacketRedis(id, user.getId());
// 业务实现:数据库方式:
return redPacketService.drawRedPacketDB(id, user.getId());
}
这是service层:
package com.spark.bitrade.service;
import static com.spark.bitrade.util.BigDecimalUtils.compare;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import com.spark.bitrade.constant.TypeEnum;
import com.spark.bitrade.constant.RedPacketTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.spark.bitrade.constant.ReceivedStatusEnum;
import com.spark.bitrade.constant.RedPacketStatusEnum;
import com.spark.bitrade.dao.CoinDao;
import com.spark.bitrade.dao.RedPacketDao;
import com.spark.bitrade.dao.RedPacketOverviewDao;
import com.spark.bitrade.dao.RedPacketRecordDao;
import com.spark.bitrade.dao.RedPacketRecordOverviewDao;
import com.spark.bitrade.entity.Coin;
import com.spark.bitrade.entity.Member;
import com.spark.bitrade.entity.MemberWallet;
import com.spark.bitrade.entity.RedPacket;
import com.spark.bitrade.entity.RedPacketOverview;
import com.spark.bitrade.entity.RedPacketRecord;
import com.spark.bitrade.entity.RedPacketRecordOverview;
import com.spark.bitrade.exception.BusinessValidationException;
import com.spark.bitrade.exception.InformationExpiredException;
import com.spark.bitrade.job.CheckRedPacketTask;
import com.spark.bitrade.system.LocaleMessageSourceService;
import com.spark.bitrade.util.BigDecimalUtils;
import com.spark.bitrade.util.HttpRequestUtil;
import com.spark.bitrade.util.Md5;
import com.spark.bitrade.util.MessageResult;
import com.spark.bitrade.util.ValidateUtil;
import com.spark.bitrade.vo.RedPacketInfo;
import com.spark.bitrade.vo.RedPacketRecordInfo;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class RedPacketService {
@Value("${im.api.url}")
private String ImApiUrl;
@Autowired
private LocaleMessageSourceService msService;
@Autowired
private MemberService memberService;
@Autowired
private MemberWalletService memberWalletService;
@Autowired
private RedPacketDao redPacketDao;
@Autowired
private RedPacketOverviewDao redPacketOverviewDao;
@Autowired
private RedPacketRecordDao redPacketRecordDao;
@Autowired
private RedPacketRecordOverviewDao redPacketRecordOverviewDao;
@Autowired
private CoinDao coinDao;
@Autowired
private RedisTemplate redisTemplate;
@Transactional(rollbackFor = Exception.class)
private RedPacket save(RedPacket redPacket) {
return redPacketDao.save(redPacket);
}
@Transactional(rollbackFor = Exception.class)
public MessageResult createRedPacket(String name, String unit, BigDecimal quantity, BigDecimal amount,
Integer type,Integer redPacketType, Long drawNo, String jyPassword,
Long memberId) throws Exception {
// 业务前置检查:2.1交易密码必须已经设置
Member member = memberService.findOne(memberId);
String mbPassword = member.getJyPassword();
ValidateUtil.hasText(mbPassword,500, msService.getMessage("NO_SET_JYPASSWORD"));
// 业务前置检查:2.2交易密码必须相等
ValidateUtil.isTrue(Md5.md5Digest(jyPassword +
member.getSalt()).toLowerCase().equals(mbPassword),500,msService.getMessage("ERROR_JYPASSWORD"));
// 业务前置检查:2.3 检查用户必须有相应币种钱包。
Coin coin = coinDao.findByUnit(unit);
MemberWallet memberWallet = memberWalletService.findByCoinAndMemberId(coin, member.getId());
// 业务前置检查:2.4 检查用户必须有相应币种钱包的余额必须大于发红包总金额。
ValidateUtil.isTrue(compare(memberWallet.getBalance(), amount),500,
msService.getMessage("INSUFFICIENT_BALANCE"));
ValidateUtil.isTrue(compare(amount, coinDao.findByUnit(unit).getMinWithdrawAmount()),500,
msService.getMessage("REDPACKET_AMOUNT_ISLESS") + coinDao.findByUnit(unit).getMinWithdrawAmount());
ValidateUtil.isTrue(compare(coinDao.findByUnit(unit).getMaxWithdrawAmount(),amount),500,
msService.getMessage("REDPACKET_AMOUNT_ISMORE") + coinDao.findByUnit(unit).getMaxWithdrawAmount());
// 业务处理:3.1 冻结相应余额
memberWallet.setFrozenBalance(amount);
MessageResult freezeResult = memberWalletService.freezeBalance(memberWallet, amount);
if (freezeResult.getCode() != 0) {
throw new InformationExpiredException("Information Expired");
} else {
MessageResult.success();
}
// 业务处理:4.1准备红包
RedPacket redPacket = new RedPacket();
RedPacketRecord record = new RedPacketRecord();
if (type.equals(TypeEnum.person.getOrdinal())) {
redPacket.setType(TypeEnum.person);
redPacket.setAmount(amount);
redPacket.setQuantity(quantity);
record.setReceivedAmount(amount);
record.setReceivedQuantity(quantity);
} else if (type.equals(TypeEnum.group.getOrdinal())) {
redPacket.setType(TypeEnum.group);
redPacket.setDrawNo(drawNo);
redPacket.setSumAmount(BigDecimalUtils.mul(amount, quantity));
if (redPacketType.equals(RedPacketTypeEnum.normal.getOrdinal())) {
redPacket.setRedPacketType(RedPacketTypeEnum.normal);
redPacket.setAmount(amount);
redPacket.setQuantity(quantity);
} else if (redPacketType.equals(RedPacketTypeEnum.random.getOrdinal())) {
redPacket.setRedPacketType(RedPacketTypeEnum.random);
redPacket.setAmount(amount);
redPacket.setQuantity(quantity);
} else {
MessageResult.error(500, msService.getMessage("REDPACKET_TYPE_DOSE_NOT_EXIST"));
}
} else {
MessageResult.error(msService.getMessage("REDPACKET_TYPE_DOSE_NOT_EXIST"));
}
redPacket.setRedPacketStatus(RedPacketStatusEnum.normal);
redPacket.setMemberId(memberId);
redPacket.setCreateTime(new Date());
redPacket.setName(name);
redPacket.setDrawNo(drawNo);
redPacket.setTerm(24 * 60 * 60);
redPacket.setUnit(unit);
// 业务处理:5:保存红包
RedPacket redPacket1 = save(redPacket);
record.setMemberId(memberId);
record.setRedPacketId(redPacket1.getId());
record.setUnit(redPacket1.getUnit());
redPacketRecordDao.save(record);
// 业务后续处理:6:缓存红包数据到redis,数据供收红包用。如果考虑先实现功能,先不考虑redis这个实现方式
// 业务后续处理:7:返回红包数据
MessageResult result = MessageResult.success();
result.setData(RedPacketInfo.toRedPacketInfo(redPacket1));
return result;
}
@Transactional(rollbackFor = Exception.class)
public MessageResult drawRedPacketDB(Long id,Long memberId) throws BusinessValidationException {
// 业务实现:Redis方式:
//TODO
// 业务实现:数据库方式:
// 业务前置检查 2.1 红包必须存在
RedPacket redPacket = findRedPacketById(id);
Member member = memberService.findOne(memberId);
// 业务前置检查2.2 红包必须是可以用状态
ValidateUtil.isTrue(redPacket.getRedPacketStatus().equals(RedPacketStatusEnum.normal),500, "红包不可用");
// 业务前置检查2.3 如果红包是个人红包, 当前用户不能是发红包用户
if(TypeEnum.person.equals(redPacket.getType())) {
ValidateUtil.isTrue(memberId.equals(redPacket.getMemberId()), 500, "");
}
// 业务前置检查2.5 如果是群红包,当前用户必须没有收取过这个红包,
if(TypeEnum.group.equals(redPacket.getType())) {
RedPacketRecord redPacketRecord = redPacketRecordDao.findByRedPacketId(id);
ValidateUtil.isTrue(redPacketRecord.getReceivedStatus() == null, 500, "已领取过此红包不可再领取");
}
// 业务处理3.1 生成红包收取记录
RedPacketRecord record = new RedPacketRecord();
Date date = new Date();
//判断领取时间,领取时间不能超过24小时
if((date.getTime() - redPacket.getCreateTime().getTime())/(24*60*60*1000) < 24) {
record.setReceivedTime(date);
record.setRedPacketId(id);
record.setUnit(redPacket.getUnit());
Coin coin = coinDao.findByUnit(redPacket.getUnit());
MemberWallet memberWallet = memberWalletService.findByCoinAndMemberId(coin, memberId);
// 业务处理3.2:红包收取金额: 如果是个人红包
if(TypeEnum.person.equals(redPacket.getType())) {
record.setMemberId(memberId);
//record.setReceivedAmount(redPacket.getAmount());
redPacket.setRedPacketStatus(RedPacketStatusEnum.normal);
//将之前冻结的金额解冻
MessageResult freezeResult = memberWalletService.thawBalance(memberWallet, redPacket.getAmount());
if (freezeResult.getCode() != 0) {
MessageResult.error("Information Expired");
}else {
MessageResult.success();
}
//如果是群红包
}else if(TypeEnum.group.equals(redPacket.getType())) {
StringBuilder params=new StringBuilder();
params.append("gid=");
params.append(redPacket.getDrawNo());
params.append("&uid=");
params.append(member.getJid());
String imUrl = ImApiUrl;
String str=HttpRequestUtil.sendPost(imUrl,params.toString(),false,false);
JSONObject json=JSONObject.parseObject(str);
Object code= json.get("code");
if (code.equals("1000")) {
log.info("此用户可以领取!");
}else if(code.equals("1003")) {
return MessageResult.error("此用户非群成员不可领取红包!");
}
else {
redPacket.setRedPacketStatus(RedPacketStatusEnum.unspecified);
}
if(RedPacketTypeEnum.normal.equals(redPacket.getRedPacketType())) {
record.setReceivedAmount(BigDecimalUtils.div(redPacket.getAmount(), redPacket.getQuantity()));
record.setReceivedStatus(ReceivedStatusEnum.received);
record.setMemberId(memberId);
}else if(RedPacketTypeEnum.random.equals(redPacket.getRedPacketType())) {
RedPacketRecord redRecord = redPacketRecordDao.findByRedPacketId(id);
//计算随机红包的金额
BigDecimal am = redPacket.getAmount();
BigDecimal no = redPacket.getQuantity();
BigDecimal min = memberWallet.getCoin().getMinWithdrawAmount();
BigDecimal max = BigDecimalUtils.mul(BigDecimalUtils.div(am, no), 2);
/*Random random = new Random();
List<Integer> list = new ArrayList<>();
int total_random = 0;
for(int i = 0; i < no.intValue(); i++) {
int r = random.nextInt(); //获取一个随机数
total_random += r;
list.add(r);
}
//获取随机金额
List<BigDecimal> packets = new ArrayList<>();
BigDecimal bi = BigDecimal.ZERO;
for(int i = 0; i < list.size(); i++) {
BigDecimal packet = BigDecimalUtils.mul((new BigDecimal(list.get(i) / total_random)), am);
packet = BigDecimalUtils.compare(packet,max) ? max:packet;
packet = BigDecimalUtils.compare(min, packet) ? min:packet;
redRecord.setReceivedAmount(packet);
packets.add(packet);
bi = BigDecimalUtils.add(packets.get(i), bi);
}*/
List<BigDecimal> list =splitRedPacket(no.intValue(),am.intValue(),min.intValue(),max.intValue());
BigDecimal check_num = BigDecimal.ZERO;
System.out.println(Arrays.toString(list.toArray()));
for (BigDecimal x : list) {
check_num = BigDecimalUtils.add(check_num, x);
}
redRecord.setReceivedSumAmount(check_num);
//获得收到的红包的最大金额
BigDecimal big = Collections.max(list);
//如果收到的金额等于最大金额,就是手气最佳
if(BigDecimalUtils.isEqual(redRecord.getReceivedAmount(), big)) {
record.setIsBestHand(true);
}else {
record.setIsBestHand(false);
}
redPacket.setSumAmount(check_num);
redPacket.setMemberId(memberId);
if(BigDecimalUtils.isEqual(redRecord.getReceivedAmount(), BigDecimal.ZERO)) {
record.setReceivedStatus(ReceivedStatusEnum.allRobbed);
}else {
record.setReceivedStatus(ReceivedStatusEnum.received);
}
record.setMemberId(memberId);
}
}
}else {
MessageResult.error(msService.getMessage("超过24小时不能领取!"));
}
RedPacketRecord rpr = redPacketRecordDao.findByRedPacketId(id);
record.setReceivedAmount(rpr.getReceivedAmount());
RedPacketRecord record1 = redPacketRecordDao.save(record);
// 业务后续处理3. 生成红包收取的统计数据
RedPacketRecordInfo info = RedPacketRecordInfo.builder()
.memberId(memberId).receivedAmount(record1.getReceivedAmount())
.receivedTime(record1.getReceivedTime()).redPacketId(id)
.avatar(member.getAvatar()).jid(member.getJid())
.nickname(member.getNickname()).unit(record1.getUnit())
.redPacketStatus(redPacket.getRedPacketStatus()).isBestHand(record1.getIsBestHand())
.build();
// 业务后续处理:返回数据
MessageResult result = MessageResult.success();
result.setData(info);
return result;
}
public MessageResult drawRedPacketRedis(Long id,Long memberId) {
// 业务实现:Redis方式:
//TODO
// 业务实现:数据库方式:
// 业务前置检查 2.1 红包必须存在
RedPacket redPacket = findRedPacketById(id);
// 业务前置检查2.2 红包必须是可以用状态
Assert.isTrue(redPacket.getRedPacketStatus()==RedPacketStatusEnum.normal, "红包不可用");
// 业务前置检查2.3 如果红包是个人红包, 当前用户不能是发红包用户
//TODO
// 业务前置检查2.4 如果是定额红包,当前用户不能是发红包用户
//TODO
// 业务前置检查2.5 如果是群红包,当前用户必须没有收取过这个红包,
//TODO
// 业务处理3.1 生成红包收取记录
//TODO
RedPacketRecord record = new RedPacketRecord();
record.setRedPacketId(id);
record.setUnit(redPacket.getUnit());
// 业务处理3.2:红包收取金额: 如果是个人红包:如果是群定额红包,如果是群随机红包
//TODO
//RedPacketRecord record1 = save(record);
//RedPacketRecordInfo info = RedPacketRecordInfo.toRedPacketRecordInfo(record1);
// 业务处理3.3. 修改红包状态1, 如果是个人红包,红包完毕,如果群定额红包,群随机红包,红包接受数量,接受金额,
// 业务后续处理3. 生成红包收取的统计数据
// 业务后续处理:返回数据
MessageResult result = MessageResult.success();
result.setData("");
return result;
}
public List<RedPacket> findRedPacketByYearAndUnit(String year,String unit){
return redPacketDao.findAllByYearAndUnit(year,unit);
}
public RedPacket findByIdAndDrawNo(Long id,Long drawNo) {
return redPacketDao.findByIdAndDrawNo(id, drawNo);
}
public RedPacket findRedPacketById(Long id) {
return redPacketDao.findById(id);
}
public RedPacketRecord findRedPacketRecordById(Long id) {
return redPacketRecordDao.findById(id);
}
public List<RedPacketRecord> findRedPacketRecordByRedPacketId(Long id) {
return redPacketRecordDao.findAllByRedPacketId(id);
}
public RedPacketOverview findRedPacketOverviewByYearAndUnit(String year, String unit) {
return redPacketOverviewDao.findByYearAndUnit(year,unit);
}
public RedPacketRecordOverview findRedPacketRecordOverviewByYearAndUnit(String year, String unit) {
return redPacketRecordOverviewDao.findByYearAndUnit(year,unit);
}
/**
*
* @param total
* 总金额
* @param splitCount
* 个数
* @param min
* 最小金额
* @param max
* 最大金额
*/
public List<BigDecimal> splitRedPacket(int total, int splitCount, int min, int max) {
System.out.println("总金额: " + total);
System.out.println("个数: " + splitCount);
System.out.println("最小金额: " + min);
System.out.println("最大金额: " + max);
List<BigDecimal> al = new ArrayList<BigDecimal>();
Random random = new Random();
if ((splitCount & 1) == 1) {// 奇数个红包,需要单独将其中一个红包先生成,以保证后续算法拆分份
System.out.println("红包个数" + splitCount + "是奇数,单独生成一个红包");
int num = 0;
do {
num = random.nextInt(max);
// num = (total - num) % (splitCount / 2) + num; //
// 将后面算法拆分时的余数加入到这个随机值中
System.out.println("单个的随机红包为:" + num);
} while (num >= max || num <= min);
total = 40000 - num;
BigDecimal number = new BigDecimal(0);
number = BigDecimal.valueOf((int)num);
al.add(number);
}
int couples = splitCount >> 1;
System.out.println(Integer.toBinaryString(splitCount));
System.out.println(Integer.toBinaryString(couples));
System.out.println("====拆分的数量是====="+couples);
int perCoupleSum = total / couples;
if ((splitCount & 1) == 1) {
System.out.println("处理后剩余的金额为:" + total);
}
System.out.println("将" + total + "元拆分为" + couples + "对金额,每对总额:" + perCoupleSum);
for (int i = 0; i < couples; i++) {
Boolean finish = true;
int num1 = 0;
int num2 = 0;
do {
num1 = random.nextInt(max);
num2 = perCoupleSum - num1;
System.out.println("***num1***"+num1);
System.out.println("num2: "+num2);
if (!al.contains(num1) && !al.contains(num2)) {
if (i == 0) {
num1 = (total - couples * perCoupleSum) + num1;
System.out.println("***num1***"+num1);
System.out.println("***num2: "+num2);
}
}
} while (num1 < min || num1 > max || num2 < min || num2 > max);
BigDecimal number1 = new BigDecimal(0);
number1=BigDecimal.valueOf((int)num1);
BigDecimal number2 = new BigDecimal(0);
number2 = BigDecimal.valueOf((int)num2);
al.add(number1);
al.add(number2);
System.out.println("num1: "+num1+" num2: "+num2);
System.out.println("-----------al:"+al);
}
return al;
}
}
这是model层:
@Entity
@Data
public class RedPacket {
/**
* 主键ID
*/
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
/**
* 红包名称
*/
private String name;
/**
* 红包期限
*/
private int term = 24*60*60; // 24小時
/**
* 红包发送者id
*/
private long memberId;
/**
* 领取标识 群发就是群ID 一对一发送就是接收人ID
*/
private Long drawNo;
/**
* 红包类型 0个人红包 1群红包
*/
private TypeEnum type;
/**
* 红包类型 0定额红包 1随机红包
*/
private RedPacketTypeEnum RedPacketType;
/**
* 红包状态 :
* 0 可正常领取
* 1 未到领取时间
* 2 红包已过期
* 3 领取人不是发送者指定的群成员
* 4 此用户已领取该红包
* 5 红包已全部领取
*/
private RedPacketStatusEnum redPacketStatus;
/**
* 货币单位
*/
private String unit;
@Column(columnDefinition = "decimal(18,8) comment '红包数量'")
private BigDecimal quantity;
@Column(columnDefinition = "decimal(18,8) comment '红包金额'")
private BigDecimal amount;
@Column(columnDefinition = "decimal(18,8) comment '红包总金额'")
private BigDecimal sumAmount;
@Excel(name = "创建时间", orderNum = "1", width = 25)
@CreationTimestamp
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
private String year = DateUtil.getDateY(new Date());
}
@Entity
@Data
public class RedPacketRecord {
/**
* 主键ID
*/
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
/**
* 红包ID
*/
private Long redPacketId;
/**
* 紅包收取人Id
*/
private Long memberId;
/**
* 年份
*/
private String year;
/**
* 货币单位
*/
private String unit;
/**
* 个人领取的状态
*/
private ReceivedStatusEnum receivedStatus;
@Excel(name = "领取时间", orderNum = "1", width = 25)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date receivedTime;
@Column(columnDefinition = "decimal(18,8) comment '领取红包金额'")
private BigDecimal receivedAmount;
@Column(columnDefinition = "decimal(18,8) comment '领取红包总金额'")
private BigDecimal receivedSumAmount;
@Column(columnDefinition = "decimal(18,8) comment '领取红包数量'")
private BigDecimal receivedQuantity;
/**
* 是否是手气最佳
*/
private Boolean isBestHand;
}
这是dao层:
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import com.spark.bitrade.entity.RedPacket;
public interface RedPacketDao extends JpaRepository<RedPacket,String>,JpaSpecificationExecutor<RedPacket>,QueryDslPredicateExecutor<RedPacket> {
List<RedPacket> findAllByYearAndUnit(String year,String unit);
List<RedPacket> findAll();
public RedPacket findByIdAndDrawNo(Long id,Long drawNo);
RedPacket findById(Long id);
}
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import com.spark.bitrade.entity.RedPacketRecord;
public interface RedPacketRecordDao extends JpaRepository<RedPacketRecord,String>,JpaSpecificationExecutor<RedPacketRecord>,QueryDslPredicateExecutor<RedPacketRecord> {
List<RedPacketRecord> findAllByYearAndUnit(String year,String unit);
List<RedPacketRecord> findAllByRedPacketId(Long redPacketId);
RedPacketRecord findById(Long id);
List<RedPacketRecord> findByMemberId(Long memberId);
List<RedPacketRecord> findAll();
RedPacketRecord findByRedPacketId(Long redPacketId);
}
这是定时任务:
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.spark.bitrade.constant.RedPacketStatusEnum;
import com.spark.bitrade.dao.CoinDao;
import com.spark.bitrade.dao.RedPacketDao;
import com.spark.bitrade.dao.RedPacketRecordDao;
import com.spark.bitrade.entity.Coin;
import com.spark.bitrade.entity.MemberWallet;
import com.spark.bitrade.entity.RedPacket;
import com.spark.bitrade.entity.RedPacketRecord;
import com.spark.bitrade.service.MemberWalletService;
import com.spark.bitrade.util.BigDecimalUtils;
import com.spark.bitrade.util.MessageResult;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class CheckRedPacketTask {
@Autowired
RedPacketRecordDao redPacketRecordDao;
@Autowired
RedPacketDao redPacketDao;
@Autowired
private CoinDao coinDao;
@Autowired
private MemberWalletService memberWalletService;
@Scheduled(fixedRate = 1000*60*60)
public void checkExpireRedPacket() {
log.info("=========开始检查24小时红包信息===========");
//获取所有的收取红包信息
List<RedPacketRecord> recordList = redPacketRecordDao.findAll();
//获取所有的发出的红包信息
List<RedPacket> redList = redPacketDao.findAll();
for(RedPacket r : redList) {
for(RedPacketRecord rr : recordList) {
//判断发出的红包时间是否超过24小时
if((new Date().getTime() - r.getCreateTime().getTime())/(24*60*60*1000) <24) {
/* if(r.getType().equals(TypeEnum.group)) {
//判断群红包里领取到的总金额和发出的总金额是否相等
if(BigDecimalUtils.isEqual(rr.getReceivedSumAmount(), r.getSumAmount())) {
r.setRedPacketStatus(RedPacketStatusEnum.allReceived);
}else if(BigDecimalUtils.compare(r.getSumAmount(), rr.getReceivedSumAmount())) {
r.setRedPacketStatus(RedPacketStatusEnum.normal);
}else {
log.error("");
}
}*/
r.setRedPacketStatus(RedPacketStatusEnum.normal);
}else {
r.setRedPacketStatus(RedPacketStatusEnum.expired);
Coin coin = coinDao.findByUnit(r.getUnit());
//将领取的金额充值到钱包
MemberWallet memberWallet = memberWalletService.findByCoinAndMemberId(coin, rr.getMemberId());
MessageResult freezeResult = memberWalletService.recharge(memberWallet, rr.getReceivedAmount());
if (freezeResult.getCode() != 0) {
MessageResult.error("Information Expired");
}else {
MessageResult.success();
}
//将剩余未领取的金额返回钱包
MemberWallet wallet = memberWalletService.findByCoinAndMemberId(coin, r.getMemberId());
int balance = memberWalletService.deductBalance(wallet, BigDecimalUtils.sub(r.getQuantity(), rr.getReceivedQuantity()));
if(balance < 0) {
MessageResult.error("Information Expired");
}else {
MessageResult.success();
}
}
}
}
log.info("=========结束检查===========");
}
}
由于我们的项目是使用的分布式和springboot实现的,所以此项目跑不起来,但是思路是对的,其他的jar包之类的还需使用者自己下载。