Add production-ready SuperAdmin API features for tenants, SMS, servers, and plugins.
Includes mobile auth, get_user/get_version, SMS wallet parity endpoints, appearance backfill, and related Prisma migrations. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import axios from 'axios';
|
||||
import { normalizeMobile } from '../common/mobile.util';
|
||||
|
||||
export type CentralSmsResult = {
|
||||
success: boolean;
|
||||
raw?: unknown;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class CentralSmsService {
|
||||
private readonly logger = new Logger(CentralSmsService.name);
|
||||
|
||||
constructor(private readonly config: ConfigService) {}
|
||||
|
||||
async send(phone: string, text: string): Promise<CentralSmsResult> {
|
||||
const to = normalizeMobile(phone);
|
||||
const message = text.trim();
|
||||
|
||||
if (!to) {
|
||||
return { success: false, error: 'شماره موبایل نامعتبر است' };
|
||||
}
|
||||
if (!message) {
|
||||
return { success: false, error: 'متن پیامک خالی است' };
|
||||
}
|
||||
|
||||
const url =
|
||||
this.config.get<string>('CENTRAL_SMS_URL') ||
|
||||
'http://185.231.112.101/api/createsms';
|
||||
const secret = this.config.get<string>('CENTRAL_SMS_SECRET')?.trim();
|
||||
if (!secret) {
|
||||
this.logger.error('CENTRAL_SMS_SECRET is not configured');
|
||||
return { success: false, error: 'سرویس پیامک پیکربندی نشده است' };
|
||||
}
|
||||
const host =
|
||||
this.config.get<string>('CENTRAL_SMS_HOST') || 'superadmin';
|
||||
const platform =
|
||||
this.config.get<string>('CENTRAL_SMS_PLATFORM') || 'superadmin';
|
||||
|
||||
try {
|
||||
const response = await axios.post(
|
||||
url,
|
||||
{
|
||||
phone: to,
|
||||
host,
|
||||
text: message,
|
||||
platform,
|
||||
},
|
||||
{
|
||||
timeout: 15000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
secret_key: secret,
|
||||
},
|
||||
// Prefer IPv4 like Hamkar curl CURLOPT_IPRESOLVE_V4
|
||||
family: 4,
|
||||
validateStatus: () => true,
|
||||
},
|
||||
);
|
||||
|
||||
const body = response.data;
|
||||
let success = response.status >= 200 && response.status < 300;
|
||||
|
||||
if (body && typeof body === 'object') {
|
||||
if (body.success === false || body.ok === false) success = false;
|
||||
const status = String(body.status ?? '').toLowerCase();
|
||||
if (['error', 'failed', 'fail'].includes(status)) success = false;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
this.logger.warn(`Central SMS failed to ${to} (HTTP ${response.status})`);
|
||||
}
|
||||
|
||||
return { success, raw: body };
|
||||
} catch (error: any) {
|
||||
const msg = error?.message || 'SMS send error';
|
||||
this.logger.error(`Central SMS exception to ${to}: ${msg}`);
|
||||
return { success: false, error: msg };
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user