|
|
@@ -13,6 +13,7 @@ import com.ruoyi.app.utils.event.PushEventService;
|
|
|
import com.ruoyi.app.utils.omg.OmgCheckMacValue;
|
|
|
import com.ruoyi.app.utils.omg.OmgPay;
|
|
|
import com.ruoyi.app.utils.omg.OmgPayConfig;
|
|
|
+import com.ruoyi.app.utils.omg.OmgQueryThrottle;
|
|
|
import com.ruoyi.common.annotation.Anonymous;
|
|
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
|
|
import com.ruoyi.common.core.controller.BaseController;
|
|
|
@@ -102,6 +103,8 @@ public class OmgPayController extends BaseController {
|
|
|
private OrderLifecycleService orderLifecycleService;
|
|
|
@Autowired
|
|
|
private PaymentCreateGuardService paymentCreateGuardService;
|
|
|
+ @Autowired
|
|
|
+ private OmgQueryThrottle omgQueryThrottle;
|
|
|
|
|
|
@Value("${omg.base-url}")
|
|
|
private String baseUrl;
|
|
|
@@ -526,7 +529,11 @@ public class OmgPayController extends BaseController {
|
|
|
if (order == null || order.getUserId() == null || !userId.equals(String.valueOf(order.getUserId()))) {
|
|
|
return error("无权操作该订单");
|
|
|
}
|
|
|
- PosOrderOmgPayment p = paymentService.getLatestByDdId(orderid);
|
|
|
+ // 优先取已付/退款行(展示回执);无则取最新行(未付款场景展示 ATM/超商虚帐)
|
|
|
+ PosOrderOmgPayment p = paymentService.getLatestRefundableByDdId(orderid);
|
|
|
+ if (p == null) {
|
|
|
+ p = paymentService.getLatestByDdId(orderid);
|
|
|
+ }
|
|
|
if (p == null) {
|
|
|
return error("无支付记录");
|
|
|
}
|
|
|
@@ -607,7 +614,7 @@ public class OmgPayController extends BaseController {
|
|
|
return OmgRefundOutcome.of(OmgRefundOutcome.Status.FAILED, "订单未支付,无需退款");
|
|
|
}
|
|
|
String ddId = String.valueOf(order.getDdId());
|
|
|
- PosOrderOmgPayment payment = paymentService.getLatestByDdId(ddId);
|
|
|
+ PosOrderOmgPayment payment = paymentService.getLatestRefundableByDdId(ddId);
|
|
|
if (payment == null) {
|
|
|
return OmgRefundOutcome.of(OmgRefundOutcome.Status.FAILED, "无 OMG 支付流水");
|
|
|
}
|
|
|
@@ -649,7 +656,7 @@ public class OmgPayController extends BaseController {
|
|
|
}
|
|
|
|
|
|
if (paymentService.markRefunding(payment.getId()) == 0) {
|
|
|
- PosOrderOmgPayment latest = paymentService.getLatestByDdId(ddId);
|
|
|
+ PosOrderOmgPayment latest = paymentService.getLatestRefundableByDdId(ddId);
|
|
|
if (latest != null && Integer.valueOf(3).equals(latest.getPayStatus())) {
|
|
|
return OmgRefundOutcome.of(OmgRefundOutcome.Status.IDEMPOTENT, "OMG 已完成退款");
|
|
|
}
|
|
|
@@ -703,7 +710,7 @@ public class OmgPayController extends BaseController {
|
|
|
return OmgRefundOutcome.of(OmgRefundOutcome.Status.FAILED, "该订单非 OMG 支付");
|
|
|
}
|
|
|
String ddId = String.valueOf(order.getDdId());
|
|
|
- PosOrderOmgPayment payment = paymentService.getLatestByDdId(ddId);
|
|
|
+ PosOrderOmgPayment payment = paymentService.getLatestRefundableByDdId(ddId);
|
|
|
if (payment == null || "Credit_CreditCard".equals(payment.getPayType())) {
|
|
|
return OmgRefundOutcome.of(OmgRefundOutcome.Status.FAILED, "无可确认的 OMG 人工退款待办");
|
|
|
}
|
|
|
@@ -813,6 +820,12 @@ public class OmgPayController extends BaseController {
|
|
|
return new int[]{isPaid ? 1 : 0, 0};
|
|
|
}
|
|
|
|
|
|
+ // 闸3:per-ddId 扫描间隔节流(/query 60s / 定时 180s),挡前端轮询放大、防 OMG 403 自残(T055)
|
|
|
+ if (!omgQueryThrottle.acquireDdIdSlot(ddId, source)) {
|
|
|
+ log.debug("[OMG-{}] per-ddId 节流,跳过本轮 OMG 查询: ddId={}", source, ddId);
|
|
|
+ return new int[]{order.getPayStatus() == null ? 0 : order.getPayStatus().intValue(), 0};
|
|
|
+ }
|
|
|
+
|
|
|
// ② 遍历全量未付(pay_status=0,含历史行)queryTrade,任一已付即补单核销(补较早 MTN 如 id=26)
|
|
|
List<PosOrderOmgPayment> unpaid = paymentService.listUnpaidByDdId(ddId);
|
|
|
if (unpaid == null || unpaid.isEmpty()) {
|
|
|
@@ -825,6 +838,16 @@ public class OmgPayController extends BaseController {
|
|
|
log.error("[OMG-{}] 门店凭证不可用: ddId={}, mtcn={}", source, ddId, p.getMerchantTradeNo());
|
|
|
continue;
|
|
|
}
|
|
|
+ // 闸1:首查延迟——下单 40min 内不查 OMG(否则按 MerchantID 403 罚 30min)(T055)
|
|
|
+ if (omgQueryThrottle.isWithinFirstQueryDelay(p.getCreateTime())) {
|
|
|
+ log.debug("[OMG-{}] 首查延迟(<40min),跳过本行: ddId={}, mtcn={}", source, ddId, p.getMerchantTradeNo());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 闸2:per-MerchantID 令牌桶(1token/3s,burst1)——拿不到令牌跳过本行本轮,不阻塞(T055)
|
|
|
+ if (!omgQueryThrottle.tryAcquireMerchantToken(p.getMerchantId())) {
|
|
|
+ log.debug("[OMG-{}] MerchantID 令牌桶限流,跳过本行本轮: ddId={}, mtcn={}", source, ddId, p.getMerchantTradeNo());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
OmgPayConfig cfg = new OmgPayConfig(cred.getMerchantId(), cred.getHashKey(), cred.getHashIv());
|
|
|
Map<String, String> resp;
|
|
|
try {
|