通过ajax发布带有google recaptcha的表单

I have the following 'contact me' form (in a partial) in OctoberCMS

    <form name="sentMessage" id="contactForm" novalidate>
        <div class="row control-group">
            <div class="form-group col-xs-12 floating-label-form-group controls">
                <label>Name</label>
                <input type="text" class="form-control" placeholder="Name" id="name" required data-validation-required-message="Please enter your name.">
                <p class="help-block text-danger"></p>
            </div>
        </div>
        <div class="row control-group">
            <div class="form-group col-xs-12 floating-label-form-group controls">
                <label>Email Address</label>
                <input type="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="Please enter your email address.">
                <p class="help-block text-danger"></p>
            </div>
        </div>
        <div class="row control-group">
            <div class="form-group col-xs-12 floating-label-form-group controls">
                <label>Phone Number</label>
                <input type="tel" class="form-control" placeholder="Phone Number" id="phone" required data-validation-required-message="Please enter your phone number.">
                <p class="help-block text-danger"></p>
            </div>
        </div>
        <div class="row control-group">
            <div class="form-group col-xs-12 floating-label-form-group controls">
                <label>Message</label>
                <textarea rows="5" class="form-control" placeholder="Message" id="message" required data-validation-required-message="Please enter a message."></textarea>
                <p class="help-block text-danger"></p>
            </div>
        </div>
        <br>
        <div class="g-recaptcha" id="gcaptcha" data-sitekey="sitekeydataCjaelksjEJlakch"></div>
        <div id="success"></div>
        <div class="row">
            <div class="form-group col-xs-12">
                <button type="submit" class="btn btn-success btn-lg">Send</button>
            </div>
        </div>
    </form>

When the user clicks submit - it's handled via javascript (which is what helps with input validation). I'm using JQuery.

The JS looks like this:

$(function() {
    $("input,textarea").jqBootstrapValidation({
        preventSubmit: true,
        submitError: function($form, event, errors) {
            // additional error messages or events
        },
        submitSuccess: function($form, event) {
            event.preventDefault(); // prevent default submit behaviour
            // get values from FORM
            var name = $("input#name").val();
            var email = $("input#email").val();
            var phone = $("input#phone").val();
            var message = $("textarea#message").val();
            var gcaptcha = $("#gcaptcha").data('sitekey');

            var firstName = name; // For Success/Failure Message
            // Check for white space in name for Success/Fail message
            if (firstName.indexOf(' ') >= 0) {
                firstName = name.split(' ').slice(0, -1).join(' ');
            }
            $.ajax({
                url: "././mail/contact_me.php",
                type: "POST",
                data: {
                    name: name,
                    phone: phone,
                    email: email,
                    message: message,
                    gcaptcha: gcaptcha
                },
                cache: false,
                success: function() {
                    // Success message
                    $('#success').html("<div class='alert alert-success'>");
                    $('#success > .alert-success').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
                        .append("</button>");
                    $('#success > .alert-success')
                        .append("<strong>Your message has been sent. </strong>");
                    $('#success > .alert-success')
                        .append('</div>');

                    //clear all fields
                    $('#contactForm').trigger("reset");
                },
                error: function() {
                    // Fail message
                    $('#success').html("<div class='alert alert-danger'>");
                    $('#success > .alert-danger').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>&times;")
                        .append("</button>");
                    $('#success > .alert-danger').append("<strong>Sorry " + firstName + ", it seems that my mail server is not responding. Please try again later!");
                    $('#success > .alert-danger').append('</div>');
                    //clear all fields
                    $('#contactForm').trigger("reset");
                },
            })
        },
        filter: function() {
            return $(this).is(":visible");
        },
    });

    $("a[data-toggle=\"tab\"]").click(function(e) {
        e.preventDefault();
        $(this).tab("show");
    });
});

The contact_me.php form looks like this:

<?php

// Check for empty fields
if(empty($_POST['name'])        ||
   empty($_POST['email'])       ||
   empty($_POST['phone'])       ||
   empty($_POST['message']) ||
   !filter_var($_POST['email'],FILTER_VALIDATE_EMAIL))
   {
    echo "No arguments Provided!";
    return false;
   }

