package com.ks.app.service.impl.vip;
|
|
import com.alipay.api.AlipayApiException;
|
import com.alipay.api.response.AlipayTradeQueryResponse;
|
import com.ks.app.dao.vip.OrderRecordDao;
|
import com.ks.app.dao.vip.UserVIPInfoDao;
|
import com.ks.app.dto.vip.OrderPaySuccessForm;
|
import com.ks.app.dto.vip.PayWayInfoDTO;
|
import com.ks.app.entity.SystemEnum;
|
import com.ks.app.entity.vip.*;
|
import com.ks.app.exception.goldcorn.GoldCornException;
|
import com.ks.app.exception.vip.OrderException;
|
import com.ks.app.exception.vip.PayException;
|
import com.ks.app.exception.vip.VIPException;
|
import com.ks.app.service.inter.user.UserInfoService;
|
import com.ks.app.service.inter.vip.IPaySuccess;
|
import com.ks.app.service.inter.vip.OrderService;
|
import com.ks.app.service.inter.vip.VIPPriceService;
|
import com.ks.app.service.manager.GoldCornManager;
|
import com.ks.app.utils.PayConstant;
|
import com.ks.app.utils.vip.VIPOrderUtil;
|
import com.ks.app.utils.vip.VipUtil;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.yeshi.utils.StringUtil;
|
import org.yeshi.utils.alipay.AlipayH5PayUtil;
|
import org.yeshi.utils.entity.wx.WXPayOrderInfoV3;
|
import org.yeshi.utils.ios.pay.IOSPayVerifyUtil;
|
import org.yeshi.utils.ios.pay.vo.IOSAPPBuyVerifyResult;
|
import org.yeshi.utils.wx.WXPayV3Util;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.Calendar;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.UUID;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* @author hxh
|
* @title: OrderServiceImpl
|
* @description: TODO
|
* @date 2021/11/17 14:52
|
*/
|
|
@Service
|
public class OrderServiceImpl implements OrderService {
|
|
private static Logger logger = LoggerFactory.getLogger("OrderService");
|
|
private static Logger orderLogger = LoggerFactory.getLogger("order");
|
|
@Resource
|
private OrderRecordDao OrderRecordDao;
|
|
@Resource
|
private RedisTemplate<String, String> redisTemplate;
|
|
@Resource
|
private GoldCornManager goldCornManager;
|
|
@Resource
|
private VIPPriceService vipPriceService;
|
|
@Resource
|
private UserInfoService userInfoService;
|
|
@Resource
|
private UserVIPInfoDao userVIPInfoDao;
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public OrderRecord createOrder(OrderRecord record) throws OrderException {
|
if (record.getMoney() == null || record.getOrderType() == null || record.getUid() == null) {
|
throw new OrderException(1, "参数不完整");
|
}
|
|
if (record.getState() == null) {
|
record.setState(OrderRecord.STATE_NOT_PAY);
|
}
|
|
if (record.getCreateTime() == null) {
|
record.setCreateTime(new Date());
|
}
|
|
if (record.getPayWay() == OrderRecord.PAY_WAY_WX) {
|
if (record.getGoldCorn() != null && record.getGoldCorn() > 0) {
|
if (record.getMoney().compareTo(new BigDecimal("0")) == 0) {
|
record.setPayWay(OrderRecord.PAY_WAY_GOLDCORN);
|
} else {
|
record.setPayWay(OrderRecord.PAY_WAY_WX_GOLDCORN);
|
}
|
}
|
} else if (record.getPayWay() == OrderRecord.PAY_WAY_ALIPAY) {
|
if (record.getGoldCorn() != null && record.getGoldCorn() > 0) {
|
if (record.getMoney().compareTo(new BigDecimal("0")) == 0) {
|
record.setPayWay(OrderRecord.PAY_WAY_GOLDCORN);
|
} else {
|
record.setPayWay(OrderRecord.PAY_WAY_ALIPAY_GOLDCORN);
|
}
|
}
|
}
|
|
|
record.setMoneyPay(false);
|
record.setGoldCornPay(false);
|
OrderRecordDao.insertSelective(record);
|
orderLogger.info("订单创建成功:id-{} 类型-{}", record.getId(), record.getOrderType().name());
|
return record;
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
// @GlobalTransactional(timeoutMills = 30000, name = "buwan-order", rollbackFor = Exception.class)
|
@Override
|
public PayWayInfoDTO payOrder(OrderRecord record) throws OrderException, GoldCornException, PayException, VIPException {
|
|
|
String orderNo = VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), record.getId());
|
switch (record.getPayWay()) {
|
case OrderRecord
|
.PAY_WAY_ALIPAY_GOLDCORN:
|
|
try {
|
goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
|
} catch (Exception e) {
|
throw new GoldCornException(1, "影视豆扣除出错");
|
}
|
paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
|
|
orderLogger.info("订单影视豆支付成功:id-{}", record.getId());
|
case OrderRecord
|
.PAY_WAY_ALIPAY: {
|
if (record.getMoney() != null && record.getMoney().compareTo(new BigDecimal(0)) == 0) {
|
return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
|
}
|
//生成支付宝支付订单
|
String form = VipUtil.getVipChargeAlipayForm(record.getId(), record.getOrderType(), orderNo, record.getMoney());
|
//暂存2分钟
|
String id = StringUtil.Md5(UUID.randomUUID().toString() + "#" + System.currentTimeMillis());
|
redisTemplate.opsForValue().set(id, form, 120, TimeUnit.SECONDS);
|
String payUrl = PayConstant.ALIPAY_PRINT_PAY_FORM_LINK.replace("{formId}", id);
|
orderLogger.info("订单创建支付宝支付链接成功:id-{} 链接-{}", record.getId(), payUrl);
|
return new PayWayInfoDTO(OrderRecord
|
.PAY_WAY_ALIPAY, payUrl);
|
}
|
case OrderRecord
|
.PAY_WAY_WX_GOLDCORN:
|
try {
|
goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
|
|
} catch (Exception e) {
|
throw new GoldCornException(1, "影视豆扣除出错");
|
}
|
paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
|
orderLogger.info("订单影视豆支付成功:id-{} 类型-{}", record.getId(), record.getOrderType().name());
|
case OrderRecord
|
.PAY_WAY_WX: {
|
if (record.getMoney() != null && record.getMoney().compareTo(new BigDecimal(0)) == 0) {
|
return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
|
}
|
//生成微信支付订单
|
try {
|
String title = "";
|
if (record.getOrderType() == OrderType.vip) {
|
title = "影视大全VIP-" + record.getType().getName();
|
} else {
|
title = "单片购买";
|
}
|
String payUrl = VipUtil.createWXOrder(record.getId(), record.getIpInfo(), orderNo, record.getMoney(), title);
|
orderLogger.info("订单创建微信支付链接成功:id-{} 链接-{}", record.getId(), payUrl);
|
return new PayWayInfoDTO(OrderRecord.PAY_WAY_WX, payUrl);
|
} catch (Exception e) {
|
logger.error("生成微信支付订单出错", e);
|
throw new PayException(2, e.getMessage());
|
}
|
}
|
|
case OrderRecord.PAY_WAY_GOLDCORN: {
|
try {
|
goldCornManager.consumeGoldCorn(record, record.getGoldCorn());
|
orderLogger.info("订单影视豆支付成功:id-{}", record.getId());
|
} catch (Exception e) {
|
throw new GoldCornException(1, "影视豆扣除出错");
|
}
|
paySuccess(new OrderPaySuccessForm(record.getId(), OrderRecord.PAY_WAY_GOLDCORN, null, new Date()));
|
return new PayWayInfoDTO(0, VipUtil.getPaySuccessUrl(record.getId()));
|
}
|
case OrderRecord.PAY_WAY_IAPP:
|
return new PayWayInfoDTO(OrderRecord.PAY_WAY_IAPP, null);
|
}
|
throw new OrderException(1, "支付方式不存在");
|
}
|
|
private int getPayState(OrderRecord record) {
|
switch (record.getPayWay()) {
|
case OrderRecord.PAY_WAY_ALIPAY:
|
case OrderRecord.PAY_WAY_WX:
|
if (record.getMoneyPay() != null && record.getMoneyPay()) {
|
return OrderRecord.STATE_PAY;
|
} else {
|
return OrderRecord.STATE_NOT_PAY;
|
}
|
case OrderRecord.PAY_WAY_ALIPAY_GOLDCORN:
|
case OrderRecord.PAY_WAY_WX_GOLDCORN:
|
if (record.getMoneyPay() != null && record.getMoneyPay() && record.getGoldCornPay() != null && record.getGoldCornPay()) {
|
return OrderRecord.STATE_PAY;
|
} else {
|
return OrderRecord.STATE_NOT_PAY;
|
}
|
case OrderRecord.PAY_WAY_GOLDCORN:
|
if (record.getGoldCornPay() != null && record.getGoldCornPay()) {
|
return OrderRecord.STATE_PAY;
|
} else {
|
return OrderRecord.STATE_NOT_PAY;
|
}
|
case OrderRecord.PAY_WAY_IAPP:
|
if (record.getMoneyPay()) {
|
return OrderRecord.STATE_PAY;
|
} else {
|
return OrderRecord.STATE_NOT_PAY;
|
}
|
}
|
return OrderRecord.STATE_NOT_PAY;
|
}
|
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public OrderRecord paySuccess(OrderPaySuccessForm successForm) throws
|
VIPException, OrderException {
|
|
return paySuccess(successForm, (OrderRecord record) -> {
|
|
//TODO 支付成功
|
});
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public OrderRecord paySuccess(OrderPaySuccessForm successForm, IPaySuccess paySuccess) throws VIPException, OrderException {
|
orderLogger.info("订单支付成功目的执行:id-{},支付方式-{},支付金额-{},支付时间-{}", successForm.getId(), successForm.getPayWay(), successForm.getPayMoney(), successForm.getPayTime());
|
|
OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(successForm.getId());
|
//修改记录
|
if (record == null) {
|
throw new OrderException(10, "订单不存在");
|
}
|
|
if (record.getState() != OrderRecord.STATE_NOT_PAY) {
|
throw new OrderException(1, "订单未处于待支付状态");
|
}
|
|
if (successForm.getPayWay() != OrderRecord.PAY_WAY_GOLDCORN) {
|
record.setPayMoney(successForm.getPayMoney());
|
record.setMoneyPay(true);
|
record.setAppleTransactionId(successForm.getAppleTransactionId());
|
record.setAppleOriginalTransactionId(successForm.getAppleOriginalTransactionId());
|
} else {
|
record.setGoldCornPay(true);
|
}
|
|
record.setPayTime(successForm.getPayTime());
|
record.setUpdateTime(new Date());
|
record.setState(getPayState(record));
|
|
//已经支付成功
|
if (record.getState() == OrderRecord.STATE_PAY) {
|
OrderRecordDao.insertPaySuccess(successForm.getId());
|
}
|
|
if (record.getOrderType() == OrderType.vip) {
|
Date[] expireDate = addExpireTime(record.getUid(), successForm.getPayTime(), record.getType());
|
record.setVipStartTime(expireDate[0]);
|
record.setVipEndTime(expireDate[1]);
|
if (expireDate == null) {
|
throw new VIPException(2, "添加用户会员时间出错");
|
}
|
OrderRecordDao.updateByPrimaryKeySelective(record);
|
|
|
if (record.getState() == OrderRecord.STATE_PAY) {
|
orderLogger.info("订单全部支付成功:id-{}", successForm.getId());
|
if (paySuccess != null) {
|
paySuccess.onSuccess(record);
|
}
|
orderLogger.info("购买VIP成功:id-{}", successForm.getId());
|
} else {
|
orderLogger.info("订单部分支付成功:id-{}", successForm.getId());
|
}
|
|
}
|
|
return record;
|
}
|
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public void cancelOrder(Long id, String reason) throws OrderException, GoldCornException {
|
OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(id);
|
if (record == null) {
|
throw new OrderException(1, "订单不存在");
|
}
|
if (record.getState() == OrderRecord.STATE_PAY) {
|
throw new OrderException(1, "已支付成功的订单不能取消");
|
}
|
|
if (record.getPayWay() != OrderRecord.PAY_WAY_GOLDCORN && record.getMoneyPay() != null && record.getMoneyPay()) {
|
throw new OrderException(2, "资金支付成功的订单不能取消");
|
}
|
|
//返回豆
|
if (record.getGoldCornPay() != null && record.getGoldCornPay() && record.getGoldCorn() != null && record.getGoldCorn() > 0) {
|
try {
|
goldCornManager.drawbackGoldCorn(record);
|
} catch (Exception e) {
|
throw new GoldCornException(1, "影视豆退款失败");
|
}
|
}
|
|
//设置订单状态
|
record.setState(OrderRecord.STATE_CANCEL);
|
record.setUpdateTime(new Date());
|
record.setRemarks(reason);
|
OrderRecordDao.updateByPrimaryKeySelective(record);
|
orderLogger.info("取消订单成功:id-{}", id);
|
}
|
|
@Override
|
public List<OrderRecord> getCanCancelOrderList(int page, int pageSize) {
|
|
OrderRecordDao.DaoQuery daoQuery = new OrderRecordDao.DaoQuery();
|
daoQuery.state = OrderRecord.STATE_NOT_PAY;
|
//30分钟未支付取消订单
|
daoQuery.maxCreateTime = new Date(System.currentTimeMillis() - 1000 * 60 * 30);
|
daoQuery.minCreateTime = new Date(daoQuery.maxCreateTime.getTime() - 1000 * 60 * 60L * 24);
|
|
return OrderRecordDao.list(daoQuery);
|
}
|
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public OrderRecord checkOrderPayState(Long id) {
|
OrderRecord record = OrderRecordDao.selectByPrimaryKeyForUpdate(id);
|
if (record.getState() == OrderRecord.STATE_PAY) {
|
return record;
|
}
|
|
switch (record.getPayWay()) {
|
case OrderRecord.PAY_WAY_ALIPAY_GOLDCORN:
|
case OrderRecord.PAY_WAY_ALIPAY: {
|
//支付宝
|
AlipayTradeQueryResponse res = null;
|
try {
|
res = AlipayH5PayUtil.queryOrder(VipUtil.getAlipayApp(), VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), id), null);
|
//支付成功
|
if (res.isSuccess() && "TRADE_SUCCESS".equalsIgnoreCase(res.getTradeStatus())) {
|
try {
|
return paySuccess(new OrderPaySuccessForm(id, OrderRecord.PAY_WAY_ALIPAY, new BigDecimal(res.getTotalAmount()), new Date()));
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
} catch (AlipayApiException e) {
|
e.printStackTrace();
|
}
|
}
|
|
break;
|
case OrderRecord.PAY_WAY_WX_GOLDCORN:
|
case OrderRecord.PAY_WAY_WX: {
|
//微信
|
try {
|
WXPayOrderInfoV3 info = WXPayV3Util.getPayOrderInfo(VIPOrderUtil.getOutOrderNo(userInfoService.getSystem(record.getUid()), record.getOrderType(), id), VipUtil.getWXAPP());
|
if (info != null && info.getTrade_state().equalsIgnoreCase("SUCCESS")) {
|
paySuccess(new OrderPaySuccessForm(id, record.getPayWay(), new BigDecimal(info.getAmount().getPayer_total()).divide(new BigDecimal(100), 2, RoundingMode.FLOOR), new Date()));
|
return record;
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
break;
|
}
|
return record;
|
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
@Override
|
public OrderRecord checkApplePay(Long orderNo, String receipt) throws Exception {
|
OrderRecord orderRecord = OrderRecordDao.selectByPrimaryKeyForUpdate(orderNo);
|
if (orderRecord == null) {
|
throw new OrderException(1, "订单号不存在");
|
}
|
|
SystemEnum system = userInfoService.getSystem(orderRecord.getUid());
|
|
if (!StringUtil.isNullOrEmpty(orderRecord.getAppleTransactionId())) {
|
throw new OrderException(2, "订单已支付");
|
}
|
|
IOSAPPBuyVerifyResult result = IOSPayVerifyUtil.buyAppVerify(receipt, "28ca52e358b94c4eba3de41dfa7dd023", false);
|
List<IOSAPPBuyVerifyResult.OrderInfo> orderInfoList = result.getLatestReceiptInfo();
|
IOSAPPBuyVerifyResult.OrderInfo orderInfo = orderInfoList.get(0);
|
String productId = orderInfo.getProduct_id();
|
VIPPrice vipPrice = vipPriceService.selectByIOSProductId(productId, system);
|
if (vipPrice == null) {
|
throw new Exception("商品ID不存在");
|
}
|
if (orderRecord.getType() != vipPrice.getType()) {
|
throw new Exception("价格类型不匹配");
|
}
|
//String id, int payWay, BigDecimal payMoney, Date payTime, String appleTransactionId, String appleOriginalTransactionId
|
OrderPaySuccessForm successForm = new OrderPaySuccessForm(orderRecord.getId(), OrderRecord.PAY_WAY_IAPP, new BigDecimal(0), new Date(orderInfo.getPurchaseDateMs()), orderInfo.getTransactionId(), orderInfo.getOriginalTransactionId());
|
paySuccess(successForm);
|
return null;
|
}
|
|
|
@Override
|
public List<OrderRecord> listOrderRecord(Long uid, OrderType orderType, Integer state, int page, int pageSize) {
|
|
OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
|
query.start = (page - 1) * pageSize;
|
query.count = pageSize;
|
query.uid = uid;
|
query.state = state;
|
query.orderType = orderType;
|
return OrderRecordDao.list(query);
|
}
|
|
@Override
|
public long countOrderRecord(Long uid, OrderType orderType, Integer state) {
|
OrderRecordDao.DaoQuery query = new OrderRecordDao.DaoQuery();
|
query.uid = uid;
|
query.state = state;
|
query.orderType = orderType;
|
return OrderRecordDao.count(query);
|
}
|
|
@Override
|
public OrderRecord getOrderRecord(Long id) {
|
return OrderRecordDao.selectByPrimaryKey(id);
|
}
|
|
|
/**
|
* 续期
|
*
|
* @param uid
|
* @param payTime
|
* @param type
|
* @return
|
*/
|
private Date[] addExpireTime(Long uid, Date payTime, VIPPriceType type) {
|
if (type == null || uid == null) {
|
return null;
|
}
|
UserVIPInfo userVIPInfo = userVIPInfoDao.selectByPrimaryKeyForUpdate(uid);
|
|
if (userVIPInfo == null) {
|
//新增
|
UserVIPInfo vip = new UserVIPInfo();
|
vip.setUid(uid);
|
vip.setCreateTime(new Date());
|
Date[] expireDate = getExpireTime(payTime, null, type);
|
vip.setExpireDate(expireDate[1]);
|
userVIPInfoDao.insertSelective(vip);
|
return expireDate;
|
} else {
|
//修改
|
UserVIPInfo update = new UserVIPInfo();
|
update.setUid(uid);
|
Date[] expireDate = getExpireTime(payTime, userVIPInfo.getExpireDate(), type);
|
update.setExpireDate(expireDate[1]);
|
update.setUpdateTime(new Date());
|
userVIPInfoDao.updateByPrimaryKeySelective(update);
|
return expireDate;
|
}
|
}
|
|
/**
|
* 获取到期时间
|
*
|
* @param payTime
|
* @param expireTime
|
* @param type
|
* @return
|
*/
|
private Date[] getExpireTime(Date payTime, Date expireTime, VIPPriceType type) {
|
Calendar calendar = Calendar.getInstance();
|
if (expireTime != null) {
|
//之前续期时间是否大于付款时间
|
if (payTime.getTime() < expireTime.getTime()) {
|
calendar.setTimeInMillis(expireTime.getTime());
|
} else {
|
calendar.setTimeInMillis(payTime.getTime());
|
}
|
} else {
|
calendar.setTimeInMillis(payTime.getTime());
|
}
|
long startTime = calendar.getTimeInMillis();
|
if (type == VIPPriceType.day) {
|
calendar.add(Calendar.DAY_OF_WEEK, 1);
|
} else if (type == VIPPriceType.week) {
|
calendar.add(Calendar.WEEK_OF_YEAR, 1);
|
} else if (type == VIPPriceType.month) {
|
calendar.add(Calendar.MONTH, 1);
|
} else if (type == VIPPriceType.season) {
|
calendar.add(Calendar.MONTH, 3);
|
} else if (type == VIPPriceType.halfYear) {
|
calendar.add(Calendar.MONTH, 6);
|
} else if (type == VIPPriceType.year) {
|
calendar.add(Calendar.YEAR, 1);
|
}
|
return new Date[]{new Date(startTime), new Date(calendar.getTimeInMillis())};
|
}
|
|
|
}
|