Просмотр исходного кода

[储值卡][新增]:卡消费接口

release_toaliyun_real
Stormeye Wu 7 лет назад
Родитель
Сommit
1c3ee8a663
10 измененных файлов: 308 добавлений и 27 удалений
  1. +115
    -0
      mallinkCApi/src/main/java/com/iformall/controller/WxCardPayController.java
  2. +5
    -0
      mallinkService/src/main/java/com/iformall/common/ErrorCode.java
  3. +4
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxCardInfo.java
  4. +21
    -6
      mallinkService/src/main/java/com/iformall/domain/po/WxCardSpend.java
  5. +13
    -1
      mallinkService/src/main/java/com/iformall/service/WxCardSpendService.java
  6. +10
    -5
      mallinkService/src/main/java/com/iformall/service/WxOrderService.java
  7. +67
    -1
      mallinkService/src/main/java/com/iformall/service/impl/WxCardSpendServiceImpl.java
  8. +42
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java
  9. +6
    -2
      mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml
  10. +25
    -12
      mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml

+ 115
- 0
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<String, String> 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());
}
}
}

+ 5
- 0
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, "优惠卡不存在"),


/**
* 微信


+ 4
- 0
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")


+ 21
- 6
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")
;


+ 13
- 1
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


+ 10
- 5
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


+ 67
- 1
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<WxCardSpend> listAsPage(WxCardSpend record, Integer pageIndex, Integer pageSize) {


+ 42
- 0
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());


+ 6
- 2
mallinkService/src/main/resources/mapper/WxCardInfoMapper.xml Просмотреть файл

@@ -7,6 +7,7 @@
<result column="coupon_id" jdbcType="BIGINT" property="couponId" />
<result column="transaction_id" jdbcType="VARCHAR" property="transactionId" />
<result column="amount" jdbcType="INTEGER" property="amount" />
<result column="sale_amount" jdbcType="INTEGER" property="saleAmount" />
<result column="remaining_amount" jdbcType="INTEGER" property="remainingAmount" />
<result column="service_fee_amount" jdbcType="INTEGER" property="serviceFeeAmount" />
<result column="share_fee_amount" jdbcType="INTEGER" property="shareFeeAmount" />
@@ -16,7 +17,7 @@
</resultMap>
<sql id="allColumns">
`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`
</sql>

<sql id="dynamicWhereConditions">
@@ -35,7 +36,10 @@
</if>
<if test=" null != amount ">
and `amount` = #{amount}
</if>
</if>
<if test=" null != saleAmount ">
and `sale_amount` = #{saleAmount}
</if>
<if test=" null != remainingAmount ">
and `remaining_amount` = #{remainingAmount}
</if>


+ 25
- 12
mallinkService/src/main/resources/mapper/WxCardSpendMapper.xml Просмотреть файл

@@ -8,16 +8,20 @@
<result column="owner_id" jdbcType="BIGINT" property="ownerId" />
<result column="merchant_id" jdbcType="BIGINT" property="merchantId" />
<result column="order_id" jdbcType="BIGINT" property="orderId" />
<result column="deduction_amount" jdbcType="INTEGER" property="deductionAmount" />
<result column="payment" jdbcType="INTEGER" property="payment" />
<result column="real_payment" jdbcType="INTEGER" property="realPayment" />
<result column="remain_amount" jdbcType="INTEGER" property="remainAmount" />
<result column="before_amount" jdbcType="INTEGER" property="beforeAmount" />
<result column="card_remain_amount" jdbcType="INTEGER" property="cardRemainAmount" />
<result column="card_before_amount" jdbcType="INTEGER" property="cardBeforeAmount" />
<result column="card_remain_real_amount" jdbcType="INTEGER" property="cardRemainRealAmount" />
<result column="card_before_real_amount" jdbcType="INTEGER" property="cardBeforeRealAmount" />
<result column="create_date" jdbcType="TIMESTAMP" property="createDate" />
<result column="update_date" jdbcType="TIMESTAMP" property="updateDate" />
</resultMap>
<sql id="allColumns">
`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`
</sql>

<sql id="dynamicWhereConditions">
@@ -39,19 +43,28 @@
</if>
<if test=" null != orderId ">
and `order_id` = #{orderId}
</if>
<if test=" null != payment ">
and `payment` = #{payment}
</if>
</if>
<if test=" null != deductionAmount ">
and `deduction_amount` = #{deductionAmount}
</if>
<if test=" null != payment ">
and `payment` = #{payment}
</if>
<if test=" null != realPayment ">
and `real_payment` = #{realPayment}
</if>
<if test=" null != remainAmount ">
and `remain_amount` = #{remainAmount}
</if>
<if test=" null != beforeAmount ">
and `before_amount` = #{beforeAmount}
<if test=" null != cardRemainAmount ">
and `card_remain_amount` = #{cardRemainAmount}
</if>
<if test=" null != cardBeforeAmount ">
and `card_before_amount` = #{cardBeforeAmount}
</if>
<if test=" null != cardRemainRealAmount ">
and `card_remain_real_amount` = #{cardRemainRealAmount}
</if>
<if test=" null != cardBeforeRealAmount ">
and `card_before_real_amount` = #{cardBeforeRealAmount}
</if>
<if test=" null != createDate ">
and `create_date` = #{createDate}
</if>


Загрузка…
Отмена
Сохранить