$name = strip_tags(htmlspecialchars($_POST['name']));
$email_address = strip_tags(htmlspecialchars($_POST['email']));
$phone = strip_tags(htmlspecialchars($_POST['phone']));
$message = strip_tags(htmlspecialchars($_POST['message']));
$secret = "alkfejasupersecretkeyalkjeociyseh13987fa9s8df7";
$gcaptcha = $_POST['gcaptcha'];
$remoteip = $_SERVER['REMOTE_ADDR'];

$url = "https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$gcaptcha."&remoteip=".$remoteip;
$result = json_decode($url, true);
var_dump($result);
/*
if ($result['success'] == 1) {
    //do mail here
}


// Create the email and send the message
$to = 'myemail@gmail.com'; // Add your email address inbetween the '' replacing yourname@yourdomain.com - This is where the form will send a message to.
$email_subject = "Website Contact Form:  $name";
$email_body = "You have received a new message from your website contact form.

"."Here are the details:

Name: $name

Email: $email_address

Phone: $phone

Message:
$message";
$headers = "From: noreply@yourdomain.com
"; // This is the email address the generated message will be from. We recommend using something like noreply@yourdomain.com.
$headers .= "Reply-To: $email_address";
mail($to,$email_subject,$email_body,$headers);
return true;
*/
?>

As you can see - I'm trying to just see if I'm even getting to the contact_me.php form which it doesn't appear I am. Before I had commented it out - the mail never sent - which is why I started playing around trying to see if my data is even hitting the contact_me.php page. I see the success message when submitting - but the data never goes anywhere and no email is ever had.

I can see in Firebug that the data is posting to contact_me - but I can't tell much beyond that. The var_dump doesn't work and I'm in need of further assistance to either better troubleshoot this issue or figure out what isn't working.

dscojuxf69080
dscojuxf69080 让我们在聊天中继续讨论。
3 年多之前 回复
douwengzao5790
douwengzao5790 目录结构是这样的:theme/assets/javascript/contact_me.js和php位于:theme/mail/contact_me.php。当我将././mail/contact_me.php更改为../../mail/contact_me.php并提交表单时-弹出错误消息并在网络选项卡(firebug)中,我看到404错误。当URL为././mail/contact_me.php时,我没有看到404
3 年多之前 回复
dongpi9480
dongpi9480 ././mail/contact_me.php,等于mail/contact_me.php。当然你找到了正确的文件?你如何只是回显数据并捕获:成功(响应){alert(response)}?这实际上就是要求诊断。
3 年多之前 回复
dou47278
dou47278 var_dump($_POST)没有说什么,我只是看到屏幕上弹出的成功消息。
3 年多之前 回复
dongzichan2886
dongzichan2886 现在,mail()被完全注释掉-只是想看看发布了什么,并确保它们都得到了适当的传递。
3 年多之前 回复
dongliuzi3410
dongliuzi3410 var_dump($_POST)说什么?
3 年多之前 回复
dongxun1244
dongxun1244 其次。如果邮件返回true或false,则采取第一步。更好的是,根本不要使用mail()。
3 年多之前 回复
dongyuntao2000
dongyuntao2000 filter_var()缺少类型检查,!==或===
3 年多之前 回复

1个回答

After a lot of help from Xorifelse in the comments I realized that the code was probably fine (or at least suitable).

I ended up going a different direction. I updated the form a bit so it looks like this:

<div class="container">
    <div class="row">
        <div class="col-lg-12 text-center">
            <h2>Contact Me</h2>
            <hr class="star-primary">
        </div>
    </div>
    <div class="row">
        <div class="col-lg-8 col-lg-offset-2">
            <form name="sentMessage" id="contactForm" data-request="onSend" data-request-success="alert('We have received your email. Thank you!'); this.reset();" novalidate>
                <div class="row control-group">
                    <div class="form-group col-xs-12 floating-label-form-group controls">
                        <label>Name</label>
                        <input name="name" type="text" class="form-control" placeholder="Name" id="name" required data-validation-required-message="Please enter your name.">
                        <p class="help-block text-danger"></p>
                    </div>
                </div>
                <div class="row control-group">
                    <div class="form-group col-xs-12 floating-label-form-group controls">
                        <label>Email Address</label>
                        <input name="email" type="email" class="form-control" placeholder="Email Address" id="email" required data-validation-required-message="Please enter your email address.">
                        <p class="help-block text-danger"></p>
                    </div>
                </div>
                <div class="row control-group">
                    <div class="form-group col-xs-12 floating-label-form-group controls">
                        <label>Phone Number</label>
                        <input name="phone" type="tel" class="form-control" placeholder="Phone Number" id="phone" required data-validation-required-message="Please enter your phone number.">
                        <p class="help-block text-danger"></p>
                    </div>
                </div>
                <div class="row control-group">
                    <div class="form-group col-xs-12 floating-label-form-group controls">
                        <label>Message</label>
                        <textarea name="contact-msg" rows="5" class="form-control" placeholder="Message" id="contact-msg" required data-validation-required-message="Please enter a message."></textarea>                         
                        <p class="help-block text-danger"></p>
                    </div>
                </div>
                <br>
                <div class="g-recaptcha" id="sitekey" data-sitekey="gcaptchasitekey3897vadf834fadf"></div>
                <div id="success"></div>
                <div class="row">
                    <div class="form-group col-xs-12">
                        <button type="submit" class="btn btn-success btn-lg">Send</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

Note the 'onSend' data-request parameter.

In the default layout - I put this snippet of PHP to handle the actual processing (the onSend function):

function onSend()
{
  if(empty(post('name'))        ||
     empty(post('email'))       ||
     empty(post('phone'))       ||
     empty(post('contact-msg')) ||
     empty(post('g-recaptcha-response')) ||
     !filter_var($_POST['email'],FILTER_VALIDATE_EMAIL))
     {
    echo "Please fill out all required fields.";
    return false;
     }
    // Collect input
    $name = post('name');
    $email = post('email');
    $phone = post('phone');
    $body = post('contact-msg');
    $response = post('g-recaptcha-response');
    $remoteip = $_SERVER['REMOTE_ADDR'];
    $secret = "32supersecretkeyackjaBcjeLCJelahd832CDo";
    $url = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$response."&remoteip=".$remoteip);
    $response = json_decode($url, true);

    // Form Validation
    $validator = Validator::make(
        [
            'name' => $name,
            'email' => $email,
            'phone' => $phone,
            'contact-msg' => $body,
        ],
        [
            'name' => 'required',
            'email' => 'required|email',
            'contact-msg' => 'required',
        ]
    );
    if ($validator->fails())
    {
        $messages = $validator->messages();
        throw new ApplicationException($messages->first());
    }

    // Make sure the captcha is verified before sending
    if (isset($response['success'])&&$response['success']=="true"){
      $to = config('mail.from.address');
      $params = compact('name','email','phone','body');
      Mail::sendTo($to, 'freelance::mail.contact', $params);

      return true;
    }
    else {

      return false;
    }

}

I was able to trim down the JS file to this:

$(function() {

    $("input,textarea").jqBootstrapValidation({
        preventSubmit: true,
        submitError: function($form, event, errors) {
            // additional error messages or events
        },

        filter: function() {
            return $(this).is(":visible");
        },
    });

    $("a[data-toggle=\"tab\"]").click(function(e) {
        e.preventDefault();
        $(this).tab("show");
    });
});


/*When clicking on Full hide fail/success boxes */
$('#name').focus(function() {
    $('#success').html('');
});

So it provides active validation as the user is typing (which is great).

This method also required a little additional setup on the backend:

You need to create a new 'Mail Template' (code: freelance::mail.contact) in the Settings portion of the backend (and of course, make sure your mail settings are setup)

I would have liked to do a little more JS once the submission is successful - so maybe in the future I'll work that into it - but this is now working as intended.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问