Commit a8af2435 by 程裕兵

feat:refund

parent f3bb7333
...@@ -18,11 +18,12 @@ public enum BrandCashierTransStateEnums { ...@@ -18,11 +18,12 @@ public enum BrandCashierTransStateEnums {
PAY_INIT(0, "支付初始态"), PAY_INIT(0, "支付初始态"),
PAYING(1, "支付中"), PAYING(1, "支付中"),
PAY_FAIL(2, "支付失败"), PAY_FAIL(2, "支付失败"),
PAY_SUCCESS(3, "入账中(支付成功)"), PAY_SUCCESS(3, "支付成功(入账中)"),
PAY_IN(4, "入账成功"), PAY_IN(4, "入账成功"),
REFUNDING(5, "退款中"), REFUND_INIT(5, "退款初始态"),
REFUND_SUCCESS(6, "退款成功"), REFUNDING(6, "退款中"),
REFUND_FAIL(7, "退款失败"), REFUND_SUCCESS(7, "退款成功"),
REFUND_FAIL(8, "退款失败"),
; ;
@EnumValue @EnumValue
......
...@@ -16,6 +16,8 @@ package com.jiejing.fitness.finance.repository.mapper; ...@@ -16,6 +16,8 @@ package com.jiejing.fitness.finance.repository.mapper;
import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord; import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord;
import com.jiejing.mbp.inject.XBaseMapper; import com.jiejing.mbp.inject.XBaseMapper;
import java.math.BigDecimal;
import org.apache.ibatis.annotations.Param;
/** /**
* <p> * <p>
...@@ -26,4 +28,6 @@ import com.jiejing.mbp.inject.XBaseMapper; ...@@ -26,4 +28,6 @@ import com.jiejing.mbp.inject.XBaseMapper;
*/ */
public interface BrandCashierRecordMapper extends XBaseMapper<BrandCashierRecord> { public interface BrandCashierRecordMapper extends XBaseMapper<BrandCashierRecord> {
BigDecimal sumRefundActualAmountByPayTransNo(@Param("payTransNo") String payTransNo);
} }
...@@ -19,5 +19,11 @@ ...@@ -19,5 +19,11 @@
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, trans_no, order_no, order_type, trans_type, brand_id, studio_id, merchant_id, merchant_no, channel_no, sub_channel, trans_amount, fee_rate, fee, actual_amount, trans_state, buyer_name, buyer_phone, goods, remark, exist_related_trans, related_trans_no, third_trans_no, fail_message, trading_time, success_time, in_time, create_time, update_time id, trans_no, order_no, order_type, trans_type, brand_id, studio_id, merchant_id, merchant_no, channel_no, sub_channel, trans_amount, fee_rate, fee, actual_amount, trans_state, buyer_name, buyer_phone, goods, remark, exist_related_trans, related_trans_no, third_trans_no, fail_message, trading_time, success_time, in_time, create_time, update_time
</sql> </sql>
<select id="sumRefundActualAmountByPayTransNo" resultType="java.math.BigDecimal">
select sum(actual_amount)
from brand_cashier_record
where related_trans_no = #{payTransNo}
and trans_state in (6, 7)
</select>
</mapper> </mapper>
...@@ -17,6 +17,8 @@ package com.jiejing.fitness.finance.repository.service; ...@@ -17,6 +17,8 @@ package com.jiejing.fitness.finance.repository.service;
import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord; import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord;
import com.jiejing.fitness.finance.repository.mapper.BrandCashierRecordMapper; import com.jiejing.fitness.finance.repository.mapper.BrandCashierRecordMapper;
import com.jiejing.mbp.MapperRepoService; import com.jiejing.mbp.MapperRepoService;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
...@@ -27,6 +29,11 @@ import org.springframework.stereotype.Service; ...@@ -27,6 +29,11 @@ import org.springframework.stereotype.Service;
* @author chengyubing, created on 2024-02-27 * @author chengyubing, created on 2024-02-27
*/ */
@Service @Service
public class BrandCashierRecordRpService extends MapperRepoService<Long, BrandCashierRecord, BrandCashierRecordMapper> { public class BrandCashierRecordRpService extends
MapperRepoService<Long, BrandCashierRecord, BrandCashierRecordMapper> {
public BigDecimal sumRefundActualAmountByPayTransNo(String payTransNo) {
return this.baseMapper.sumRefundActualAmountByPayTransNo(payTransNo);
}
} }
...@@ -17,6 +17,8 @@ import com.jiejing.fitness.finance.service.utils.FeeUtil; ...@@ -17,6 +17,8 @@ import com.jiejing.fitness.finance.service.utils.FeeUtil;
import com.jiejing.fitness.finance.service.utils.MoneyUtil; import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.paycenter.api.merchant.vo.MerchantVO; import com.jiejing.paycenter.api.merchant.vo.MerchantVO;
import com.jiejing.paycenter.api.pay.request.PayRequest; import com.jiejing.paycenter.api.pay.request.PayRequest;
import com.jiejing.paycenter.api.pay.request.RefundPayRequest;
import com.jiejing.paycenter.api.pay.vo.RefundVO;
import com.jiejing.paycenter.common.enums.common.TransStateEnums; import com.jiejing.paycenter.common.enums.common.TransStateEnums;
import com.jiejing.paycenter.common.enums.merchant.SubChannelEnums; import com.jiejing.paycenter.common.enums.merchant.SubChannelEnums;
import com.jiejing.paycenter.common.enums.merchant.SubChannelOpenTypeEnums; import com.jiejing.paycenter.common.enums.merchant.SubChannelOpenTypeEnums;
...@@ -42,18 +44,17 @@ public class PayConvert { ...@@ -42,18 +44,17 @@ public class PayConvert {
private static final List<String> WX_AUTH_CODE_PREFIX = Lists.newArrayList("10", "11", "12", "13", "14", private static final List<String> WX_AUTH_CODE_PREFIX = Lists.newArrayList("10", "11", "12", "13", "14",
"15"); "15");
public static PayRequest convert(BrandMerchantPayParams params, BrandCashierRecord record, public static PayRequest convert(BrandMerchantPayParams params, BrandCashierRecord record) {
MerchantVO merchant) {
PayRequest request = BeanUtil.map(params, PayRequest.class); PayRequest request = BeanUtil.map(params, PayRequest.class);
request.setTransNo(record.getTransNo()); request.setTransNo(record.getTransNo());
request.setMerchantId(merchant.getId()); request.setMerchantId(record.getMerchantId());
request.setExtra(Optional.ofNullable(params.getExtra()).orElse(new JSONObject()) request.setExtra(Optional.ofNullable(params.getExtra()).orElse(new JSONObject())
.fluentPut("studioId", params.getStudioId()) .fluentPut("studioId", record.getStudioId())
.fluentPut("buyerName", params.getBuyerName()) .fluentPut("buyerName", record.getBuyerName())
.fluentPut("buyerPhone", params.getBuyerPhone()) .fluentPut("buyerPhone", record.getBuyerPhone())
.fluentPut("remark", params.getRemark()) .fluentPut("remark", record.getRemark())
); );
request.setTransTime(new Date()); request.setTransTime(record.getTradingTime());
return request; return request;
} }
...@@ -157,8 +158,58 @@ public class PayConvert { ...@@ -157,8 +158,58 @@ public class PayConvert {
case FAILED: case FAILED:
return BrandCashierTransStateEnums.PAY_FAIL; return BrandCashierTransStateEnums.PAY_FAIL;
default: default:
return null; return BrandCashierTransStateEnums.PAYING;
}
} }
public static BrandCashierRecord convertRefundInit(BrandMerchantRefundParams params,
BrandCashierRecord pay, BigDecimal historyRefundActualAmount) {
BrandCashierRecord record = BeanUtil.map(pay, BrandCashierRecord.class);
record.setId(IdWorker.getId());
record.setTransNo(record.getId().toString());
record.setOrderNo(params.getOrderNo());
record.setRelatedTransNo(params.getPayTransNo());
record.setTransAmount(params.getTransAmount());
record.setFeeRate(pay.getFeeRate());
record.setFee(
FeeUtil.calculateRefundFee(params.getTransAmount(), pay.getTransAmount(), pay.getActualAmount(),
pay.getFee(), historyRefundActualAmount));
record.setActualAmount(MoneyUtil.subtract(record.getTransAmount(), record.getFee()));
record.setRemark(params.getRefundReason());
record.setStudioId(params.getStudioId());
record.setTransState(BrandCashierTransStateEnums.REFUND_INIT);
record.setTradingTime(new Date());
record.setCreateTime(new Date());
record.setUpdateTime(new Date());
return record;
}
public static RefundPayRequest convert(BrandMerchantRefundParams params, BrandCashierRecord record) {
RefundPayRequest request = BeanUtil.map(params, RefundPayRequest.class);
request.setTransNo(record.getTransNo());
return request;
}
public static BrandCashierRecord convertRefund(BrandCashierRecord record, RefundVO vo) {
return BrandCashierRecord.builder()
.id(record.getId())
.transState(convertTransState(vo.getRefundState()))
.failMessage(vo.getFailMessage())
.successTime(vo.getSuccessTime())
.updateTime(new Date())
.build();
} }
private static BrandCashierTransStateEnums convertTransState(TransStateEnums state) {
switch (state) {
case SUCCESS:
return BrandCashierTransStateEnums.REFUND_SUCCESS;
case FAIL:
return BrandCashierTransStateEnums.REFUND_FAIL;
case PROCESS:
case INIT:
default:
return BrandCashierTransStateEnums.REFUNDING;
}
}
} }
package com.jiejing.fitness.finance.service.pay.impl; package com.jiejing.fitness.finance.service.pay.impl;
import com.jiejing.common.exception.BizException;
import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord; import com.jiejing.fitness.finance.repository.entity.BrandCashierRecord;
import com.jiejing.fitness.finance.repository.entity.BrandToMerchant; import com.jiejing.fitness.finance.repository.entity.BrandToMerchant;
import com.jiejing.fitness.finance.repository.service.BrandCashierRecordRpService; import com.jiejing.fitness.finance.repository.service.BrandCashierRecordRpService;
import com.jiejing.fitness.finance.repository.service.BrandToMerchantRpService; import com.jiejing.fitness.finance.repository.service.BrandToMerchantRpService;
import com.jiejing.fitness.finance.service.enums.FinanceErrorEnums;
import com.jiejing.fitness.finance.service.pay.PayService; import com.jiejing.fitness.finance.service.pay.PayService;
import com.jiejing.fitness.finance.service.pay.convert.PayConvert; import com.jiejing.fitness.finance.service.pay.convert.PayConvert;
import com.jiejing.fitness.finance.service.pay.params.BrandMerchantPayParams; import com.jiejing.fitness.finance.service.pay.params.BrandMerchantPayParams;
...@@ -16,8 +18,11 @@ import com.jiejing.paycenter.api.pay.request.PayRequest; ...@@ -16,8 +18,11 @@ import com.jiejing.paycenter.api.pay.request.PayRequest;
import com.jiejing.paycenter.api.pay.request.RefundPayRequest; import com.jiejing.paycenter.api.pay.request.RefundPayRequest;
import com.jiejing.paycenter.api.pay.vo.PayVO; import com.jiejing.paycenter.api.pay.vo.PayVO;
import com.jiejing.paycenter.api.pay.vo.RefundVO; import com.jiejing.paycenter.api.pay.vo.RefundVO;
import com.jiejing.paycenter.common.enums.pay.PayStateEnums;
import com.jiejing.paycenter.common.event.PayEvent; import com.jiejing.paycenter.common.event.PayEvent;
import com.jiejing.studio.api.studio.vo.StudioVO; import com.jiejing.studio.api.studio.vo.StudioVO;
import java.math.BigDecimal;
import java.util.List;
import javax.annotation.Resource; import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -55,7 +60,7 @@ public class PayServiceImpl implements PayService { ...@@ -55,7 +60,7 @@ public class PayServiceImpl implements PayService {
BrandCashierRecord record = PayConvert.convertPayInit(params, relation, merchant); BrandCashierRecord record = PayConvert.convertPayInit(params, relation, merchant);
brandCashierRecordRpService.insert(record); brandCashierRecordRpService.insert(record);
PayRequest request = PayConvert.convert(params, record, merchant); PayRequest request = PayConvert.convert(params, record);
return payRpcService.pay(request); return payRpcService.pay(request);
} }
...@@ -73,17 +78,21 @@ public class PayServiceImpl implements PayService { ...@@ -73,17 +78,21 @@ public class PayServiceImpl implements PayService {
@Override @Override
public RefundVO merchantRefund(BrandMerchantRefundParams params) { public RefundVO merchantRefund(BrandMerchantRefundParams params) {
StudioVO studio = studioRpcService.getStudio(params.getStudioId()); BrandCashierRecord pay = brandCashierRecordRpService.getById(Long.parseLong(params.getPayTransNo()))
BrandToMerchant relation = brandToMerchantRpService.getByBrandId(studio.getBrandId()); .orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
MerchantVO merchant = merchantRpcService.getByMerchantId(relation.getMerchantId()); BigDecimal historyRefundActualAmount = brandCashierRecordRpService.sumRefundActualAmountByPayTransNo(
params.getPayTransNo());
// BrandCashierRecord record = PayConvert.convertRefundInit(params, relation, merchant); BrandCashierRecord record = PayConvert.convertRefundInit(params, pay, historyRefundActualAmount);
// brandCashierRecordRpService.insert(record); brandCashierRecordRpService.insert(record);
//
// RefundPayRequest request = PayConvert.convert(params, record, merchant); RefundPayRequest request = PayConvert.convert(params, record);
// return payRpcService.refund(request); RefundVO vo = payRpcService.refund(request);
return null;
BrandCashierRecord toModify = PayConvert.convertRefund(record, vo);
brandCashierRecordRpService.updateById(toModify);
return vo;
} }
} }
package com.jiejing.fitness.finance.service.pay.params; package com.jiejing.fitness.finance.service.pay.params;
import com.alibaba.fastjson.JSONObject;
import com.jiejing.paycenter.common.enums.merchant.SubChannelEnums;
import com.jiejing.paycenter.common.enums.pay.PayTypeEnums;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal; import java.math.BigDecimal;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
...@@ -33,52 +29,16 @@ public class BrandMerchantRefundParams { ...@@ -33,52 +29,16 @@ public class BrandMerchantRefundParams {
@NotNull(message = "支付总金额不能为空") @NotNull(message = "支付总金额不能为空")
private BigDecimal transAmount; private BigDecimal transAmount;
@ApiModelProperty(name = "业务订单号", required = true) @ApiModelProperty(name = "上层业务退款单号", required = true)
@NotBlank(message = "业务订单号不能为空") @NotBlank(message = "上层业务退款单号不能为空")
private String orderNo; private String orderNo;
@ApiModelProperty(name = "业务订单类型", required = true) @ApiModelProperty(name = "退款请求对应的支付流水号", required = true)
@NotNull(message = "业务订单类型不能为空") @NotBlank(message = "退款请求对应的支付流水号不能为空")
private Integer orderType; private String payTransNo;
@ApiModelProperty(name = "支付类型", required = true) @ApiModelProperty(name = "退款原因", required = true)
@NotNull(message = "支付类型不能为空") @NotBlank(message = "退款原因不能为空")
private PayTypeEnums payType; private String refundReason;
@ApiModelProperty(name = "正扫:三方支付账户ID", notes = "微信的openId,支付宝的userId,JS、MINI、NATIVE支付必传")
private String openId;
@ApiModelProperty(name = "反扫:支付授权码", notes = "扫码设备读出的条形码或者二维码信息,BARCODE支付必传")
private String authCode;
@ApiModelProperty(name = "支付子渠道", notes = "聚合支付时需要")
private SubChannelEnums subChannel;
@ApiModelProperty(name = "商品名称", required = true)
@NotBlank(message = "商品名称不能为空")
private String goods;
@ApiModelProperty(name = "付款人姓名", required = true)
@NotBlank(message = "付款人姓名不能为空")
@Size(max = 30)
private String buyerName;
@ApiModelProperty(name = "付款人手机号", required = true)
@NotBlank(message = "付款人手机号不能为空")
@Size(max = 11)
private String buyerPhone;
@ApiModelProperty(name = "备注")
private String remark;
@ApiModelProperty(name = "appId", notes = "指定本次使用的appId")
private String appId;
@ApiModelProperty(name = "过期时间(单位:秒)", required = true)
@NotNull(message = "过期时间不能为空")
private Integer timeExpire;
@ApiModelProperty(name = "业务扩展信息")
private JSONObject extra;
} }
...@@ -6,6 +6,7 @@ import com.jiejing.paycenter.api.pay.request.PayRequest; ...@@ -6,6 +6,7 @@ import com.jiejing.paycenter.api.pay.request.PayRequest;
import com.jiejing.paycenter.api.pay.request.RefundPayRequest; import com.jiejing.paycenter.api.pay.request.RefundPayRequest;
import com.jiejing.paycenter.api.pay.vo.PayVO; import com.jiejing.paycenter.api.pay.vo.PayVO;
import com.jiejing.paycenter.api.pay.vo.RefundVO; import com.jiejing.paycenter.api.pay.vo.RefundVO;
import com.jiejing.paycenter.common.enums.common.TransStateEnums;
import com.jiejing.paycenter.common.enums.pay.PayStateEnums; import com.jiejing.paycenter.common.enums.pay.PayStateEnums;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -31,9 +32,13 @@ public class PayRpcService { ...@@ -31,9 +32,13 @@ public class PayRpcService {
} }
public RefundVO refund(RefundPayRequest request) { public RefundVO refund(RefundPayRequest request) {
try {
JsonResult<RefundVO> result = payApi.refund(request); JsonResult<RefundVO> result = payApi.refund(request);
result.assertSuccess(); result.assertSuccess();
return result.getResult(); return result.getResult();
} catch (Exception e) {
return RefundVO.builder().refundState(TransStateEnums.FAIL).failMessage(e.getMessage()).build();
}
} }
} }
...@@ -2,6 +2,7 @@ package com.jiejing.fitness.finance.service.utils; ...@@ -2,6 +2,7 @@ package com.jiejing.fitness.finance.service.utils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.Objects;
/** /**
* @author chengyubing * @author chengyubing
...@@ -10,7 +11,7 @@ import java.math.RoundingMode; ...@@ -10,7 +11,7 @@ import java.math.RoundingMode;
public class FeeUtil { public class FeeUtil {
/** /**
* 计算支付手续费,保留小数点后两位,四舍五入 * 【支付】计算支付手续费,保留小数点后两位,四舍五入
* *
* @param feeRate 费率(%) * @param feeRate 费率(%)
* @param amount 支付金额 * @param amount 支付金额
...@@ -22,4 +23,103 @@ public class FeeUtil { ...@@ -22,4 +23,103 @@ public class FeeUtil {
amount)); amount));
} }
/**
* 【退款】计算退款手续费
*
* <p>实退手续费计算公式:退款手续费=向下取整(退款金额*原交易手续费金额/原交易金额)</p>
*
* @param refundTransAmount 退款申请金额
* @param payTransAmount 原支付交易金额
* @param payActualAmount 用户实收金额
* @param payFee 平台实收手续费
* @param historyRefundActualAmount 历史实退金额
* @return 本次退款应退手续费
*/
public static BigDecimal calculateRefundFee(BigDecimal refundTransAmount, BigDecimal payTransAmount,
BigDecimal payActualAmount, BigDecimal payFee, BigDecimal historyRefundActualAmount) {
// 机构剩余实收金额
BigDecimal leftPayActualAmount = MoneyUtil.subtract(payActualAmount, historyRefundActualAmount);
// 试算手续费
BigDecimal trialFee = MoneyUtil.divide(refundTransAmount.multiply(payFee), payTransAmount, 0,
RoundingMode.FLOOR);
// 试算实退金额
BigDecimal trialActualAmount = MoneyUtil.subtract(refundTransAmount, trialFee);
// 实退手续费
return leftPayActualAmount.compareTo(trialActualAmount) >= 0 ? trialFee
: MoneyUtil.add(trialFee, MoneyUtil.subtract(trialActualAmount, leftPayActualAmount));
}
/**
* 计算补贴回退金额(向上取整ceil)
*
* @param refundTransAmount 退款申请金额
* @param payTransAmount 原支付交易金额
* @param subsidyAmount 补贴金额
* @param historyBackAmount 历史补贴回退金额
* @return 补贴回退金额
*/
public static BigDecimal calculateSubsidyBackAmount(BigDecimal refundTransAmount,
BigDecimal payTransAmount, BigDecimal subsidyAmount, BigDecimal historyBackAmount) {
if (Objects.isNull(subsidyAmount)) {
return BigDecimal.ZERO;
}
// 剩余可回退补贴金额
BigDecimal leftSubsidyBackAmount = MoneyUtil.subtract(subsidyAmount, historyBackAmount);
// 试算补贴回退金额
BigDecimal trialAmount = MoneyUtil.divide(refundTransAmount.multiply(subsidyAmount),
payTransAmount, 0, RoundingMode.CEILING);
return leftSubsidyBackAmount.compareTo(trialAmount) >= 0 ? trialAmount : leftSubsidyBackAmount;
}
public static BigDecimal calculateAdvanceAmount(BigDecimal refundAmount, BigDecimal qyqbhTransitBalance,
BigDecimal yxyjhTransitBalance) {
BigDecimal transitBalance = MoneyUtil.subtract(qyqbhTransitBalance, yxyjhTransitBalance);
if (refundAmount.compareTo(transitBalance) <= 0) {
// 若:退款金额 <= 业务钱包入账中余额,则无需佣金垫付记录记账
return null;
}
// 若:退款金额 > 业务钱包入账中余额,则添加佣金垫付记录记账
// 垫付金额 = (退款金额 - 业务入帐中金额) > 佣金入账中 ? 佣金入账中 : (退款金额 - 入帐中金额)
BigDecimal advanceAmount = MoneyUtil.subtract(refundAmount, transitBalance);
if (advanceAmount.compareTo(yxyjhTransitBalance) > 0) {
advanceAmount = yxyjhTransitBalance;
}
return advanceAmount;
}
public static void main(String[] args) {
// 1. 首次退款
// BigDecimal refundTransAmount = new BigDecimal("498");
// BigDecimal payTransAmount = new BigDecimal("500");
// BigDecimal payActualAmount = new BigDecimal("498");
// BigDecimal payFee = new BigDecimal("2");
// BigDecimal historyRefundActualAmount = new BigDecimal("0");
// 预计输出:1
// 实退金额:497, 实退手续费:1。剩余可退金额:2(剩余实退金额:1,剩余实退手续费:1),历史实退金额:497,历史实退手续费:1
// 2. 二次退款
// BigDecimal refundTransAmount = new BigDecimal("1");
// BigDecimal payTransAmount = new BigDecimal("500");
// BigDecimal payActualAmount = new BigDecimal("498");
// BigDecimal payFee = new BigDecimal("2");
// BigDecimal historyRefundActualAmount = new BigDecimal("497");
// 预计输出:0
// 实退金额:1,实退手续费:0。剩余可退金额:1(剩余实退金额:0,剩余实退手续费:1),历史实退金额:498,历史实退手续费:1
// 3. 三次退款
BigDecimal refundTransAmount = new BigDecimal("40");
BigDecimal payTransAmount = new BigDecimal("10000");
BigDecimal payActualAmount = new BigDecimal("9943");
BigDecimal payFee = new BigDecimal("57");
BigDecimal historyRefundActualAmount = new BigDecimal("9904");
// 预计输出:1
// 实退金额:0,实退手续费:1。剩余可退金额:0,历史实退金额:498,历史实退手续费:2
System.out.println(
FeeUtil.calculateRefundFee(refundTransAmount, payTransAmount, payActualAmount, payFee,
historyRefundActualAmount));
}
} }
...@@ -110,7 +110,7 @@ public class MoneyUtil { ...@@ -110,7 +110,7 @@ public class MoneyUtil {
* @param v2 加数 * @param v2 加数
* @return 累加值 * @return 累加值
*/ */
private static BigDecimal add(BigDecimal v1, BigDecimal v2) { public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
return v1.add(v2); return v1.add(v2);
} }
...@@ -254,6 +254,19 @@ public class MoneyUtil { ...@@ -254,6 +254,19 @@ public class MoneyUtil {
} }
/** /**
* 两数相除,进位规则自定义,小数点位数自定义
*
* @param v1 被除数
* @param v2 除数
* @param scale 小数点后保留位数
* @param roundingMode 进位规则
* @return 相除值
*/
public static BigDecimal divide(BigDecimal v1, BigDecimal v2, int scale, RoundingMode roundingMode) {
return v1.divide(v2, scale, roundingMode);
}
/**
* 针对浮点数进行四舍五入,返回整型 * 针对浮点数进行四舍五入,返回整型
* *
* @param v 浮点数 * @param v 浮点数
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment