|
|
|
@ -0,0 +1,271 @@
|
|
|
|
|
package com.luoo.user.service;
|
|
|
|
|
|
|
|
|
|
import api.Result;
|
|
|
|
|
import com.ijpay.core.kit.WxPayKit;
|
|
|
|
|
import com.luoo.user.config.WxPayConfig;
|
|
|
|
|
import com.luoo.user.config.WxPayPublicKeyConfig;
|
|
|
|
|
import com.luoo.user.dao.MembershipOrderDao;
|
|
|
|
|
import com.luoo.user.dao.UserInfoDao;
|
|
|
|
|
import com.luoo.user.dao.VipSkuDao;
|
|
|
|
|
import com.luoo.user.pojo.MembershipOrder;
|
|
|
|
|
import com.luoo.user.pojo.QMembershipOrder;
|
|
|
|
|
import com.luoo.user.pojo.UserInfo;
|
|
|
|
|
import com.luoo.user.pojo.VipSku;
|
|
|
|
|
import com.luoo.user.vo.membership.VipSkuVO;
|
|
|
|
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
|
|
|
|
import com.wechat.pay.java.service.payments.app.AppService;
|
|
|
|
|
import com.wechat.pay.java.service.payments.app.model.Amount;
|
|
|
|
|
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
|
|
|
|
|
import com.wechat.pay.java.service.payments.app.model.PrepayResponse;
|
|
|
|
|
import com.wechat.pay.java.service.payments.model.Transaction;
|
|
|
|
|
import constants.TaskPointIdConstants;
|
|
|
|
|
import dto.UserLoginDto;
|
|
|
|
|
import enums.MembershipEnums;
|
|
|
|
|
import enums.PointEnums;
|
|
|
|
|
import enums.UserVipStatusEnum;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import util.IdWorker;
|
|
|
|
|
import util.JwtUtil;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @program: luoo_parent
|
|
|
|
|
* @description: 会员业务
|
|
|
|
|
* @author: yawei.huang
|
|
|
|
|
* @create: 2024-11-14 20:10
|
|
|
|
|
**/
|
|
|
|
|
@Service
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class MemberShipService {
|
|
|
|
|
|
|
|
|
|
private final VipSkuDao vipSkuDao;
|
|
|
|
|
|
|
|
|
|
private final WxPayConfig wxPayConfig;
|
|
|
|
|
|
|
|
|
|
private final IdWorker idWorker;
|
|
|
|
|
|
|
|
|
|
private final WxPayPublicKeyConfig wxPayPublicKeyConfig;
|
|
|
|
|
|
|
|
|
|
public static AppService wxPayAppService;
|
|
|
|
|
|
|
|
|
|
private final MembershipOrderDao membershipOrderDao;
|
|
|
|
|
|
|
|
|
|
private final JwtUtil jwtUtil;
|
|
|
|
|
|
|
|
|
|
private final JPAQueryFactory jpaQueryFactory;
|
|
|
|
|
|
|
|
|
|
private final UserInfoDao userInfoDao;
|
|
|
|
|
|
|
|
|
|
private final UserPointLogService userPointLogService;
|
|
|
|
|
private final UserInfoService userInfoService;
|
|
|
|
|
|
|
|
|
|
public MemberShipService(VipSkuDao vipSkuDao, WxPayConfig wxPayConfig, IdWorker idWorker, WxPayPublicKeyConfig wxPayPublicKeyConfig, MembershipOrderDao membershipOrderDao, JwtUtil jwtUtil, JPAQueryFactory jpaQueryFactory, UserInfoDao userInfoDao, UserPointLogService userPointLogService, UserInfoService userInfoService) {
|
|
|
|
|
this.vipSkuDao = vipSkuDao;
|
|
|
|
|
this.wxPayConfig = wxPayConfig;
|
|
|
|
|
this.idWorker = idWorker;
|
|
|
|
|
this.wxPayPublicKeyConfig = wxPayPublicKeyConfig;
|
|
|
|
|
this.membershipOrderDao = membershipOrderDao;
|
|
|
|
|
this.jwtUtil = jwtUtil;
|
|
|
|
|
this.jpaQueryFactory = jpaQueryFactory;
|
|
|
|
|
this.userInfoDao = userInfoDao;
|
|
|
|
|
this.userPointLogService = userPointLogService;
|
|
|
|
|
this.userInfoService = userInfoService;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取会员商品SKU
|
|
|
|
|
*
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public List<VipSkuVO> getVipSkuList() {
|
|
|
|
|
List<VipSku> all = vipSkuDao.findAll();
|
|
|
|
|
return all.stream().map(item -> VipSkuVO.builder()
|
|
|
|
|
.id(item.getId())
|
|
|
|
|
.description(item.getDescription())
|
|
|
|
|
.days(item.getDays())
|
|
|
|
|
.lifeFlag(item.getLifeFlag())
|
|
|
|
|
.amount(item.getAmount())
|
|
|
|
|
.build()).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 前端发起支付请求,获得预支付id,同时创建订单
|
|
|
|
|
*
|
|
|
|
|
* @param skuId 会员商品id
|
|
|
|
|
* @return 拉起微信支付的参数
|
|
|
|
|
*/
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public Object prepay(String skuId) {
|
|
|
|
|
VipSku one = vipSkuDao.getOne(skuId);
|
|
|
|
|
|
|
|
|
|
PrepayRequest request = new PrepayRequest();
|
|
|
|
|
// 初始化服务
|
|
|
|
|
wxPayAppService = new AppService.Builder().config(wxPayPublicKeyConfig.config()).build();
|
|
|
|
|
// 内部订单号
|
|
|
|
|
String outTradeNo = idWorker.nextId() + "";
|
|
|
|
|
UserLoginDto user = jwtUtil.getUser();
|
|
|
|
|
|
|
|
|
|
// 创建订单
|
|
|
|
|
MembershipOrder membershipOrder = MembershipOrder.builder()
|
|
|
|
|
.orderCode(outTradeNo)
|
|
|
|
|
.skuId(skuId)
|
|
|
|
|
.payType(MembershipEnums.WX_PAY.getCode())
|
|
|
|
|
.amount(one.getAmount())
|
|
|
|
|
.duration(one.getDays())
|
|
|
|
|
.life(one.getLifeFlag())
|
|
|
|
|
.userId(user.getUserId())
|
|
|
|
|
.nickName(user.getNickName())
|
|
|
|
|
.status(MembershipEnums.WAIT_PAY.getCode())
|
|
|
|
|
.build();
|
|
|
|
|
membershipOrder.setId(String.valueOf(idWorker.nextId()));
|
|
|
|
|
membershipOrderDao.save(membershipOrder);
|
|
|
|
|
|
|
|
|
|
// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
|
|
|
|
|
Amount amount = new Amount();
|
|
|
|
|
amount.setTotal(one.getAmount());
|
|
|
|
|
request.setAmount(amount);
|
|
|
|
|
request.setAppid(wxPayConfig.getAppId());
|
|
|
|
|
request.setMchid(wxPayConfig.getMchId());
|
|
|
|
|
request.setDescription(one.getDescription());
|
|
|
|
|
request.setNotifyUrl(wxPayConfig.getNotifyUrl());
|
|
|
|
|
|
|
|
|
|
request.setOutTradeNo(outTradeNo);
|
|
|
|
|
// 调用接口
|
|
|
|
|
PrepayResponse response = wxPayAppService.prepay(request);
|
|
|
|
|
Map<String, String> map = null;
|
|
|
|
|
try {
|
|
|
|
|
map = WxPayKit.appCreateSign(wxPayConfig.getAppId(), wxPayConfig.getMchId(), response.getPrepayId(), wxPayConfig.getPrivateKeyPath());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void updateOrderStatus(Transaction transaction) {
|
|
|
|
|
String outTradeNo = transaction.getOutTradeNo();
|
|
|
|
|
QMembershipOrder qMembershipOrder = QMembershipOrder.membershipOrder;
|
|
|
|
|
MembershipOrder one = jpaQueryFactory.selectFrom(qMembershipOrder)
|
|
|
|
|
.where(qMembershipOrder.orderCode.eq(outTradeNo))
|
|
|
|
|
.fetchOne();
|
|
|
|
|
|
|
|
|
|
if ("SUCCESS".equals(transaction.getTradeState().toString())) {
|
|
|
|
|
one.setStatus(MembershipEnums.PAY_SUCCESS.getCode());
|
|
|
|
|
|
|
|
|
|
dealUserVipCalc(one);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
one.setStatus(MembershipEnums.PAY_FAIL.getCode());
|
|
|
|
|
}
|
|
|
|
|
membershipOrderDao.save(one);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理用户vip状态
|
|
|
|
|
*
|
|
|
|
|
* @param one 会员订单表
|
|
|
|
|
*/
|
|
|
|
|
private void dealUserVipCalc(MembershipOrder one) {
|
|
|
|
|
// 处理用户表
|
|
|
|
|
UserInfo userInfo = userInfoDao.findById(one.getUserId()).get();
|
|
|
|
|
|
|
|
|
|
if (Objects.equals(userInfo.getVipStatus(), UserVipStatusEnum.INITIAL.getCode())) {
|
|
|
|
|
// 首次开通会员
|
|
|
|
|
userPointLogService.addByTaskDailyAndUserId(TaskPointIdConstants.BUY_MEMBER, one.getUserId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 永久会员码
|
|
|
|
|
if (Objects.equals(one.getLife(), PointEnums.MEMBERSHIP_LIFE.getCode())) {
|
|
|
|
|
userInfo.setVipStatus(UserVipStatusEnum.LIFE.getCode());
|
|
|
|
|
} else {
|
|
|
|
|
// 非永久会员码
|
|
|
|
|
// 计算会员到期时间
|
|
|
|
|
LocalDate vipExpireTime;
|
|
|
|
|
if (Objects.equals(UserVipStatusEnum.ACTIVE.getCode(), userInfo.getVipStatus())) {
|
|
|
|
|
// 如果是当前正是会员,以到期时间为基准,再增加membershipCode的duration天
|
|
|
|
|
vipExpireTime = (userInfo.getVipExpireTime() == null ? LocalDate.now() : userInfo.getVipExpireTime()).plusDays(one.getDuration());
|
|
|
|
|
} else {
|
|
|
|
|
// 如果是当前不是会员,从今天开始,增加membershipCode的duration天
|
|
|
|
|
userInfo.setVipStatus(UserVipStatusEnum.INITIAL.getCode());
|
|
|
|
|
vipExpireTime = LocalDate.now().plusDays(one.getDuration());
|
|
|
|
|
}
|
|
|
|
|
userInfo.setVipExpireTime(vipExpireTime);
|
|
|
|
|
// 无论如何当即设置为会员生效状态
|
|
|
|
|
userInfo.setVipStatus(UserVipStatusEnum.ACTIVE.getCode());
|
|
|
|
|
}
|
|
|
|
|
userInfoDao.save(userInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 苹果内购
|
|
|
|
|
*
|
|
|
|
|
* @param type 会员种类
|
|
|
|
|
* @param userId 用户id
|
|
|
|
|
*/
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void applePayMembershipOrder(String type, String userId) {
|
|
|
|
|
// 内部订单号
|
|
|
|
|
String outTradeNo = idWorker.nextId() + "";
|
|
|
|
|
UserInfo userInfo = userInfoService.findById(userId);
|
|
|
|
|
// 创建订单
|
|
|
|
|
// 苹果支付只有成功
|
|
|
|
|
MembershipOrder membershipOrder = MembershipOrder.builder()
|
|
|
|
|
.orderCode(outTradeNo)
|
|
|
|
|
.payType(MembershipEnums.APPLE_PAY.getCode())
|
|
|
|
|
.userId(userInfo.getId())
|
|
|
|
|
.nickName(userInfo.getNickName())
|
|
|
|
|
.status(MembershipEnums.PAY_SUCCESS.getCode())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
String skuId = "";
|
|
|
|
|
switch (type) {
|
|
|
|
|
case "cn.luoo.IndieMusic.annual": {
|
|
|
|
|
// 年度会员 逻辑从这开始
|
|
|
|
|
System.out.println("appleIAP 年度会员 逻辑从这开始,userid___" + userId);
|
|
|
|
|
// todo 这边会员种类是写死的,最好苹果支付有个字段能对应,否则每次都要改代码后发布
|
|
|
|
|
skuId = "2";
|
|
|
|
|
|
|
|
|
|
//这里拿到userId,在我们自己的订单逻辑里插一条订单记录,给用户开通相应的会员
|
|
|
|
|
userId = "";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "cn.luoo.IndieMusic.monthly": {
|
|
|
|
|
// 月度会员逻辑从这开始
|
|
|
|
|
System.out.println("appleIAP 月度会员 逻辑从这开始,userid___" + userId);
|
|
|
|
|
;
|
|
|
|
|
skuId = "1";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "cn.luoo.IndieMusic.lifetime": {
|
|
|
|
|
// 终身会员逻辑从这开始
|
|
|
|
|
System.out.println("appleIAP 终身会员 逻辑从这开始,userid___" + userId);
|
|
|
|
|
skuId = "3";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isNotBlank(skuId)) {
|
|
|
|
|
membershipOrder.setId(String.valueOf(idWorker.nextId()));
|
|
|
|
|
membershipOrder.setSkuId(skuId);
|
|
|
|
|
VipSku vipSku = vipSkuDao.getOne(skuId);
|
|
|
|
|
membershipOrder.setAmount(vipSku.getAmount());
|
|
|
|
|
membershipOrder.setLife(vipSku.getLifeFlag());
|
|
|
|
|
membershipOrder.setDuration(vipSku.getDays());
|
|
|
|
|
|
|
|
|
|
dealUserVipCalc(membershipOrder);
|
|
|
|
|
membershipOrderDao.save(membershipOrder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|