Опубликовать пользовательский URL-адрес HANDLER reCAPTCHA

Я пытаюсь реализовать проверку reCAPTCHA через Marketing Cloud — облачную страницу.

Для этого я использовал это руководство: https://ampscript.xyz/how-tos/how-to-implement-google-recaptcha-on-marketing-cloud-forms/

Что я хочу сделать, так это создать почтовый запрос вместо использования свойства формы действия.

Побочный сценарий моего Клинта:

<!doctype html>
<html>
<head>
 <meta charset="utf-8">
 <title></title>
 <meta name="description" content="">
 <meta name="viewport" content="width=device-width, initial-scale=1">

 <script src="https://www.google.com/recaptcha/api.js"></script>
</head>

<body>



<form id="form" >
    <label>Email: </label>
    <input type="email" name="EmailAddress">
    <div 
        class="g-recaptcha" 
        data-sitekey="XXXXXXXXXXXXXXXXXXXXXX" 
        data-callback="grecaptchaCallback" 
        data-size="invisible"
    ></div>
    <br>
    <button>Send</button>
</form>


<script>
    var form = document.getElementById('form');

    form.addEventListener('submit', grecaptchaValidate);

    function grecaptchaCallback() {
        return new Promise(function (resolve, reject) {
            if (grecaptcha.getResponse() !== '') {
                var x=grecaptcha.getResponse();
                console.log(x);
                var xhttp = new XMLHttpRequest();
                xhttp.open("POST", "https://pub.s7.exacttarget.com/jnmlkgsfquv", true);
                xhttp.setRequestHeader("Content-type",  'text/html',['Accept-Encoding'], ['identity'] );
                xhttp.send();
                http.onreadystatechange =  function() {
        if (this.readyState == 4 && this.status == 200) {
        
        var response=this.responseText;
        console.log(response);
        response=response.split("<script>");
        console.log(response);
        console.log(response[0].trim());
    }

}
            }
            grecaptcha.reset();
        })
    }

    function grecaptchaValidate(e) {
        e.preventDefault();
        grecaptcha.execute();
    }
</script>


</body>
</html>
    </script>
</body>
</html>

А это мой серверный скрипт:


<script runat="server">
 
    Platform.Load("core", "1.1.1");

    try {

        var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
        var secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var payload = "secret=" + secret + "&response=" + g_recaptcha_response;
  var contentType = "application/x-www-form-urlencoded";
  var endpoint = "https://www.google.com/recaptcha/api/siteverify";
        var req = HTTP.Post(endpoint, contentType, payload);

        if (req.StatusCode == 200) {

            var resp = Platform.Function.ParseJSON(String(req.Response));

            if (!resp.success) throw "Wrong reCAPTCHA";

        } else {
            throw "reCAPTCHA API error";
        }

        /// DO SOMETHING

        Write(Stringify(resp));

    } catch (error) {
        Write(Stringify({ status: "Error", message: error }));
    }

</script>

Ошибка, которую я получаю при отправке запроса:

{"status":"Error","message":"Wrong reCAPTCHA"}




<script>(function(a,m,i,g,o,s){o=a.createElement(g);s=a.getElementsByTagName(i)[0];o.src=m.origin+m.pathname+"/_t?eventType=CLOUDPAGESVISIT";o.width=0;o.height=0;o.style.display="none";s.appendChild(o);})(document,window.location,"body","img");</script>
    <script src="https:&#x2F;&#x2F;7231513.collect.igodigital.com&#x2F;collect.js"></script>
    <script>
        if (_etmc && typeof _etmc.push === 'function') {
            _etmc.push(['setOrgId', '7231513']);
            _etmc.push(['trackPageView']);
        }
    </script>

Еще один вывод, к которому я пришел: если я вручную вставлю значение, полученное на стороне клиента от объекта x (grecaptcha.getResponse()), правильный ответ:

 {"success":true,"challenge_ts":"2020-07-29T09:30:03Z","hostname":"pub.s7.exacttarget.com"}

