ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot/React] CoolSMS API 사용해 문자 인증 구현
    Project/외국인 관광객을 위한 카드 플랫폼 2024. 8. 24. 19:49

    - 백엔드 코드 (Spring Boot)

     

    1. buil.gradle에 아래 코드 추가

    implementation 'net.nurigo:sdk:4.2.7'

     

     

    2. application.yaml에 아래 코드 추가

    coolsms:
      api:
        key: 쿨SMS에서 받은 API키
        secret: 쿨SMS에서 받은 SECRET키
        number: 핸드폰 번호

     

     

    3. Controller 코드 작성

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import net.nurigo.sdk.NurigoApp;
    import net.nurigo.sdk.message.model.Message;
    import net.nurigo.sdk.message.request.SingleMessageSendingRequest;
    import net.nurigo.sdk.message.response.SingleMessageSentResponse;
    import net.nurigo.sdk.message.service.DefaultMessageService;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.*;
    
    import jakarta.annotation.PostConstruct;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    @RestController
    public class SMSController {
    
    	private DefaultMessageService messageService;
    	private Map<String, String> verificationCodes = new HashMap<>(); // 전화번호별 인증번호 저장
    
    	@Value("${coolsms.api.key}")
    	private String apiKey;
    
    	@Value("${coolsms.api.secret}")
    	private String apiSecret;
    
    	@Value("${coolsms.api.number}")
    	private String fromNumber;
    
    	@PostConstruct
    	public void init() {
    		this.messageService = NurigoApp.INSTANCE.initialize(apiKey, apiSecret, "https://api.coolsms.co.kr");
    	}
    
    	/**
    	 * 단일 메시지 발송 예제
    	 */
    	@PostMapping("/send-one")
    	public SingleMessageSentResponse sendOne(@RequestBody SMSRequest smsRequest) {
    		String phoneNumber = smsRequest.getPhoneNumber();
    		String verificationCode = generateVerificationCode();
    		verificationCodes.put(phoneNumber, verificationCode); // 전화번호와 인증번호 매핑
    
    		Message message = new Message();
    		message.setFrom(fromNumber);
    		message.setTo(phoneNumber);
    		message.setText("인증번호는 " + verificationCode + "입니다.");
    
    		SingleMessageSentResponse response = this.messageService.sendOne(new SingleMessageSendingRequest(message));
    		System.out.println(response);
    
    		return response;
    	}
    
    	/**
    	 * 인증번호 확인 예제
    	 */
    	@PostMapping("/verify-code")
    	public boolean verifyCode(@RequestBody VerificationRequest verificationRequest) {
    		String sentCode = verificationCodes.get(verificationRequest.getPhoneNumber());
    		return verificationRequest.getVerificationCode().equals(sentCode);
    	}
    
    	private String generateVerificationCode() {
    		Random random = new Random();
    		int code = 100000 + random.nextInt(900000); // 100000 ~ 999999 사이의 랜덤 6자리 숫자 생성
    		return String.valueOf(code);
    	}
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class SMSRequest {
    	private String phoneNumber;
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class VerificationRequest {
    	private String phoneNumber;
    	private String verificationCode;
    }

     


     

    - 프론트 코드 (React)

    import React, { useState } from 'react';
    import { Input, Button } from '@mui/material';
    import axios from 'axios';
    
    function Card2() {
        // 상태 관리: 휴대전화 번호, 인증번호, 인증번호 발송 여부, 인증 성공 여부
        const [phoneNumber, setPhoneNumber] = useState(''); // 입력된 휴대전화 번호
        const [verificationCode, setVerificationCode] = useState(''); // 입력된 인증번호
        const [isVerificationSent, setIsVerificationSent] = useState(false); // 인증번호 발송 여부
        const [isVerificationSuccessful, setIsVerificationSuccessful] = useState(null); // 인증 성공 여부
    
        // 인증번호 요청 함수
        const handleVerificationRequest = () => {
            // 서버에 인증번호 발송 요청을 보냄
            axios.post('/send-one', { phoneNumber })
                .then(response => {
                    console.log('인증번호 발송 성공:', response.data);
                    setIsVerificationSent(true); // 인증번호 발송 성공 시 입력 필드를 표시하기 위해 상태를 true로 설정
                })
                .catch(error => {
                    console.error('인증번호 발송 실패:', error);
                });
        };
    
        // 인증번호 입력 값 업데이트 함수
        const handleVerificationCodeChange = (event) => {
            setVerificationCode(event.target.value); // 입력된 인증번호를 상태에 저장
        };
    
        // 인증번호 검증 요청 함수
        const handleVerificationSubmit = () => {
            // 서버에 입력된 인증번호 검증 요청을 보냄
            axios.post('/verify-code', { phoneNumber, verificationCode })
                .then(response => {
                    setIsVerificationSuccessful(response.data); // 서버의 응답에 따라 인증 성공 여부를 업데이트
                    if (response.data) {
                        alert('인증 성공!'); // 인증 성공 시 알림 표시
                    } else {
                        alert('인증 실패! 다시 시도해주세요.'); // 인증 실패 시 알림 표시
                    }
                })
                .catch(error => {
                    console.error('인증 실패:', error);
                });
        };
    
        return (
            <div>
                {/* 휴대전화 번호 입력 및 인증번호 요청 버튼 */}
                <div style={{ marginBottom: '30px' }}>
                    <div style={{ justifyContent: 'flex-start', display: 'flex' }}>휴대전화 번호</div>
                    <Input
                        id="phone"
                        placeholder="휴대전화 번호를 입력하세요"
                        value={phoneNumber}
                        onChange={(e) => setPhoneNumber(e.target.value)} // 입력된 전화번호를 상태에 저장
                        style={{ width: '80%' }}
                    />
                    <Button
                        variant="contained"
                        color="primary"
                        onClick={handleVerificationRequest} // 인증번호 요청 버튼 클릭 시 호출
                    >
                        인증
                    </Button>
                    <br />
                </div>
    
                {/* 인증번호 입력 필드 및 확인 버튼, 인증번호 발송 후에만 표시됨 */}
                {isVerificationSent && (
                    <div style={{ marginBottom: '30px' }}>
                        <div style={{ justifyContent: 'flex-start', display: 'flex' }}>인증번호 입력</div>
                        <Input
                            id="verification-code"
                            placeholder="인증번호를 입력하세요"
                            value={verificationCode}
                            onChange={handleVerificationCodeChange} // 입력된 인증번호를 상태에 저장
                            style={{ width: '80%' }}
                        />
                        <Button
                            variant="contained"
                            color="primary"
                            onClick={handleVerificationSubmit} // 인증번호 확인 버튼 클릭 시 호출
                        >
                            확인
                        </Button>
                    </div>
                )}
            </div>
        );
    }
    
    export default Card2;
Designed by Tistory.