Я пытаюсь реализовать проверку 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://7231513.collect.igodigital.com/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 и передачи его в полезную нагрузку, теперь я получаю ответ об успешном завершении.
Но я не уверен, есть ли какие-либо проблемы с безопасностью таким образом.