diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 9da703b..9d38b61 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,4 +1,4 @@ -# 复制到 admin .gitea/workflows/deploy.yml +# 复制到 admin .gitea/workflows/deploy.yml name: Build and Deploy on: diff --git a/src/Oms.Application/Integrations/Itfx/ItfxGatewayOptions.cs b/src/Oms.Application/Integrations/Itfx/ItfxGatewayOptions.cs index 1ba817e..6cbe9af 100644 --- a/src/Oms.Application/Integrations/Itfx/ItfxGatewayOptions.cs +++ b/src/Oms.Application/Integrations/Itfx/ItfxGatewayOptions.cs @@ -8,9 +8,9 @@ public class ItfxGatewayOptions public const string SectionName = "Oms:Itfx"; /// - /// itfx 服务根地址,如 http://api.nanafa.com/itfx。 + /// itfx 服务根地址。生产默认 api.ideship.com;测试用 appsettings.Development / Consul 覆盖为 api.nanafa.com。 /// - public string BaseUrl { get; set; } = "http://api.nanafa.com/itfx"; + public string BaseUrl { get; set; } = "https://api.ideship.com/itfx"; public int TimeoutSeconds { get; set; } = 30; diff --git a/src/SimpleAdmin.Api.IntegrationTests/WeChatRouteIntegrationTests.cs b/src/SimpleAdmin.Api.IntegrationTests/WeChatRouteIntegrationTests.cs index 5c4f785..9a412b6 100644 --- a/src/SimpleAdmin.Api.IntegrationTests/WeChatRouteIntegrationTests.cs +++ b/src/SimpleAdmin.Api.IntegrationTests/WeChatRouteIntegrationTests.cs @@ -30,8 +30,9 @@ public class WeChatRouteIntegrationTests await using var host = await SimpleAdminApiTestHost.CreateAsync(configureServices: ConfigureWeChatFallback); host.RoutePatterns.Should().Contain("apiwechat/verification"); - host.RoutePatterns.Should().Contain("wechat/mp/{appId}"); + host.RoutePatterns.Should().Contain("wechat/mp/{appId:regex(^wx[A-Za-z0-9]+$)}"); host.RoutePatterns.Should().Contain("wechat/mp/login-qrcode"); + host.RoutePatterns.Should().Contain("wechat/oauth/config"); host.RoutePatterns.Should().Contain("wechat/mp/follow-qrcode"); host.RoutePatterns.Should().Contain("wechat/oauth/user-info"); host.RoutePatterns.Should().Contain("wechat/customer/register"); diff --git a/src/SimpleAdmin.Api/Auth/AuthService.WeChatMp.cs b/src/SimpleAdmin.Api/Auth/AuthService.WeChatMp.cs index 05bc350..914cee0 100644 --- a/src/SimpleAdmin.Api/Auth/AuthService.WeChatMp.cs +++ b/src/SimpleAdmin.Api/Auth/AuthService.WeChatMp.cs @@ -70,9 +70,10 @@ public partial class AuthService /// /// 微信服务器接入验签,验签通过后原样返回 echostr。 + /// appId 仅匹配 wx 开头,避免 login-qrcode / oauth-config 等静态段落入本路由。 /// [AllowAnonymous] - [HttpGet("/wechat/mp/{appId}")] + [HttpGet("/wechat/mp/{appId:regex(^wx[A-Za-z0-9]+$)}")] [Produces("text/plain")] [ApiExplorerSettings(GroupName = "WeChat")] public async Task WeChatValidateAsync( @@ -120,7 +121,7 @@ public partial class AuthService /// 微信消息/事件推送(明文,XML/JSON)。 /// [AllowAnonymous] - [HttpPost("/wechat/mp/{appId}")] + [HttpPost("/wechat/mp/{appId:regex(^wx[A-Za-z0-9]+$)}")] [Consumes("text/xml", "application/xml", "application/json", "text/plain")] [Produces("text/plain", "application/xml")] [ApiExplorerSettings(GroupName = "WeChat")] @@ -159,6 +160,32 @@ public partial class AuthService cancellationToken); } + /// + /// H5 网页授权公开配置:AppId + OAuth 回调根(来自其他配置 wechat_mp)。 + /// 注意:勿挂在 /wechat/mp/{appId} 下,避免被公众号回调路由吞掉。 + /// + [AllowAnonymous] + [HttpGet("/wechat/oauth/config")] + [ApiExplorerSettings(GroupName = "WeChat")] + public async Task GetWeChatOAuthConfigAsync( + CancellationToken cancellationToken = default) + { + var options = await WeChatMpConfigProvider.GetAsync(cancellationToken); + if (string.IsNullOrWhiteSpace(options.AppId)) + { + throw new BusinessException( + "未配置微信公众号 AppId。请在「其他配置」维护 wechat_mp,AppKey 填公众号 AppId。"); + } + + return new WxOAuthConfigOutput + { + AppId = options.AppId.Trim(), + OAuthRedirectBase = string.IsNullOrWhiteSpace(options.OAuthRedirectBase) + ? null + : options.OAuthRedirectBase.Trim().TrimEnd('/') + }; + } + /// /// 获取 PC 扫码登录二维码。 /// diff --git a/src/SimpleAdmin.Api/WeChat/Dtos/WeChatDtos.cs b/src/SimpleAdmin.Api/WeChat/Dtos/WeChatDtos.cs index f5c09ba..d254466 100644 --- a/src/SimpleAdmin.Api/WeChat/Dtos/WeChatDtos.cs +++ b/src/SimpleAdmin.Api/WeChat/Dtos/WeChatDtos.cs @@ -12,6 +12,19 @@ public class WxLoginQrcodeOutput public int ExpiresIn { get; set; } = 600; } +/// H5 网页授权所需公开配置(不含 Secret/Token)。 +public class WxOAuthConfigOutput +{ + /// 公众号 AppId(来自其他配置 wechat_mp.AppKey)。 + public string AppId { get; set; } = string.Empty; + + /// + /// OAuth 回调根地址(来自 wechat_mp.BaseUrl),如 https://ideship.com。 + /// 为空时前端回退到当前页面 origin。 + /// + public string? OAuthRedirectBase { get; set; } +} + /// 引导关注公众号:优先返回可直接跳转的公众号链接。 public class WxFollowQrcodeOutput { diff --git a/src/SimpleAdmin.Api/appsettings.Development.json b/src/SimpleAdmin.Api/appsettings.Development.json index f9647a9..1439c62 100644 --- a/src/SimpleAdmin.Api/appsettings.Development.json +++ b/src/SimpleAdmin.Api/appsettings.Development.json @@ -12,7 +12,12 @@ }, "App": { "Urls": ["http://localhost:5281"], - "CorsOrigins": ["http://localhost:5173", "http://localhost:5281"], + "CorsOrigins": [ + "http://localhost:5173", + "http://localhost:5281", + "https://oms.nanafa.com", + "http://oms.nanafa.com" + ], "SendStartupNotification": false }, "Jwt": { @@ -46,7 +51,7 @@ }, "WeChat": { "Mp": { - "AppId": "wxd5141ba46c856e1f", + "AppId": "wxfffea62e089ee15f", "Secret": "379f51a89419dc36fbb9167feef6f89a", "Token": "c6ca74013df823c0e1da0feaaaf8bf66", "EncodingAesKey": "", diff --git a/src/SimpleAdmin.Api/appsettings.Production.json b/src/SimpleAdmin.Api/appsettings.Production.json new file mode 100644 index 0000000..49f2a98 --- /dev/null +++ b/src/SimpleAdmin.Api/appsettings.Production.json @@ -0,0 +1,34 @@ +{ + "UseLocalConfigs": false, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "App": { + "CorsOrigins": [ + "https://ideship.com", + "https://www.ideship.com" + ], + "SendStartupNotification": false + }, + "WeChat": { + "Mp": { + "OAuthRedirectBase": "https://ideship.com", + "FollowUrl": "" + } + }, + "Oms": { + "TrackService": { + "Enabled": true, + "BaseUrl": "https://api.ideship.com/track" + }, + "Itfx": { + "BaseUrl": "https://api.ideship.com/itfx" + }, + "PlatformShop": { + "FrontendBaseUrl": "https://ideship.com" + } + } +}