11 changed files with 275 additions and 32 deletions
@ -0,0 +1,9 @@ |
|||
package cc.hiver.mall.dao.mapper; |
|||
|
|||
import cc.hiver.mall.entity.MallOrderDeliveryFeeRecord; |
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import org.springframework.stereotype.Repository; |
|||
|
|||
@Repository |
|||
public interface MallOrderDeliveryFeeRecordMapper extends BaseMapper<MallOrderDeliveryFeeRecord> { |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
package cc.hiver.mall.entity; |
|||
|
|||
import cc.hiver.core.common.utils.SnowFlakeUtil; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import com.baomidou.mybatisplus.annotation.TableName; |
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import javax.persistence.Entity; |
|||
import javax.persistence.Id; |
|||
import javax.persistence.Table; |
|||
import java.io.Serializable; |
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
@Entity |
|||
@Table(name = "mall_order_delivery_fee_record") |
|||
@TableName("mall_order_delivery_fee_record") |
|||
@ApiModel(value = "订单追加配送佣金记录表") |
|||
public class MallOrderDeliveryFeeRecord implements Serializable { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@Id |
|||
@TableId |
|||
private String id = SnowFlakeUtil.nextId().toString(); |
|||
|
|||
@ApiModelProperty(value = "关联核心订单ID") |
|||
private String orderId; |
|||
|
|||
@ApiModelProperty(value = "微信支付商户订单号") |
|||
private String wxOrderId; |
|||
|
|||
@ApiModelProperty(value = "追加配送佣金金额") |
|||
private BigDecimal amount; |
|||
|
|||
@ApiModelProperty(value = "退款状态 0未退 1已退") |
|||
private Integer refundStatus; |
|||
|
|||
@ApiModelProperty(value = "创建时间") |
|||
private Date createTime; |
|||
|
|||
@ApiModelProperty(value = "退款时间") |
|||
private Date refundTime; |
|||
} |
|||
@ -0,0 +1,118 @@ |
|||
package cc.hiver.mall.utils; |
|||
|
|||
import cc.hiver.mall.dao.mapper.MallOrderDeliveryFeeRecordMapper; |
|||
import cc.hiver.mall.entity.MallOrder; |
|||
import cc.hiver.mall.entity.MallOrderDeliveryFeeRecord; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
@Component |
|||
public class MallOrderDeliveryFeeRefundHelper { |
|||
private static final int DELIVERY_TYPE_EXPRESS = 1; |
|||
private static final int REFUND_STATUS_WAIT = 0; |
|||
private static final int REFUND_STATUS_DONE = 1; |
|||
|
|||
@Autowired |
|||
private MallOrderDeliveryFeeRecordMapper mallOrderDeliveryFeeRecordMapper; |
|||
|
|||
@Autowired |
|||
private WechatPayUtil wechatPayUtil; |
|||
|
|||
public void recordAddedDeliveryFee(String orderId, String wxOrderId, BigDecimal amount) { |
|||
MallOrderDeliveryFeeRecord record = new MallOrderDeliveryFeeRecord(); |
|||
record.setOrderId(orderId); |
|||
record.setWxOrderId(wxOrderId); |
|||
record.setAmount(amount); |
|||
record.setRefundStatus(REFUND_STATUS_WAIT); |
|||
record.setCreateTime(new Date()); |
|||
mallOrderDeliveryFeeRecordMapper.insert(record); |
|||
} |
|||
|
|||
public boolean existsAddedDeliveryFee(String wxOrderId) { |
|||
LambdaQueryWrapper<MallOrderDeliveryFeeRecord> qw = new LambdaQueryWrapper<>(); |
|||
qw.eq(MallOrderDeliveryFeeRecord::getWxOrderId, wxOrderId).last("LIMIT 1"); |
|||
return mallOrderDeliveryFeeRecordMapper.selectOne(qw) != null; |
|||
} |
|||
|
|||
public void refundOrder(MallOrder order, BigDecimal refundAmount) { |
|||
refundOrder(order, refundAmount, false); |
|||
} |
|||
|
|||
public void refundOrderWithAddedDeliveryFee(MallOrder order, BigDecimal refundAmount) { |
|||
refundOrder(order, refundAmount, true); |
|||
} |
|||
|
|||
private void refundOrder(MallOrder order, BigDecimal refundAmount, boolean refundAddedDeliveryFee) { |
|||
if (!isDeliveryOrder(order)) { |
|||
wechatPayUtil.refund(order.getId(), toCent(order.getTotalAmount()), toCent(refundAmount)); |
|||
return; |
|||
} |
|||
|
|||
List<MallOrderDeliveryFeeRecord> records = selectAddedDeliveryFeeRecords(order.getId()); |
|||
if (records == null || records.isEmpty()) { |
|||
wechatPayUtil.refund(order.getId(), toCent(order.getTotalAmount()), toCent(refundAmount)); |
|||
return; |
|||
} |
|||
|
|||
BigDecimal addedTotal = records.stream() |
|||
.map(MallOrderDeliveryFeeRecord::getAmount) |
|||
.reduce(BigDecimal.ZERO, BigDecimal::add); |
|||
BigDecimal mainOrderTotal = subtractNonNegative(order.getTotalAmount(), addedTotal); |
|||
BigDecimal mainRefundAmount = refundAddedDeliveryFee |
|||
? subtractNonNegative(refundAmount, addedTotal) |
|||
: refundAmount; |
|||
|
|||
if (mainRefundAmount.compareTo(BigDecimal.ZERO) > 0) { |
|||
wechatPayUtil.refund(order.getId(), toCent(mainOrderTotal), toCent(mainRefundAmount)); |
|||
} |
|||
|
|||
if (refundAddedDeliveryFee) { |
|||
refundAddedDeliveryFeeRecords(records); |
|||
} |
|||
} |
|||
|
|||
private List<MallOrderDeliveryFeeRecord> selectAddedDeliveryFeeRecords(String orderId) { |
|||
LambdaQueryWrapper<MallOrderDeliveryFeeRecord> qw = new LambdaQueryWrapper<>(); |
|||
qw.eq(MallOrderDeliveryFeeRecord::getOrderId, orderId); |
|||
return mallOrderDeliveryFeeRecordMapper.selectList(qw); |
|||
} |
|||
|
|||
private void refundAddedDeliveryFeeRecords(List<MallOrderDeliveryFeeRecord> records) { |
|||
for (MallOrderDeliveryFeeRecord record : records) { |
|||
if (record.getRefundStatus() != null && record.getRefundStatus() == REFUND_STATUS_DONE) { |
|||
continue; |
|||
} |
|||
Boolean success = wechatPayUtil.refundDeliveryFeeRecord(record.getWxOrderId(), toCent(record.getAmount()), toCent(record.getAmount())); |
|||
if (Boolean.TRUE.equals(success)) { |
|||
LambdaUpdateWrapper<MallOrderDeliveryFeeRecord> uw = new LambdaUpdateWrapper<>(); |
|||
uw.eq(MallOrderDeliveryFeeRecord::getId, record.getId()) |
|||
.set(MallOrderDeliveryFeeRecord::getRefundStatus, REFUND_STATUS_DONE) |
|||
.set(MallOrderDeliveryFeeRecord::getRefundTime, new Date()); |
|||
mallOrderDeliveryFeeRecordMapper.update(null, uw); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private boolean isDeliveryOrder(MallOrder order) { |
|||
return order != null && order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS; |
|||
} |
|||
|
|||
private BigDecimal subtractNonNegative(BigDecimal amount, BigDecimal subtractAmount) { |
|||
BigDecimal result = safeAmount(amount).subtract(safeAmount(subtractAmount)); |
|||
return result.compareTo(BigDecimal.ZERO) > 0 ? result : BigDecimal.ZERO; |
|||
} |
|||
|
|||
private long toCent(BigDecimal amount) { |
|||
return safeAmount(amount).multiply(new BigDecimal(100)).longValue(); |
|||
} |
|||
|
|||
private BigDecimal safeAmount(BigDecimal amount) { |
|||
return amount == null ? BigDecimal.ZERO : amount; |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
CREATE TABLE IF NOT EXISTS `mall_order_delivery_fee_record` ( |
|||
`id` varchar(64) NOT NULL COMMENT '主键ID', |
|||
`order_id` varchar(64) NOT NULL COMMENT '关联核心订单ID', |
|||
`wx_order_id` varchar(128) NOT NULL COMMENT '微信支付商户订单号', |
|||
`amount` decimal(10,2) NOT NULL COMMENT '追加配送佣金金额', |
|||
`refund_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '退款状态 0未退 1已退', |
|||
`create_time` datetime DEFAULT NULL COMMENT '创建时间', |
|||
`refund_time` datetime DEFAULT NULL COMMENT '退款时间', |
|||
PRIMARY KEY (`id`), |
|||
KEY `idx_order_id` (`order_id`), |
|||
UNIQUE KEY `uk_wx_order_id` (`wx_order_id`) |
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单追加配送佣金记录表'; |
|||
Loading…
Reference in new issue