|
@@ -30,6 +30,7 @@ public class BankingPaymentStatusScheduler {
|
|
|
|
|
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(BankingPaymentStatusScheduler.class);
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(BankingPaymentStatusScheduler.class);
|
|
|
private static final String PAYMENT_SUCCESS_STATUS = "X0000";
|
|
private static final String PAYMENT_SUCCESS_STATUS = "X0000";
|
|
|
|
|
+ private static final String YIDA_FORM_DATA_DELETED_MESSAGE = "宜搭数据不存在或已删除";
|
|
|
private static final int TRANSACTION_LOOKBACK_DAYS = 7;
|
|
private static final int TRANSACTION_LOOKBACK_DAYS = 7;
|
|
|
private static final DateTimeFormatter ACCOUNTING_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
private static final DateTimeFormatter ACCOUNTING_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
|
private static final DateTimeFormatter UPDATED_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
private static final DateTimeFormatter UPDATED_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
@@ -71,9 +72,15 @@ public class BankingPaymentStatusScheduler {
|
|
|
Map<String, Object> paymentStatusResponse = bankingService.queryPaymentStatus(payment.getBusinessTransNo());
|
|
Map<String, Object> paymentStatusResponse = bankingService.queryPaymentStatus(payment.getBusinessTransNo());
|
|
|
String paymentStatus = extractPaymentStatus(paymentStatusResponse);
|
|
String paymentStatus = extractPaymentStatus(paymentStatusResponse);
|
|
|
trackingRepository.recordPaymentStatus(payment.getBusinessTransNo(), paymentStatus);
|
|
trackingRepository.recordPaymentStatus(payment.getBusinessTransNo(), paymentStatus);
|
|
|
- boolean yidaWritten = writePaymentStatusToYida(payment, paymentStatus);
|
|
|
|
|
|
|
+ YidaWriteBackResult yidaWriteBackResult = writePaymentStatusToYida(payment, paymentStatus);
|
|
|
|
|
+ if (yidaWriteBackResult == YidaWriteBackResult.FORM_DATA_DELETED) {
|
|
|
|
|
+ trackingRepository.markYidaFormDataDeleted(payment.getBusinessTransNo());
|
|
|
|
|
+ LOGGER.warn("Banking payment processing skipped because Yida form data was deleted businessTransNo={}",
|
|
|
|
|
+ payment.getBusinessTransNo());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
if (!PAYMENT_SUCCESS_STATUS.equals(paymentStatus)) {
|
|
if (!PAYMENT_SUCCESS_STATUS.equals(paymentStatus)) {
|
|
|
- if (yidaWritten && isTerminalFailure(paymentStatus)) {
|
|
|
|
|
|
|
+ if (yidaWriteBackResult == YidaWriteBackResult.SUCCEEDED && isTerminalFailure(paymentStatus)) {
|
|
|
trackingRepository.markTerminalFailure(payment.getBusinessTransNo(), paymentStatus);
|
|
trackingRepository.markTerminalFailure(payment.getBusinessTransNo(), paymentStatus);
|
|
|
}
|
|
}
|
|
|
return;
|
|
return;
|
|
@@ -111,15 +118,18 @@ public class BankingPaymentStatusScheduler {
|
|
|
/**
|
|
/**
|
|
|
* 回写当前支付状态。支付成功时先回写状态,回单生成后会再次回写附件。
|
|
* 回写当前支付状态。支付成功时先回写状态,回单生成后会再次回写附件。
|
|
|
*/
|
|
*/
|
|
|
- private boolean writePaymentStatusToYida(PendingBankingPayment payment, String paymentStatus) {
|
|
|
|
|
|
|
+ private YidaWriteBackResult writePaymentStatusToYida(PendingBankingPayment payment, String paymentStatus) {
|
|
|
try {
|
|
try {
|
|
|
yidaWriteBackService.writePaymentResult(payment.getFormID(), payment.getFormInstanceId(),
|
|
yidaWriteBackService.writePaymentResult(payment.getFormID(), payment.getFormInstanceId(),
|
|
|
paymentStatus, null);
|
|
paymentStatus, null);
|
|
|
- return true;
|
|
|
|
|
|
|
+ return YidaWriteBackResult.SUCCEEDED;
|
|
|
} catch (RuntimeException exception) {
|
|
} catch (RuntimeException exception) {
|
|
|
|
|
+ if (isYidaFormDataDeleted(exception)) {
|
|
|
|
|
+ return YidaWriteBackResult.FORM_DATA_DELETED;
|
|
|
|
|
+ }
|
|
|
LOGGER.error("Banking payment status was not written back to Yida businessTransNo={}",
|
|
LOGGER.error("Banking payment status was not written back to Yida businessTransNo={}",
|
|
|
payment.getBusinessTransNo(), exception);
|
|
payment.getBusinessTransNo(), exception);
|
|
|
- return false;
|
|
|
|
|
|
|
+ return YidaWriteBackResult.RETRY_LATER;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -153,11 +163,10 @@ public class BankingPaymentStatusScheduler {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private boolean matchesTransaction(Map<String, Object> transaction, PendingBankingPayment payment) {
|
|
private boolean matchesTransaction(Map<String, Object> transaction, PendingBankingPayment payment) {
|
|
|
|
|
+ // 支行信息由银企侧返回,可能与制单时填写的开户行不一致,不能作为回单归属判断条件。
|
|
|
return amountsEqual(transaction.get("drAmount"), payment.getPayAmount())
|
|
return amountsEqual(transaction.get("drAmount"), payment.getPayAmount())
|
|
|
- && equalsText(transaction.get("accountNo"), payment.getPaymentAccountNo())
|
|
|
|
|
&& equalsText(transaction.get("customerAccountNo"), payment.getCustomerAccountNo())
|
|
&& equalsText(transaction.get("customerAccountNo"), payment.getCustomerAccountNo())
|
|
|
&& equalsText(transaction.get("customerName"), payment.getCustomerName())
|
|
&& equalsText(transaction.get("customerName"), payment.getCustomerName())
|
|
|
- && matchesBankName(transaction.get("customerBank"), payment.getCustomerBank())
|
|
|
|
|
&& equalsText(transaction.get("userMemo"), payment.getRemake());
|
|
&& equalsText(transaction.get("userMemo"), payment.getRemake());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -172,18 +181,6 @@ public class BankingPaymentStatusScheduler {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 银企流水通常返回银行全称,而制单时可能仅保存简称;忽略银行主体后缀后匹配支行名称。
|
|
|
|
|
- */
|
|
|
|
|
- private boolean matchesBankName(Object actualValue, String expectedValue) {
|
|
|
|
|
- if (!hasText(expectedValue) || actualValue == null || !hasText(String.valueOf(actualValue))) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- String actual = normalizeBankName(String.valueOf(actualValue));
|
|
|
|
|
- String expected = normalizeBankName(expectedValue);
|
|
|
|
|
- return actual.equals(expected) || actual.contains(expected) || expected.contains(actual);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private boolean equalsText(Object actualValue, String expectedValue) {
|
|
private boolean equalsText(Object actualValue, String expectedValue) {
|
|
|
if (!hasText(expectedValue) || actualValue == null || !hasText(String.valueOf(actualValue))) {
|
|
if (!hasText(expectedValue) || actualValue == null || !hasText(String.valueOf(actualValue))) {
|
|
|
return false;
|
|
return false;
|
|
@@ -195,12 +192,6 @@ public class BankingPaymentStatusScheduler {
|
|
|
return value == null ? "" : value.replaceAll("\\s+", "").trim().toLowerCase();
|
|
return value == null ? "" : value.replaceAll("\\s+", "").trim().toLowerCase();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private String normalizeBankName(String value) {
|
|
|
|
|
- return normalizeText(value)
|
|
|
|
|
- .replace("股份有限公司", "")
|
|
|
|
|
- .replace("有限责任公司", "");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private List<Map<String, Object>> extractTransactionRecords(Map<String, Object> response) {
|
|
private List<Map<String, Object>> extractTransactionRecords(Map<String, Object> response) {
|
|
|
if (response == null) {
|
|
if (response == null) {
|
|
|
return Collections.emptyList();
|
|
return Collections.emptyList();
|
|
@@ -268,6 +259,12 @@ public class BankingPaymentStatusScheduler {
|
|
|
LOGGER.info("Banking electronic bill downloaded businessTransNo={} fileName={}", businessTransNo,
|
|
LOGGER.info("Banking electronic bill downloaded businessTransNo={} fileName={}", businessTransNo,
|
|
|
receipt.getFileName());
|
|
receipt.getFileName());
|
|
|
} catch (RuntimeException exception) {
|
|
} catch (RuntimeException exception) {
|
|
|
|
|
+ if (isYidaFormDataDeleted(exception)) {
|
|
|
|
|
+ trackingRepository.markYidaFormDataDeleted(businessTransNo);
|
|
|
|
|
+ LOGGER.warn("Banking receipt processing skipped because Yida form data was deleted businessTransNo={}",
|
|
|
|
|
+ businessTransNo);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
trackingRepository.markReceiptDownloadFailed(businessTransNo);
|
|
trackingRepository.markReceiptDownloadFailed(businessTransNo);
|
|
|
// 回单下载、文件保存和宜搭链接回写任一环节失败时均保留重试状态,日志必须包含原因以便排查。
|
|
// 回单下载、文件保存和宜搭链接回写任一环节失败时均保留重试状态,日志必须包含原因以便排查。
|
|
|
LOGGER.warn("Banking payment succeeded but electronic bill is unavailable businessTransNo={}",
|
|
LOGGER.warn("Banking payment succeeded but electronic bill is unavailable businessTransNo={}",
|
|
@@ -293,6 +290,24 @@ public class BankingPaymentStatusScheduler {
|
|
|
return value != null && !value.trim().isEmpty();
|
|
return value != null && !value.trim().isEmpty();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private boolean isYidaFormDataDeleted(Throwable exception) {
|
|
|
|
|
+ Throwable current = exception;
|
|
|
|
|
+ while (current != null) {
|
|
|
|
|
+ String message = current.getMessage();
|
|
|
|
|
+ if (message != null && message.contains(YIDA_FORM_DATA_DELETED_MESSAGE)) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ current = current.getCause();
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private enum YidaWriteBackResult {
|
|
|
|
|
+ SUCCEEDED,
|
|
|
|
|
+ RETRY_LATER,
|
|
|
|
|
+ FORM_DATA_DELETED
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private String buildReceiptUrl(String fileName, String option) {
|
|
private String buildReceiptUrl(String fileName, String option) {
|
|
|
return bankingProperties.getPublicBaseUrl().replaceAll("/+$", "")
|
|
return bankingProperties.getPublicBaseUrl().replaceAll("/+$", "")
|
|
|
+ "/api/banking/electronic-bills/files/"
|
|
+ "/api/banking/electronic-bills/files/"
|