feat(payment): 优化支付回调地址配置逻辑

- 开发测试环境支持强制覆盖回调地址,便于本地联调
- 生产环境优先使用数据库中的notifyUrl配置
- 数据库未配置时才使用环境默认配置作为兜底方案
- 实现从通知URL提取基础API URL的功能
- 重构默认回调URL生成逻辑,优先使用数据库配置
- 移除重复的回调地址添加,优化地址列表构建流程
This commit is contained in:
2026-02-24 12:05:10 +08:00
parent 8bafc724a4
commit a5f18859dc
2 changed files with 47 additions and 18 deletions

View File

@@ -50,15 +50,26 @@ public class EnvironmentAwarePaymentService {
return null;
}
// 根据环境调整回调地址
// 开发/测试环境允许强制覆盖,方便本地联调。
if (isDevelopmentEnvironment()) {
Payment envPayment = clonePayment(payment);
String notifyUrl = getEnvironmentNotifyUrl();
log.info("环境感知支付配置 - 环境: {}, 原始回调: {}, 调整后回调: {}",
log.info("环境感知支付配置(开发/测试) - 环境: {}, 原始回调: {}, 覆盖后回调: {}",
activeProfile, payment.getNotifyUrl(), notifyUrl);
envPayment.setNotifyUrl(notifyUrl);
return envPayment;
}
// 生产/其它环境:优先使用数据库中的 notifyUrl多租户域名可能不同
if (payment.getNotifyUrl() != null && !payment.getNotifyUrl().trim().isEmpty()) {
return payment;
}
// 数据库未配置时才兜底使用环境配置。
Payment envPayment = clonePayment(payment);
String notifyUrl = getEnvironmentNotifyUrl();
log.info("环境感知支付配置(兜底) - 环境: {}, 原始回调为空,兜底回调: {}", activeProfile, notifyUrl);
envPayment.setNotifyUrl(notifyUrl);
return envPayment;
}

View File

@@ -133,6 +133,22 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
return base + suffix;
}
private static String baseApiUrlFromNotifyUrl(String notifyUrl) {
if (StrUtil.isBlank(notifyUrl)) {
return null;
}
String u = trimTrailingSlashes(notifyUrl);
if (u.endsWith("/api")) {
return u;
}
int idx = u.indexOf("/api/");
if (idx >= 0) {
return u.substring(0, idx + "/api".length());
}
// Fallback: treat notifyUrl itself as base.
return u;
}
private String prepaySnapshotKey(Payment payment, String outTradeNo) {
return WECHAT_PREPAY_SNAPSHOT_KEY_PREFIX + payment.getMchId() + ":" + outTradeNo;
}
@@ -188,16 +204,21 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
return fen.intValueExact();
}
private String defaultShopOrderNotifyUrl(Integer tenantId) {
String base = trimTrailingSlashes(config.getApiUrl());
private String defaultShopOrderNotifyUrl(Payment payment, Integer tenantId) {
String base = payment != null ? trimTrailingSlashes(payment.getNotifyUrl()) : null;
if (StrUtil.isBlank(base) || tenantId == null) {
return null;
}
// If DB notifyUrl is already a notify endpoint (recommended), just append tenantId if missing.
if (base.contains("/notify")) {
return ensureTenantSuffix(base, tenantId);
}
// If DB notifyUrl is just the API gateway base, append the standard notify path.
return base + "/shop/shop-order/notify/" + tenantId;
}
private String legacySystemWxPayNotifyUrl(Integer tenantId) {
String base = trimTrailingSlashes(config.getApiUrl());
private String legacySystemWxPayNotifyUrl(Payment payment, Integer tenantId) {
String base = baseApiUrlFromNotifyUrl(payment != null ? payment.getNotifyUrl() : null);
if (StrUtil.isBlank(base) || tenantId == null) {
return null;
}
@@ -224,18 +245,15 @@ public class ShopOrderServiceImpl extends ServiceImpl<ShopOrderMapper, ShopOrder
if (snapshot != null && StrUtil.isNotBlank(snapshot.getNotifyUrl())) {
urls.add(trimTrailingSlashes(snapshot.getNotifyUrl()));
}
if (payment != null && StrUtil.isNotBlank(payment.getNotifyUrl())) {
urls.add(ensureTenantSuffix(payment.getNotifyUrl(), order.getTenantId()));
}
// 新默认回调(本项目已实现)
String shopOrderNotify = defaultShopOrderNotifyUrl(order.getTenantId());
if (StrUtil.isNotBlank(shopOrderNotify)) {
urls.add(shopOrderNotify);
// 回调地址优先从数据库支付配置读取
String paymentNotify = defaultShopOrderNotifyUrl(payment, order.getTenantId());
if (StrUtil.isNotBlank(paymentNotify)) {
urls.add(paymentNotify);
}
// 兼容历史回调地址(用于已创建订单的“重新支付”重入校验)
String legacySystem = legacySystemWxPayNotifyUrl(order.getTenantId());
String legacySystem = legacySystemWxPayNotifyUrl(payment, order.getTenantId());
if (StrUtil.isNotBlank(legacySystem)) {
urls.add(legacySystem);
}