| | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.tourguide.common.exception.BusinessException; |
| | | import com.tourguide.common.huifu.properties.HuiFuProperties; |
| | | import com.tourguide.modules.order.domain.OrderStatus; |
| | | import com.tourguide.modules.order.domain.RefundAmountCalculator; |
| | | import com.tourguide.modules.order.domain.RefundStatus; |
| | | import com.tourguide.modules.order.entity.TourOrder; |
| | | import com.tourguide.modules.order.mapper.TourOrderMapper; |
| | |
| | | if (order == null) throw new BusinessException(404, "Refund order does not exist"); |
| | | |
| | | String status = first(body, "refund_stat", "trans_stat"); |
| | | if (!isSuccess(status)) { |
| | | if (!RefundStatus.REFUNDED.matches(order.getRefundStatus())) { |
| | | String result = StringUtils.hasText(status) ? status : first(body, "resp_code", "code"); |
| | | if (!isSuccess(result)) { |
| | | if (RefundStatus.REFUNDING.matches(order.getRefundStatus())) { |
| | | order.setRefundStatus(RefundStatus.REFUND_FAILED.getCode()); |
| | | orderMapper.updateById(order); |
| | | } |
| | | return false; |
| | | } |
| | | if (RefundStatus.REFUNDED.matches(order.getRefundStatus())) { |
| | | if (!RefundStatus.REFUNDING.matches(order.getRefundStatus())) { |
| | | return false; |
| | | } |
| | | BigDecimal callbackAmount = amount(body); |
| | | if (order.getRefundAmount() == null || order.getRefundAmount().compareTo(callbackAmount) != 0) { |
| | | throw new BusinessException(409, "Refund amount does not match order"); |
| | | } |
| | | order.setRefundStatus(RefundStatus.REFUNDED.getCode()); |
| | | order.setRefundTime(callbackTime(body)); |
| | | BigDecimal refundedAmount = RefundAmountCalculator.refundedAmount(order).add(callbackAmount); |
| | | BigDecimal paidAmount = RefundAmountCalculator.paidAmount(order); |
| | | if (refundedAmount.compareTo(paidAmount) > 0) { |
| | | throw new BusinessException(409, "Refund amount exceeds order payment"); |
| | | } |
| | | order.setRefundedAmount(refundedAmount); |
| | | if (refundedAmount.compareTo(paidAmount) >= 0) { |
| | | order.setRefundStatus(RefundStatus.REFUNDED.getCode()); |
| | | order.setStatus(OrderStatus.REFUNDED.getCode()); |
| | | } else { |
| | | order.setRefundStatus(RefundStatus.PARTIAL.getCode()); |
| | | order.setStatus(OrderStatus.CANCELLED.getCode()); |
| | | } |
| | | LocalDateTime refundCompletedAt = callbackTime(body); |
| | | order.setRefundTime(refundCompletedAt); |
| | | if (order.getCancelledAt() == null) order.setCancelledAt(refundCompletedAt); |
| | | orderMapper.updateById(order); |
| | | return true; |
| | | } |
| | |
| | | } |
| | | |
| | | private boolean isSuccess(String status) { |
| | | return "S".equalsIgnoreCase(status) || "SUCCESS".equalsIgnoreCase(status); |
| | | return "S".equalsIgnoreCase(status) || "SUCCESS".equalsIgnoreCase(status) |
| | | || "SUCCEEDED".equalsIgnoreCase(status) || "00000100".equalsIgnoreCase(status); |
| | | } |
| | | |
| | | private String first(JSONObject body, String... keys) { |
| | | if (body == null) return null; |
| | | for (String key : keys) { |
| | | String value = body.getString(key); |
| | | if (StringUtils.hasText(value)) return value; |
| | | } |
| | | JSONObject data = body.getJSONObject("data"); |
| | | if (data != null) return first(data, keys); |
| | | return null; |
| | | } |
| | | } |