微信支付回调信息接收设计

策略模式 + springboot + maven
微信回调文档参考 https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/development/pay/callback/

在这里插入图片描述

如图所示,在接收到微信支付平台推送信息后对数据进行解析处理,根据类型不同解析到不同的处理器中,灵活运用springboot对组件的代理控制
使用就很简单了,把对应的maven子工程引入,然后实现主页业务最下对应接口
实际上根据业务需求,代码中间抛出的异常可以设计一个微信支付异常类,在异常捕获的时候进行接口特殊处理
代码中的包装类根据微信回调文档实体进行设计根据每个公司业务不同自行创建

消息处理器 NotificationHandler.java

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.*.payment.wechat.common.component.provider.ConfProvider;
import com.*.payment.wechat.notification.common.cont.ProcessorEnum;
import com.*.payment.wechat.notification.common.parser.Parser;
import com.*.payment.wechat.notification.common.processor.Processor;
import com.*.payment.wechat.notification.domain.NotificationHandLog;
import com.*.payment.wechat.notification.service.base.NotificationHandLogService;
import com.ruoyi.common.exception.GlobalException;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.RequestParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * NotificationHandler
 *
 * @author SERVER-ZJ
 * @since 2023/11/22 19:29
 */
@Slf4j
@Component
public class NotificationHandler {

    @Autowired
    private NotificationHandLogService handLogService;

    /**
     * 处理请求参数
     *
     * @param request http请求信息
     */
    public void hand(HttpServletRequest request) {
        RequestParam requestParam = getRequestParamFromRequest(request);
        // 初始化 NotificationParser
        Parser notificationParser
                = new Parser((NotificationConfig) ConfProvider.getRSAAutoCertificateConfig());
        // 获取消息通知实体信息
        Notification notification
                = notificationParser.getNotificationFromRequestParam(requestParam);
        log.info(notification.toString());
        String eventType = notification.getEventType();
        ProcessorEnum processorEnum = ProcessorEnum.getByEventTypeCode(eventType);
        boolean handedFlag = false;
        Object decryptObj = null;
        if (processorEnum != null) {
            // springboot容器中根据接口获取接口实现类bean集合
            Map<String, ?> processorBeanMap =
                    SpringUtil.getBeansOfType(processorEnum.getClazz());
            if (processorBeanMap != null && !processorBeanMap.isEmpty()) {
                Object processorBeanObj;
                Processor processorBean;
                handedFlag = true;
                // 后置处理
                for (Map.Entry<String, ?> processorBeanMapEntry : processorBeanMap.entrySet()) {
                    // 调用bean的process方法,无须指定业务处理类
                    processorBeanObj = processorBeanMapEntry.getValue();
                    if (processorBeanObj instanceof Processor) {
                        processorBean = (Processor) processorBeanObj;
                        decryptObj = processorBean.process(notification, notificationParser);
                    }
                }
            } else {
                log.warn("无对应处理业务");
            }
        } else {
            log.warn("没有对应处理器");
        }
        // 处理日志记录
        NotificationHandLog notificationHandLogDo
                = new NotificationHandLog(eventType, notification.toString(), (handedFlag ? 1 : 0), String.valueOf(decryptObj));
        handLogService.save(notificationHandLogDo);
        if (!handedFlag) {
            throw new GlobalException("处理失败");
        }
    }

    /**
     * 从请求中获取参数信息
     *
     * @param request 请求信息
     * @return 参数信息
     */
    private RequestParam getRequestParamFromRequest(HttpServletRequest request) {
        //从请求头获取验签字段
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        String wechatPayNonce = request.getHeader("Wechatpay-Nonce");
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");

        String requestBody = ServletUtil.getBody(request);

        // 构造 RequestParam
        return new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatPayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(requestBody)
                .build();
    }
}

后置处理器 Processor.java


import com.*.payment.wechat.notification.common.parser.Parser;
import com.wechat.pay.java.core.notification.Notification;

/**
 * Processor
 * 后置处理器
 *
 * @author SERVER-ZJ
 * @since 2023/11/22 18:06
 */
public interface Processor {

    /**
     * 处理信息
     *
     * @param notification 处理信息
     */
    Object process(Notification notification, Parser parser);
}

支付成功处理接口 TransactionSuccessProcessor.java

import com.hhkj.payment.wechat.notification.common.parser.Parser;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.service.payments.model.Transaction;

/**
 * TransactionSuccessProcessor
 *
 * @author SERVER-ZJ
 * @since 2023/11/22 20:37
 */
public interface TransactionSuccessProcessor extends Processor {

    /**
     * 处理对应数据
     *
     * @param notification 处理信息
     */
    default Object process(Notification notification, Parser parser) {
        Transaction transaction = parser.getDecryptObject(notification, Transaction.class);
        process(transaction);
        return transaction;
    }

    /**
     * 处理转账信息
     *
     * @param transaction 信息
     */
    void process(Transaction transaction);
}

退款成功处理接口 RefundSuccessProcessor.java

