♻️ 重构代码。支付回调 代码重构

This commit is contained in:
冷冷 committed 2019-06-28 09:31:36 +08:00
1 parent 04f620dc8a
commit ff510396d3
16 files changed
+408 -167

No files matched your search

@@ -17,7 +17,7 @@ spring:
datasource:
platform: mysql
security:
enabled: false
enabled: true
server:
tomcat:
@@ -112,6 +112,7 @@ public class PayGoodsOrderController {
* @param payGoodsOrder 商品订单表
* @return
*/
@ResponseBody
@GetMapping("/page")
public R getPayGoodsOrderPage(Page page, PayGoodsOrder payGoodsOrder) {
return R.ok(payGoodsOrderService.page(page, Wrappers.query(payGoodsOrder)));
@@ -124,6 +125,7 @@ public class PayGoodsOrderController {
* @param goodsOrderId id
* @return R
*/
@ResponseBody
@GetMapping("/{goodsOrderId}")
public R getById(@PathVariable("goodsOrderId") Integer goodsOrderId) {
return R.ok(payGoodsOrderService.getById(goodsOrderId));
@@ -137,6 +139,7 @@ public class PayGoodsOrderController {
*/
@SysLog("新增商品订单表")
@PostMapping
@ResponseBody
@PreAuthorize("@pms.hasPermission('generator_paygoodsorder_add')")
public R save(@RequestBody PayGoodsOrder payGoodsOrder) {
return R.ok(payGoodsOrderService.save(payGoodsOrder));
@@ -150,6 +153,7 @@ public class PayGoodsOrderController {
*/
@SysLog("修改商品订单表")
@PutMapping
@ResponseBody
@PreAuthorize("@pms.hasPermission('generator_paygoodsorder_edit')")
public R updateById(@RequestBody PayGoodsOrder payGoodsOrder) {
return R.ok(payGoodsOrderService.updateById(payGoodsOrder));
@@ -162,6 +166,7 @@ public class PayGoodsOrderController {
* @return R
*/
@SysLog("删除商品订单表")
@ResponseBody
@DeleteMapping("/{goodsOrderId}")
@PreAuthorize("@pms.hasPermission('generator_paygoodsorder_del')")
public R removeById(@PathVariable Integer goodsOrderId) {
@@ -26,9 +26,8 @@ import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.handler.MessageDuplicateCheckerHandler;
import com.pig4cloud.pigx.pay.handler.PayNotifyCallbakHandler;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import com.pig4cloud.pigx.pay.utils.PayConstants;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
@@ -53,8 +52,9 @@ import java.util.Map;
@RequestMapping("/notify")
@Api(value = "notify", tags = "notify管理")
public class PayNotifyRecordController {
private final MessageDuplicateCheckerHandler duplicateCheckerHandler;
private final PayNotifyRecordService payNotifyRecordService;
private final PayNotifyCallbakHandler alipayCallback;
private final PayNotifyCallbakHandler weChatCallback;
/**
* 分页查询
@@ -120,7 +120,7 @@ public class PayNotifyRecordController {
}
/**
* 渠道异步回调
* 支付宝渠道异步回调
*
* @param request 渠道请求
* @return
@@ -131,36 +131,25 @@ public class PayNotifyRecordController {
public void aliCallbak(HttpServletRequest request, HttpServletResponse response) {
// 解析回调信息
Map<String, String> params = AliPayApi.toMap(request);
// 判断10秒内是否已经回调处理
if (!duplicateCheckerHandler.isDuplicate(params.get(PayConstants.OUT_TRADE_NO))) {
log.warn("支付宝订单重复回调 {} 不做处理", params);
payNotifyRecordService.saveAliRecord(params, "");
return;
}
String result = payNotifyRecordService.aliCallbak(params);
payNotifyRecordService.saveAliRecord(params, result);
//写出处理结果
response.getWriter().print(result);
alipayCallback.handle(params);
response.getWriter().print(alipayCallback.handle(params));
}
/**
* 微信渠道支付回调
*
* @param request
* @return
*/
@Inner(false)
@SneakyThrows
@ResponseBody
@PostMapping("/wx/callbak")
public String wxCallbak(HttpServletRequest request, HttpServletResponse response) {
public String wxCallbak(HttpServletRequest request) {
String xmlMsg = HttpKit.readData(request);
log.info("微信订单回调信息:{}", xmlMsg);
Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);
// 判断10秒内是否已经回调处理
if (!duplicateCheckerHandler.isDuplicate(params.get(PayConstants.OUT_TRADE_NO))) {
log.warn("微信订单重复回调 {} 不做处理", params);
payNotifyRecordService.saveAliRecord(params, "");
return null;
}
String result = payNotifyRecordService.wxCallbak(params);
payNotifyRecordService.saveAliRecord(params, result);
return result;
return weChatCallback.handle(params);
}
}
@@ -64,7 +64,7 @@ public class PayGoodsOrder extends Model<PayGoodsOrder> {
/**
* 订单状态,订单生成(0),支付成功(1),处理完成(2),处理失败(-1)
*/
private Integer status;
private String status;
/**
* 支付订单号
*/
@@ -80,11 +80,11 @@ public class PayRefundOrder extends Model<PayRefundOrder> {
/**
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败,4-业务处理完成
*/
private Integer status;
private String status;
/**
* 退款结果:0-不确认结果,1-等待手动处理,2-确认成功,3-确认失败
*/
private Integer result;
private String result;
/**
* 客户端IP
*/
@@ -61,7 +61,7 @@ public class PayTradeOrder extends Model<PayTradeOrder> {
/**
* 支付状态,0-订单生成,1-支付中(目前未使用),2-支付成功,3-业务处理完成
*/
private Integer status;
private String status;
/**
* 客户端IP
*/
@@ -138,7 +138,7 @@ public class PayTradeOrder extends Model<PayTradeOrder> {
* 删除标记
*/
@TableLogic
private String delFlaag;
private String delFlag;
/**
* 租户ID
*/
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.handler;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* @author lengleng
* @date 2019-06-27
*/
@Slf4j
public abstract class AbstractPayNotifyCallbakHandler implements PayNotifyCallbakHandler {
/**
* 调用入口
*
* @param params
* @return
*/
@Override
public String handle(Map<String, String> params) {
// 去重处理
if (duplicateChecker(params)) {
return null;
}
// 验签处理
if (!verifyNotify(params)) {
return null;
}
return parse(params);
}
}
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.handler;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.jpay.alipay.AliPayApiConfig;
import com.jpay.alipay.AliPayApiConfigKit;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import com.pig4cloud.pigx.pay.utils.PayConstants;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author lengleng
* @date 2019-06-27
* <p>
* 支付宝回调处理
*/
@Slf4j
@AllArgsConstructor
@Service("alipayCallback")
public class AlipayPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHandler {
private final MessageDuplicateCheckerHandler duplicateCheckerHandler;
private final PayTradeOrderService tradeOrderService;
private final PayGoodsOrderService goodsOrderService;
private final PayNotifyRecordService recordService;
/**
* 去重处理
*
* @param params 回调报文
* @return
*/
@Override
public Boolean duplicateChecker(Map<String, String> params) {
// 判断10秒内是否已经回调处理
if (!duplicateCheckerHandler.isDuplicate(params.get(PayConstants.OUT_TRADE_NO))) {
log.warn("支付宝订单重复回调 {} 不做处理", params);
this.saveNotifyRecord(params, "重复回调");
return true;
}
return false;
}
/**
* 验签逻辑
*
* @param params 回调报文
* @return
*/
@Override
public Boolean verifyNotify(Map<String, String> params) {
String callReq = MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED);
log.info("支付宝发起回调 报文: {}", callReq);
String appId = params.get("app_id");
if (StrUtil.isBlank(appId)) {
log.warn("支付宝回调报文 appid 为空 {}", callReq);
return false;
}
AliPayApiConfig apiConfig = AliPayApiConfigKit.getApiConfig(appId);
if (apiConfig == null) {
log.warn("支付宝回调报文 appid 不合法 {}", callReq);
return false;
}
try {
return AlipaySignature.rsaCheckV1(params, apiConfig.getAlipayPublicKey()
, CharsetUtil.UTF_8, "RSA2");
} catch (AlipayApiException e) {
log.error("支付宝验签失败", e);
return false;
}
}
/**
* 解析报文
*
* @param params 回调报文
* @return
*/
@Override
public String parse(Map<String, String> params) {
goodsOrderService.updateOrder(params);
tradeOrderService.updateOrder(params);
return "success";
}
/**
* 保存回调记录
*
* @param result 处理结果
* @param params 回调报文
*/
@Override
public void saveNotifyRecord(Map<String, String> params, String result) {
PayNotifyRecord record = new PayNotifyRecord();
String notifyId = params.get("notify_id");
record.setNotifyId(notifyId);
String orderNo = params.get("out_trade_no");
record.setOrderNo(orderNo);
record.setRequest(MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED));
record.setResponse(result);
recordService.save(record);
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.handler;
import java.util.Map;
/**
* @author lengleng
* @date 2019-06-27
* <p>
* 支付回调处理器
*/
public interface PayNotifyCallbakHandler {
/**
* 去重处理
*
* @param params 回调报文
* @return
*/
Boolean duplicateChecker(Map<String, String> params);
/**
* 验签逻辑
*
* @param params 回调报文
* @return
*/
Boolean verifyNotify(Map<String, String> params);
/**
* 解析报文
*
* @param params
* @return
*/
String parse(Map<String, String> params);
/**
* 调用入口
*
* @param params
* @return
*/
String handle(Map<String, String> params);
/**
* 保存回调记录
*
* @param result 处理结果
* @param params 回调报文
*/
void saveNotifyRecord(Map<String, String> params, String result);
}
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.pay.handler;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.jpay.ext.kit.PaymentKit;
import com.jpay.weixin.api.WxPayApiConfigKit;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import com.pig4cloud.pigx.pay.utils.PayConstants;
import com.pig4cloud.pigx.pay.utils.TradeStatusEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @author lengleng
* @date 2019-06-27
* <p>
* 微信回调处理
*/
@Slf4j
@AllArgsConstructor
@Service("weChatCallback")
public class WeChatPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHandler {
private final MessageDuplicateCheckerHandler duplicateCheckerHandler;
private final PayTradeOrderService tradeOrderService;
private final PayGoodsOrderService goodsOrderService;
private final PayNotifyRecordService recordService;
/**
* 去重处理
*
* @param params 回调报文
* @return
*/
@Override
public Boolean duplicateChecker(Map<String, String> params) {
// 判断10秒内是否已经回调处理
if (!duplicateCheckerHandler.isDuplicate(params.get(PayConstants.OUT_TRADE_NO))) {
log.warn("微信订单重复回调 {} 不做处理", params);
this.saveNotifyRecord(params, "重复回调");
return true;
}
return false;
}
/**
* 验签逻辑
*
* @param params 回调报文
* @return
*/
@Override
public Boolean verifyNotify(Map<String, String> params) {
if (!PaymentKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey())) {
log.warn("微信支付回调验签失败", params);
return null;
}
return true;
}
/**
* 解析报文
*
* @param params
* @return
*/
@Override
public String parse(Map<String, String> params) {
params.put("trade_status", TradeStatusEnum.TRADE_SUCCESS.getDescription());
goodsOrderService.updateOrder(params);
tradeOrderService.updateOrder(params);
Map<String, String> xml = new HashMap<>(4);
xml.put("return_code", "SUCCESS");
xml.put("return_msg", "OK");
return PaymentKit.toXml(xml);
}
/**
* 保存回调记录
*
* @param result 处理结果
* @param params 回调报文
*/
@Override
public void saveNotifyRecord(Map<String, String> params, String result) {
PayNotifyRecord record = new PayNotifyRecord();
String notifyId = params.get("notify_id");
record.setNotifyId(notifyId);
String orderNo = params.get("out_trade_no");
record.setOrderNo(orderNo);
record.setRequest(MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED));
record.setResponse(result);
recordService.save(record);
}
}
@@ -20,8 +20,6 @@ package com.pig4cloud.pigx.pay.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import java.util.Map;
/**
* 异步通知记录
*
@@ -30,27 +28,4 @@ import java.util.Map;
*/
public interface PayNotifyRecordService extends IService<PayNotifyRecord> {
/**
* 处理支付宝渠道回调
*
* @param params
* @return
*/
String aliCallbak(Map<String, String> params);
/**
* 保存支付宝回调结果
*
* @param params
* @param result
*/
void saveAliRecord(Map<String, String> params, String result);
/**
* 处理微信渠道回调
*
* @param params
* @return
*/
String wxCallbak(Map<String, String> params);
}
@@ -84,7 +84,7 @@ public class PayGoodsOrderServiceImpl extends ServiceImpl<PayGoodsOrderMapper, P
@Transactional(rollbackFor = Exception.class)
public void updateOrder(Map<String, String> params) {
PayGoodsOrder goodsOrder = new PayGoodsOrder();
Integer tradeStatus = EnumUtil.fromString(TradeStatusEnum.class, params.get("trade_status")).getStatus();
String tradeStatus = EnumUtil.fromString(TradeStatusEnum.class, params.get("trade_status")).getStatus();
goodsOrder.setStatus(tradeStatus);
this.baseMapper.update(goodsOrder, Wrappers.<PayGoodsOrder>lambdaQuery()
.eq(PayGoodsOrder::getPayOrderId, params.
@@ -16,30 +16,14 @@
*/
package com.pig4cloud.pigx.pay.service.impl;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jpay.alipay.AliPayApiConfig;
import com.jpay.alipay.AliPayApiConfigKit;
import com.jpay.ext.kit.PaymentKit;
import com.jpay.weixin.api.WxPayApiConfigKit;
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
import com.pig4cloud.pigx.pay.mapper.PayNotifyRecordMapper;
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
import com.pig4cloud.pigx.pay.utils.TradeStatusEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* 异步通知记录
*
@@ -50,92 +34,5 @@ import java.util.Map;
@Service
@AllArgsConstructor
public class PayNotifyRecordServiceImpl extends ServiceImpl<PayNotifyRecordMapper, PayNotifyRecord> implements PayNotifyRecordService {
private final PayTradeOrderService tradeOrderService;
private final PayGoodsOrderService goodsOrderService;
/**
* 处理微信渠道回调
*
* @param params
* @return
*/
@Override
public String wxCallbak(Map<String, String> params) {
if (!PaymentKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey())) {
log.warn("微信支付回调验签失败", params);
return null;
}
params.put("trade_status", TradeStatusEnum.TRADE_SUCCESS.getDescription());
goodsOrderService.updateOrder(params);
tradeOrderService.updateOrder(params);
Map<String, String> xml = new HashMap<>(4);
xml.put("return_code", "SUCCESS");
xml.put("return_msg", "OK");
return PaymentKit.toXml(xml);
}
/**
* 处理渠道回调
*
* @param params
* @return
*/
@Override
public String aliCallbak(Map<String, String> params) {
String callReq = MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED);
log.info("支付宝发起回调 报文: {}", callReq);
String appId = params.get("app_id");
if (StrUtil.isBlank(appId)) {
log.warn("支付宝回调报文 appid 为空 {}", callReq);
return "failure";
}
AliPayApiConfig apiConfig = AliPayApiConfigKit.getApiConfig(appId);
if (apiConfig == null) {
log.warn("支付宝回调报文 appid 不合法 {}", callReq);
return "failure";
}
boolean verifyResult;
try {
verifyResult = AlipaySignature.rsaCheckV1(params, apiConfig.getAlipayPublicKey(), CharsetUtil.UTF_8,
"RSA2");
} catch (AlipayApiException e) {
log.warn("验签异常 {} {}", e.getErrCode(), e.getErrMsg());
return "failure";
}
if (!verifyResult) {
log.warn("支付宝回调验签:{}", MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED));
return "failure";
}
goodsOrderService.updateOrder(params);
tradeOrderService.updateOrder(params);
return "success";
}
/**
* 保存支付宝回调结果
*
* @param params
* @param result
*/
@Async
@Override
public void saveAliRecord(Map<String, String> params, String result) {
PayNotifyRecord record = new PayNotifyRecord();
String notifyId = params.get("notify_id");
record.setNotifyId(notifyId);
String orderNo = params.get("out_trade_no");
record.setOrderNo(orderNo);
record.setRequest(MapUtil.join(params, StrUtil.DASHED, StrUtil.DASHED));
record.setResponse(result);
this.baseMapper.insert(record);
}
}
@@ -15,28 +15,28 @@ public enum OrderStatusEnum {
/**
* 订单初始 下单
*/
INIT(0, "下单"),
INIT("0", "下单"),
/**
* 订单支付成功
*/
SUCCESS(1, "成功"),
SUCCESS("1", "成功"),
/**
* 订单支付完成
*/
COMPLETE(2, "完成"),
COMPLETE("2", "完成"),
/**
* 订单支付失败
*/
FAIL(-1, "失败");
FAIL("-1", "失败");
/**
* 状态
*/
private Integer status;
private String status;
/**
* 描述
*/
@@ -38,5 +38,5 @@ public enum TradeStatusEnum {
/**
* 描述
*/
private Integer status;
private String status;
}
@@ -47,7 +47,7 @@
<result property="paySuccTime" column="pay_succ_time"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlaag" column="del_flaag"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>