import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { HttpService } from '@nestjs/axios'; import { firstValueFrom } from 'rxjs'; // 省市公司授权信息 export interface RegionAuthorization { authorizationId: string; userId: string; roleType: string; regionCode: string; regionName: string; benefitActive: boolean; // 算力百分比(正式省公司 1%,正式市公司 2%) hashpowerPercent: number; } // 社区授权信息 export interface CommunityAuthorization { authorizationId: string; userId: string; communityName: string; benefitActive: boolean; } // 系统账户信息 export interface SystemAccountInfo { accountId: string; accountType: string; regionCode: string | null; walletAddress: string | null; } // 分配上下文 - 包含授权查询结果 export interface AllocationContext { // 省公司授权(区域权益 15U + 1% 算力) provinceCompanyAuth: RegionAuthorization | null; // 授权省公司(团队权益 20U) authProvinceCompanyAuth: RegionAuthorization | null; // 市公司授权(区域权益 35U + 2% 算力) cityCompanyAuth: RegionAuthorization | null; // 授权市公司(团队权益 40U) authCityCompanyAuth: RegionAuthorization | null; // 社区授权(80U) communityAuth: CommunityAuthorization | null; // 系统账户(用于无授权时的fallback) systemAccounts: { costAccount: SystemAccountInfo; operationAccount: SystemAccountInfo; hqCommunityAccount: SystemAccountInfo; rwadPoolAccount: SystemAccountInfo; systemProvinceAccount: SystemAccountInfo; systemCityAccount: SystemAccountInfo; }; } @Injectable() export class AuthorizationServiceClient { private readonly logger = new Logger(AuthorizationServiceClient.name); private readonly baseUrl: string; constructor( private readonly configService: ConfigService, private readonly httpService: HttpService, ) { this.baseUrl = this.configService.get('AUTHORIZATION_SERVICE_URL') || 'http://localhost:3005'; } /** * 获取分配上下文 - 查询省市社区授权状态和系统账户 */ async getAllocationContext( planterId: string, provinceCode: string, cityCode: string, ): Promise { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/allocations/context`, { params: { planterId, provinceCode, cityCode, }, }, ), ); return response.data; } catch (error) { this.logger.error( `Failed to get allocation context for planter ${planterId}`, error, ); // 开发环境返回默认数据 if (this.configService.get('NODE_ENV') === 'development') { this.logger.warn( 'Development mode: returning default allocation context', ); return this.getDefaultAllocationContext(provinceCode, cityCode); } throw error; } } /** * 获取省区域权益接收方 */ async getProvinceAreaRightsRecipient( provinceCode: string, ): Promise<{ recipientType: 'USER' | 'SYSTEM'; recipientId: string; hashpowerPercent: number }> { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/authorizations/province/${provinceCode}/area-rights`, ), ); return response.data; } catch (error) { this.logger.error(`Failed to get province area rights recipient for ${provinceCode}`, error); // 返回系统省账户作为默认 return { recipientType: 'SYSTEM', recipientId: `SYSTEM_PROVINCE:${provinceCode}`, hashpowerPercent: 0, }; } } /** * 获取省团队权益接收方 */ async getProvinceTeamRightsRecipient( provinceCode: string, ): Promise<{ recipientType: 'USER' | 'SYSTEM'; recipientId: string }> { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/authorizations/province/${provinceCode}/team-rights`, ), ); return response.data; } catch (error) { this.logger.error(`Failed to get province team rights recipient for ${provinceCode}`, error); return { recipientType: 'SYSTEM', recipientId: `SYSTEM_PROVINCE:${provinceCode}`, }; } } /** * 获取市区域权益接收方 */ async getCityAreaRightsRecipient( cityCode: string, ): Promise<{ recipientType: 'USER' | 'SYSTEM'; recipientId: string; hashpowerPercent: number }> { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/authorizations/city/${cityCode}/area-rights`, ), ); return response.data; } catch (error) { this.logger.error(`Failed to get city area rights recipient for ${cityCode}`, error); return { recipientType: 'SYSTEM', recipientId: `SYSTEM_CITY:${cityCode}`, hashpowerPercent: 0, }; } } /** * 获取市团队权益接收方 */ async getCityTeamRightsRecipient( cityCode: string, ): Promise<{ recipientType: 'USER' | 'SYSTEM'; recipientId: string }> { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/authorizations/city/${cityCode}/team-rights`, ), ); return response.data; } catch (error) { this.logger.error(`Failed to get city team rights recipient for ${cityCode}`, error); return { recipientType: 'SYSTEM', recipientId: `SYSTEM_CITY:${cityCode}`, }; } } /** * 获取社区权益接收方 */ async getCommunityRightsRecipient( planterId: string, ): Promise<{ recipientType: 'USER' | 'SYSTEM'; recipientId: string } | null> { try { const response = await firstValueFrom( this.httpService.get( `${this.baseUrl}/api/v1/authorizations/user/${planterId}/community-rights`, ), ); return response.data; } catch (error) { this.logger.error(`Failed to get community rights recipient for ${planterId}`, error); return null; } } /** * 通知认种完成,更新考核进度 */ async notifyPlantingCompleted(params: { planterId: string; treeCount: number; provinceCode: string; cityCode: string; orderId: string; }): Promise { try { await firstValueFrom( this.httpService.post( `${this.baseUrl}/api/v1/allocations/planting-completed`, params, ), ); } catch (error) { this.logger.error('Failed to notify planting completed', error); // 不抛出错误,允许继续执行 } } /** * 获取默认分配上下文(开发环境用) */ private getDefaultAllocationContext( provinceCode: string, cityCode: string, ): AllocationContext { return { provinceCompanyAuth: null, authProvinceCompanyAuth: null, cityCompanyAuth: null, authCityCompanyAuth: null, communityAuth: null, systemAccounts: { costAccount: { accountId: '1', accountType: 'COST_ACCOUNT', regionCode: null, walletAddress: null, }, operationAccount: { accountId: '2', accountType: 'OPERATION_ACCOUNT', regionCode: null, walletAddress: null, }, hqCommunityAccount: { accountId: '3', accountType: 'HQ_COMMUNITY', regionCode: null, walletAddress: null, }, rwadPoolAccount: { accountId: '4', accountType: 'RWAD_POOL_PENDING', regionCode: null, walletAddress: null, }, systemProvinceAccount: { accountId: `PROVINCE:${provinceCode}`, accountType: 'SYSTEM_PROVINCE', regionCode: provinceCode, walletAddress: null, }, systemCityAccount: { accountId: `CITY:${cityCode}`, accountType: 'SYSTEM_CITY', regionCode: cityCode, walletAddress: null, }, }, }; } }