[英]How to get recaptcha token in SvelteKit contact form
我正在使用 SvelteKit 开发一个静态网站,以获得我的第一种瘦身方法。 我几乎让一切都按预期工作。 除了联系表格上的 recaptcha 保护之外的所有内容。
我可以获得recaptcha令牌,但在将其传递给formData请求时丢失了它。 我的相对代码是:
<script lang="ts">
import * as yup from "yup";
import {createForm, ErrorMessage} from "svelte-forms-lib";
...
function getCaptcha(){
grecaptcha.ready(function () {
grecaptcha.execute('recaptcha-key', { action: 'contactForm' })
.then(function (token) {
console.log(token) // here I get the token
return token;
});
});
}
const sendMail= (values)=>
{
const url = '/sendmail.php';
const formData = new FormData();
let token = getCaptcha();
console.log('token: '+token); // here token is null
formData.append("token", token);
fetch(url, {
method: 'post',
body: formData,
})
.then(function (response) {
console.debug(response.status)
})
.catch(function (e) {
sendError = true;
console.debug(e);
});
}
</script>
表单提交工作正常,显然,除了 recaptcha 令牌。
感谢您提供有关如何解决它的任何想法。
token
为空,因为您的getCaptcha
函数实际上并未返回任何内容,因为您正在使用回调来获取令牌。
function getCaptcha(){ // <- this function isn't returning anything
grecaptcha.ready(function () {
grecaptcha.execute('recaptcha-key', { action: 'contactForm' })
.then(function (token) { // <- this function returns, but the value isn't going anywhere
console.log(token);
return token;
});
});
}
要解决此问题,您可能需要考虑对 promise 使用async
/ await
语法。 如果您有兴趣, MDN 有一篇很棒的文章。
你可能想要做这样的事情:
async function getCaptcha(){
await new Promise((resolve, reject) => {
// grecaptcha.ready needs a callback so we create a promise to await
grecaptcha.ready(resolve);
});
// grecaptcha.execute returns a promise so we can await it
const token = await grecaptcha.execute('recaptcha-key', { action: 'contactForm' });
console.log(token);
return token;
}
const sendMail = async (values) => {
const url = '/sendmail.php';
const formData = new FormData();
let token = await getCaptcha();
console.log('token: ' + token);
formData.append("token", token);
// you have a few options for converting
// the Promise.catch()
// you can use a try {} catch {} block
// or you can use .catch() on this sendMail function
try {
const response = fetch(url, {
method: 'post',
body: formData,
});
console.debug(response.status);
} catch (e) {
sendError = true;
console.debug(e);
}
}
请记住,这将使sendMail
函数成为async
函数,这意味着您必须await
对它的调用,或使用sendMail().then()
。 我相信也可以直接在同步代码中调用async
函数并让它们运行,只是不能保证函数中的内容会在调用后的代码之前运行。
为了澄清起见,我的最终代码在提交功能方面略有不同,我将其发布以供将来参考,以防万一。
async function getCaptcha(){ await new Promise((resolve, reject) => { // grecaptcha.ready needs a callback so we create a promise to await grecaptcha.ready(resolve); }); // grecaptcha.execute returns a promise so we can await it const token = await grecaptcha.execute('site-key', { action: 'contactForm' }); return token; } const sendMail = async (values) => { const url = '/sendmail.php'; const formData = new FormData(); let token = await getCaptcha(); formData.append("name", values.name); formData.append("surname", values.surname); formData.append("email", values.email); formData.append("phone", values.phone); formData.append("message", values.message); formData.append("token", token); formData.append("action", "contactForm"); // you have a few options for converting // the Promise.catch() // you can use a try {} catch {} block // or you can use .catch() on this sendMail function try { let response = await fetch(url, { method: 'post', body: formData, }); if(response.status == 202){ sendSuccess = true; document.querySelector('form').reset(); } if(response.status == 400){ sendError = true; } } catch(err) { sendError = true; } }
您可以使用svelte-recaptcha-v2
代替自己处理。
https://github.com/basaran/svelte-recaptcha-v2
https://basaran.github.io/svelte-recaptcha-v2/demo
P.S 我是这个包的作者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.