• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Google reCAPTCHA v3

Object Storage Arubacloud
0 głosów
1,116 wizyt
pytanie zadane 30 grudnia 2020 w JavaScript przez WiktroH Mądrala (6,550 p.)
zamknięte 3 stycznia 2021 przez WiktroH

Cześć!

Pracuję nad stroną, w której chcę użyć Google reCAPTCHA w wersji 3. Mój kod JS jest zgodny z przykładami, lecz mimo wszystko zapisuje się tylko wynik, a formularz się nie wysyła (działa, przy dodaniu drugiego przycisku wysyłającego). Oczywiście chodzi o to, aby po naciśnięciu przycisku zapisywał się wynik i formularz wysyłał się automatycznie. Poniżej mój kod - z góry dzięki za pomoc.

P.S.: Dodałem jeszcze własną stylizację - ciemny motyw (poprzez grecaptcha.render()). Wiem, że całość da się zrobić dużo prościej, ale zależy mi, żeby to zachować.

<script>			
	function onSubmit(e){
		e.preventDefault();
		grecaptcha.ready(() => {
			grecaptcha.execute('G-reCAPTCHA-site_key', {'action' : 'forgot-password'})
			.then((token) => {
				$('#log-form').submit();
			});
		});
	};
	
	var onloadCallback = function(){
		grecaptcha.render('g-recaptcha', {
			'sitekey' : 'G-reCAPTCHA-site_key',
			'theme' : 'dark'
		});
	};
</script>

<form method="post" id="log-form">
	<div class="form" style="margin-top:20vh!important;">
		<h3 class="mb-4">Przypominanie hasła</h3>
		<input type="mail" name="fg_pss_mail" placeholder="Wpisz swój adres e-mail" onfocus="this.placeholder=''" onblur="this.placeholder='Wpisz swój adres e-mail'" value="">
		<button
			class="g-recaptcha"
			id="g-recaptcha"
			data-callback="onSubmit(this)"
			data-action="forgot-password"
		>Przypomnij hasło</button>
	</div>
</form>

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=pl" async defer></script>

 

komentarz zamknięcia: mam odpowiedź

1 odpowiedź

+1 głos
odpowiedź 30 grudnia 2020 przez ScriptyChris Mędrzec (190,190 p.)
wybrane 3 stycznia 2021 przez WiktroH
 
Najlepsza

Mój kod JS jest zgodny z przykładami

W punkcie trzecim przykładu z dokumentacji, do przycisku z atrybutem data-callback jest przypisany string z nazwą funkcji do wywołania: "onSubmit". Natomiast u Ciebie jest data-callback="onSubmit(this)", gdzie niepotrzebnie dodałeś nawiasy wywołujące funkcję - obstawiam, że przez to do tego atrybutu jest przypisane undefined (może konsola rzuca błędem o próbie wywołania niezdefiniowanej funkcji z tego powodu).

formularz się nie wysyła (działa, przy dodaniu drugiego przycisku wysyłającego)

Co masz na myśli przez drugi przycisk wysyłający? 

komentarz 30 grudnia 2020 przez WiktroH Mądrala (6,550 p.)

1.

Natomiast u Ciebie jest data-callback="onSubmit(this)"

Niestety, usunięcie argumentu nic nie dało (dzieje się dokładnie to samo).

 

2.

(może konsola rzuca błędem o próbie wywołania niezdefiniowanej funkcji z tego powodu)

Zapomniałem napisać: konsola nie zwraca żadnego błędu

 

3. 

Co masz na myśli przez drugi przycisk wysyłający?

Oprócz tego button'a

<button
	class="g-recaptcha"
	id="g-recaptcha"
	data-callback="onSubmit(this)"
	data-action="forgot-password"
>Przypomnij hasło</button>

Dodałem jeszcze:

<input type="submit" value="Wyślij">
1
komentarz 30 grudnia 2020 przez ScriptyChris Mędrzec (190,190 p.)

Niestety, usunięcie argumentu nic nie dało (dzieje się dokładnie to samo).

