SmsService.java 5.63 KB
package com.ecommerce.notification.service;

import com.ecommerce.notification.model.Notification;
import com.ecommerce.notification.model.dto.SmsRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class SmsService {
    
    private final RestTemplate restTemplate;
    private final TemplateService templateService;
    
    @Value("${sms.provider:twilio}")
    private String smsProvider;
    
    @Value("${twilio.account-sid:default-sid}")
    private String twilioAccountSid;
    
    @Value("${twilio.auth-token:default-token}")
    private String twilioAuthToken;
    
    @Value("${twilio.phone-number:+1234567890}")
    private String twilioPhoneNumber;
    
    @Value("${aws.sns.region:us-east-1}")
    private String awsSnsRegion;
    
    public boolean sendSms(Notification notification) {
        try {
            String message = notification.getContent();
            
            // Process template if provided
            if (notification.getTemplateName() != null) {
                Map<String, Object> templateResult = templateService.processTemplate(
                        notification.getTemplateName(), 
                        "SMS", 
                        new HashMap<>()
                );
                message = (String) templateResult.get("content");
            }
            
            switch (smsProvider.toUpperCase()) {
                case "TWILIO":
                    return sendViaTwilio(notification.getPhone(), message);
                case "AWS_SNS":
                    return sendViaAwsSns(notification.getPhone(), message);
                default:
                    log.warn("SMS provider {} not supported, using simulation", smsProvider);
                    return simulateSms(notification.getPhone(), message);
            }
            
        } catch (Exception e) {
            log.error("Failed to send SMS to {}: {}", notification.getPhone(), e.getMessage());
            return false;
        }
    }
    
    public boolean sendSms(SmsRequest request) {
        try {
            String message = request.getMessage();
            
            // Process template if provided
            if (request.getTemplateName() != null) {
                Map<String, Object> templateResult = templateService.processTemplate(
                        request.getTemplateName(), 
                        "SMS", 
                        request.getVariables()
                );
                message = (String) templateResult.get("content");
            }
            
            switch (smsProvider.toUpperCase()) {
                case "TWILIO":
                    return sendViaTwilio(request.getTo(), message);
                case "AWS_SNS":
                    return sendViaAwsSns(request.getTo(), message);
                default:
                    log.warn("SMS provider {} not supported, using simulation", smsProvider);
                    return simulateSms(request.getTo(), message);
            }
            
        } catch (Exception e) {
            log.error("Failed to send SMS to {}: {}", request.getTo(), e.getMessage());
            return false;
        }
    }
    
    private boolean sendViaTwilio(String to, String message) {
        try {
            String url = String.format("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json", 
                    twilioAccountSid);
            
            HttpHeaders headers = new HttpHeaders();
            headers.setBasicAuth(twilioAccountSid, twilioAuthToken);
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            
            String body = String.format("From=%s&To=%s&Body=%s", 
                    twilioPhoneNumber, to, message);
            
            HttpEntity<String> request = new HttpEntity<>(body, headers);
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
            
            boolean success = response.getStatusCode().is2xxSuccessful();
            if (success) {
                log.info("SMS sent via Twilio to: {}", to);
            } else {
                log.error("Twilio API error: {}", response.getBody());
            }
            
            return success;
            
        } catch (Exception e) {
            log.error("Twilio SMS sending failed: {}", e.getMessage());
            return false;
        }
    }
    
    private boolean sendViaAwsSns(String to, String message) {
        try {
            // In production, use AWS SDK for Java v2
            // For demo, simulate AWS SNS
            log.info("Simulating AWS SNS SMS to {}: {}", to, message);
            return simulateSms(to, message);
            
        } catch (Exception e) {
            log.error("AWS SNS SMS sending failed: {}", e.getMessage());
            return false;
        }
    }
    
    private boolean simulateSms(String to, String message) {
        try {
            // Simulate SMS sending with 95% success rate
            boolean success = Math.random() > 0.05;
            
            if (success) {
                log.info("SMS simulated successfully to {}: {}", to, message);
            } else {
                log.warn("SMS simulation failed to: {}", to);
            }
            
            return success;
            
        } catch (Exception e) {
            log.error("SMS simulation failed: {}", e.getMessage());
            return false;
        }
    }
}