微信支付回调信息接收设计
如图所示,在接收到微信支付平台推送信息后对数据进行解析处理,根据类型不同解析到不同的处理器中,灵活运用springboot对组件的代理控制。实际上根据业务需求,代码中间抛出的异常可以设计一个微信支付异常类,在异常捕获的时候进行接口特殊处理。退款成功处理接口 RefundSuccessProcessor.java。
·
策略模式 + 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();
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)