Commit 2535caf2 by FM00879

Merge branch 'feature/退款支持优化' into qa

parents fb4ec179 a7584850
......@@ -19,6 +19,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
public class CancelOrderRequest extends BaseConfig {
......@@ -73,6 +75,17 @@ public class CancelOrderRequest extends BaseConfig {
@Builder.Default
private boolean isRefundDeliveryAmount = true;
/**
* 部分退申请金额
*/
private BigDecimal reqAmount;
/**
* 是否部分退,默认否(全退)
*/
@Builder.Default
private boolean isPartRefund = false;
//用户预约时间,仅为预约单时存放
private String expectTime;
......
......@@ -8,6 +8,8 @@ import com.freemud.sdk.api.assortment.order.enums.OperationClientEnum;
import com.freemud.sdk.api.assortment.order.request.order.CancelOrderRequest;
import org.apache.commons.lang.StringUtils;
import java.math.BigDecimal;
/**
* @author Clover.z
* @version 1.0.0
......@@ -15,7 +17,7 @@ import org.apache.commons.lang.StringUtils;
*/
public class CancelOrderRequestAdapter {
public static CancelOrderRequest convert(OrderInfoReqs order, String refundId, AfterSalesType afterSalesType, String reason, Boolean refundDeliveryFee, Byte refundMode) {
public static CancelOrderRequest convert(OrderInfoReqs order, String refundId, AfterSalesType afterSalesType, Long refundAmount, String reason, String remark, Boolean refundDeliveryFee, Byte refundMode) {
CancelOrderRequest req = new CancelOrderRequest();
req.setOrderId(order.getOrderCode());
req.setPartnerId(order.getPartnerId());
......@@ -27,6 +29,10 @@ public class CancelOrderRequestAdapter {
req.setReason(reason);
req.setTrackingNo(LogThreadLocal.getTrackingNo());
req.setRefundSerialNo(refundId);
req.setPartRefund(refundAmount != null); // 是否部分退
req.setReqAmount(refundAmount != null ? new BigDecimal(refundAmount) : null); // 退款金额
//操作来源客户端 1:POS插件 2:小助手 3:开放平台 4:自动任务 5:用户端 6:系统 7:万象 8:太一
req.setOperationClient(OperationClientEnum.STATE_5.getIndex());
req.setOperator(order.getUserName());
......@@ -36,7 +42,7 @@ public class CancelOrderRequestAdapter {
}
// 这里给默认值,外面调用者 自己的根据业务判断退款 状态
req.setRefundState(AfterSalesRefunStateEnum.STATE_1.getIndex());
req.setReqRemark(reason);
req.setReqRemark(remark);
req.setRefundDeliveryAmount(refundDeliveryFee);
// 商城订单 增加拓展信息
CancelOrderRequest.AfterSalesOrderExtInfoReq ext = new CancelOrderRequest.AfterSalesOrderExtInfoReq();
......
......@@ -251,7 +251,7 @@ public class OrderController {
// 微商城因为没有退款原因选项 所以将用户退款说明用户作为退款原因
String reason = StringUtils.isBlank(reqVo.getReason())
? reqVo.getRemarks() : reqVo.getReason();
refundService.refundOrder(reqVo.getPartnerId(), reqVo.getOid(), reason, reqVo.getRefundMode());
refundService.refundOrder(reqVo.getPartnerId(), reqVo.getOid(), reqVo.getRefundAmount(), reason, reqVo.getRemarks(), reqVo.getRefundMode());
return ResponseUtil.success();
}
......
......@@ -43,6 +43,11 @@ public class OrderRefundVo {
private String partnerId;
/**
* 退款金额
*/
private Long refundAmount;
/**
* 微商城退款方式
*
* @see RefundModeEnum#getIndex()
......
......@@ -104,16 +104,19 @@ public class RefundService {
/**
* C端用户发起退款
* @param partnerId 商户号
* @param orderCode 订单号
* @param reason 退款原因/说明
* @param refundMode 商城订单 退款模式
*
* @param partnerId 商户号
* @param orderCode 订单号
* @param refundAmount 退款金额
* @param reason 退款原因/说明
* @param remark 退款备注
* @param refundMode 商城订单 退款模式
*/
public void refundOrder(String partnerId, String orderCode, String reason, Byte refundMode) {
if (StringUtils.isEmpty(reason)) reason = "退款";
public void refundOrder(String partnerId, String orderCode, Long refundAmount, String reason, String remark, Byte refundMode) {
if (StringUtils.isEmpty(reason)) reason = "退款";
// 退款校验
OrderInfoReqs order = preValidRefund(partnerId, orderCode, refundMode);
//存在售后信息
// 存在售后信息
if (CollectionUtils.isNotEmpty(order.getAfterSalesOrderList())) {
Optional<AfterSalesOrderResp> exists = order.getAfterSalesOrderList().stream()
.filter(r -> AfterSalesStatus.PENDING.getIndex().equals(r.getAfterSalesStatus()))
......@@ -124,21 +127,22 @@ public class RefundService {
if (!orderVerifyHandle.getRefundConfig(order))
throw new ServiceException("该门店不支持线上退款,请联系门店进行线下处理");
//退款是否退配送费
boolean refundDeliveryFee = isRefundDeliveryFee(order);
// 退款是否退配送费
boolean refundDeliveryFee = isRefundDeliveryFee(order, refundAmount);
// 未接单
if (NewOrderStatus.PLACE_AN_ORDER.getIndex().equals(order.getOrderState())) {
//商家未接单逻辑处理 1.调用支付退款 2.根据支付退款返回状态组装订单取消参数,调用订单取消接口
refundOrder(order, reason, refundDeliveryFee, refundMode);
// 商家未接单逻辑处理 1.调用支付退款 2.根据支付退款返回状态组装订单取消参数,调用订单取消接口
refundOrder(order, reason, remark, refundDeliveryFee, refundMode);
orderQueueService.backOrdersStatusChange(order.getOrderCode(), order.getOrderState(), order.getPayState(), order.getPartnerId());
} else {
//已接单的,创建售后单
createAfterSales(order, reason, refundDeliveryFee, refundMode);
// 已接单的,创建售后单
createAfterSales(order, refundAmount, reason, remark, refundDeliveryFee, refundMode);
}
}
/**
* 退订单金额(仅退款,不会处理订单状态)
*
* @param partnerId 商户号
* @param orderCode 订单号
* @return 退款状态 {@link PayRefundStatus}
......@@ -155,7 +159,6 @@ public class RefundService {
/**
* 研发批量退款,内部技术支持使用
*
*/
public Map<String, String> batchDevelopRefund(OrderDevelopRefundVo orderRefundVo) {
if (CollectionUtils.isEmpty(orderRefundVo.getOrderCodes())) {
......@@ -189,7 +192,7 @@ public class RefundService {
throw new ServiceException("订单未支付!");
// fisherman 该接口的调用 肯定是因已经商户确认要退款的操作, 所以不走正常的 是否可退款判断
boolean refundDeliveryFee = isRefundDeliveryFee(order);
boolean refundDeliveryFee = isRefundDeliveryFee(order, order.getActualPayAmount().longValue());
// 未接单
if (NewOrderStatus.PLACE_AN_ORDER.getIndex().equals(order.getOrderState())) {
// 未接单的 请用户直接操作C端小程序处理
......@@ -207,7 +210,7 @@ public class RefundService {
if (!isCreateAfter) {
// 没有已申请的售后单,创建售后单
createAfterSales(order, reqVo.getReason(), refundDeliveryFee, reqVo.getRefundMode());
createAfterSales(order, null, reqVo.getReason(), reqVo.getReason(), refundDeliveryFee, reqVo.getRefundMode());
}
// 调用oms的 同意退款操作
OrderManagerRequest request = new OrderManagerRequest();
......@@ -221,9 +224,13 @@ public class RefundService {
}
/**
* 是否退配送费判断
* 是否退配送费判断
*/
private boolean isRefundDeliveryFee(OrderInfoReqs order) {
private boolean isRefundDeliveryFee(OrderInfoReqs order, Long refundAmount) {
// 退款金额小于实付金额的情况,表示部分退不需要退配送费
if (refundAmount != null && refundAmount < order.getActualPayAmount().longValue()) {
return false;
}
boolean refundDeliveryFee = true;
if (Objects.equals(BizTypeEnum.MALL.getBizType(), order.getBizType())
&& StringUtils.isNotEmpty(order.getExtInfo())) {
......@@ -266,9 +273,8 @@ public class RefundService {
/**
* 商家未接单,取消订单逻辑处理
* 1.调用支付退款 2.根据支付退款返回状态组装订单取消参数,调用订单取消接口
*
*/
private void refundOrder(OrderInfoReqs order, String reason, Boolean isRefundDeliveryFee, Byte refundMode) {
private void refundOrder(OrderInfoReqs order, String reason, String remark, Boolean isRefundDeliveryFee, Byte refundMode) {
int state = PayRefundStatus.SUCCESS.getCode();
if (order.getActualPayAmount().longValue() > 0) {
PayRefundResponse refundResponse = paymentHandle.getCommonPayRefundResponse(order, reason);
......@@ -276,7 +282,7 @@ public class RefundService {
}
CancelOrderRequest req = CancelOrderRequestAdapter.convert(order, UUID.randomUUID().toString(),
AfterSalesType.USER_CANCEL, reason, isRefundDeliveryFee, refundMode);
AfterSalesType.USER_CANCEL, null, reason, remark, isRefundDeliveryFee, refundMode);
req.setRefundState(AfterSalesRefunStateEnum.STATE_4.getIndex());
if (Objects.equals(PayRefundStatus.SUCCESS.getCode(), state)) {
//退款成功
......@@ -304,33 +310,33 @@ public class RefundService {
/**
* 创建售后单
*/
private void createAfterSales(OrderInfoReqs order, String reason, Boolean refundDeliveryFee, Byte refundMode) {
private void createAfterSales(OrderInfoReqs order, Long refundAmount, String reason, String remark, Boolean refundDeliveryFee, Byte refundMode) {
AfterSalesType type = NewOrderStatus.COMPLETE.getIndex().equals(order.getOrderState())
? AfterSalesType.USER_SALE_RETURN : AfterSalesType.USER_CANCEL;
CancelOrderRequest req = CancelOrderRequestAdapter.convert(order, null, type, reason, refundDeliveryFee, refundMode);
req.setRefundState(AfterSalesRefunStateEnum.STATE_1.getIndex());
CancelOrderRequest req = CancelOrderRequestAdapter.convert(order, null, type, refundAmount, reason, remark, refundDeliveryFee, refundMode);
BaseOrderResponse resp = orderCenterSdkService.orderCancel(req);
if (!Objects.equals(resp.getErrcode(), 100)) {
throw new ServiceException(ResponseResult.ORDER__ERRORREFUND.getCode(), resp.getErrmsg());
}
// 金额大于0的退款,发送到消息中心推送到pos
if (order.getActualPayAmount().longValue() > 0) {
PushMessageNoticeDto notify = MessageNoticeAdapter.convent2PushMessageNoticeDto(2, order.getPartnerId(), order.getStoreId(),
null, null, null, null);
messageCenterClient.createMessage(notify, LogThreadLocal.getTrackingNo());
}
//通知小助手发送申请退款公众号订阅消息
// 通知小助手发送申请退款公众号订阅消息
sendApplyRefundSubscriptionNotice(order, reason);
//已接单可发起退款申请,查询门店有无云打印机,有则打印退款申请小票
// 已接单可发起退款申请,查询门店有无云打印机,有则打印退款申请小票
printApplyRefundSmallTicket(order, reason);
}
/**
* 通知小助手发送申请退款公众号订阅消息
*/
private void sendApplyRefundSubscriptionNotice(OrderInfoReqs order, String reason) {
try {
if (StringUtils.isBlank(order.getAppId())) return;
if (StringUtils.isBlank(order.getAppId())) return;
SendMessageRequest sendMessageRequest = new SendMessageRequest();
sendMessageRequest.setMessageType("REFUND_ORDER");
sendMessageRequest.setOrderId(order.getOrderCode());
......@@ -350,7 +356,6 @@ public class RefundService {
/**
* 申请退款小票打印
*
*/
private void printApplyRefundSmallTicket(OrderInfoReqs order, String reason) {
// 有云打印机 打印小票,杯贴
......
......@@ -89,5 +89,4 @@ public interface OrderServiceClient {
@LogIgnoreFeign(logMessage="queryByKeys")
@PostMapping(value = "/order/config/queryByKeys")
BaseResponse<List<QueryByKeysResp>> queryByKeys(@RequestBody QueryByKeysReq req);
}
......@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Objects;
import java.util.UUID;
/**
......@@ -42,7 +43,12 @@ public class PaymentSdkAdapter {
refundRequestDTO.setNotifyUrl(refundNotifyCallback);
OrderExtInfoDto orderExtInfoDto = JSONObject.parseObject(extInfoStr, OrderExtInfoDto.class);
refundRequestDTO.setAppId(orderExtInfoDto.getAppid());
// 为空从extinfo中获取
if (StringUtils.isBlank(payNo) || Objects.equals("0", payNo)) {
payNo = orderExtInfoDto.getFmId();
}
refundRequestDTO.setOrgPayFmId(payNo);
refundRequestDTO.setOpenid(orderExtInfoDto.getOpenid());
refundRequestDTO.setRefundId(getRefundSerialNo().toString());
refundRequestDTO.setRefundDesc(StringUtils.isNotBlank(reason) ? reason : "商家退款");
......
......@@ -639,7 +639,9 @@ public class OrderVerifyHandle {
//外卖单,使用外卖单的退款配置
switch (orderState) {
// 未接单
case 1: orderRefund = config.getDeliveryTakeOrderRefund(); break;
case 1:
case 2:
orderRefund = config.getDeliveryTakeOrderRefund(); break;
//已接单
case 3: orderRefund = config.getDeliveryReceiptOrderRefund(); break;
//制作完成
......@@ -652,7 +654,9 @@ public class OrderVerifyHandle {
//其他,使用堂食的退款配置(必须先判断收银单,因为收银单的类型也是堂食,只是orderClient不一样
switch (orderState) {
// 未接单
case 1: orderRefund = config.getTakeOrderRefund(); break;
case 1:
case 2:
orderRefund = config.getTakeOrderRefund(); break;
//已接单
case 3: orderRefund = config.getReceiptOrderRefund(); break;
//制作完成
......
......@@ -87,19 +87,20 @@ public class PaymentHandle {
public PayRefundResponse getCommonPayRefundResponse(OrderManagerRequest request, OrderBeanV1 orderBean) {
PayRefundResponse refundResponse;
try {
BigDecimal refundAmount = getRefundAmount(orderBean.getCompanyId(), new BigDecimal(orderBean.getAmount()), orderBean.getOid());
if (null != orderBean.getOrderPayItem() && orderBean.getOrderPayItem().size() > 0) {
// payment/application/refund
refundResponse = this.multiRefund(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), getRefundAmount(orderBean));
refundResponse = this.multiRefund(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), refundAmount);
} else {
OrderExtendedReq extended = orderBean.getOrderExtended();
if (StringUtils.isNotBlank(extended.getAgentPayerId()) && !Objects.equals(extended.getAgentPayerId(), orderBean.getUserId())) {
OrderExtInfoDto ext = JSON.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class);
//代付人信息不为空 并且和订单创建人不一样,表示代付单 payment/application/agentRefund
refundResponse = this.agentPayRefund(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), getRefundAmount(orderBean), ext.getPayTransId());
refundResponse = this.agentPayRefund(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), refundAmount, ext.getPayTransId());
} else {
//正常订单现金退款 paymentcenter/refund
PayRefundRequestDto req = paymentSdkAdapter.getOrderRefundRequest(orderBean.getCompanyId(), orderBean.getShopId(),
orderBean.getOid(), getRefundAmount(orderBean), orderBean.getPayVoucher(), orderBean.getExtInfo(), request.getReason());
orderBean.getOid(), refundAmount, orderBean.getPayVoucher(), orderBean.getExtInfo(), request.getReason());
// 抖音订单,退款时需要传递商品信息
if (OrderClientType.TIKTOKPAY.getIndex().toString().equals(orderBean.getOrderClient())) {
Map<String, String> extParam = new HashMap<>();
......@@ -139,19 +140,20 @@ public class PaymentHandle {
public PayRefundResponse getCommonPayRefundResponse(OrderInfoReqs order, String reason) {
PayRefundResponse refundResponse;
try {
BigDecimal refundAmount = getRefundAmount(order.getPartnerId(), order.getActualPayAmount(), order.getOrderCode());
if (CollectionUtils.isNotEmpty(order.getOrderPayItemCreateReqList())) {
// payment/application/refund
refundResponse = this.multiRefund(order.getPartnerId(), order.getStoreId(), order.getOrderCode(), order.getActualPayAmount());
refundResponse = this.multiRefund(order.getPartnerId(), order.getStoreId(), order.getOrderCode(), refundAmount);
} else {
OrderExtendedReq extended = order.getOrderExtended();
if (StringUtils.isNotBlank(extended.getAgentPayerId()) && !Objects.equals(extended.getAgentPayerId(), order.getUserId())) {
OrderExtInfoDto ext = JSON.parseObject(order.getExtInfo(), OrderExtInfoDto.class);
//代付人信息不为空 并且和订单创建人不一样,表示代付单 payment/application/agentRefund
refundResponse = this.agentPayRefund(order.getPartnerId(), order.getStoreId(), order.getOrderCode(), order.getActualPayAmount(), ext.getPayTransId());
refundResponse = this.agentPayRefund(order.getPartnerId(), order.getStoreId(), order.getOrderCode(), refundAmount, ext.getPayTransId());
} else {
//正常订单现金退款 paymentcenter/refund
PayRefundRequestDto req = paymentSdkAdapter.getOrderRefundRequest(order.getPartnerId(), order.getStoreId(),
order.getOrderCode(), order.getActualPayAmount(), order.getPayRequestNo(), order.getExtInfo(), reason);
order.getOrderCode(), refundAmount, order.getPayRequestNo(), order.getExtInfo(), reason);
// 抖音订单,退款时需要传递商品信息
if (OrderClientType.TIKTOKPAY.getIndex().equals(order.getOrderClient())) {
OrderExtInfoDto ext = JSON.parseObject(order.getExtInfo(), OrderExtInfoDto.class);
......@@ -352,8 +354,9 @@ public class PaymentHandle {
public PayRefundResponse refund(String reason, OrderBeanV1 orderBean) {
PayRefundStatus refundStatus = PayRefundStatus.SUCCESS;
BigDecimal refundAmount = getRefundAmount(orderBean.getCompanyId(), new BigDecimal(orderBean.getAmount()), orderBean.getOid());
PayRefundRequestDto orderRefundRequest = paymentSdkAdapter
.getOrderRefundRequest(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), getRefundAmount(orderBean), orderBean.getPayVoucher(), orderBean.getExtInfo(), reason);
.getOrderRefundRequest(orderBean.getCompanyId(), orderBean.getShopId(), orderBean.getOid(), refundAmount, orderBean.getPayVoucher(), orderBean.getExtInfo(), reason);
if (ObjectUtils.equals(orderBean.getAmount(), 0L)) {
return handlePayRefundResponse(refundStatus, orderRefundRequest.getRefundId());
}
......@@ -410,12 +413,13 @@ public class PaymentHandle {
/**
* 获取退款金额
*
* @param data
* @return
* @param partnerId 商户号
* @param refundAmount 总金额
* @param orderId 订单号
* @return 退款金额
*/
private BigDecimal getRefundAmount(OrderBeanV1 data) {
BigDecimal refundAmount = new BigDecimal(data.getAmount());
OrderBaseResp<List<AfterSalesOrderResp>> listBaseResponse = orderSdkService.queryAfterSaleByOrderCode(data.getCompanyId(), data.getOid());
private BigDecimal getRefundAmount(String partnerId, BigDecimal refundAmount, String orderId) {
OrderBaseResp<List<AfterSalesOrderResp>> listBaseResponse = orderSdkService.queryAfterSaleByOrderCode(partnerId, orderId);
if (CollectionUtils.isNotEmpty(listBaseResponse.getResult())) {
refundAmount = new BigDecimal(listBaseResponse.getResult().get(0).getActualAmount());
}
......
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