From 1c3ee8a6630d71cdb3183524021eba54563039bf Mon Sep 17 00:00:00 2001 From: Stormeye Wu Date: Sat, 15 Dec 2018 20:54:01 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=82=A8=E5=80=BC=E5=8D=A1][=E6=96=B0?= =?UTF-8?q?=E5=A2=9E]:=E5=8D=A1=E6=B6=88=E8=B4=B9=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/WxCardPayController.java | 115 ++++++++++++++++++ .../java/com/iformall/common/ErrorCode.java | 5 + .../com/iformall/domain/po/WxCardInfo.java | 4 + .../com/iformall/domain/po/WxCardSpend.java | 27 +++- .../iformall/service/WxCardSpendService.java | 14 ++- .../com/iformall/service/WxOrderService.java | 15 ++- .../service/impl/WxCardSpendServiceImpl.java | 68 ++++++++++- .../service/impl/WxOrderServiceImpl.java | 42 +++++++ .../resources/mapper/WxCardInfoMapper.xml | 8 +- .../resources/mapper/WxCardSpendMapper.xml | 37 ++++-- 10 files changed, 308 insertions(+), 27 deletions(-) create mode 100644 mallinkCApi/src/main/java/com/iformall/controller/WxCardPayController.java diff --git a/mallinkCApi/src/main/java/com/iformall/controller/WxCardPayController.java b/mallinkCApi/src/main/java/com/iformall/controller/WxCardPayController.java new file mode 100644 index 000000000..2c7699394 --- /dev/null +++ b/mallinkCApi/src/main/java/com/iformall/controller/WxCardPayController.java @@ -0,0 +1,115 @@ +package com.iformall.controller; + + +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.domain.po.*; +import com.iformall.exception.MallinkException; +import com.iformall.service.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.Map; + +/** + * @author Stormeye Wu wuguoqiang@iformall.com + */ +@RestController +@Api(description = "C端扫B端商户码储值卡支付") +@RequestMapping("/api/carday") +public class WxCardPayController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxMerchantService wxMerchantService; + + @Autowired + WxOrderService wxOrderService; + + @Autowired + WxCardSpendService wxCardSpendService; + + @ApiOperation(value = "C端扫B端商户码支付订单", notes = "params:{\"cardId\":\"String\",\"merchantCode\":\"String\",\"totalFee\":\"String\"}") + @PostMapping("order_create") + public ResultData saveCardPayOrder(@RequestBody Map paramMap, HttpServletRequest request) { + String ipStr = getIpAddr(); + logger.info("saveCardPayOrder: " + ipStr + " :"+ paramMap.toString()); + String cardIdStr = paramMap.get("cardId"); + String merchantCode = paramMap.get("merchantCode"); + String totalFeeStr = paramMap.get("totalFee"); + + if (StringUtils.isBlank(cardIdStr)) { + logger.error("cardId不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "cardId不能为空"); + } + if (StringUtils.isBlank(merchantCode)) { + logger.error("merchantCode不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "merchantCode不能为空"); + } + if (StringUtils.isBlank(totalFeeStr)) { + logger.error("totalFee不能为空"); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "totalFee不能为空"); + } + + Long cardId = null; + Long merchantId = null; + try { + cardId = Long.valueOf(cardIdStr); + } catch (Exception e) { + logger.error("cardId convert failed:" + cardIdStr); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "cardIdStr转换失败"); + } + try { + merchantId = Long.valueOf(merchantCode); + } catch (Exception e) { + logger.error("merchantCode convert failed:" + merchantCode); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "merchantCode转换失败"); + } + + BigDecimal totalFee = new BigDecimal(totalFeeStr); + totalFee.setScale(2, BigDecimal.ROUND_HALF_UP); // 第一个变量是小数位数,第二个变量是取舍方法(四舍五入) + + Integer payment = totalFee.multiply(new BigDecimal(100)).intValue(); + + WxCUser user = getUser(); + + WxMerchant merchant = wxMerchantService.getById(merchantId); + + WxOrder order = null; + try { + order = wxOrderService.saveCardPayOrder(merchant, totalFeeStr, payment); + } catch (MallinkException e) { + logger.error("saveCardPayOrder 1" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("saveCardPayOrder 2" + e.getMessage()); + return new ResultData(ErrorCode.ORDER_IS_FAIL, e.getMessage()); + } + + WxCardSpend record = new WxCardSpend(); + record.setTenantId(merchant.getTenantId()); + record.setCardId(cardId); + record.setOwnerId(user.getId()); + record.setMerchantId(merchantId); + record.setOrderId(order.getId()); + record.setIp(ipStr); + record.setDeductionAmount(payment); + + try { + return wxCardSpendService.createCardSpend(record, order, user); + } catch (MallinkException e) { + logger.error("card spend error, req 2: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + logger.error("card spend error, req 3: " + record.toString() + ", e:" + e.getMessage()); + return new ResultData(ErrorCode.PAY_ORDER_ERROR, e.getMessage()); + } + } +} diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index 30ed33c0a..204c859b1 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -142,6 +142,11 @@ public enum ErrorCode{ COUPON_ORDER_IS_INVALID(4003, "卡券已经作废"), COUPON_ORDER_BUSER_IS_NULL(4004, "卡券B端用户不存在"), + /** + * 卡 + */ + CARD_IS_NOT_FOUND(9001, "优惠卡不存在"), + /** * 微信 diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxCardInfo.java b/mallinkService/src/main/java/com/iformall/domain/po/WxCardInfo.java index f103d666b..d299c1b30 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxCardInfo.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxCardInfo.java @@ -33,6 +33,9 @@ public class WxCardInfo implements Serializable { /**面额总金额*/ @io.swagger.annotations.ApiModelProperty(value="面额总金额",name="amount") private Integer amount; + /**购买总金额*/ + @io.swagger.annotations.ApiModelProperty(value="购买总金额",name="saleAmount") + private Integer saleAmount; /**剩余面额*/ @io.swagger.annotations.ApiModelProperty(value="剩余面额",name="remainingAmount") private Integer remainingAmount; @@ -61,6 +64,7 @@ public class WxCardInfo implements Serializable { ,CouponId_ASC("`coupon_id` ASC"),CouponId_DESC("`coupon_id` DESC") ,TransactionId_ASC("`transaction_id` ASC"),TransactionId_DESC("`transaction_id` DESC") ,Amount_ASC("`amount` ASC"),Amount_DESC("`amount` DESC") + ,SaleAmount_ASC("`sale_amount` ASC"),SaleAmount_DESC("`sale_amount` DESC") ,RemainingAmount_ASC("`remaining_amount` ASC"),RemainingAmount_DESC("`remaining_amount` DESC") ,ServiceFeeAmount_ASC("`service_fee_amount` ASC"),ServiceFeeAmount_DESC("`service_fee_amount` DESC") ,ShareFeeAmount_ASC("`share_fee_amount` ASC"),ShareFeeAmount_DESC("`share_fee_amount` DESC") diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java b/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java index 1f29d5291..b0070fa73 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java @@ -36,6 +36,12 @@ public class WxCardSpend implements Serializable { /**订单账号*/ @io.swagger.annotations.ApiModelProperty(value="订单账号",name="orderId") private Long orderId; + /**ip地址*/ + @io.swagger.annotations.ApiModelProperty(value="ip地址",name="ip") + private String ip; + /**抵扣金额*/ + @io.swagger.annotations.ApiModelProperty(value="抵扣金额",name="deductionAmount") + private Integer deductionAmount; /**支付金额(包含通道费)*/ @io.swagger.annotations.ApiModelProperty(value="支付金额(包含通道费)",name="payment") private Integer payment; @@ -43,11 +49,17 @@ public class WxCardSpend implements Serializable { @io.swagger.annotations.ApiModelProperty(value="实收金额(不包含通道费)",name="realPayment") private Integer realPayment; /**卡剩余总金额*/ - @io.swagger.annotations.ApiModelProperty(value="卡剩余总金额",name="remainAmount") - private Integer remainAmount; + @io.swagger.annotations.ApiModelProperty(value="卡剩余总金额",name="cardRemainAmount") + private Integer cardRemainAmount; /**卡支付前总金额*/ - @io.swagger.annotations.ApiModelProperty(value="卡支付前总金额",name="beforeAmount") - private Integer beforeAmount; + @io.swagger.annotations.ApiModelProperty(value="卡支付前总金额",name="cardBeforeAmount") + private Integer cardBeforeAmount; + /**卡剩余实际总金额*/ + @io.swagger.annotations.ApiModelProperty(value="卡剩余总金额",name="cardRemainRealAmount") + private Integer cardRemainRealAmount; + /**卡支付前实际总金额*/ + @io.swagger.annotations.ApiModelProperty(value="卡支付前总金额",name="cardBeforeRealAmount") + private Integer cardBeforeRealAmount; /**创建时间*/ @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") private Date createDate; @@ -65,10 +77,13 @@ public class WxCardSpend implements Serializable { ,OwnerId_ASC("`owner_id` ASC"),OwnerId_DESC("`owner_id` DESC") ,MerchantId_ASC("`merchant_id` ASC"),MerchantId_DESC("`merchant_id` DESC") ,OrderId_ASC("`order_id` ASC"),OrderId_DESC("`order_id` DESC") + ,Ip_ASC("`ip` ASC"),Ip_DESC("`ip` DESC") ,Payment_ASC("`payment` ASC"),Payment_DESC("`payment` DESC") ,RealPayment_ASC("`real_payment` ASC"),RealPayment_DESC("`real_payment` DESC") - ,RemainAmount_ASC("`remain_amount` ASC"),RemainAmount_DESC("`remain_amount` DESC") - ,BeforeAmount_ASC("`before_amount` ASC"),BeforeAmount_DESC("`before_amount` DESC") + ,CardRemainAmount_ASC("`card_remain_amount` ASC"),CardRemainAmount_DESC("`card_remain_amount` DESC") + ,CardBeforeAmount_ASC("`card_before_amount` ASC"),CardBeforeAmount_DESC("`card_before_amount` DESC") + ,CardRemainRealAmount_ASC("`card_remain_real_amount` ASC"),CardRemainRealAmount_DESC("`card_remain_real_amount` DESC") + ,CardBeforeRealAmount_ASC("`card_before_real_amount` ASC"),CardBeforeRealAmount_DESC("`card_before_real_amount` DESC") ,CreateDate_ASC("`create_date` ASC"),CreateDate_DESC("`create_date` DESC") ,UpdateDate_ASC("`update_date` ASC"),UpdateDate_DESC("`update_date` DESC") ; diff --git a/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java b/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java index 52dd3cd2f..470dfc1fe 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java @@ -1,11 +1,23 @@ package com.iformall.service; import com.github.pagehelper.PageInfo; +import com.iformall.common.ResultData; +import com.iformall.domain.po.WxCUser; import com.iformall.domain.po.WxCardSpend; +import com.iformall.domain.po.WxOrder; public interface WxCardSpendService { - /** + /** + * 创建卡花费 + * @param record + * @param order + * @param user + * @return + */ + ResultData createCardSpend(WxCardSpend record, WxOrder order, WxCUser user); + + /** * 根据实体查询分页列表 * * @param record diff --git a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java index 8ca8c289e..dae516d91 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxOrderService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxOrderService.java @@ -2,10 +2,7 @@ package com.iformall.service; import com.github.pagehelper.PageInfo; import com.iformall.common.ResultData; -import com.iformall.domain.po.WxCUser; -import com.iformall.domain.po.WxCouponOrder; -import com.iformall.domain.po.WxMerchantBUser; -import com.iformall.domain.po.WxOrder; +import com.iformall.domain.po.*; import com.iformall.domain.vo.WxOrderCouponVo; import com.iformall.domain.vo.WxOrderQueryVo; import com.iformall.enums.EnumOrderStatus; @@ -44,13 +41,21 @@ public interface WxOrderService { WxOrder saveCouponOrder(WxCUser user, Long couponChannelId, Long couponId); /** - * 刷卡支付 + * 付款码支付 * @param user * @param totalFeeStr * @return 订单id */ WxOrder saveMicroPayOrder(WxMerchantBUser user, String totalFeeStr); + /** + * 商户码-储值卡支付 + * @param merchant + * @param totalFeeStr + * @return 订单id + */ + WxOrder saveCardPayOrder(WxMerchant merchant, String totalFeeStr, Integer payment); + /** * 免费券订单接口 * @param userId diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java index 167f6b8b4..2eb216c5a 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java @@ -2,19 +2,85 @@ package com.iformall.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; -import com.iformall.domain.po.WxCardSpend; +import com.iformall.common.ErrorCode; +import com.iformall.common.ResultData; +import com.iformall.domain.po.*; +import com.iformall.mapper.WxCardInfoMapper; import com.iformall.mapper.WxCardSpendMapper; +import com.iformall.mapper.WxPayAccountMapper; import com.iformall.service.WxCardSpendService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.iformall.common.IdWorker; @Service public class WxCardSpendServiceImpl implements WxCardSpendService { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired WxCardSpendMapper wxCardSpendMapper; + @Autowired + WxCardInfoMapper wxCardInfoMapper; + + @Autowired + WxPayAccountMapper payAccountMapper; + + @Override + public ResultData createCardSpend(WxCardSpend record, WxOrder order, WxCUser user) { + // 1. get card info + WxCardInfo cardInfo = wxCardInfoMapper.selectByPrimaryKey(record.getCardId()); + if (cardInfo != null) { + logger.error("card not found: " + record.getCardId()); + return new ResultData(ErrorCode.CARD_IS_NOT_FOUND); + } + // 2. get pay account + WxPayAccount payAccount = null; + WxPayAccount payAccountQ = new WxPayAccount(); + payAccountQ.setTenantId(user.getTenantId()); + try { + payAccount = payAccountMapper.selectOne(payAccountQ); + } catch (Exception e) { + logger.error("获取payAccount error: " + user.getTenantId()); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "获取payAccount失败"); + } + + // 3. 扣减计算 + Integer payment = cardInfo.getSaleAmount() * record.getDeductionAmount() / cardInfo.getAmount(); + Double dChargeFee = Math.ceil(payment * 1.0D * payAccount.getRate() / 1000); + Integer real_payment = payment - dChargeFee.intValue(); + + // 4 insert card_spend + record.setPayment(payment); + record.setRealPayment(real_payment); + record.setCardBeforeAmount(cardInfo.getRemainingAmount()); + record.setCardRemainAmount(cardInfo.getRemainingAmount()-record.getDeductionAmount()); + record.setCardBeforeRealAmount(cardInfo.getRemainingShareFeeAmount()); + record.setCardRemainAmount(cardInfo.getRemainingShareFeeAmount()-real_payment); + try { + wxCardSpendMapper.insertSelective(record); + } catch (Exception e) { + logger.error("card spend insert error"); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "card spend 插入出错!"); + } + + + // 5. update card info + cardInfo.setRemainingAmount(cardInfo.getRemainingAmount()-record.getDeductionAmount()); + cardInfo.setRemainingShareFeeAmount(cardInfo.getRemainingShareFeeAmount()-real_payment); + try { + wxCardInfoMapper.updateByPrimaryKey(cardInfo); + } catch (Exception e) { + logger.error("card info update error"); + return new ResultData(ErrorCode.DB_FAIL.getCode(), "card info 更新出错!"); + } + + return new ResultData(record); + } + @Override public PageInfo listAsPage(WxCardSpend record, Integer pageIndex, Integer pageSize) { diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java index 050462d0f..e4159504d 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java @@ -444,6 +444,46 @@ public class WxOrderServiceImpl implements WxOrderService { return record; } + @Override + @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) + public WxOrder saveCardPayOrder(WxMerchant merchant, String totalFeeStr, Integer payment) { + if (merchant.getStatus() == EnumMerchantStatus.NOT_VALID.getCode()) { + logger.error("商户已禁用, merchantId: " + merchant.getId()); + throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_VALID); + } + + Date curr = new Date(); + + final IdWorker idWorker = IdWorker.get(); + Long orderNumber = idWorker.nextId(); + + // body + // tenant_id + merchant_id + title + subtitle + String bodyStr = "C扫B储值卡支付, 金额:" + totalFeeStr; + + WxOrder record = new WxOrder(); + record.setId(orderNumber); + record.setTenantId(merchant.getTenantId()); + record.setOrderNumber(orderNumber); + record.setType(EnumOrderType.PREPAIDCARD.getCode()); + record.setProductId(merchant.getId()); + record.setPaymentType(EnumPayType.PAY_PAYMENT.getCode()); + record.setPayment(payment); + record.setOrderStatus(EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()); + record.setDetail(bodyStr); + record.setCreateDate(curr); + record.setUpdateDate(curr); + + try { + // 保存订单 + wxOrderMapper.insertSelective(record); + } catch (RuntimeException e) { + logger.error("保存订单:" + e.getMessage()); + throw new MallinkException(ErrorCode.ORDER_SAVE_ERR); + } + return record; + } + /** * 创建 couponOrder * @@ -512,9 +552,11 @@ public class WxOrderServiceImpl implements WxOrderService { WxCardInfo cardInfo = new WxCardInfo(); cardInfo.setId(couponOrder.getId()); + cardInfo.setTenantId(user.getTenantId()); cardInfo.setCouponId(order.getProductId()); cardInfo.setTransactionId(payOrder.getTransactionId()); cardInfo.setAmount(coupon.getPrice()); + cardInfo.setSaleAmount(coupon.getSalePrice()); cardInfo.setRemainingAmount(coupon.getPrice()); cardInfo.setServiceFeeAmount(fee); cardInfo.setShareFeeAmount(payOrder.getShareAmount()); diff --git a/mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml b/mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml index a64f59270..6122e560d 100644 --- a/mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml @@ -7,6 +7,7 @@ + @@ -16,7 +17,7 @@ - `id`,`tenant_id`,`coupon_id`,`transaction_id`,`amount`,`remaining_amount`,`service_fee_amount`,`share_fee_amount`,`remaining_share_fee_amount`,`create_date`,`update_date` + `id`,`tenant_id`,`coupon_id`,`transaction_id`,`amount`,`sale_amount`,`remaining_amount`,`service_fee_amount`,`share_fee_amount`,`remaining_share_fee_amount`,`create_date`,`update_date` @@ -35,7 +36,10 @@ and `amount` = #{amount} - + + + and `sale_amount` = #{saleAmount} + and `remaining_amount` = #{remainingAmount} diff --git a/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml b/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml index 02002f502..21b7443a8 100644 --- a/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml @@ -8,16 +8,20 @@ + - - + + + + - `id`,`tenant_id`,`card_id`,`owner_id`,`merchant_id`,`order_id`,`payment`,`real_payment`,`remain_amount`,`before_amount`,`create_date`,`update_date` + `id`,`tenant_id`,`card_id`,`owner_id`,`merchant_id`,`order_id`,`deduction_amount`,`payment`,`real_payment`, + `card_remain_amount`,`card_before_amount`,`card_remain_real_amount`,`card_before_real_amount`,`create_date`,`update_date` @@ -39,19 +43,28 @@ and `order_id` = #{orderId} - - - and `payment` = #{payment} - + + + and `deduction_amount` = #{deductionAmount} + + + and `payment` = #{payment} + and `real_payment` = #{realPayment} - - and `remain_amount` = #{remainAmount} - - - and `before_amount` = #{beforeAmount} + + and `card_remain_amount` = #{cardRemainAmount} + + and `card_before_amount` = #{cardBeforeAmount} + + + and `card_remain_real_amount` = #{cardRemainRealAmount} + + + and `card_before_real_amount` = #{cardBeforeRealAmount} + and `create_date` = #{createDate}