diff --git a/ebike-feign/src/main/java/com/ebike/feign/model/rsp/PayDetailDto.java b/ebike-feign/src/main/java/com/ebike/feign/model/rsp/PayDetailDto.java index 78634cdc..b5f95ff1 100644 --- a/ebike-feign/src/main/java/com/ebike/feign/model/rsp/PayDetailDto.java +++ b/ebike-feign/src/main/java/com/ebike/feign/model/rsp/PayDetailDto.java @@ -21,6 +21,10 @@ public class PayDetailDto implements Serializable { * 费用项目ID */ private String itemId; + /** + * 费用类型 1-骑行时长费 2-运营区调度费用 3-停车区调度费用 4-高峰时段出行费用 5-高峰日出行费用 6-起步费用 + */ + private Integer itemType; /** * 费用名称 */ diff --git a/ebike-orders/src/main/java/com/cdzy/orders/service/impl/UserOrdersServiceImpl.java b/ebike-orders/src/main/java/com/cdzy/orders/service/impl/UserOrdersServiceImpl.java index 5a503182..bde5c907 100644 --- a/ebike-orders/src/main/java/com/cdzy/orders/service/impl/UserOrdersServiceImpl.java +++ b/ebike-orders/src/main/java/com/cdzy/orders/service/impl/UserOrdersServiceImpl.java @@ -397,6 +397,7 @@ public class UserOrdersServiceImpl extends ServiceImpl { PayDetailDto payDetailDto = new PayDetailDto(); + payDetailDto.setItemType(orderDetail.getItemType()); payDetailDto.setItemName(orderDetail.getItemName()); payDetailDto.setItemId(String.valueOf(orderDetail.getItemId())); payDetailDto.setQuantity(1); diff --git a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java index 91b5cbf7..d21d6517 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java @@ -84,20 +84,25 @@ public class EbikeWxPaymentController { */ @PostMapping("/refund") public JsonResult refund(@RequestBody ReqRefundDto refundDto) { - boolean r = wxPayService.refund(refundDto); - return r?JsonResult.failed("退款失败"):JsonResult.success(r); + HandleNotifyResult r = wxPayService.refund(refundDto); + if (r.isSuccess()) + return JsonResult.success(); + JSONObject error = JSONObject.parseObject(r.getMessage()); + if (error==null) + return JsonResult.failed(r.getMessage()); + return JsonResult.failed("退款失败", error); } /** * 审核退款申请 * * @param processDto 退款处理信息 - * @return 退款成功返回true,否则返回false + * @return 审核成功返回true,否则返回false */ @PostMapping("/reviewRefund") - public JsonResult rejectRefund(@RequestBody ReqRefundProcessDto processDto) { + public JsonResult reviewRefund(@RequestBody ReqRefundProcessDto processDto) { boolean r = wxPayService.refundReview(processDto); - return r?JsonResult.failed("退款失败"):JsonResult.success(r); + return r?JsonResult.success(true):JsonResult.failed("审核失败"); } /** @@ -124,5 +129,15 @@ public class EbikeWxPaymentController { return JsonResult.success(list); } - + /** + * 退款订单详情 + * + * @param refundId 退款id + * @return 退款详情 + */ + @GetMapping("/refundOrderDetail/{refundId}") + public JsonResult refundOrderDetail(@PathVariable(name = "refundId") String refundId) { + ResOrderInfoDto r = wxPayService.queryRefundOrderById(refundId); + return r == null?JsonResult.failed(String.format("退款单号{%s}查询订单详情失败", refundId)):JsonResult.success(r); + } } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/model/dto/ResOrderInfoDto.java b/ebike-payment/src/main/java/com/cdzy/payment/model/dto/ResOrderInfoDto.java index 99009ff8..b5c3c938 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/model/dto/ResOrderInfoDto.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/model/dto/ResOrderInfoDto.java @@ -16,70 +16,75 @@ import java.time.LocalDateTime; @Data public class ResOrderInfoDto { + /** + * 订单id + */ + private String orderId; + /** * 订单金额 */ - private BigDecimal totalAmount; + private Double totalAmount = 0.0; /** * 起步费用 */ - private BigDecimal startupCost; + private Double startupCost = 0.0; /** * 时长费 */ - private BigDecimal durationCost; + private Double durationCost = 0.0; /** * 调度费 */ - private BigDecimal dispatchFee; + private Double dispatchFee = 0.0; /** * 运营区外掉付费 */ - private BigDecimal dispatchFeeOutOperateArea; + private Double dispatchFeeOutOperateArea = 0.0; /** * 禁停区调度费 */ - private BigDecimal dispatchFeeBanArea; + private Double dispatchFeeBanArea = 0.0; /** * 停车区外调度费 */ - private BigDecimal parkingAreaOutDispatchFee; + private Double parkingAreaOutDispatchFee = 0.0; /** * 头盔管理费 */ - private BigDecimal helmetManagementFee; + private Double helmetManagementFee = 0.0; /** * 不规范停车费 */ - private BigDecimal improperParkFee; + private Double improperParkFee = 0.0; /** * 实付金额 */ - private BigDecimal actualAmount; + private Double actualAmount = 0.0; /** * 优惠金额 */ - private BigDecimal discountAmount; + private Double discountAmount = 0.0; /** * 优惠卷抵扣金额 */ - private BigDecimal couponAmount; + private Double couponAmount = 0.0; /** * 骑行卡抵扣金额 */ - private BigDecimal cyclingCardAmount; + private Double cyclingCardAmount = 0.0; /** * 支付方式 @@ -87,9 +92,14 @@ public class ResOrderInfoDto { private String payMethod; /** - * 用户手机与姓名 + * 用户姓名 */ - private String phoneAndUser; + private String user; + + /** + * 用户手机 + */ + private String phone; /** * 申请原因 @@ -99,6 +109,6 @@ public class ResOrderInfoDto { /** * 申请退款金额 */ - private BigDecimal applyRefundAmount; + private Double applyRefundAmount = 0.0; } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java index 88201789..ee3c82bd 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java @@ -80,9 +80,9 @@ public class EbikePayment implements Serializable { */ private Double costPrice; /** - * 货币 + * 货币, 默认人民币CNY */ - private String currency; + private String currency = "CNY"; /** * 实际支付金额 diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java index 6901e6b9..499d007b 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikeRefundService.java @@ -79,4 +79,11 @@ public interface EbikeRefundService extends IService { */ Page getClosedList(ReqRefundQueryDto refundDto); + /** + * 退款订单详情 + * + * @param refundId 退款id + * @return 退款详情 + */ + ResOrderInfoDto getRefundOrderDetail(String refundId); } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java index 9ba15ef1..a4186e68 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java @@ -2,10 +2,7 @@ package com.cdzy.payment.service; import com.alibaba.fastjson2.JSONObject; -import com.cdzy.payment.model.dto.HandleNotifyResult; -import com.cdzy.payment.model.dto.ReqRefundDto; -import com.cdzy.payment.model.dto.ReqRefundProcessDto; -import com.cdzy.payment.model.dto.ReqRefundQueryDto; +import com.cdzy.payment.model.dto.*; import com.mybatisflex.core.paginate.Page; import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.refund.model.Refund; @@ -94,7 +91,7 @@ public interface WxPayService { * @param refundDto 退款请求 * @return 退款信息id */ - Boolean refund(ReqRefundDto refundDto); + HandleNotifyResult refund(ReqRefundDto refundDto); /** @@ -128,4 +125,12 @@ public interface WxPayService { * @return 退款列表 */ Page queryRefundList(ReqRefundQueryDto refundDto); + + /** + * 退款订单详情 + * + * @param refundId 退款id + * @return 退款详情 + */ + ResOrderInfoDto queryRefundOrderById(String refundId); } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeRefundServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeRefundServiceImpl.java index 898200f8..25a78956 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeRefundServiceImpl.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikeRefundServiceImpl.java @@ -209,4 +209,22 @@ public class EbikeRefundServiceImpl extends ServiceImpl page = refundDto.getPageParam().getPage(); return pageAs(page, query, ResCloseRefundDto.class); } + + @Override + public ResOrderInfoDto getRefundOrderDetail(String refundId) { + QueryWrapper query = QueryWrapper.create() + .select(EBIKE_REFUND.REFUND_APPLY.as("apply_refund_amount"), EBIKE_REFUND.REASON.as("apply_reason"), + EBIKE_REFUND.ORDER_ID.as("order_id"), + QueryMethods.case_(EBIKE_PAYMENT.PAYMENT_METHOD) + .when(PayMethod.wechat.name()).then("微信支付") + .when(PayMethod.alipay.name()).then("支付宝") + .when(PayMethod.balance.name()).then("余额").end().as("pay_method"), + EBIKE_PAYMENT.TOTAL.as("actual_amount"),EBIKE_PAYMENT.COST_PRICE.as("total_amount"), + EBIKE_USER.NICKNAME.as("user"), EBIKE_USER.MOBILE.as("phone") + ) + .leftJoin(EBIKE_PAYMENT).on(EBIKE_PAYMENT.ORDER_ID.eq(EBIKE_REFUND.ORDER_ID)) + .leftJoin(EBIKE_USER).on(EBIKE_USER.USER_ID.eq(EBIKE_PAYMENT.USER_ID)) + .where(EBIKE_REFUND.REFUND_ID.eq(refundId)); + return getOneAs(query, ResOrderInfoDto.class); + } } diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java index 499737ce..f1f19b78 100644 --- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java +++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java @@ -19,6 +19,7 @@ import com.ebike.feign.clients.OrdersFeignClient; import com.ebike.feign.model.rsp.AmountDto; import com.ebike.feign.model.rsp.DetailDto; import com.ebike.feign.model.rsp.EbikePaymentDto; +import com.ebike.feign.model.rsp.PayDetailDto; import com.mybatisflex.core.paginate.Page; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.cipher.Signer; @@ -219,6 +220,7 @@ public class WxPayServiceImpl implements WxPayService { ebikePayment.setPaymentMethod(PayMethod.wechat.name()); ebikePayment.setCostPrice(amount.getTotal()); ebikePayment.setTradeState(String.valueOf(Transaction.TradeStateEnum.NOTPAY.ordinal())); + ebikePayment.setCurrency(paymentDto.getAmount().getCurrency()); ebikePaymentService.save(ebikePayment); } else { ebikePayment.setPaymentId(payId); @@ -382,7 +384,7 @@ public class WxPayServiceImpl implements WxPayService { ebikeRefund.setProcessState(processDto.getOperate()); ebikeRefund.setProcessTime(LocalDateTime.now()); ebikeRefund.setRemark(processDto.getReason()); - if (String.valueOf(RefundProcessState.processing).equals(processDto.getOperate())) { + if (String.valueOf(RefundProcessState.processing.ordinal()).equals(processDto.getOperate())) { ebikeRefund.setRefund(ebikeRefund.getRefundApply()); ebikeRefund.setRefundMethod(processDto.getMethod()); } @@ -390,7 +392,9 @@ public class WxPayServiceImpl implements WxPayService { } @Override - public Boolean refund(ReqRefundDto refundDto) { + public HandleNotifyResult refund(ReqRefundDto refundDto) { + HandleNotifyResult result_ = new HandleNotifyResult(); + result_.setSuccess(false); // 首先验证密码 //if (!wxPayConfig.getRefundPassword().equals(refundDto.getPassword())) { // @@ -399,7 +403,8 @@ public class WxPayServiceImpl implements WxPayService { EbikeRefund ebikeRefund = ebikeRefundService.getById(refundDto.getRefundId()); if (ebikeRefund == null) { log.error("退款refund失败,{} 退款申请不存在", refundDto.getRefundId()); - return false; + result_.setMessage(String.format("{%s}退款申请不存在", refundDto.getRefundId())); + return result_; } // 查询支付记录 String outTradeNo = ebikeRefund.getOrderId(); @@ -408,7 +413,7 @@ public class WxPayServiceImpl implements WxPayService { AmountRefundDto amount = new AmountRefundDto(); amount.setTotal(ebikePayment.getCostPrice()); amount.setRefund(ebikePayment.getTotal()); - amount.setCurrency(ebikePayment.getCurrency()); + amount.setCurrency(ebikeRefund.getCurrency()); // 发起退款 CreateRequest request = new CreateRequest(); request.setTransactionId(transactionId); @@ -421,25 +426,34 @@ public class WxPayServiceImpl implements WxPayService { amountReq.setTotal(BigDecimal.valueOf(amount.getTotal() * 100.0).longValue()); amountReq.setCurrency(amount.getCurrency()); request.setAmount(amountReq); - Refund result = wxRefundService.create(request); - // 更新退款信息 - if (result != null) { - ebikeRefund.setOrderId(outTradeNo); - ebikeRefund.setTransactionId(transactionId); - ebikeRefund.setTotal(amount.getTotal()); - ebikeRefund.setStatus(String.valueOf(result.getStatus().ordinal())); - ebikeRefund.setCurrency(amount.getCurrency()); - if (Status.SUCCESS.equals(result.getStatus())) { - ebikeRefund.setRefund(result.getAmount().getRefund().doubleValue() / 100.0); - ebikeRefund.setRefundTime(LocalDateTime.now()); - ebikeRefund.setRemark(refundDto.getRemark()); - ebikeRefund.setRefundTransactionId(result.getRefundId()); + try { + Refund result = wxRefundService.create(request); + // 更新退款信息 + if (result != null) { + ebikeRefund.setOrderId(outTradeNo); + ebikeRefund.setTransactionId(transactionId); + ebikeRefund.setTotal(amount.getTotal()); + ebikeRefund.setStatus(String.valueOf(result.getStatus().ordinal())); + ebikeRefund.setCurrency(amount.getCurrency()); + if (Status.SUCCESS.equals(result.getStatus())) { + ebikeRefund.setRefund(result.getAmount().getRefund().doubleValue() / 100.0); + ebikeRefund.setRefundTime(LocalDateTime.now()); + ebikeRefund.setRemark(refundDto.getRemark()); + ebikeRefund.setRefundTransactionId(result.getRefundId()); + } + ebikeRefundService.updateById(ebikeRefund); + result_.setSuccess(true); + result_.setMessage("退款成功"); + return result_; } - ebikeRefundService.updateById(ebikeRefund); - return Status.SUCCESS.equals(result.getStatus()); + log.error("退款refund失败,订单号:{}", outTradeNo); + result_.setMessage("退款失败"); + return result_; + } catch (Exception e) { + String err = logError("退款refund", e); + result_.setMessage(err); + return result_; } - log.error("退款refund失败,订单号:{}", outTradeNo); - return false; } @Override @@ -523,24 +537,57 @@ public class WxPayServiceImpl implements WxPayService { }; } + @Override + public ResOrderInfoDto queryRefundOrderById(String refundId) { + ResOrderInfoDto orderDto = ebikeRefundService.getRefundOrderDetail(refundId); + if (orderDto==null){ + log.error("{}退款订单不存在", refundId); + return null; + } + //查询订单, orderFeingClient.getOrderById(orderId) + JsonResult result = ordersFeignClient.getPaymentDetails(Long.valueOf(orderDto.getOrderId())); + if (result.getCode() != 200) { + log.error("查询订单 {} 失败, {}", orderDto.getOrderId(), result.getMessage()); + return null; + } + EbikePaymentDto paymentDto = JSON.parseObject(JSONObject.toJSONString(result.getData()), EbikePaymentDto.class); + for (PayDetailDto detailDto : paymentDto.getDetail().getGoodsDetail()) { + //1-骑行时长费 2-运营区调度费用 3-停车区调度费用 4-高峰时段出行费用 5-高峰日出行费用 6-起步费用 + switch (detailDto.getItemType()) { + case 1, 4, 5 -> orderDto.setDurationCost(orderDto.getDurationCost()+detailDto.getUnitPrice()); + case 2 -> orderDto.setDispatchFeeOutOperateArea(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice()); + case 3 -> orderDto.setParkingAreaOutDispatchFee(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice()); + case 6 -> orderDto.setStartupCost(orderDto.getStartupCost() + detailDto.getUnitPrice()); + } + } + orderDto.setDispatchFee(orderDto.getDispatchFee() + orderDto.getParkingAreaOutDispatchFee()+orderDto.getDispatchFeeOutOperateArea()+orderDto.getDispatchFeeBanArea()); + + orderDto.setOrderId(null); + return orderDto; + } + /** * 打印日志 * * @param desc 描述 * @param e 异常 */ - private void logError(String desc, Exception e) { + private String logError(String desc, Exception e) { + String msg = e.getMessage(); if (e instanceof HttpException httpException) { log.error("{} 发送HTTP请求失败, {}", desc, httpException.getHttpRequest()); } else if (e instanceof ServiceException serviceException) { log.error("{} 服务返回状态不正常, {}", desc, serviceException.getResponseBody()); + msg = serviceException.getResponseBody(); } else if (e instanceof MalformedMessageException malformedMessageException) { log.error("{} 返回体类型不合法或者解析返回体失败, {}", desc, malformedMessageException.getMessage()); + msg = malformedMessageException.getMessage(); } else if (e instanceof ValidationException validationException) { log.error("{} 验签失败,验证签名失败,{}", desc, validationException.getMessage()); + msg = validationException.getMessage(); } else { log.error("{} 执行异常, {}", desc, e.getMessage()); } - + return msg; } }