rk
17 小时以前 ab9cd2c82bd64de8e33510db1d1e78a5b3b4de70
server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
@@ -1,23 +1,28 @@
package com.doumee.api.web.mall;
package com.doumee.api.web;
import com.doumee.api.web.ApiController;
import com.doumee.core.utils.Constants;
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.core.wx.WxMiniConfig;
import com.doumee.dao.business.model.ActivitySign;
import com.doumee.dao.business.model.Fund;
import com.doumee.dao.business.model.Goodsorder;
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.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.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Objects;
import java.util.HashMap;
import java.util.Map;
/**
 * 支付回调
@@ -30,128 +35,183 @@
@CrossOrigin
public class PaymentCallback extends ApiController {
    @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_STR.equals(result.getReturnCode())) {
                // 支付成功
            if (Constants.SUCCESS.equals(result.getReturnCode())) {
                switch (result.getAttach()) {
                    //活动参与支付
                    case "ActivitySign": {
                        ActivitySign activitySign = activitySignService.findById(Integer.valueOf(outTradeNo));
                        if(Objects.isNull(activitySign)){
                            return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!");
                        }
                        if(activitySign.getStatus().equals(Constants.ONE)){
                            return WxPayNotifyResponse.success("处理成功!");
                        }
                        activitySign.setPayStatus(Constants.ONE);
                        activitySign.setPayDate(new Date());
                        activitySign.setPayOrderId(paymentNo);
                        activitySign.setStatus(Constants.ONE);
                        activitySignService.updateById(activitySign);
                    case "storageOrder": {
                        ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo);
                        break;
                    }
                    case "terraceMall": {
                        Goodsorder DBGoodsOrder = new Goodsorder();
                        DBGoodsOrder.setCode(Long.valueOf(outTradeNo));
                        Goodsorder goodsOrder = goodsorderService.findOne(DBGoodsOrder);
                        if(Objects.isNull(goodsOrder)){
                            return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!");
                        }
                        if(goodsOrder.getStatus().equals(Constants.ONE)){
                            return WxPayNotifyResponse.success("处理成功!");
                        }
                        goodsOrder.setPayStatus(Constants.ONE);
                        goodsOrder.setPayDate(new Date());
                        goodsOrder.setPayOrderId(paymentNo);
                        goodsOrder.setStatus(Constants.OrderStatus.PAY_DONE.getKey());
                        goodsOrder.setPayMethod(Constants.ZERO);
                        goodsorderService.updateById(goodsOrder);
                        //生成 咖啡计划订单明细表
                        if(goodsOrder.getType().equals(Constants.TWO)){
                            planorderDetailService.createPlanOrderDetail(goodsOrder);
                        }
                        Fund fund = new Fund();
                        fund.setOrderCode(goodsOrder.getPayOrderId());
                        fund.setCreator(goodsOrder.getMemberId());
                        fund.setCreateDate(new Date());
                        fund.setIsdeleted(Constants.ZERO);
                        fund.setRemark(goodsOrder.getCode().toString());
                        fund.setMemberId(goodsOrder.getMemberId());
                        fund.setTitle("订单支付");
                        fund.setContent("订单支付");
                        fund.setObjId(goodsOrder.getId());
                        fund.setObjType(Constants.ONE);
                        fund.setType(Constants.ZERO);
                        fund.setNum(goodsOrder.getPrice());
                        fundService.create(fund);
                    case "shopDeposit": {
                        ordersService.handleShopDepositPayNotify(outTradeNo, paymentNo);
                        break;
                    }
                    case "shopGoods": {
                        Goodsorder DBGoodsOrder = new Goodsorder();
                        DBGoodsOrder.setCode(Long.valueOf(outTradeNo));
                        Goodsorder goodsOrder = goodsorderService.findOne(DBGoodsOrder);
                        if(Objects.isNull(goodsOrder)){
                            return WxPayNotifyResponse.fail( "支付回调信息("+ wxId + ") = > 未查询到支付对象信息!");
                        }
                        if(goodsOrder.getStatus().equals(Constants.ONE)){
                            return WxPayNotifyResponse.success("处理成功!");
                        }
                        goodsOrder.setPayStatus(Constants.ONE);
                        goodsOrder.setPayDate(new Date());
                        goodsOrder.setPayOrderId(paymentNo);
                        goodsOrder.setStatus(Constants.OrderStatus.PAY_DONE.getKey());
                        //生成核销码
                        if(Constants.equalsInteger(goodsOrder.getReceiveType(),Constants.ONE)){
                            goodsOrder.setExchangeCode(goodsorderService.createExchangeCode());
                        }
                        goodsOrder.setPayMethod(Constants.ZERO);
                        goodsorderService.updateById(goodsOrder);
                        if(Objects.nonNull(goodsOrder.getPickUpShopId())){
                            //发送站内信 - 经销商
                            noticeService.orderPayNotice(goodsOrder.getPickUpShopId(),goodsOrder.getId(),goodsOrder.getReceiveType());
                        }
                        Fund fund = new Fund();
                        fund.setOrderCode(goodsOrder.getPayOrderId());
                        fund.setCreator(goodsOrder.getMemberId());
                        fund.setCreateDate(new Date());
                        fund.setIsdeleted(Constants.ZERO);
                        fund.setRemark(goodsOrder.getCode().toString());
                        fund.setMemberId(goodsOrder.getMemberId());
                        fund.setTitle("订单支付");
                        fund.setContent("订单支付");
                        fund.setObjId(goodsOrder.getId());
                        fund.setObjType(Constants.ONE);
                        fund.setType(Constants.ZERO);
                        fund.setNum(goodsOrder.getPrice());
                        fundService.create(fund);
                    case "overdueFee": {
                        ordersService.handleOverdueFeePayNotify(outTradeNo, paymentNo);
                        break;
                    }
                }
                return WxPayNotifyResponse.success("处理成功!");
            }
            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;
        }
    }
}