Designing a Unified Verification Code Sending Interface

This article discusses the implementation of a unified verification code sending system that handles multiple business scenarios through a comon interface.

Core Implementation

The system processes verification code requests through a cenrtalized service that delegates to specific handler implemantations based on business type codes.

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import com.example.captcha.handler.VerificationHandler;
import com.example.captcha.service.VerificationService;
import com.example.captcha.model.VerificationRequest;
import com.example.common.exception.BusinessException;

@Service
public class VerificationServiceImpl implements VerificationService {

    @Autowired
    private ListableBeanFactory beanFactory;

    @Override
    public void sendVerificationCode(VerificationRequest request) {
        if (!isValidPhoneNumber(request.getPhoneNumber())) {
            throw new BusinessException("Invalid phone number format");
        }
        
        Map<String, VerificationHandler> handlers = 
            beanFactory.getBeansOfType(VerificationHandler.class);
            
        if (CollectionUtils.isEmpty(handlers)) {
            throw new BusinessException("No verification handlers available");
        }

        VerificationHandler targetHandler = handlers.values().stream()
            .filter(handler -> request.getBusinessCode().equals(handler.getHandlerCode()))
            .findFirst()
            .orElseThrow(() -> new BusinessException("Unsupported business type"));
            
        targetHandler.processVerification(request.getPhoneNumber());
    }
    
    private boolean isValidPhoneNumber(String phone) {
        return StringUtils.hasText(phone) && phone.matches("^1[3-9]\\d{9}$");
    }
}

Handler Interface Definition

The VerificationHandler interface defines the contract for all verification code implementations:

import java.time.Duration;
import java.time.LocalDateTime;
import com.example.captcha.manager.VerificationManager;
import com.example.sms.SmsService;
import com.example.sms.model.SmsRequest;

public interface VerificationHandler {
    
    default VerificationManager getVerificationManager() {
        return ApplicationContextProvider.getBean(VerificationManager.class);
    }
    
    String getHandlerCode();
    
    default void processVerification(String phoneNumber) {
        validateBeforeProcessing(phoneNumber);
        
        VerificationRecord existingRecord = 
            getVerificationManager().getVerificationRecord(getHandlerCode(), phoneNumber);
            
        if (existingRecord != null) {
            Duration timeSinceLastSend = Duration.between(
                existingRecord.getCreationTime(), LocalDateTime.now());
                
            if (timeSinceLastSend.getSeconds() < 60) {
                throw new BusinessException("Please wait " + 
                    (60 - timeSinceLastSend.getSeconds()) + " seconds before requesting again");
            }
        }
        
        VerificationRecord newRecord = 
            getVerificationManager().createVerificationRecord(getHandlerCode(), phoneNumber);
            
        SmsService.sendSms(phoneNumber, buildSmsContent(newRecord));
    }
    
    void validateBeforeProcessing(String phoneNumber);
    
    SmsRequest buildSmsContent(VerificationRecord record);
    
    default void validateCode(String phoneNumber, String code) {
        VerificationRecord record = 
            getVerificationManager().getVerificationRecord(getHandlerCode(), phoneNumber);
            
        if (record == null || !record.getPhoneNumber().equals(phoneNumber)) {
            throw new BusinessException("Invalid verification code");
        }
        
        if (!record.getCode().equals(code)) {
            throw new BusinessException("Verification code mismatch");
        }
    }
}

Concrete Handler Implementation

Example implementation for user registration verification:

@Component
public class UserRegistrationHandler implements VerificationHandler {

    @Autowired
    private UserValidationService validationService;

    @Override
    public String getHandlerCode() {
        return "user_registration";
    }

    @Override
    public void validateBeforeProcessing(String phoneNumber) {
        validationService.validateRegistrationPhone(phoneNumber);
    }

    @Override
    public SmsRequest buildSmsContent(VerificationRecord record) {
        return SmsTemplate.createVerificationSms(
            "YourCompany", 
            "SMS_TEMPLATE_12345", 
            Map.of("code", record.getCode())
        );
    }
}

Tags: java Spring Boot SMS Verification Design Patterns Interface Design

Posted on Fri, 24 Jul 2026 16:32:55 +0000 by docmattman