Merge remote-tracking branch 'origin/main'

This commit is contained in:
attiya 2025-05-19 15:33:25 +08:00
commit 2494cdad98
9 changed files with 159 additions and 52 deletions

View File

@ -21,6 +21,10 @@ public class PayDetailDto implements Serializable {
* 费用项目ID
*/
private String itemId;
/**
* 费用类型 1-骑行时长费 2-运营区调度费用 3-停车区调度费用 4-高峰时段出行费用 5-高峰日出行费用 6-起步费用
*/
private Integer itemType;
/**
* 费用名称
*/

View File

@ -397,6 +397,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
detailDto.setCostPrice(orderDetailsInfo.getTotalAmount().doubleValue());
detailDto.setGoodsDetail(orderDetailsInfo.getDetails().stream().map(orderDetail -> {
PayDetailDto payDetailDto = new PayDetailDto();
payDetailDto.setItemType(orderDetail.getItemType());
payDetailDto.setItemName(orderDetail.getItemName());
payDetailDto.setItemId(String.valueOf(orderDetail.getItemId()));
payDetailDto.setQuantity(1);

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -80,9 +80,9 @@ public class EbikePayment implements Serializable {
*/
private Double costPrice;
/**
* 货币
* 货币 默认人民币CNY
*/
private String currency;
private String currency = "CNY";
/**
* 实际支付金额

View File

@ -79,4 +79,11 @@ public interface EbikeRefundService extends IService<EbikeRefund> {
*/
Page<ResCloseRefundDto> getClosedList(ReqRefundQueryDto refundDto);
/**
* 退款订单详情
*
* @param refundId 退款id
* @return 退款详情
*/
ResOrderInfoDto getRefundOrderDetail(String refundId);
}

View File

@ -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);
}

View File

@ -209,4 +209,22 @@ public class EbikeRefundServiceImpl extends ServiceImpl<EbikeRefundMapper, Ebike
Page<ResCloseRefundDto> 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);
}
}

View File

@ -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,6 +426,7 @@ public class WxPayServiceImpl implements WxPayService {
amountReq.setTotal(BigDecimal.valueOf(amount.getTotal() * 100.0).longValue());
amountReq.setCurrency(amount.getCurrency());
request.setAmount(amountReq);
try {
Refund result = wxRefundService.create(request);
// 更新退款信息
if (result != null) {
@ -436,10 +442,18 @@ public class WxPayServiceImpl implements WxPayService {
ebikeRefund.setRefundTransactionId(result.getRefundId());
}
ebikeRefundService.updateById(ebikeRefund);
return Status.SUCCESS.equals(result.getStatus());
result_.setSuccess(true);
result_.setMessage("退款成功");
return result_;
}
log.error("退款refund失败订单号{}", outTradeNo);
return false;
result_.setMessage("退款失败");
return result_;
} catch (Exception e) {
String err = logError("退款refund", e);
result_.setMessage(err);
return result_;
}
}
@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;
}
}