Jakiego argumentu? Chodzi Ci o przekazany w parametrze this? Miałem na myśli, abyś w ogóle tam nie wołał funkcji - zapisz po prostu data-callback="onSubmit" (tak jak w przykładzie dokumentacji). Inna sprawa - czy funkcja onSubmit jest w ogóle wołana na kliknięcie w przycisk? Wstaw na jej początku jakiś console.log i sprawdź czy coś się wypisze do konsoli. Dalej, formularz jest submitowany programowalnie, po rozwiązaniu promisa. Sprawdź, czy ten promis jest rozwiązywany - wstaw kolejny console.log przed linijkę $('#log-form').submit(); Jeśli do tego momentu jest ok, to wg mnie problemem jest zapętlanie się tego procesu:

  1. klikasz w przycisk
  2. wołana jest funkcja onSubmit
  3. submitowanie formularza jest blokowane przez e.preventDefault()
  4. wysyłany jest jakiś Ajax, który zwraca promisa
  5. po rozwiązaniu promisa formularz jest znowu submitowany (tym razem programowalnie)
  6. funkcja onSubmit wołana jest drugi raz - ale znowu wysłanie jest blokowane przez e.preventDefault()
  7. dalej nie wiem, czy Ajax leci drugi raz i to się zapętla

Jeśli tak się dzieje, to spróbuj inną drogą. Zapnij się na zdarzenie click przycisku, tam wyślij Ajaxa, a dopiero po nim odpal submit programowalnie.

1
komentarz 30 grudnia 2020 przez WiktroH Mądrala (6,550 p.)
edycja 30 grudnia 2020 przez WiktroH

Miałem na myśli, abyś w ogóle tam nie wołał funkcji - zapisz po prostu data-callback="onSubmit"

Tak zrobiłem (niestety - bez rezultatów). 

Inna sprawa - czy funkcja onSubmit jest w ogóle wołana na kliknięcie w przycisk? [...]

Tutaj trafiłeś w sedno - funkcja się nie wykonuje, a myślałem, że nie wykonuje się tylko .then().

 

