diff --git a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/direct/auth/DouyinDirectAuthStrategy.java b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/direct/auth/DouyinDirectAuthStrategy.java index 5e4916bb5..fd04592af 100644 --- a/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/direct/auth/DouyinDirectAuthStrategy.java +++ b/daxpay-channel/daxpay-channel-douyin/src/main/java/cn/daxpay/open/channel/douyin/strategy/direct/auth/DouyinDirectAuthStrategy.java @@ -47,7 +47,7 @@ public class DouyinDirectAuthStrategy extends AbsProductAuthStrategy { @Override public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param, String authToken) { DouyinDirectApp app = douyinDirectAppCapabilityService.resolveWebAppForH5Auth( - param.getChannelMchNo(), param.getCapability(), param.getChannelAppId()); + param.getChannelMchNo(), param.getMethod(), param.getChannelAppId()); DouyinDirectAppAuthConfig authConfig = douyinDirectAppAuthConfigService.findByDouyinDirectAppIdForAuth(app.getId()); if (StrUtil.isBlank(authConfig.getAppSecret())) { // 抖音: 直连应用授权密钥未配置 @@ -64,7 +64,7 @@ public class DouyinDirectAuthStrategy extends AbsProductAuthStrategy { public AuthResult doAuth(AuthCodeParam param, AuthSession session) { var ctx = resolveContext(param, session); DouyinDirectApp app = douyinDirectAppCapabilityService.resolveWebAppForH5Auth( - ctx.channelMchNo(), ctx.capability(), ctx.channelAppId()); + ctx.channelMchNo(), ctx.method(), ctx.channelAppId()); DouyinDirectAppAuthConfig authConfig = douyinDirectAppAuthConfigService.findByDouyinDirectAppIdForAuth(app.getId()); if (StrUtil.isBlank(authConfig.getAppSecret())) { // 抖音: 直连应用授权密钥未配置 diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/auth/WechatDirectAuthStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/auth/WechatDirectAuthStrategy.java index 952736bee..7602b5dd7 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/auth/WechatDirectAuthStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/direct/auth/WechatDirectAuthStrategy.java @@ -52,7 +52,7 @@ public class WechatDirectAuthStrategy extends AbsProductAuthStrategy { @Override public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param, String authToken) { WxAppView app = resolveApp(param.getMchNo(), param.getChannelMchNo(), - param.getCapability(), param.getChannelAppId()); + param.getMethod(), param.getChannelAppId()); String redirectUri = AuthRedirectUri.WECHAT.buildRedirectUri(platformUrlConfigService); WechatAuthUrlResult result = wechatMpAuthService.generateAuthUrl( redirectUri, app.wxAppId(), app.appSecret(), authToken); @@ -65,7 +65,7 @@ public class WechatDirectAuthStrategy extends AbsProductAuthStrategy { @Override public AuthResult doAuth(AuthCodeParam param, AuthSession session) { var ctx = resolveContext(param, session); - WxAppView app = resolveApp(param.getMchNo(), ctx.channelMchNo(), ctx.capability(), ctx.channelAppId()); + WxAppView app = resolveApp(param.getMchNo(), ctx.channelMchNo(), ctx.method(), ctx.channelAppId()); WechatAuthResult data = wechatMpAuthService.getTokenAndOpenId( param.getAuthCode(), app.wxAppId(), app.appSecret()); if (StrUtil.isBlank(data.getOpenId())) { diff --git a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/auth/WechatIsvAuthStrategy.java b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/auth/WechatIsvAuthStrategy.java index 18930180d..11990a38c 100644 --- a/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/auth/WechatIsvAuthStrategy.java +++ b/daxpay-channel/daxpay-channel-wechat/src/main/java/cn/daxpay/open/channel/wechat/strategy/isv/auth/WechatIsvAuthStrategy.java @@ -57,7 +57,7 @@ public class WechatIsvAuthStrategy extends AbsProductAuthStrategy { @Override public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param, String authToken) { ResolvedAuthApp app = resolveAuthApp(param.getMchNo(), param.getChannelMchNo(), - param.getCapability(), param.getChannelAppId()); + param.getMethod(), param.getChannelAppId()); String redirectUri = AuthRedirectUri.WECHAT.buildRedirectUri(platformUrlConfigService); WechatAuthUrlResult result = wechatMpAuthService.generateAuthUrl( redirectUri, app.wxAppId(), app.appSecret(), authToken); @@ -68,7 +68,7 @@ public class WechatIsvAuthStrategy extends AbsProductAuthStrategy { @Override public AuthResult doAuth(AuthCodeParam param, AuthSession session) { var ctx = resolveContext(param, session); - ResolvedAuthApp app = resolveAuthApp(param.getMchNo(), ctx.channelMchNo(), ctx.capability(), ctx.channelAppId()); + ResolvedAuthApp app = resolveAuthApp(param.getMchNo(), ctx.channelMchNo(), ctx.method(), ctx.channelAppId()); WechatAuthResult data = wechatMpAuthService.getTokenAndOpenId( param.getAuthCode(), app.wxAppId(), app.appSecret()); if (StrUtil.isBlank(data.getOpenId())) { diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/core/AuthSession.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/core/AuthSession.java index af5bcb557..9d2e963ac 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/core/AuthSession.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/core/AuthSession.java @@ -53,9 +53,9 @@ public class AuthSession { /// 通道商户号 private String channelMchNo; - /// 支付能力编码(用于解析具体应用) - /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayCapabilityEnum - private String capability; + /// 支付方式编码(用于解析具体应用) + /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayMethodEnum + private String method; /// 指定认证应用AppId(可选, 优先级高于配置自动解析) private String channelAppId; diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/AbsProductAuthStrategy.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/AbsProductAuthStrategy.java index f38c29712..1b988a90a 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/AbsProductAuthStrategy.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/AbsProductAuthStrategy.java @@ -23,22 +23,22 @@ public abstract class AbsProductAuthStrategy implements PaymentStrategy { /// 通过AuthCode获取认证结果 /// /// @param session 认证会话上下文(H5场景从 authToken 恢复; 小程序直连场景可为空, 此时从 param 取上下文)。 - /// 策略需兼容 session 为 null 的情况(优先用 param 的 channelMchNo/capability/channelAppId)。 + /// 策略需兼容 session 为 null 的情况(优先用 param 的 channelMchNo/method/channelAppId)。 public abstract AuthResult doAuth(AuthCodeParam param, AuthSession session); /// 解析认证上下文: session 字段优先, param 兜底 /// /// H5 OAuth 重定向场景从 session 恢复(param 仅含 authToken); /// 小程序直连场景 session 为空, 从 param 取上下文。 - /// 返回 [ProductAuthContext](channelMchNo / capability / channelAppId)。 + /// 返回 [ProductAuthContext](channelMchNo / method / channelAppId)。 protected ProductAuthContext resolveContext(AuthCodeParam param, AuthSession session) { String channelMchNo = session != null && StrUtil.isNotBlank(session.getChannelMchNo()) ? session.getChannelMchNo() : param.getChannelMchNo(); - String capability = session != null && StrUtil.isNotBlank(session.getCapability()) - ? session.getCapability() : param.getCapability(); + String method = session != null && StrUtil.isNotBlank(session.getMethod()) + ? session.getMethod() : param.getMethod(); String channelAppId = session != null && StrUtil.isNotBlank(session.getChannelAppId()) ? session.getChannelAppId() : param.getChannelAppId(); - return new ProductAuthContext(channelMchNo, capability, channelAppId); + return new ProductAuthContext(channelMchNo, method, channelAppId); } } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthContext.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthContext.java index 8b1523799..4ac1bb54f 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthContext.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthContext.java @@ -7,7 +7,7 @@ package cn.daxpay.open.payment.auth.merchant; /// /// ## 字段含义 /// - `channelMchNo`: 通道商户号(定位特约商户主数据 / 反查 mchNo) -/// - `capability`: 支付能力编码(公众号 / 小程序, 决定应用维度与 openId 类型) +/// - `method`: 支付方式编码(公众号 / 小程序, 决定应用维度与 openId 类型) /// - `channelAppId`: 显式指定的应用 AppId(可选, 优先级高于配置自动解析) -public record ProductAuthContext(String channelMchNo, String capability, String channelAppId) { +public record ProductAuthContext(String channelMchNo, String method, String channelAppId) { } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthService.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthService.java index 1b296660d..2b13f1c29 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthService.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/auth/merchant/ProductAuthService.java @@ -13,7 +13,9 @@ import cn.daxpay.open.payment.unipay.result.assist.AuthResult; import cn.daxpay.open.payment.unipay.result.assist.AuthUrlResult; import cn.daxpay.open.platform.core.code.CommonErrorCode; import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum; +import cn.daxpay.open.platform.core.enums.pay.channel.PayMethodEnum; import cn.daxpay.open.platform.core.enums.unipay.ChannelAuthStatusEnum; +import cn.daxpay.open.platform.core.enums.unipay.ChannelAuthTypeEnum; import cn.daxpay.open.platform.core.exception.BizInfoException; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.RandomUtil; @@ -47,6 +49,8 @@ public class ProductAuthService { /// 不含 queryCode, 需随会话保存)。 public AuthUrlResult generateAuthUrl(GenerateAuthUrlParam param) { initMchContext(param.getAppId(), param.getMchNo(), null); + // 支付方式缺失时按认证类型推导默认值(OAuth 重定向天然只适用于公众号场景) + param.setMethod(resolveDefaultMethod(param.getAuthType(), param.getMethod())); // 支付产品: 显式传入优先, 否则从通道商户号反查(调试工具/直接指定通道商户场景) String product = resolveProduct(param); assertNotAlipayProduct(product); @@ -58,7 +62,7 @@ public class ProductAuthService { AuthSession session = new AuthSession() .setProduct(product) .setChannelMchNo(param.getChannelMchNo()) - .setCapability(param.getCapability()) + .setMethod(param.getMethod()) .setChannelAppId(param.getChannelAppId()) .setReturnPath(param.getReturnPath()) .setQueryCode(queryCode) @@ -78,6 +82,8 @@ public class ProductAuthService { /// 由认证分发层在调用前通过 [AuthSessionStore#loadSession] 加载后注入。 public AuthResult auth(AuthCodeParam param, AuthSession session) { initMchContext(param.getAppId(), param.getMchNo(), session); + // 支付方式缺失时按认证类型推导(session 恢复场景已有 method, 小程序直连场景需补) + param.setMethod(resolveDefaultMethod(param.getAuthType(), param.getMethod())); // product 优先从会话恢复, 其次取参数(小程序直连场景) String product = (session != null && StrUtil.isNotBlank(session.getProduct())) ? session.getProduct() : param.getProduct(); @@ -136,4 +142,21 @@ public class ProductAuthService { throw new IllegalStateException("支付宝认证应走平台级 Provider, 不应进入产品策略: " + product); } } + + /// 支付方式缺失时按认证类型推导默认值 + /// + /// OAuth 重定向认证天然只适用于公众号(H5网页授权)场景, 微信默认补 jsapi, 抖音默认补 h5。 + /// 已显式传入 method 的场景(网关/码牌)不受影响。 + private static String resolveDefaultMethod(String authType, String method) { + if (StrUtil.isNotBlank(method)) { + return method; + } + if (ChannelAuthTypeEnum.WECHAT.getCode().equals(authType)) { + return PayMethodEnum.WECHAT_JSAPI.getCode(); + } + if (ChannelAuthTypeEnum.DOUYIN.getCode().equals(authType)) { + return PayMethodEnum.DOUYIN_H5.getCode(); + } + return method; + } } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/gateway/GatewayAuthService.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/gateway/GatewayAuthService.java index 9ec32ef9f..2b1fa10fe 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/gateway/GatewayAuthService.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/trade/runtime/service/pay/gateway/GatewayAuthService.java @@ -85,7 +85,7 @@ public class GatewayAuthService { RouteSnapshot route = resolveRoute(order, param); authParam.setProduct(route.product()); authParam.setChannelMchNo(route.channelMchNo()); - authParam.setCapability(route.capability()); + authParam.setMethod(route.method()); authParam.setChannelAppId(route.channelAppId()); } return channelAuthService.generateAuthUrl(authParam); @@ -261,6 +261,6 @@ public class GatewayAuthService { } /// 路由快照(供组装 GenerateAuthUrlParam) - private record RouteSnapshot(String product, String channelMchNo, String capability, String channelAppId) { + private record RouteSnapshot(String product, String channelMchNo, String method, String channelAppId) { } } diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/AuthCodeParam.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/AuthCodeParam.java index 203155982..f53c4a201 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/AuthCodeParam.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/AuthCodeParam.java @@ -52,11 +52,11 @@ public class AuthCodeParam extends MerchantPaymentCommonParam { @Schema(description = "支付产品编码") private String product; - /// 支付能力编码, 用于解析具体应用, 小程序场景需要; 会话码场景从会话恢复 - /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayCapabilityEnum - @Size(max = 32, message = "{validation.field.capability.size}") - @Schema(description = "支付能力编码") - private String capability; + /// 支付方式编码, 用于解析具体应用, 小程序场景需要; 会话码场景从会话恢复 + /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayMethodEnum + @Size(max = 32, message = "{validation.field.method.size}") + @Schema(description = "支付方式编码") + private String method; /// 指定认证使用的应用AppId, 会话码恢复上下文时可不传, 优先级高于配置自动解析 @Size(max = 128, message = "{validation.field.channelAppId.size}") diff --git a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/GenerateAuthUrlParam.java b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/GenerateAuthUrlParam.java index 615c28c55..49ce5e3b1 100644 --- a/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/GenerateAuthUrlParam.java +++ b/daxpay-payment/daxpay-payment-core/src/main/java/cn/daxpay/open/payment/unipay/param/assist/GenerateAuthUrlParam.java @@ -38,10 +38,10 @@ public class GenerateAuthUrlParam extends MerchantPaymentCommonParam { @Schema(description = "来源回跳路径") private String returnPath; - /// 支付能力编码, 用于解析具体应用(公众号/小程序), 不同能力对应不同应用维度的openId - /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayCapabilityEnum - @Size(max = 32, message = "{validation.field.capability.size}") - @Schema(description = "支付能力编码") - private String capability; + /// 支付方式编码, 决定解析哪个应用(公众号/小程序等), 不同方式对应不同应用维度的 openId + /// @see cn.daxpay.open.platform.core.enums.pay.channel.PayMethodEnum + @Size(max = 32, message = "{validation.field.method.size}") + @Schema(description = "支付方式编码") + private String method; } diff --git a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/client/service/CodePayAssistService.java b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/client/service/CodePayAssistService.java index ccb80c172..1af7701d9 100644 --- a/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/client/service/CodePayAssistService.java +++ b/daxpay-payment/daxpay-payment-unipay/src/main/java/cn/daxpay/open/payment/unipay/client/service/CodePayAssistService.java @@ -182,7 +182,7 @@ public class CodePayAssistService { authParam.setAppId(mchApp.getAppId()); authParam.setProduct(routeParam.getProduct()); authParam.setChannelMchNo(routeParam.getChannelMchNo()); - authParam.setCapability(routeParam.getCapability()); + authParam.setMethod(routeParam.getCapability()); authParam.setReturnPath(returnPath); authParam.setAuthType(this.mapAuthType(clientEnv)); return channelAuthService.generateAuthUrl(authParam);