So I had an issue with svelte and google Recaptcha API.
My main HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bitter:400,700">
<link rel="stylesheet" href="/css/styles.min.css">
<script defer src='/build/bundle.js'></script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
</head>
<body>
</body>
</html>
My main.svelte
<script>
import swal from "sweetalert";
function verifyUser() {
swal({
title: "Please wait a minute!",
text: "Do not close or exit this tab, we are currently verifying you...",
icon: "info",
backdrop: `rgba(0,0,0,1)`,
showConfirmButton: false,
allowOutsideClick: false,
allowEscapeKey: false
});
}
</script>
<div>
<div class="header-dark">
<nav class="navbar navbar-dark navbar-expand-lg navigation-clean-search">
<div class="container">
<a class="navbar-brand" href="/">QSP Human Verification Module</a>
<button class="navbar-toggler" data-toggle="collapse">
<span class="sr-only">Toggle navigation</span>
<span class="navbar-toggler-icon" />
</button>
</div>
</nav>
<div class="container hero">
<div class="row">
<div class="col-md-8 offset-md-2">
<h1 class="text-center">
Please complete the Captcha challenge to continue to the server.
</h1>
<form action="" method="post">
<div
class="g-recaptcha"
data-sitekey="key"
data-callback={verifyUser}
/>
</form>
</div>
</div>
</div>
</div>
</div>
Problem is that function just becomes string of itself and can’t be executed using just "verifyUser" or
verifyUser()returns
ReCAPTCHA couldn’t find user-provided function: verifyUser`
using {verifyUser}
becomes string (for more https://prnt.sc/qhyc2w)
executing like that returns:
ReCAPTCHA couldn't find user-provided function: function verifyUser() {
swal({
title: "Please wait a minute!",
text: "Do not close or exit this tab, we are currently verifying you...",
icon: "info",
backdrop: `rgba(0,0,0,1)`,
showConfirmButton: false,
allowOutsideClick: false,
allowEscapeKey: false
});
}
rollup config
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file — better for performance
css: css => {
css.write('public/build/bundle.css');
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration —
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
}
}
};
}
Any how to properly pass the function?
3
Answers
im Rour- the guy from discord. I want to share solution here for others.
Thinking that
data-callback
is searching for name of global function, so we defineverifyUser
as global function in the browser by assign it to thewindow
variableYou can try
svelte-recaptcha-v2
package on npm for a more straight forward experience.Repository
https://github.com/basaran/svelte-recaptcha-v2
Demo
https://basaran.github.io/svelte-recaptcha-v2/
P.S I’m the author of the package.
If using TypeScript, you’ll need to define your function for the Window interface.
global.d.ts
RecaptchaButton.svelte
ContactForm.svelte
You should add an error handler to the Recaptcha button component if using something like the above, you can use the "data-error-callback" property on the buttton; set up the Window interface, mount and destroy the same as "onSubmit" but with "onError".