Мне бы хотелось получить представление о том, как я создаю запрос со стороны клиента на страницу на стороне сервера в соответствии с сообщением, которое я инициирую?

Есть ли что-то, что я упускаю? Или может я не правильно работаю?

Изменить:

Проблема была с полезной нагрузкой на серверной странице, потому что переменная g_recaptcha_response была нулевой.

Мой обходной путь - поймать переменную с переменной строки запроса:


%%[
  set @x = RequestParameter("x")
]%%
<script runat="server">
 
    Platform.Load("core", "1.1.1");
  var x = Variable.GetValue("@x");  
 

    try {

 
      //  var g_recaptcha_response = Request.GetFormField("g-recaptcha-response");
      
        var secret = "XXXXXXXXXXXXXXXXXXXXXXXXX";
        var payload = "secret=" + secret + "&response=" + x;
  var contentType = "application/x-www-form-urlencoded";
  var endpoint = "https://www.google.com/recaptcha/api/siteverify";
        var req = HTTP.Post(endpoint, contentType, payload);

        if (req.StatusCode == 200) {

            var resp = Platform.Function.ParseJSON(String(req.Response));

            if (!resp.success) throw "Wrong reCAPTCHA";

        } else {
            throw "reCAPTCHA API error";
        }

        /// DO SOMETHING

        Write(Stringify(resp));

    } catch (error) {
        Write(Stringify({ status: "Error", message: error }));
    }

</script>

Поскольку нет способа перехватить данные URL-адреса на SSJS, я использую AMPscript для перехвата x и передачи его в полезную нагрузку, теперь я получаю ответ об успешном завершении.

Но я не уверен, есть ли какие-либо проблемы с безопасностью таким образом.


person nadav_z    schedule 29.07.2020    source источник


Ответы (1)


Прежде всего, вам нужно создать свою облачную страницу с помощью опции Content Builder. Это удалит теги script в вашем ответе.

Во-вторых, вы отправляете свои данные с типом контента text/html, попробуйте вместо этого использовать application/x-www-form-urlencoded.

Я полагаю, что ваш обработчик форм не фиксирует g-recaptcha-response, потому что его нельзя получить с помощью Request.GetFormField, когда вы отправляете тип контента text/html.

Пожалуйста, ознакомьтесь с этой статьей: https://ampscript.xyz/how-tos/perform-an-http-request/

В противном случае используйте Axios для клиентских запросов: https://github.com/axios/axios.

person Ivan Razine    schedule 29.07.2020
comment
Привет @Ivan Razine, спасибо за ваш подробный комментарий. Я попытался реализовать предложенное вами решение, но это совершенно не помогло. тем не менее, есть тот же ответ. Я также создаю облачную страницу, используя опцию Content Builder, хотя я не получил дополнительный скрипт, я получил больше тегов STYLE и BODY. и ответ все еще Ошибка. Более того, я прочитал статью, которую вы прислали, и они говорят об отдельной серверной странице. Я хочу получить ответ на мою клиентскую страницу и продолжить свой пользовательский поток. - person nadav_z; 30.07.2020
comment
может быть, у вас есть идея, почему запрос не работает? и когда я добавляю тот же URL-адрес (=pub.s7.exacttarget.com/jnmlkgsfquv) на свойство действия формы я получаю успешный ответ? - person nadav_z; 30.07.2020
comment
Когда вы вручную помещали g_recaptcha_response в свой обработчик форм, он работал, верно? Если это так, это означает, что ваш запрос ajax и обработчик формы не могут связаться. Может быть много причин, почему это происходит, поэтому я предлагаю вам попробовать простую страницу, где вы отправляете 1 параметр на облачную страницу с помощью Ajax и отображаете его в результате. - person Ivan Razine; 31.07.2020
comment
Я смог решить проблему. Спасибо за ваши комментарии, они помогли мне понять источник проблемы. - person nadav_z; 01.08.2020
comment
Я отредактировал свой вопрос и написал свое решение. Вы можете посмотреть и сказать свое мнение. Спасибо за помощь:) - person nadav_z; 01.08.2020