export interface NetGsmConfig { username?: string; password?: string; header?: string; apiUrl?: string; } export interface SmsResult { success: boolean; jobId?: string; error?: string; code?: string; } export class NetGsmService { private config: NetGsmConfig; constructor(config: NetGsmConfig) { this.config = config; } /** * Send SMS using NetGSM GET API * Refer: https://www.netgsm.com.tr/dokuman/#http-get-servisi */ async sendSms(phone: string, message: string): Promise { if (!this.config.username || !this.config.password || !this.config.header) { return { success: false, error: "NetGSM konfigürasyonu eksik." }; } // Clean phone number (remove spaces, parentheses, etc) // NetGSM expects 905xxxxxxxxx or just 5xxxxxxxxx, we'll ensure format let cleanPhone = phone.replace(/\D/g, ''); if (cleanPhone.startsWith('90')) { cleanPhone = cleanPhone.substring(0); // keep it } else if (cleanPhone.startsWith('0')) { cleanPhone = '9' + cleanPhone; } else if (cleanPhone.length === 10) { cleanPhone = '90' + cleanPhone; } try { // Encode parameters const params = new URLSearchParams({ usercode: this.config.username, password: this.config.password, gsmno: cleanPhone, message: message, msgheader: this.config.header, dil: 'TR' // Turkish characters support }); const url = `${this.config.apiUrl || 'https://api.netgsm.com.tr/sms/send/get'}?${params.toString()}`; const response = await fetch(url); const textResponse = await response.text(); // NetGSM returns a code (e.g. 00 123456789) or error code (e.g. 20) // Codes starting with 00, 01, 02 indicate success const code = textResponse.split(' ')[0]; if (['00', '01', '02'].includes(code)) { return { success: true, jobId: textResponse.split(' ')[1] || code, code }; } else { const errorMap: Record = { '20': 'Mesaj metni ya da karakter sınırını (1.000) aştı veya mesaj boş.', '30': 'Geçersiz kullanıcı adı , şifre veya kullanıcınızın API erişim izni yok.', '40': 'Gönderici adı (Başlık) sistemde tanımlı değil.', '70': 'Hatalı sorgu.', '50': 'Kendi numaranıza veya Rehberden SMS gönderiyorsanız; Abone kendi numarasını veya rehberindeki bir numarayı gönderici kimliği (MsgHeader) olarak kullanamaz.', '51': 'Aboneliğinizin süresi dolmuş.', '52': 'Aboneliğiniz bulunmamaktadır.', '60': 'Bakiyeniz yetersiz.', '71': 'Gönderim yapmak istediğiniz gsm numarası/numaraları hatalı.' }; return { success: false, code, error: errorMap[code] || `Bilinmeyen hata kodu: ${code} - Yanıt: ${textResponse}` }; } } catch (error) { return { success: false, error: (error as Error).message }; } } }