import com.hhkj.payment.wechat.notification.common.parser.Parser;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.service.refund.model.RefundNotification;

/**
 * RefundSuccessProcessor
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/11/22 20:49
 */
public interface RefundSuccessProcessor extends Processor {

    /**
     * 处理对应数据
     *
     * @param notification 处理信息
     */
    default Object process(Notification notification, Parser parser) {
        RefundNotification refundNotification = parser.getDecryptObject(notification, RefundNotification.class);
        process(refundNotification);
        return refundNotification;
    }

    /**
     * 处理退款信息
     *
     * @param refundNotification 信息
     */
    void process(RefundNotification refundNotification);
}
import com.*.payment.wechat.notification.common.processor.RefundSuccessProcessor;
import com.*.payment.wechat.notification.common.processor.TransactionSuccessProcessor;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * ProcessorEnum
 *
 * @author zheng
 * @since 2023/11/22 21:43
 */
@Getter
@AllArgsConstructor
public enum ProcessorEnum {
    REFUND_SUCCESS("REFUND.SUCCESS", RefundSuccessProcessor.class),
    TRANSACTION_SUCCESS("TRANSACTION.SUCCESS", TransactionSuccessProcessor.class),
    ;

    /** 事件类型编码 */
    private final String eventTypeCode;

    /** 类型信息 */
    private final Class<?> clazz;

    public static ProcessorEnum getByEventTypeCode(String eventTypeCode) {
        for (ProcessorEnum processorEnum : values()) {
            if (processorEnum.getEventTypeCode().equals(eventTypeCode)) {
                return processorEnum;
            }
        }
        return null;
    }
}

退款成功实现类距离 ApiOrderWechatPayRefundSuccessProcessor.java

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.*.admin.order.domain.OrderRefund;
import com.*.admin.order.model.req.OrderRefundReq;
import com.*.admin.order.service.base.OrderRefundService;
import com.*.admin.order.service.biz.OrderRefundBizService;
import com.*.admin.order.service.extend.OrderRefundExtendService;
import com.*.payment.wechat.notification.common.processor.RefundSuccessProcessor;
import com.ruoyi.common.exception.GlobalException;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * ApiOrderWechatPayRefundSuccessProcessor
 *
 * @author zheng
 * @since 2023/11/22 22:51
 */
@Slf4j
@Component
public class ApiOrderWechatPayRefundSuccessProcessor implements RefundSuccessProcessor {

    @Autowired
    private OrderRefundExtendService orderRefundExtendService;
    @Autowired
    private OrderRefundService orderRefundService;
    @Autowired
    private OrderRefundBizService orderRefundBizService;

    @Override
    public void process(RefundNotification refundNotification) {
        if (ObjectUtil.isEmpty(refundNotification)) {
            throw new GlobalException("信息读取失败!");
        }
        log.info(refundNotification.toString());
        OrderRefund refundPo
                = orderRefundExtendService.getByNum(refundNotification.getOutRefundNo());
        if (ObjectUtil.isEmpty(refundPo)) {
            throw new GlobalException("退款信息不存在!");
        }
        OrderRefundReq orderRefundReq = new OrderRefundReq();
        orderRefundReq.setOrderId(refundPo.getOrderId());
        orderRefundReq.setFinalPrice(refundPo.getPrice());
        orderRefundReq.setPayoutDate(DateUtil.parse(refundNotification.getSuccessTime()));
        orderRefundBizService.payout(orderRefundReq, refundPo.getCreateBy());
    }
}

简单看一下入口之间的代码

import com.*.payment.wechat.notification.model.res.NotificationRes;
import com.*.payment.wechat.notification.service.biz.NotificationBizService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * WechatPayNotificationController
 * 微信通知回调前端
 *
 * @author SERVER-ZJ
 * @since 2023/11/22 18:08
 */
@RestController
@RequestMapping("/open/wechat/pay/notification")
public class WechatPayNotificationController {

    @Autowired
    private NotificationBizService notificationBizService;

    /** 接收回调 */
    @PostMapping("/receive")
    public NotificationRes receive(HttpServletRequest request) {
        return notificationBizService.receive(request);
    }

}
import com.*.payment.wechat.notification.common.cont.ResEnum;
import com.*.payment.wechat.notification.common.handler.NotificationHandler;
import com.*.payment.wechat.notification.model.res.NotificationRes;
import com.*.payment.wechat.notification.service.biz.NotificationBizService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * WechatPayNotificationBizServiceImpl
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/11/22 19:25
 */
@Slf4j
@Service
public class NotificationBizServiceImpl implements NotificationBizService {

    @Autowired
    private NotificationHandler notificationHandler;

    @Override
    public NotificationRes receive(HttpServletRequest request) {
        try {
            notificationHandler.hand(request);
        } catch (Exception e) {
            log.error("微信通知接受数据处理失败,{" + e.getMessage() + "}");
            return ResEnum.FAIL.getRes();
        }
        return ResEnum.SUCCESS.getRes();
    }
}
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值