Recaptcha v3 및 PHP를 사용한 문의 양식

7588 단어 javascriptphprecapcha
제 웹사이트의 이전 문의 양식은 꽤 기능하지 않는 인증 코드 시스템이 있는 오래된 워드프레스 플러그인이었기 때문에 최근에 업데이트하기로 결정했습니다. 나는 DIY하고 사용할 것이라고 생각했습니다. Google's Recapcha V3 . 그것은 기본 html, 바닐라 자바 ​​스크립트 및 PHP입니다. javascript의 forEach 기능을 사용하고 있기 때문에 IE에서는 지원하지 않습니다.

HTML

<div id="contact-form-box">
    <form method="post" id="contactform" action="your-file-to-post-to.php">
        <div>
            <label for="name">Name <span class="req">*</span></label>
            <input id="name" type="text" class="einput" name="name" required="required">
        </div>
        <div>
            <label for="email">Email <span class="req">*</span></label>
            <input id="email" type="email" class="einput" name="email" required="required">
        </div>
        <div>
            <label for="message">Message <span class="req">*</span></label>
            <textarea id="message" class="einput" name="message" required="required"></textarea>
        </div>
        <div id="errorlog"></div>
        <div>
            <button type="submit">Submit</button>
        </div>
    </form>
</div>


자바스크립트
recapcha 토큰을 받고 양식을 제출합니다. 발생하는 모든 오류는 양식의 #errorlog div에 사용자에게 친숙한 메시지를 넣습니다.
두 가지 기능이 있습니다. 하나는 발생하는 오류를 처리하는 기능이고 다른 하나는 양식을 제출하는 기능입니다. 먼저 양식을 제출하는 동안 제출 버튼이 disabled이 되도록 설정했습니다. 그런 다음 불완전한 제출을 피하기 위해 빈 필드(.einput)를 확인합니다. 마지막으로 Google에서 제공하는 스크립트를 사용하여 recapcha 토큰을 얻고 javascriptfetch api를 사용하여 양식을 제출합니다. 오류가 없으면 양식이 지워지고 제출된 메시지가 그 안에 들어갑니다.

<script src="https://www.google.com/recaptcha/api.js?render=YOUR RECAPCHA KEY"></script>
<script>

function doError(msg){
    button.disabled = false;
    button.textContent = "Submit";
    log.className = "error message";
    log.textContent = msg;
}

function formSubmit(event){
    event.preventDefault();
    button.disabled = true;
    button.textContent = "Sending...";
    log.className = "";
    log.textContent = "";
    try{
        form.querySelectorAll(".einput").forEach(einput => {
            console.log(einput.value);
            if(einput.value == ""){
                throw "Please fill out all fields.";
            }
        });
        const formdata = new FormData(form);
        grecaptcha.ready(function() {
            grecaptcha.execute('YOUR RECAPCHA KEY', {action: 'submit'}).then(function(token) {
            formdata.append('g-recaptcha-response', token);
                fetch(form.action, {
                    method: 'POST',
                    body: formdata
                })
                .then((res) => res.json())
                .then((data) => {
                    if(data.status == 200){
                        form.innerHTML = "";
                        form.textContent = "Submitted, thanks!";
                        form.classList.add("submitted");
                    }
                    else{
                        throw data.message;
                    }
                })
                .catch((err) => {
                    doError("Sorry there was a problem submitting the form, please try again.");
                });
            });
        });
    }
    catch(e){
        doError(e);
    }
}
const form = document.getElementById("contactform");
const log = document.getElementById("errorlog");
const button = form.querySelector("button");
form.addEventListener("submit", formSubmit);

</script>


PHP
마지막으로 양식의 게시된 데이터를 처리하는 스크립트가 포함된 PHP 파일(your-file-to-post-to.php)이 있습니다.
checkPostAndSendEmail 기능은 빈 메시지에 대한 마지막 확인을 수행하고 recapcha 비밀 및 recapcha 토큰도 확인하고 이메일 주소 구조의 유효성을 검사합니다. 그런 다음 cURL을 사용하여 Google의 recapcha 확인 URL에 비밀 및 토큰을 게시하고 응답을 확인하고 문제가 없으면 이메일을 보내기 위해 이동합니다. 내 요구 사항은 매우 간단하므로 이메일을 보내는 데 많은 처리가 필요하지 않습니다. 게시된 필드를 implode()과 함께 붙여서 보내면 됩니다. 최종 결과는 상태(200 또는 400) 및 메시지와 함께 자바스크립트로 다시 전송되는 json 문자열입니다.

function checkPostAndSendEmail($post=[],$secret=''){
  if(empty($secret)){
    throw new \Exception('fail');
  }
  if(empty($post['g-recaptcha-response'])){
    throw new \Exception('Recapcha empty');
  }
  if (!filter_var($post['email'], FILTER_VALIDATE_EMAIL)) {
    throw new \Exception('Bad Email');
  }
  if(empty($post['message'])){
    throw new \Exception('No Message');  
  }
  $recapchapost['secret'] = $secret;
  $recapchapost['response'] = $post['g-recaptcha-response'];
  $url = 'https://www.google.com/recaptcha/api/siteverify';
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $recapchapost);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 
  curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  $response = curl_exec($ch);
  if(curl_errno($ch)){
    throw new \Exception(curl_error($ch));
  }
  curl_close($ch);
  $capcharesponse = json_decode($response,true);
  if(!$capcharesponse['success'] || $capcharesponse['score']<.5){
    throw new \Exception('Recapcha failed '.json_encode($capcharesponse['error-codes']));
  }
  unset($post['g-recaptcha-response']);
  $message = implode('<br>',$post);
  $to = 'ADDRESS WHERE THE EMAIL IS SENT';
  $subject = 'Contact Form Submit';
  $headers = "MIME-Version: 1.0\r\n";
  $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";
  $headers .= "X-Priority: 3\r\n";
  $headers .= "X-Mailer: PHP". phpversion() ."\r\n";

  if(!mail($to, $subject, $message, $headers)){
    throw new \Exception('Unable to send email');
  }
}



if(isset($_POST['name'])){
  try{
    checkPostAndSendEmail($_POST,'RECAPCHA SECRET');
    $response = ['status'=>200, 'message'=>'message sent'];
  }
  catch(\Exception $e){
    $errormsg = $e->getMessage();
    $response = ['status'=>400, 'message'=>$errormsg];
  }
  header('Content-type: application/json');
  exit(json_encode($response));
}


Google's site에서 Recapcha 프로세스 및 세부 정보에 대해 자세히 알아볼 수 있습니다.

좋은 웹페이지 즐겨찾기