package org.xmx0632.deliciousfruit.service; import java.math.BigDecimal; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest; import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment; import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment.CashCouponPay; import org.xmx0632.deliciousfruit.api.v1.bo.OrderRequest.Payment.GiftCardPay; import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.DeductionPay; import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.PayByCashCoupon; import org.xmx0632.deliciousfruit.api.v1.bo.OrderResponse.PayByGiftCard; import org.xmx0632.deliciousfruit.erp.ErpApiService; import org.xmx0632.deliciousfruit.erp.bo.DeductionMessage; import org.xmx0632.deliciousfruit.erp.bo.ErpCard; import org.xmx0632.deliciousfruit.erp.bo.ErpCash; import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCard; import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCash; import org.xmx0632.deliciousfruit.erp.bo.ErpChangeCoin; import org.xmx0632.deliciousfruit.erp.bo.ErpChangePoint; import org.xmx0632.deliciousfruit.erp.bo.ErpCustomer; import org.xmx0632.deliciousfruit.erp.bo.ErpMessage; /** * 客户端IOS订购商品时,使用的抵扣券/礼品卡/积分/账户余额等需要实时到ERP查询的信息,并扣除 * * @author xmx0632 * */ // Spring Bean的标识. @Component public class DeductionPayService { private static Logger log = LoggerFactory .getLogger(DeductionPayService.class); @Autowired private ErpApiService erpApiService; public DeductionPayService() { } /** * 查询验证用户请求的抵扣信息 * * @param orderRequest * @param customerId * @return */ public DeductionPay getDeductionPay(OrderRequest orderRequest, String customerId) { DeductionPay deductionPay = new DeductionPay(); DeductionMessage deductionMessage = new DeductionMessage(); try { Payment payment = orderRequest.getPayment(); if (payment == null) { return deductionPay; } // 现金券 List<CashCouponPay> cashCoupons = payment.getCashCoupons(); if (cashCoupons != null) { for (CashCouponPay cashCouponPay : cashCoupons) { // 发送消息到ERP查询现金券余额,检查是否可用 ErpCash erpCash = erpApiService.getCashBy(cashCouponPay .getId()); log.debug("ErpCash:{}", erpCash); if (erpCash == null) { log.warn("can not find cashCoupon with id:{}!", cashCouponPay.getId()); throw new ServiceException("can not find cashCoupon!"); } int availableUseTime = erpCash.getIntUseStatus(); if (availableUseTime < 1) { log.warn("ErpCash status abnormal! erpCash:{} ", erpCash); throw new ServiceException("erpCard status abnormal!"); } String decValue = erpCash.getDecValue(); Double availableValue = Double.valueOf(decValue); BigDecimal availableAmount = BigDecimal .valueOf(availableValue); // 检查请求抵扣的现金券金额与现金券的面值是否一致 BigDecimal payAmount = cashCouponPay.getPayAmount(); if (availableAmount.compareTo(payAmount) != 0) { log.warn( "ErpCash payAmount abnormal! availableAmount:{} payAmount:{}", availableAmount, payAmount); throw new ServiceException( "ErpCash payAmount abnormal! availableAmount:" + availableAmount + " payAmount:" + payAmount); } // 如果可用,发送抵扣现金券消息到ERP deductionMessage .addErpChangeCash(new ErpMessage<ErpChangeCash>( new ErpChangeCash(erpCash.getStrCashNo(), availableUseTime))); // 记录使用后的剩余使用次数 int leftTimes = availableUseTime - 1; log.debug("leftTimes:{}", leftTimes); PayByCashCoupon payByCashCoupon = new PayByCashCoupon(); payByCashCoupon.setPayLeftTimes(leftTimes); payByCashCoupon.setDeductionAmount(payAmount); payByCashCoupon.setId(cashCouponPay.getId()); deductionPay.getPayByCashCouponInfo().add(payByCashCoupon); } } // 礼品卡 List<GiftCardPay> giftcards = payment.getGiftCards(); if (giftcards != null) { for (GiftCardPay giftCardPay : giftcards) { PayByGiftCard payByGiftCard = new PayByGiftCard(); // 发送消息到ERP查询礼品卡余额 ErpCard erpCard = erpApiService.getCardBy(giftCardPay .getId()); log.debug("erpCard:{}", erpCard); if (erpCard == null) { log.warn("can not find giftCard with id:{}!", giftCardPay.getId()); throw new ServiceException("can not find giftCard!"); } if (!ErpCard.Status_NORMAL.equals(erpCard.getIntStatus())) { log.warn("ErpCard status abnormal! erpCard:{} ", erpCard); throw new ServiceException( "ErpCard status abnormal! erpCard:" + erpCard); } String decValue = erpCard.getDecValue(); Double availableValue = Double.valueOf(decValue); BigDecimal currentGiftCardAvailableAmount = BigDecimal .valueOf(availableValue); // 验证礼品卡金额是否 > 请求扣除金额 BigDecimal payAmount = giftCardPay.getPayAmount(); if (currentGiftCardAvailableAmount.compareTo(payAmount) < 0) { log.warn( "ErpCard available amount is not enough! payAmount:{} but available amount:{}", payAmount, currentGiftCardAvailableAmount); throw new ServiceException( "ErpCard available amount is not enough!payAmount:" + payAmount + " but available amount:" + currentGiftCardAvailableAmount); } // 发送抵扣礼品卡消息到ERP deductionMessage .addErpChangeCard( new ErpMessage<ErpChangeCard>( new ErpChangeCard(giftCardPay .getId(), payAmount .toString()))); BigDecimal leftBalance = currentGiftCardAvailableAmount .subtract(payAmount); payByGiftCard.setDeductionAmount(payAmount); payByGiftCard.setBalance(leftBalance); payByGiftCard.setId(giftCardPay.getId()); deductionPay.getPayByGiftCardInfo().add(payByGiftCard); } } int payPoint = payment.getPayPonit(); BigDecimal payCoin = payment.getPayAmountFromAccount(); log.debug("payPoint:{} payCoin:{}", payPoint, payCoin); boolean shouldPayByPoint = shouldPayByPoint(payPoint); boolean shouldPayByCoin = shouldPayByCoin(payCoin); log.debug("shouldPayByPoint:{} shouldPayByCoin:{}", shouldPayByPoint, shouldPayByCoin); ErpCustomer erpCustomer = getErpCustomerIfNeed(customerId, shouldPayByPoint, shouldPayByCoin); if (shouldPayByPoint) { BigDecimal payAmountFromPonit = payment.getPayAmountFromPonit(); log.debug("payAmountFromPonit:{}", payAmountFromPonit); // 验证客户端积分抵扣金额是否计算正确(100:1) validatePointRatio(payPoint, payAmountFromPonit); // 调用ERP接口查询用户当前可用的抵扣积分 Integer point = Integer.valueOf(erpCustomer.getIntPoint()); // 检查用户是否有足够的请求抵扣积分额度 if (pointNotEnough(payPoint, point)) { log.warn( "point not enough! payPoint:{} but available point:{}", payPoint, point); throw new ServiceException("point not enough! payPoint:" + payPoint + " but available point:" + point); } // 调用ERP接口抵扣用户积分 deductionMessage.setPayByPoint(new ErpChangePoint(customerId, payAmountFromPonit.toString())); deductionPay.setPayByPoint(payAmountFromPonit); } if (shouldPayByCoin) { // 从ERP接口查询账户余额 BigDecimal coin = BigDecimal.valueOf(Double.valueOf(erpCustomer .getDecCoin())); // 检查用户是否有足够的请求抵扣账户余额 if (notEnoughCoin(payCoin, coin)) { log.warn( "coin not enough! payCoin:{} but available coin:{}", payCoin, coin); throw new ServiceException( "coin not enough! payAmountFromAccount:" + payCoin + " but available coin:" + coin); } // 调用ERP接口抵扣账户余额 deductionMessage.setPayFromAccount(new ErpChangeCoin( customerId, payCoin.toString())); deductionPay.setPayFromAccount(payCoin); } // 下一步统一调用ERP抵扣接口,如果有任何失败,则回滚之前的抵扣操作 deductionPay.setDeductionMessage(deductionMessage); return deductionPay; } catch (Exception e) { log.warn(e.getMessage(), e); throw new ServiceException(e.getMessage(), e); } } private boolean notEnoughCoin(BigDecimal payCoin, BigDecimal coin) { return payCoin.compareTo(coin) > 0; } private ErpCustomer getErpCustomerIfNeed(String customerId, boolean shouldPayByPoint, boolean shouldPayByCoin) { if (!shouldPayByPoint && !shouldPayByCoin) { return null; } ErpCustomer erpCustomer = erpApiService.getCustomerBy(customerId); log.debug("erpCustomer:{}", erpCustomer); if (erpCustomer == null) { log.warn("can not find customer with id:{}", customerId); throw new ServiceException("can not find customer with id:" + customerId); } return erpCustomer; } private boolean pointNotEnough(int payPoint, Integer point) { return payPoint > point; } private void validatePointRatio(int payPoint, BigDecimal payAmountFromPonit) { BigDecimal payAmount = BigDecimal.valueOf(payPoint).divide( BigDecimal.valueOf(100.0).setScale(2)); log.debug("payAmount:{}", payAmount); if (payAmount.compareTo(payAmountFromPonit) != 0) { log.warn( "calc PayAmountFromPonit error! payPoint:{} payAmountFromPonit:{}", payPoint, payAmountFromPonit); throw new ServiceException( "calc PayAmountFromPonit error! payPoint:" + payPoint + " payAmountFromPonit:" + payAmountFromPonit + " must be " + payAmount); } } private boolean shouldPayByPoint(int payPoint) { return payPoint > 0; } private boolean shouldPayByCoin(BigDecimal payCoin) { return payCoin.compareTo(BigDecimal.ZERO) == 1; } /** * 发送抵扣消息到ERP * * @param deductionMessage */ public void sendDeductionPayMessage(DeductionMessage deductionMessage) { List<ErpMessage<ErpChangeCard>> erpChangeCardList = deductionMessage .getErpChangeCardList(); for (ErpMessage<ErpChangeCard> erpMessage : erpChangeCardList) { boolean sentSuccess = erpApiService.changeCard(erpMessage .getMessage()); erpMessage.setHasSent(sentSuccess); log.debug("erpChangeCard message:{} sentSuccess:{}", sentSuccess, erpMessage.getMessage()); if (!sentSuccess) { return; } } List<ErpMessage<ErpChangeCash>> erpChangeCashList = deductionMessage .getErpChangeCashList(); for (ErpMessage<ErpChangeCash> erpMessage : erpChangeCashList) { boolean sentSuccess = erpApiService.changeCash(erpMessage .getMessage()); erpMessage.setHasSent(sentSuccess); log.debug("erpChangeCash message:{} sentSuccess:{}", sentSuccess, erpMessage.getMessage()); if (!sentSuccess) { return; } } ErpMessage<ErpChangePoint> erpChangePoint = deductionMessage .getErpChangePoint(); if (erpChangePoint != null) { boolean sentSuccess = erpApiService.changePoint(erpChangePoint .getMessage()); erpChangePoint.setHasSent(sentSuccess); log.debug("erpChangePoint message:{} sentSuccess:{}", sentSuccess, erpChangePoint.getMessage()); if (!sentSuccess) { return; } } ErpMessage<ErpChangeCoin> erpChangeCoin = deductionMessage .getErpChangeCoin(); if (erpChangeCoin != null) { boolean sentSuccess = erpApiService.changeCoin(erpChangeCoin .getMessage()); erpChangeCoin.setHasSent(sentSuccess); log.debug("erpChangeCoin message:{} sentSuccess:{}", sentSuccess, erpChangeCoin.getMessage()); if (!sentSuccess) { return; } } } /** * 回滚已经发送的抵扣消息 * * @param deductionMessage */ public void rollbackDeductionPayMessage(DeductionMessage deductionMessage) { List<ErpMessage<ErpChangeCard>> erpChangeCardList = deductionMessage .getErpChangeCardList(); for (ErpMessage<ErpChangeCard> erpMessage : erpChangeCardList) { if (erpMessage.hasSent()) { ErpChangeCard rollbackMessage = erpMessage.getMessage() .getRollback(); boolean sentSuccess = erpApiService.changeCard(rollbackMessage); erpMessage.setHasRollback(sentSuccess); log.debug("rollback message:[{}] result:[{}]", rollbackMessage, sentSuccess); } } List<ErpMessage<ErpChangeCash>> erpChangeCashList = deductionMessage .getErpChangeCashList(); for (ErpMessage<ErpChangeCash> erpMessage : erpChangeCashList) { if (erpMessage.hasSent()) { ErpChangeCash rollbackMessage = erpMessage.getMessage() .getRollback(); boolean sentSuccess = erpApiService.changeCash(rollbackMessage); erpMessage.setHasRollback(sentSuccess); log.debug("rollback message:[{}] result:[{}]", rollbackMessage, sentSuccess); } } ErpMessage<ErpChangeCoin> erpChangeCoin = deductionMessage .getErpChangeCoin(); if (erpChangeCoin != null && erpChangeCoin.hasSent()) { ErpChangeCoin rollbackMessage = erpChangeCoin.getMessage() .getRollback(); boolean sentSuccess = erpApiService.changeCoin(rollbackMessage); erpChangeCoin.setHasRollback(sentSuccess); log.debug("rollback message:[{}] result:[{}]", rollbackMessage, sentSuccess); } ErpMessage<ErpChangePoint> erpChangePoint = deductionMessage .getErpChangePoint(); if (erpChangePoint != null && erpChangePoint.hasSent()) { ErpChangePoint rollbackMessage = erpChangePoint.getMessage() .getRollback(); boolean sentSuccess = erpApiService.changePoint(rollbackMessage); erpChangePoint.setHasRollback(sentSuccess); log.debug("rollback message:[{}] result:[{}]", rollbackMessage, sentSuccess); } } }