|
@@ -421,8 +421,10 @@ public class AlipayBatchPayService {
|
|
|
.eq(BatchOrderEntity::getOutBatchNo, outBatchNo)
|
|
.eq(BatchOrderEntity::getOutBatchNo, outBatchNo)
|
|
|
.eq(BatchOrderEntity::getEnterpriseId, enterpriseId));
|
|
.eq(BatchOrderEntity::getEnterpriseId, enterpriseId));
|
|
|
if (order == null) throw new BusinessException(404, "批次不存在");
|
|
if (order == null) throw new BusinessException(404, "批次不存在");
|
|
|
- if (!"INIT".equals(order.getStatus()))
|
|
|
|
|
- throw new BusinessException(400, "仅受理中的批次可支付,当前状态: " + order.getStatus());
|
|
|
|
|
|
|
+ // INIT=已受理 / WAIT_PAY=等待支付(render 过支付链接但未支付)均可生成(或重新生成)支付链接——
|
|
|
|
|
+ // 用户实测: 本地被定时同步成 WAIT_PAY 后无法二次发起支付
|
|
|
|
|
+ if (!"INIT".equals(order.getStatus()) && !"WAIT_PAY".equals(order.getStatus()))
|
|
|
|
|
+ throw new BusinessException(400, "仅受理中/等待支付的批次可支付,当前状态: " + order.getStatus());
|
|
|
try {
|
|
try {
|
|
|
AlipayFundTransRenderPayModel model = new AlipayFundTransRenderPayModel();
|
|
AlipayFundTransRenderPayModel model = new AlipayFundTransRenderPayModel();
|
|
|
model.setProductCode(BATCH_PRODUCT_CODE);
|
|
model.setProductCode(BATCH_PRODUCT_CODE);
|
|
@@ -518,9 +520,9 @@ public class AlipayBatchPayService {
|
|
|
.eq(BatchOrderEntity::getOutBatchNo, outBatchNo)
|
|
.eq(BatchOrderEntity::getOutBatchNo, outBatchNo)
|
|
|
.eq(BatchOrderEntity::getEnterpriseId, enterpriseId));
|
|
.eq(BatchOrderEntity::getEnterpriseId, enterpriseId));
|
|
|
if (order == null) throw new BusinessException(404, "批次不存在");
|
|
if (order == null) throw new BusinessException(404, "批次不存在");
|
|
|
- // 与 renderPay 一致的前置守卫: 仅 INIT 状态可关闭(提前给友好提示而非透传支付宝原文案)
|
|
|
|
|
- if (!"INIT".equals(order.getStatus()))
|
|
|
|
|
- throw new BusinessException(400, "仅 INIT 状态的批次可关闭");
|
|
|
|
|
|
|
+ // INIT=已受理 / WAIT_PAY=等待支付(未支付)均可关闭——用户实测: 本地被定时同步成 WAIT_PAY 后关闭按钮直接消失
|
|
|
|
|
+ if (!"INIT".equals(order.getStatus()) && !"WAIT_PAY".equals(order.getStatus()))
|
|
|
|
|
+ throw new BusinessException(400, "仅受理中/等待支付的批次可关闭,当前状态: " + order.getStatus());
|
|
|
try {
|
|
try {
|
|
|
AlipayFundBatchCloseModel model = new AlipayFundBatchCloseModel();
|
|
AlipayFundBatchCloseModel model = new AlipayFundBatchCloseModel();
|
|
|
model.setBatchTransId(order.getBatchTransId());
|
|
model.setBatchTransId(order.getBatchTransId());
|
|
@@ -530,8 +532,12 @@ public class AlipayBatchPayService {
|
|
|
request.setBizModel(model);
|
|
request.setBizModel(model);
|
|
|
AlipayFundBatchCloseResponse response =
|
|
AlipayFundBatchCloseResponse response =
|
|
|
alipayClientFactory.getClient(enterpriseId, BIZ_TYPE).certificateExecute(request);
|
|
alipayClientFactory.getClient(enterpriseId, BIZ_TYPE).certificateExecute(request);
|
|
|
- if (!response.isSuccess())
|
|
|
|
|
- throw new BusinessException(400, "关闭批次失败: " + response.getMsg());
|
|
|
|
|
|
|
+ if (!response.isSuccess()) {
|
|
|
|
|
+ // 关闭失败多为支付宝侧批次已不可关闭(如 INVALID 明细全部无效)——回写真实状态,
|
|
|
|
|
+ // 避免本地残留 INIT 让用户反复点关闭(用户实测: BATCH_ORDER_STATUS_INVALID)
|
|
|
|
|
+ syncBatchStatusFromAlipay(order, enterpriseId);
|
|
|
|
|
+ throw new BusinessException(400, "关闭批次失败: " + response.getMsg() + " (" + response.getSubCode() + ")");
|
|
|
|
|
+ }
|
|
|
order.setStatus("DISUSE");
|
|
order.setStatus("DISUSE");
|
|
|
batchOrderMapper.updateById(order);
|
|
batchOrderMapper.updateById(order);
|
|
|
return Map.of("status", "DISUSE");
|
|
return Map.of("status", "DISUSE");
|
|
@@ -540,6 +546,27 @@ public class AlipayBatchPayService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /** 关闭失败后回写支付宝侧真实批次状态(detail.query),失败静默(不掩盖关闭错误本身) */
|
|
|
|
|
+ private void syncBatchStatusFromAlipay(BatchOrderEntity order, String enterpriseId) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ AlipayFundBatchDetailQueryModel model = new AlipayFundBatchDetailQueryModel();
|
|
|
|
|
+ model.setOutBatchNo(order.getOutBatchNo());
|
|
|
|
|
+ model.setProductCode(BATCH_PRODUCT_CODE);
|
|
|
|
|
+ model.setBizScene(BATCH_BIZ_SCENE);
|
|
|
|
|
+ AlipayFundBatchDetailQueryRequest request = new AlipayFundBatchDetailQueryRequest();
|
|
|
|
|
+ request.setBizModel(model);
|
|
|
|
|
+ AlipayFundBatchDetailQueryResponse response =
|
|
|
|
|
+ alipayClientFactory.getClient(enterpriseId, BIZ_TYPE).certificateExecute(request);
|
|
|
|
|
+ if (response.isSuccess() && response.getBatchStatus() != null
|
|
|
|
|
+ && !response.getBatchStatus().equals(order.getStatus())) {
|
|
|
|
|
+ order.setStatus(response.getBatchStatus());
|
|
|
|
|
+ batchOrderMapper.updateById(order);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (AlipayApiException ignored) {
|
|
|
|
|
+ // 回写失败不掩盖关闭失败本身
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// ==================== 定时状态同步(batchQuery 兜底) ====================
|
|
// ==================== 定时状态同步(batchQuery 兜底) ====================
|
|
|
|
|
|
|
|
/**
|
|
/**
|