fix: 全服务注册 JwtStrategy + 修复微信 WxApi 未配置 crash
**后端** - packages/common: 新增并导出 JwtStrategy(共享 Passport JWT 策略) - 6 个服务模块(user/issuer/clearing/compliance/notification/telemetry) 均缺少 JwtStrategy provider,导致所有受保护接口返回 500 "Unknown authentication strategy jwt" - 统一修复:各模块 providers 添加 JwtStrategy **Flutter** - welcome_page: _onWechatTap() 的 isWeChatInstalled 调用未设 WECHAT_APP_ID 时会抛出 PlatformException,catch 后降级为"未安装"提示 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6bdd8d1e19
commit
75ed31cc04
|
|
@ -8,6 +8,9 @@ export * from './decorators/roles.decorator';
|
|||
export * from './guards/jwt-auth.guard';
|
||||
export * from './guards/roles.guard';
|
||||
|
||||
// Strategies
|
||||
export * from './strategies/jwt.strategy';
|
||||
|
||||
// Interceptors
|
||||
export * from './interceptors/logging.interceptor';
|
||||
export * from './interceptors/transform.interceptor';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
|
||||
/**
|
||||
* Shared JWT Passport Strategy.
|
||||
* Register as a provider in each service module that uses JwtAuthGuard.
|
||||
*
|
||||
* Usage in module:
|
||||
* providers: [JwtStrategy, ...]
|
||||
*/
|
||||
@Injectable()
|
||||
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
||||
constructor() {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: process.env.JWT_ACCESS_SECRET || 'dev-access-secret',
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: { sub: string; role: string; kycLevel: number; type: string }) {
|
||||
return { sub: payload.sub, role: payload.role, kycLevel: payload.kycLevel };
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// Domain entities
|
||||
import { Settlement } from './domain/entities/settlement.entity';
|
||||
|
|
@ -44,6 +45,7 @@ import { AdminReportsController } from './interface/http/controllers/admin-repor
|
|||
],
|
||||
controllers: [ClearingController, AdminFinanceController, AdminReportsController],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
// Repository DI bindings (interface -> implementation)
|
||||
{ provide: SETTLEMENT_REPOSITORY, useClass: SettlementRepository },
|
||||
{ provide: REFUND_REPOSITORY, useClass: RefundRepository },
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// ─── Domain Entities ───
|
||||
import { AmlAlert } from './domain/entities/aml-alert.entity';
|
||||
|
|
@ -75,6 +76,7 @@ import { AdminInsuranceController } from './interface/http/controllers/admin-ins
|
|||
AdminInsuranceController,
|
||||
],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
// ─── Repository DI bindings (interface → implementation) ───
|
||||
{ provide: AML_ALERT_REPOSITORY, useClass: AmlAlertRepository },
|
||||
{ provide: OFAC_SCREENING_REPOSITORY, useClass: OfacScreeningRepository },
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// Domain entities
|
||||
import { Issuer } from './domain/entities/issuer.entity';
|
||||
|
|
@ -88,6 +89,7 @@ import { RolesGuard } from './interface/http/guards/roles.guard';
|
|||
CouponBatchController,
|
||||
],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
// Infrastructure -> Domain port binding (Repository pattern)
|
||||
{ provide: ISSUER_REPOSITORY, useClass: IssuerRepository },
|
||||
{ provide: COUPON_REPOSITORY, useClass: CouponRepository },
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// Domain entities
|
||||
import { Notification } from './domain/entities/notification.entity';
|
||||
|
|
@ -94,6 +95,7 @@ import { DeviceTokenController } from './interface/http/controllers/device-token
|
|||
DeviceTokenController,
|
||||
],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
// Infrastructure -> Domain repository binding
|
||||
{ provide: NOTIFICATION_REPOSITORY, useClass: NotificationRepository },
|
||||
{ provide: ANNOUNCEMENT_REPOSITORY, useClass: AnnouncementRepositoryImpl },
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
|||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// Domain entities
|
||||
import { TelemetryEvent } from './domain/entities/telemetry-event.entity';
|
||||
|
|
@ -72,6 +73,7 @@ import { HealthController } from './interface/http/controllers/health.controller
|
|||
HealthController,
|
||||
],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
{ provide: TELEMETRY_EVENT_REPOSITORY, useClass: TelemetryEventRepository },
|
||||
{ provide: ONLINE_SNAPSHOT_REPOSITORY, useClass: OnlineSnapshotRepository },
|
||||
{ provide: DAILY_ACTIVE_STATS_REPOSITORY, useClass: DailyActiveStatsRepository },
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { JwtStrategy } from '@genex/common';
|
||||
|
||||
// Domain entities
|
||||
import { User } from './domain/entities/user.entity';
|
||||
|
|
@ -59,6 +60,7 @@ import { AdminAnalyticsController } from './interface/http/controllers/admin-ana
|
|||
AdminDashboardController, AdminUserController, AdminSystemController, AdminAnalyticsController,
|
||||
],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
// Infrastructure -> Domain port binding
|
||||
{ provide: USER_REPOSITORY, useClass: UserRepository },
|
||||
{ provide: KYC_REPOSITORY, useClass: KycRepository },
|
||||
|
|
|
|||
|
|
@ -78,7 +78,12 @@ class _WelcomePageState extends ConsumerState<WelcomePage> {
|
|||
// ── 微信 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
Future<void> _onWechatTap() async {
|
||||
final installed = await _fluwx.isWeChatInstalled;
|
||||
bool installed = false;
|
||||
try {
|
||||
installed = await _fluwx.isWeChatInstalled;
|
||||
} catch (_) {
|
||||
// WxApi not configured (WECHAT_APP_ID not provided) — treat as not installed
|
||||
}
|
||||
if (!installed) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
|
|
|
|||
Loading…
Reference in New Issue