完成 pingxx 支付回调接口
This commit is contained in:
@@ -14,18 +14,6 @@ import java.util.List;
|
||||
|
||||
public interface PayTransactionService {
|
||||
|
||||
/**
|
||||
* 更新交易支付成功
|
||||
*
|
||||
* 该接口用于不同支付平台,支付成功后,回调该接口
|
||||
*
|
||||
* @param payChannel 支付渠道
|
||||
* @param params 回调参数。
|
||||
* 因为不同平台,能够提供的参数不同,所以使用 String 类型统一接收,然后在使用不同的 AbstractPaySDK 进行处理。
|
||||
* @return 是否支付成功
|
||||
*/
|
||||
Boolean updateTransactionPaySuccess(Integer payChannel, String params);
|
||||
|
||||
List<PayTransactionBO> getTransactionList(Collection<Integer> ids);
|
||||
|
||||
PayTransactionPageBO getTransactionPage(PayTransactionPageDTO payTransactionPageDTO);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package cn.iocoder.mall.pay.api.constant;
|
||||
|
||||
/**
|
||||
* 支付通知类型
|
||||
*/
|
||||
public enum PayNotifyType {
|
||||
|
||||
TRANSACTION(1, "支付"),
|
||||
REFUND(2, "退款"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private Integer value;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
|
||||
PayNotifyType(Integer value, String name) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public PayNotifyType setValue(Integer value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public PayNotifyType setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package cn.iocoder.mall.pay.api.constant;
|
||||
|
||||
/**
|
||||
* 支付交易通知状态枚举
|
||||
*/
|
||||
public enum PayTransactionNotifyStatusEnum {
|
||||
|
||||
WAITING(1, "等待通知"),
|
||||
SUCCESS(2, "通知成功"),
|
||||
FAILURE(3, "通知失败"), // 多次尝试,彻底失败
|
||||
REQUEST_SUCCESS(4, "请求成功,但是结果失败"),
|
||||
REQUEST_FAILURE(5, "请求失败"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer value;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
|
||||
PayTransactionNotifyStatusEnum(Integer value, String name) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package cn.iocoder.mall.pay.api.message;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AbstractPayNotifySuccessMessage {
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 当前通知次数
|
||||
*/
|
||||
private Integer notifyTimes;
|
||||
/**
|
||||
* 通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package cn.iocoder.mall.pay.api.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付退款成功的消息对象
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayRefundSuccessMessage extends AbstractPayNotifySuccessMessage {
|
||||
|
||||
public static final String TOPIC = "PAY_REFUND_SUCCESS";
|
||||
|
||||
/**
|
||||
* 退款单编号
|
||||
*/
|
||||
private Integer refundId;
|
||||
/**
|
||||
* 交易编号
|
||||
*/
|
||||
private Integer transactionId;
|
||||
/**
|
||||
* 应用订单编号
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package cn.iocoder.mall.pay.api.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付交易单支付成功的消息对象
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionSuccessMessage extends AbstractPayNotifySuccessMessage {
|
||||
|
||||
public static final String TOPIC = "PAY_TRANSACTION_SUCCESS";
|
||||
|
||||
/**
|
||||
* 交易编号
|
||||
*/
|
||||
private Integer transactionId;
|
||||
/**
|
||||
* 应用订单编号
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package cn.iocoder.mall.pay.application.controller.users;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.constant.PayChannelEnum;
|
||||
import org.apache.dubbo.config.annotation.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
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;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("users/refund") // TODO 芋艿,理论来说,是用户无关的。这里先酱紫先~
|
||||
public class UsersPayRefundController {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Reference(validation = "true", version = "${dubbo.provider.PayRefundService.version}")
|
||||
private PayRefundService payRefundService;
|
||||
|
||||
@PostMapping(value = "pingxx_refund_success", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public String pingxxRefundSuccess(HttpServletRequest request) throws IOException {
|
||||
logger.info("[pingxxRefundSuccess][被回调]");
|
||||
// 读取 webhook
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader reader = request.getReader()) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
CommonResult<Boolean> result = payRefundService.updateRefundSuccess(PayChannelEnum.PINGXX.getId(), sb.toString());
|
||||
if (result.isError()) {
|
||||
logger.error("[pingxxRefundSuccess][message({}) result({})]", sb, result);
|
||||
return "failure";
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage;
|
||||
import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface PayNotifyConvert {
|
||||
|
||||
PayNotifyConvert INSTANCE = Mappers.getMapper(PayNotifyConvert.class);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "transaction.transactionId", target = "transactionId"),
|
||||
@Mapping(source = "transaction.orderId", target = "orderId"),
|
||||
})
|
||||
PayTransactionSuccessMessage convertTransaction(PayNotifyTaskDO payTransactionNotifyTaskDO);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "refund.transactionId", target = "transactionId"),
|
||||
@Mapping(source = "refund.orderId", target = "orderId"),
|
||||
@Mapping(source = "refund.refundId", target = "refundId"),
|
||||
})
|
||||
PayRefundSuccessMessage convertRefund(PayNotifyTaskDO payTransactionNotifyTaskDO);
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.dao;
|
||||
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayNotifyLogDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PayNotifyLogMapper {
|
||||
|
||||
void insert(PayNotifyLogDO entity);
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.dao;
|
||||
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface PayNotifyTaskMapper {
|
||||
|
||||
void insert(PayNotifyTaskDO entity);
|
||||
|
||||
int update(PayNotifyTaskDO entity);
|
||||
|
||||
/**
|
||||
* 获得需要通知的 PayTransactionNotifyTaskDO 记录。需要满足如下条件:
|
||||
*
|
||||
* 1. status 非成功
|
||||
* 2. nextNotifyTime 小于当前时间
|
||||
* 3. lastExecuteTime > nextNotifyTime
|
||||
*
|
||||
* @return PayTransactionNotifyTaskDO 数组
|
||||
*/
|
||||
List<PayNotifyTaskDO> selectByNotify();
|
||||
|
||||
}
|
||||
@@ -11,9 +11,6 @@ import java.util.List;
|
||||
@Repository
|
||||
public interface PayTransactionMapper {
|
||||
|
||||
int update(@Param("entity") PayTransactionDO entity,
|
||||
@Param("whereStatus") Integer whereStatus);
|
||||
|
||||
int updateForRefundTotal(@Param("id") Integer id,
|
||||
@Param("refundTotalIncr") Integer refundTotalIncr);
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.dataobject;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 交易日志 DO
|
||||
*
|
||||
* 通过该日志,我们可以追溯整个执行过程
|
||||
*
|
||||
* TODO 芋艿,后面在捉摸
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayLogDO {
|
||||
|
||||
/**
|
||||
* 编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 业务线订单编号
|
||||
*/
|
||||
private Integer orderId;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付通知 App 的日志 DO
|
||||
*
|
||||
* 通过该表,记录通知 App 时,产生的日志
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayNotifyLogDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 日志编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 通知编号
|
||||
*/
|
||||
private Integer notifyId;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private String request;
|
||||
/**
|
||||
* 响应结果
|
||||
*/
|
||||
private String response;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* @see cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.dataobject;
|
||||
|
||||
import cn.iocoder.common.framework.dataobject.DeletableDO;
|
||||
import cn.iocoder.mall.pay.biz.service.PayTransactionServiceImpl;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付通知 App 的任务 DO
|
||||
*
|
||||
* 目前包括支付通知、退款通知。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayNotifyTaskDO extends DeletableDO {
|
||||
|
||||
/**
|
||||
* 通知频率,单位为秒。
|
||||
*
|
||||
* 算上首次的通知,实际是一共 1 + 8 = 9 次。
|
||||
*/
|
||||
public static final Integer[] NOTIFY_FREQUENCY = new Integer[]{
|
||||
15, 15, 30, 180,
|
||||
1800, 1800, 1800, 3600
|
||||
};
|
||||
|
||||
/**
|
||||
* 编号,自增
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* 类型
|
||||
*
|
||||
* @see cn.iocoder.mall.pay.api.constant.PayNotifyType
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 通知状态
|
||||
*
|
||||
* @see cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 下一次通知时间
|
||||
*/
|
||||
private Date nextNotifyTime;
|
||||
/**
|
||||
* 最后一次执行时间
|
||||
*
|
||||
* 这个字段,需要结合 {@link #nextNotifyTime} 一起使用。
|
||||
*
|
||||
* 1. 初始时,{@link PayTransactionServiceImpl#updateTransactionPaySuccess(Integer, String)}
|
||||
* nextNotifyTime 为当前时间 + 15 秒
|
||||
* lastExecuteTime 为空
|
||||
* 并发送给 MQ ,执行执行
|
||||
*
|
||||
* 2. MQ 消费时,更新 lastExecuteTime 为当时时间
|
||||
*
|
||||
* 3. 定时任务,扫描 nextNotifyTime < lastExecuteTime 的任务
|
||||
* nextNotifyTime 为当前时间 + N 秒。具体的 N ,由第几次通知决定
|
||||
* lastExecuteTime 为当前时间
|
||||
*/
|
||||
private Date lastExecuteTime;
|
||||
/**
|
||||
* 当前通知次数
|
||||
*/
|
||||
private Integer notifyTimes;
|
||||
/**
|
||||
* 最大可通知次数
|
||||
*/
|
||||
private Integer maxNotifyTimes;
|
||||
/**
|
||||
* 通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
// TODO 芋艿,未来把 transaction 和 refund 优化成一个字段。现在为了方便。
|
||||
/**
|
||||
* 支付数据
|
||||
*/
|
||||
private Transaction transaction;
|
||||
/**
|
||||
* 退款数据
|
||||
*/
|
||||
private Refund refund;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Transaction {
|
||||
|
||||
/**
|
||||
* 应用订单编号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 交易编号
|
||||
*
|
||||
* {@link PayTransactionDO#getId()}
|
||||
*/
|
||||
private Integer transactionId;
|
||||
/**
|
||||
* 交易拓展编号
|
||||
*
|
||||
* {@link PayTransactionExtensionDO#getId()}
|
||||
*/
|
||||
private Integer transactionExtensionId;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Refund {
|
||||
|
||||
/**
|
||||
* 应用订单编号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 交易编号
|
||||
*
|
||||
* {@link PayTransactionDO#getId()}
|
||||
*/
|
||||
private Integer transactionId;
|
||||
/**
|
||||
* 退款单编号
|
||||
*/
|
||||
private Integer refundId;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.common.framework.util.DateUtil;
|
||||
import cn.iocoder.mall.pay.api.constant.PayNotifyType;
|
||||
import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum;
|
||||
import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage;
|
||||
import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage;
|
||||
import cn.iocoder.mall.pay.biz.convert.PayNotifyConvert;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Calendar;
|
||||
|
||||
@Service
|
||||
public class PayNotifyServiceImpl {
|
||||
|
||||
@Autowired
|
||||
private PayNotifyTaskMapper payTransactionNotifyTaskMapper;
|
||||
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Deprecated // 参见 PayRefundSuccessConsumer 类的说明
|
||||
public void addRefundNotifyTask(PayRefundDO refund) {
|
||||
PayNotifyTaskDO payTransactionNotifyTask = this.createBasePayNotifyTaskDO(refund.getAppId(), refund.getNotifyUrl())
|
||||
.setType(PayNotifyType.REFUND.getValue());
|
||||
// 设置 Refund 属性
|
||||
payTransactionNotifyTask.setRefund(new PayNotifyTaskDO.Refund().setRefundId(refund.getId())
|
||||
.setTransactionId(refund.getTransactionId()).setOrderId(refund.getOrderId()));
|
||||
// 保存到数据库
|
||||
payTransactionNotifyTaskMapper.insert(payTransactionNotifyTask);
|
||||
// 发送 MQ 消息
|
||||
sendNotifyMessage(payTransactionNotifyTask);
|
||||
}
|
||||
|
||||
public void addTransactionNotifyTask(PayTransactionDO transaction, PayTransactionExtensionDO extension) {
|
||||
PayNotifyTaskDO payTransactionNotifyTask = this.createBasePayNotifyTaskDO(transaction.getAppId(), transaction.getNotifyUrl())
|
||||
.setType(PayNotifyType.TRANSACTION.getValue());
|
||||
// 设置 Transaction 属性
|
||||
payTransactionNotifyTask.setTransaction(new PayNotifyTaskDO.Transaction().setOrderId(transaction.getOrderId())
|
||||
.setTransactionId(extension.getTransactionId()).setTransactionExtensionId(extension.getId()));
|
||||
payTransactionNotifyTaskMapper.insert(payTransactionNotifyTask);
|
||||
// 3.2 发送 MQ
|
||||
sendNotifyMessage(payTransactionNotifyTask);
|
||||
}
|
||||
|
||||
private PayNotifyTaskDO createBasePayNotifyTaskDO(String appId, String notifyUrl) {
|
||||
return new PayNotifyTaskDO()
|
||||
.setAppId(appId)
|
||||
.setStatus(PayTransactionNotifyStatusEnum.WAITING.getValue())
|
||||
.setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1)
|
||||
.setNextNotifyTime(DateUtil.addDate(Calendar.SECOND, PayNotifyTaskDO.NOTIFY_FREQUENCY[0]))
|
||||
.setNotifyUrl(notifyUrl);
|
||||
}
|
||||
|
||||
public void sendNotifyMessage(PayNotifyTaskDO notifyTask) {
|
||||
if (PayNotifyType.TRANSACTION.getValue().equals(notifyTask.getType())) {
|
||||
rocketMQTemplate.convertAndSend(PayTransactionSuccessMessage.TOPIC,
|
||||
PayNotifyConvert.INSTANCE.convertTransaction(notifyTask));
|
||||
} else if (PayNotifyType.REFUND.getValue().equals(notifyTask.getType())) {
|
||||
rocketMQTemplate.convertAndSend(PayRefundSuccessMessage.TOPIC,
|
||||
PayNotifyConvert.INSTANCE.convertRefund(notifyTask));
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("通知任务(%s) 无法发送通知消息", notifyTask.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,63 +50,6 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
return payTransactionExtensionMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean updateTransactionPaySuccess(Integer payChannel, String params) {
|
||||
// TODO 芋艿,记录回调日志
|
||||
// 解析传入的参数,成 TransactionSuccessBO 对象
|
||||
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payChannel);
|
||||
CommonResult<TransactionSuccessBO> paySuccessResult = paySDK.parseTransactionSuccessParams(params);
|
||||
if (paySuccessResult.isError()) {
|
||||
throw ServiceExceptionUtil.exception(paySuccessResult.getCode(), paySuccessResult.getMessage());
|
||||
}
|
||||
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
|
||||
// 1.1 查询 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO extension = payTransactionExtensionMapper.selectByTransactionCode(paySuccessResult.getData().getTransactionCode());
|
||||
if (extension == null) {
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(extension.getStatus())) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 1.2 更新 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO updatePayTransactionExtension = new PayTransactionExtensionDO()
|
||||
.setId(extension.getId())
|
||||
.setStatus(PayTransactionStatusEnum.SUCCESS.getValue())
|
||||
.setExtensionData(params);
|
||||
int updateCounts = payTransactionExtensionMapper.update(updatePayTransactionExtension, PayTransactionStatusEnum.WAITING.getValue());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
logger.info("[updateTransactionPaySuccess][PayTransactionExtensionDO({}) 更新为已支付]", extension.getId());
|
||||
// 2.1 判断 PayTransactionDO 是否处于待支付
|
||||
PayTransactionDO transaction = payTransactionMapper.selectById(extension.getTransactionId());
|
||||
if (transaction == null) {
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(transaction.getStatus())) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 2.2 更新 PayTransactionDO
|
||||
PayTransactionDO updatePayTransaction = new PayTransactionDO()
|
||||
.setId(transaction.getId())
|
||||
.setStatus(PayTransactionStatusEnum.SUCCESS.getValue())
|
||||
.setExtensionId(extension.getId())
|
||||
.setPayChannel(payChannel)
|
||||
.setPaymentTime(paySuccessResult.getData().getPaymentTime())
|
||||
.setNotifyTime(new Date())
|
||||
.setTradeNo(paySuccessResult.getData().getTradeNo());
|
||||
updateCounts = payTransactionMapper.update(updatePayTransaction, PayTransactionStatusEnum.WAITING.getValue());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付 TODO 这种类型,需要思考下。需要返回错误,但是又要保证事务回滚
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
logger.info("[updateTransactionPaySuccess][PayTransactionDO({}) 更新为已支付]", transaction.getId());
|
||||
// 3 新增 PayNotifyTaskDO 注释原因,参见 PayRefundSuccessConsumer 类。
|
||||
// payNotifyService.addTransactionNotifyTask(transaction, extension);
|
||||
// 返回结果
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PayTransactionBO> getTransactionList(Collection<Integer> ids) {
|
||||
return PayTransactionConvert.INSTANCE.convertList(payTransactionMapper.selectListByIds(ids));
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.mall.pay.biz.dao.PayNotifyLogMapper">
|
||||
|
||||
<!--<sql id="FIELDS">-->
|
||||
<!--id, transaction_id, transaction_extension_id, app_id, order_id,-->
|
||||
<!--status, next_notify_time, last_execute_time, notify_times, max_notify_times,-->
|
||||
<!--create_time-->
|
||||
<!--</sql>-->
|
||||
|
||||
<insert id="insert" parameterType="PayNotifyLogDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||
INSERT INTO notify_log (
|
||||
notify_id, request, response, status
|
||||
) VALUES (
|
||||
#{notifyId}, #{request}, #{response}, #{status}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!--<update id="update" parameterType="PayTransactionNotifyTaskDO">-->
|
||||
<!--UPDATE transaction_notify_task-->
|
||||
<!--<set>-->
|
||||
<!--<if test="status != null">-->
|
||||
<!--, status = #{status}-->
|
||||
<!--</if>-->
|
||||
<!--<if test="nextNotifyTime != null">-->
|
||||
<!--, last_notify_time = #{nextNotifyTime}-->
|
||||
<!--</if>-->
|
||||
<!--<if test="lastExecuteTime != null">-->
|
||||
<!--, last_execute_time = #{lastExecuteTime}-->
|
||||
<!--</if>-->
|
||||
<!--<if test="notifyTimes != null">-->
|
||||
<!--, notify_times = #{notifyTimes}-->
|
||||
<!--</if>-->
|
||||
<!--</set>-->
|
||||
<!--WHERE id = #{id}-->
|
||||
<!--</update>-->
|
||||
|
||||
<!--<select id="selectByTransactionCode" parameterType="String" resultType="PayTransactionExtensionDO">-->
|
||||
<!--SELECT-->
|
||||
<!--<include refid="FIELDS"/>-->
|
||||
<!--FROM transaction_extension-->
|
||||
<!--WHERE transaction_code = #{transactionCode}-->
|
||||
<!--LIMIT 1-->
|
||||
<!--</select>-->
|
||||
|
||||
</mapper>
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper">
|
||||
|
||||
<sql id="FIELDS">
|
||||
id, app_id, type,
|
||||
status, next_notify_time, last_execute_time, notify_times, max_notify_times,
|
||||
create_time
|
||||
</sql>
|
||||
|
||||
<resultMap id="PayNotifyTaskResultMap" type="PayNotifyTaskDO">
|
||||
<result property="transaction" column="transaction"
|
||||
javaType="cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO$Transaction"
|
||||
typeHandler="cn.iocoder.mall.mybatis.core.type.JSONTypeHandler"/>
|
||||
<result property="refund" column="refund"
|
||||
javaType="cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO$Refund"
|
||||
typeHandler="cn.iocoder.mall.mybatis.core.type.JSONTypeHandler"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insert" parameterType="PayNotifyTaskDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||
INSERT INTO notify_task (
|
||||
app_id, type,
|
||||
status, next_notify_time, notify_times, max_notify_times,
|
||||
`transaction`, refund
|
||||
) VALUES (
|
||||
#{appId}, #{type},
|
||||
#{status}, #{nextNotifyTime}, #{notifyTimes}, #{maxNotifyTimes},
|
||||
#{transaction, typeHandler=cn.iocoder.common.framework.mybatis.JSONTypeHandler},
|
||||
#{refund, typeHandler=cn.iocoder.common.framework.mybatis.JSONTypeHandler}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="update" parameterType="PayNotifyTaskDO">
|
||||
UPDATE notify_task
|
||||
<set>
|
||||
<if test="status != null">
|
||||
, status = #{status}
|
||||
</if>
|
||||
<if test="nextNotifyTime != null">
|
||||
, next_notify_time = #{nextNotifyTime}
|
||||
</if>
|
||||
<if test="lastExecuteTime != null">
|
||||
, last_execute_time = #{lastExecuteTime}
|
||||
</if>
|
||||
<if test="notifyTimes != null">
|
||||
, notify_times = #{notifyTimes}
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<select id="selectByNotify" resultMap="PayNotifyTaskResultMap">
|
||||
SELECT
|
||||
<include refid="FIELDS"/>
|
||||
FROM notify_task
|
||||
WHERE status IN (1, 4, 5)
|
||||
AND next_notify_time <![CDATA[ <= ]]> NOW()
|
||||
AND last_execute_time > next_notify_time
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -7,32 +7,6 @@
|
||||
create_ip, status, create_time
|
||||
</sql>
|
||||
|
||||
<insert id="insert" parameterType="PayTransactionExtensionDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||
INSERT INTO transaction_extension (
|
||||
transaction_id, pay_channel, transaction_code, extension_data,
|
||||
create_ip, status
|
||||
) VALUES (
|
||||
#{transactionId}, #{payChannel}, #{transactionCode}, #{extensionData},
|
||||
#{createIp}, #{status}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="update">
|
||||
UPDATE transaction_extension
|
||||
<set>
|
||||
<if test="entity.extensionData != null">
|
||||
, extension_data = #{entity.extensionData}
|
||||
</if>
|
||||
<if test="entity.status != null">
|
||||
, status = #{entity.status}
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{entity.id}
|
||||
<if test="whereStatus != null">
|
||||
AND status = #{whereStatus}
|
||||
</if>
|
||||
</update>
|
||||
|
||||
<select id="selectByTransactionCode" parameterType="String" resultType="PayTransactionExtensionDO">
|
||||
SELECT
|
||||
<include refid="FIELDS"/>
|
||||
|
||||
Reference in New Issue
Block a user