SpringBoot 문자 인증 서비스

정윤서·2023년 12월 12일
0
post-custom-banner

문자 인증 서비스 구현 (CoolSMS)

1. build.gradle에 의존성 추가

dependencies {
	implementation group: 'net.nurigo', name: 'javaSDK', version: '2.2'
    // ..다른 의존성들
}

2. SMSService 작성

먼저 coolSMS 사이트에서 apiKey 발급받기

@Service
public class SMSService {

    private String apiKey = "your_api_key";

    private String apiSecret = "your_api_secret";

    public void sendMessage(String phoneNumber, String verKey) {
        Message coolsms = new Message(apiKey, apiSecret);
        HashMap<String, String> params = new HashMap();
        params.put("to", phoneNumber);
        params.put("from", "your_phone_number");
        params.put("type", "SMS");
        params.put("text", "[프로젝트 이름] 인증번호는 " + "["+verKey+"]" + " 입니다.");

        try {
            JSONObject obj = (JSONObject) coolsms.send(params);
        } catch (CoolsmsException e) {
            e.printStackTrace();
        }
    }

}

메시지는 json 형식으로 전송 가능하다.

3. SMSController 작성

@Controller
@RequiredArgsConstructor
public class SMSController {

    private final SMSService smsService;

	// 랜덤으로 4자리 인증번호 만들어줄 함수
    public String createRandomNumber() {
        Random rand = new Random();
        String randomNum = "";
        for (int i = 0; i < 4; i++) {
            String random = Integer.toString(rand.nextInt(10));
            randomNum += random;
        }

        return randomNum;
    }

	// html에서 사용자의 전화번호를 받아와 인증번호를 전송하는 함수
    @GetMapping("/send")
    public String send(@RequestParam String phoneNumber, HttpSession session) {
        String verKey = createRandomNumber();
        smsService.sendMessage(phoneNumber, verKey);

        session.setAttribute("verKey", verKey);

        return "redirect:/";
    }
	
	// 전송된 인증번호를 html 폼으로 보내는 함수
    // -> 사용자가 입력한 인증번호와 실제로 전송된 인증번호가 일치한지 확인하기 위해
    @GetMapping("/sendVerKey")
    public ResponseEntity<Map<String, String>> getVerificationKey(HttpSession session) {
        String verKey = (String) session.getAttribute("verKey");

        Map<String, String> response = new HashMap<>();
        response.put("verKey", verKey);
        return ResponseEntity.ok(response);
    }

}
// 인증번호
// 전화번호를 받아서 컨트롤러로 보내는 함수
function sendMessage() {
  var phoneNumber = document.getElementById("phoneNum").value;
  if (phoneNumber == "")
    alert("전화번호를 입력해주세요.");
  else {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/send?phoneNumber=" + encodeURIComponent(phoneNumber), true);

    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4 && xhr.status == 200) {
        $('#exampleModal').modal('hide');
        requestVerificationKey();
      }
    };

    xhr.send();
  }
}

var serverVerKey;

// 컨트롤러에서 인증번호를 받아오는 함수
function requestVerificationKey() {
  $.ajax({
    url: "/sendVerKey",
    type: "GET",
    data: { timestamp: new Date().getTime() },
    success: function (response) {
      serverVerKey = response.verKey;
    },
    error: function () {
      console.error("인증번호를 가져오는 중에 오류가 발생했습니다.");
    }
  });
}

// 인증 확인을 위한 함수
$("#verKeyBtn").click(function () {
  document.getElementById("verKey").value = "";
  requestVerificationKey();
});

$(document).ready(function () {
  requestVerificationKey();
});

function checkVerificationKey() {
  var enteredKey = document.getElementById("verKey").value;

  if (enteredKey === serverVerKey) {
    document.getElementById("verKey").classList.remove("is-invalid");
    document.getElementById("verKey").classList.add("is-valid");
    document.getElementById("verResult").classList.remove("invalid-feedback");
    document.getElementById("verResult").classList.add("valid-feedback");
    document.getElementById("verResult").textContent = "인증 완료되었습니다.";
  } else {
    document.getElementById("verKey").classList.add("is-invalid");
    document.getElementById("verResult").classList.add("invalid-feedback");
    document.getElementById("verResult").textContent = "인증번호가 일치하지 않습니다.";
  }
}
<!-- 전화번호 인증을 위한 html폼 -->
<div class="mb-3">
  <label class="form-label border-bottom" for="verify">전화번호 인증</label>
  <!-- 인증 버튼 -->
  <div class="mb-3">
    <button type="button" class="버튼 btn btn-sm me-2"
            data-bs-toggle="modal"
            data-bs-target="#exampleModal" id="verBtn">
      전화번호 인증
    </button>
    <span style="font-size:13px;">※ '-' 를 제외한 전화번호 11자리를 입력해주세요.</span>
  </div>
  <div class="d-flex justify-content-between align-items-start" style="width:70%;">
    <div style="width:85%;" class="me-1">
      <input type="text" class="form-control" id="verKey" placeholder="인증번호 입력">
      <div id="verResult"></div>
    </div>
    <input type="button" class="버튼 btn" value="확인" onclick="checkVerificationKey()">
  </div>
  <!-- 모달 -->
  <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel"
       aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h1 class="modal-title fs-5" id="exampleModalLabel">전화번호 인증</h1>
          <button type="button" class="btn-close" data-bs-dismiss="modal"
                  aria-label="Close">
          </button>
        </div>
        <div class="modal-body">
          <input type="text" class="form-control" placeholder="'-' 없이 입력해주세요."
                 id="phoneNum">
        </div>
        <div class="modal-footer">
          <button type="button" class="버튼 btn" id="verKeyBtn"
                  onclick="sendMessage()">인증번호 발송
          </button>
        </div>
      </div>
    </div>
  </div>
</div>
post-custom-banner

0개의 댓글