Rzeczy, które zrobiłem:

  • Usunąłem argument z funkcji onSubmit() (formularz się nie wysyła przez to, że dodałem do button'a ' type="button" ')
  • Dodałem do button'a zdarzenie onclick z funkcją onSubmit()

Rezultaty:

  • Funkcja onSubmit() już się wykonuje (ale obietnica się nie spełnia)
  • W konsoli pojawił się błąd
Uncaught Error: Invalid site key or not loaded in api.js:
G-reCAPTCHA-site_key
    at Array.<anonymous> (recaptcha__pl.js:87)
    at recaptcha__pl.js:374
    at login?act=forgot-pass:58

Oczywiście jestem pewny, że klucz witryny jest poprawny.

 

Promise się nie spełnia przez błąd klucza, ale ja nie mam pojęcia, na czym ten błąd. Masz jakiś pomysł?

1
komentarz 30 grudnia 2020 przez ScriptyChris Mędrzec (190,190 p.)

Czy onloadCallback jest wołany? Powinien być w wyniku załadowania skryptu api.js

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=pl" async defer></script>

Nie wiem, czy wartość explicit jest poprawna dla klucza render. W dokumentacji jest tam render=reCAPTCHA_site_key, co bym rozumiał jako przypisanie klucza strony do render. Ale to może robisz innym sposobem, bo przypisujesz klucz w parametrze do metody grecaptcha.render (o ile ona jest wołana - wstaw console.log nad nią).

P.S. Na przyszłość - nie podawaj w Internecie (tyczy się również forów) prywatnych/developerskich kluczy lub innych poufnych danych.

komentarz 30 grudnia 2020 przez WiktroH Mądrala (6,550 p.)

Czy onloadCallback jest wołany? Powinien być w wyniku załadowania skryptu api.js

Tak, jest ładowany - sprawdziłem to.

 

Nie wiem, czy wartość explicit jest poprawna dla klucza render.

Jest - zostało to opisane tutaj (stylizowanie reCAPTCH'y v3).

 

P.S. Na przyszłość - nie podawaj w Internecie [...] prywatnych/developerskich kluczy lub innych poufnych danych.

Dzięki za radę. To akurat wiedziałem, ale tutaj nastąpiła zwyczajna ludzka pomyłka - zapomniałem usunąć klucza przez wrzuceniem wątku na forum frown.

komentarz 30 grudnia 2020 przez ScriptyChris Mędrzec (190,190 p.)

Spróbuj przepisać swój kod na taki z pełnoprawnego przykładu użycia reCAPTCHA v3.

Fragment kodu ładującego captchę z tej strony (linijki 30-47):

    <script src="https://www.google.com/recaptcha/api.js?render=6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696"></script>
    <script>
        const steps = document.getElementById('recaptcha-steps');
        grecaptcha.ready(function() {
            document.querySelector('.step1').classList.remove('hidden');
            grecaptcha.execute('6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696', {action: 'examples/v3scores'}).then(function(token) {
                document.querySelector('.token').innerHTML = 'fetch(\'/recaptcha-v3-verify.php?action=examples/v3scores&token=\'' + token;
                document.querySelector('.step2').classList.remove('hidden');

                fetch('/recaptcha-v3-verify.php?action=examples/v3scores&token='+token).then(function(response) {
                    response.json().then(function(data) {
                        document.querySelector('.response').innerHTML = JSON.stringify(data, null, 2);
                        document.querySelector('.step3').classList.remove('hidden');
                    });
                });
            });
        });
    </script>
  1. podepnij skrypt api.js z parametrem render=TWÓJ_KLUCZ_STRONY bez async ani defer
  2. pod spodem wrzuć skrypt i tam użyj grecaptcha.ready oraz grecaptcha.execute, w tym drugim obsłuż promisa
  3. zignoruj linijki, które Ci się nie przydadzą (raczej głównie te z querySelectorem)

Czy wtedy promis z tokenem się rozwiąże? Póki co zignoruj submitowanie formularza - sprawdź samo pobranie tokena na podstawie klucza.

1
komentarz 3 stycznia 2021 przez WiktroH Mądrala (6,550 p.)

Zadziałało coś takiego:

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=pl"></script>
		
<script>
	var onSubmit = function(token){
		$("#log-form").submit();
	}
			
	var onloadCallback = function(){
		grecaptcha.render('submit-btn', {
			sitekey : 'G_reCAPTCHA_site-key',
			callback : 'onSubmit',
			action : 'forgotPassword',
			theme : 'dark'
		});
	};
</script>
		
<form method="post" id="log-form">
	<div class="form" style="margin-top: 20vh;">
		<h3 class="mb-4">Przypominanie hasła</h3>
		<input type="mail" name="fg_pss_mail" placeholder="Wpisz swój adres e-mail" onfocus="this.placeholder=''" onblur="this.placeholder='Wpisz swój adres e-mail'" style="margin-top: 15px !important;">
		<button
			type="button"
			id="submit-btn"
			class="g-recaptcha" 
		>Przypomnij hasło</button>
	</div>
</form>

 

komentarz 3 stycznia 2021 przez ScriptyChris Mędrzec (190,190 p.)

Fajnie. A, z ciekawości, co woła funkcję onSubmit i w jaki sposób wysyłasz request z kluczem strony (ten, który zwracał promisa)?

komentarz 3 stycznia 2021 przez WiktroH Mądrala (6,550 p.)

A więc tak: funkcja grecaptcha.render (do której jako argument podaje się atrybuty callback i klucz strony) renderuje reCAPTCH'ę w buttonie o id=sumit-btn. Kiedy użytkownik naciska tego buttona - request wysyła się automatycznie (klucz witryny został do niego przypisany wcześniej przez grecaptcha.render). Funkcja onSubmit też jest jako parametr w grecaptcha.render ("callback"); nazwa funkcji tam podanej, wykonuje się po poprawnym przesłaniu requesta reCAPTCH'y.

Podobne pytania

+6 głosów
1 odpowiedź 877 wizyt
0 głosów
1 odpowiedź 562 wizyt
pytanie zadane 14 stycznia 2023 w PHP przez kingkushlee Gaduła (3,960 p.)
0 głosów
1 odpowiedź 2,355 wizyt
pytanie zadane 4 listopada 2018 w Offtop przez StEvo Nowicjusz (170 p.)

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...