| | |
| | | package com.doumee.api.web; |
| | | |
| | | import com.doumee.config.wx.WxMiniConfig; |
| | | import com.doumee.config.wx.WxPayV3Service; |
| | | import com.doumee.core.constants.Constants; |
| | | import com.doumee.core.utils.ID; |
| | | import com.doumee.dao.business.OrdersRefundMapper; |
| | | import com.doumee.dao.business.OrdersMapper; |
| | | import com.doumee.dao.business.model.Notice; |
| | | import com.doumee.dao.business.model.Orders; |
| | | import com.doumee.dao.business.model.OrdersRefund; |
| | | import com.doumee.service.business.NoticeService; |
| | | import com.doumee.service.business.OrdersService; |
| | | import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; |
| | | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| | | import com.wechat.pay.java.service.payments.model.Transaction; |
| | | import com.wechat.pay.java.service.refund.model.RefundNotification; |
| | | import com.wechat.pay.java.service.refund.model.Status; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.CrossOrigin; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Date; |
| | | import java.util.Objects; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 支付回调 |
| | |
| | | @Autowired |
| | | private OrdersService ordersService; |
| | | |
| | | @Autowired |
| | | private WxPayV3Service wxPayV3Service; |
| | | |
| | | @Autowired |
| | | private OrdersRefundMapper ordersRefundMapper; |
| | | |
| | | @Autowired |
| | | private OrdersMapper ordersMapper; |
| | | |
| | | @Autowired |
| | | private NoticeService noticeService; |
| | | |
| | | |
| | | // ==================== V2 回调 ==================== |
| | | |
| | | @PostMapping("/web/api/wxPayNotify") |
| | | public String wxPay_notify(@RequestBody String xmlResult) { |
| | | String wxId = ID.nextGUID(); |
| | | log.info("支付回调信息("+wxId+") = > " + xmlResult); |
| | | if (StringUtils.isEmpty(xmlResult)){ |
| | | log.info("V2支付回调信息(" + wxId + ") => " + xmlResult); |
| | | if (StringUtils.isEmpty(xmlResult)) { |
| | | return null; |
| | | } |
| | | try { |
| | | WxPayOrderNotifyResult result = WxMiniConfig.wxPayService.parseOrderNotifyResult(xmlResult); |
| | | //自定义订单号 |
| | | String outTradeNo = result.getOutTradeNo(); |
| | | //微信订单号 |
| | | String paymentNo = result.getTransactionId(); |
| | | |
| | | |
| | | |
| | | if (Constants.SUCCESS.equals(result.getReturnCode())) { |
| | | // 支付成功 |
| | | switch (result.getAttach()) { |
| | | //寄存订单 |
| | | case "storageOrder": { |
| | | ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | } |
| | | //店铺押金订单 |
| | | case "shopDeposit": { |
| | | |
| | | ordersService.handleShopDepositPayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | } |
| | | //逾期费用订单 |
| | | case "overdueFee": { |
| | | |
| | | ordersService.handleOverdueFeePayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | } |
| | | } |
| | |
| | | return WxPayNotifyResponse.fail(result.getReturnMsg()); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("微信回调结果异常,异常原因{}", e.getLocalizedMessage()); |
| | | log.error("V2微信回调结果异常,异常原因{}", e.getLocalizedMessage()); |
| | | return WxPayNotifyResponse.fail(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // ==================== V3 回调 ==================== |
| | | |
| | | /** |
| | | * V3支付回调 |
| | | */ |
| | | @PostMapping("/web/api/wxPayV3Notify") |
| | | public Map<String, String> wxPayV3Notify( |
| | | @RequestHeader("Wechatpay-Serial") String serialNumber, |
| | | @RequestHeader("Wechatpay-Timestamp") String timestamp, |
| | | @RequestHeader("Wechatpay-Nonce") String nonce, |
| | | @RequestHeader("Wechatpay-Signature") String signature, |
| | | @RequestBody String body) { |
| | | String wxId = ID.nextGUID(); |
| | | log.info("V3支付回调信息({}) => {}", wxId, body); |
| | | try { |
| | | Transaction transaction = wxPayV3Service.parsePayNotify( |
| | | serialNumber, timestamp, nonce, signature, body); |
| | | |
| | | String outTradeNo = transaction.getOutTradeNo(); |
| | | String paymentNo = transaction.getTransactionId(); |
| | | |
| | | if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) { |
| | | String attach = transaction.getAttach(); |
| | | if (StringUtils.isNotBlank(attach)) { |
| | | switch (attach) { |
| | | case "storageOrder": |
| | | ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | case "shopDeposit": |
| | | ordersService.handleShopDepositPayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | case "overdueFee": |
| | | ordersService.handleOverdueFeePayNotify(outTradeNo, paymentNo); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | Map<String, String> response = new HashMap<>(); |
| | | response.put("code", "SUCCESS"); |
| | | response.put("message", "处理成功"); |
| | | return response; |
| | | } catch (Exception e) { |
| | | log.error("V3支付回调异常,异常原因{}", e.getLocalizedMessage()); |
| | | Map<String, String> response = new HashMap<>(); |
| | | response.put("code", "FAIL"); |
| | | response.put("message", e.getMessage()); |
| | | return response; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * V3退款回调 |
| | | */ |
| | | @PostMapping("/web/api/wxRefundV3Notify") |
| | | public Map<String, String> wxRefundV3Notify( |
| | | @RequestHeader("Wechatpay-Serial") String serialNumber, |
| | | @RequestHeader("Wechatpay-Timestamp") String timestamp, |
| | | @RequestHeader("Wechatpay-Nonce") String nonce, |
| | | @RequestHeader("Wechatpay-Signature") String signature, |
| | | @RequestBody String body) { |
| | | String wxId = ID.nextGUID(); |
| | | log.info("V3退款回调信息({}) => {}", wxId, body); |
| | | try { |
| | | RefundNotification refundNotification = wxPayV3Service.parseRefundNotify( |
| | | serialNumber, timestamp, nonce, signature, body); |
| | | |
| | | log.info("V3退款回调结果, outTradeNo={}, outRefundNo={}, refundStatus={}", |
| | | refundNotification.getOutTradeNo(), |
| | | refundNotification.getOutRefundNo(), |
| | | refundNotification.getRefundStatus()); |
| | | |
| | | // 根据退款单号更新退款记录状态 |
| | | String outRefundNo = refundNotification.getOutRefundNo(); |
| | | OrdersRefund refundRecord = ordersRefundMapper.selectOne( |
| | | new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<OrdersRefund>().lambda() |
| | | .eq(OrdersRefund::getRefundCode, outRefundNo) |
| | | .eq(OrdersRefund::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (refundRecord != null) { |
| | | Status refundStatus = refundNotification.getRefundStatus(); |
| | | if (Status.SUCCESS.equals(refundStatus)) { |
| | | refundRecord.setStatus(Constants.ONE); // 退款成功 |
| | | refundRecord.setRefundTime(new java.util.Date()); |
| | | } else if (Status.CLOSED.equals(refundStatus) || Status.ABNORMAL.equals(refundStatus)) { |
| | | refundRecord.setStatus(Constants.TWO); // 退款失败 |
| | | } |
| | | ordersRefundMapper.updateById(refundRecord); |
| | | log.info("退款记录状态已更新, refundRecordId={}, status={}", refundRecord.getId(), refundRecord.getStatus()); |
| | | |
| | | // 退款成功 → 通知会员 |
| | | if (Status.SUCCESS.equals(refundStatus) && refundRecord.getOrderId() != null) { |
| | | Orders refundOrder = ordersMapper.selectById(refundRecord.getOrderId()); |
| | | if (refundOrder != null) { |
| | | Notice notice = new Notice(); |
| | | notice.setUserType(0); |
| | | notice.setUserId(refundOrder.getMemberId()); |
| | | notice.setTitle(Constants.MemberOrderNotify.REFUNDED.getTitle()); |
| | | notice.setContent(Constants.MemberOrderNotify.REFUNDED.format( |
| | | "orderNo", refundOrder.getCode(), |
| | | "amount", String.valueOf(Constants.getFormatMoney(refundOrder.getRefundAmount() != null ? refundOrder.getRefundAmount() : 0L)))); |
| | | notice.setObjId(refundOrder.getId()); |
| | | notice.setObjType(0); |
| | | notice.setStatus(0); |
| | | notice.setIsdeleted(Constants.ZERO); |
| | | notice.setCreateDate(new java.util.Date()); |
| | | noticeService.create(notice); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Map<String, String> response = new HashMap<>(); |
| | | response.put("code", "SUCCESS"); |
| | | response.put("message", "处理成功"); |
| | | return response; |
| | | } catch (Exception e) { |
| | | log.error("V3退款回调异常,异常原因{}", e.getLocalizedMessage()); |
| | | Map<String, String> response = new HashMap<>(); |
| | | response.put("code", "FAIL"); |
| | | response.put("message", e.getMessage()); |
| | | return response; |
| | | } |
| | | } |
| | | |
| | | } |