douglasjunior / react-native-recaptcha-that-works Goto Github PK
View Code? Open in Web Editor NEW⚛ A reCAPTCHA bridge for React Native that works (Android and iOS)
License: MIT License
⚛ A reCAPTCHA bridge for React Native that works (Android and iOS)
License: MIT License
Maybe clear it up in the ReadMe.
Thanks for a ReCaptcha that really works
@douglasjunior I am trying to implement invisible reCaptcha. On iOS I notice on first attempt, App display image grid.
<Recaptcha
ref={recaptcha}
siteKey="<Site-Key>"
baseUrl="https://my.nasdaq.com"
onVerify={onVerify}
onExpire={onExpire}
size="invisible"
/>
hi! Can you do this? so that when the property is invisible, the captcha icon in the right, bottom corner is not visible. You can give a webview component, for example, flex = 0. And the background Loading component, darkening. Users are annoyed by this banner
Hey! thanks for this lib thats really works 🚀
I'm using the invisible, but found out that the Modal block the whole UI until it's not visible the token verified.
in the current implementation is there a way to mitigate this behaviour?
Playing around I found out that without rendering the Modal (just the web-view) I can still get it to work
Thanks!
First of all, congrats on this lib.
About this loading when webview returns the Recaptcha token, I think that this should be optional, because when some scenarios we only want to get a token, and not have UI feedback.
What do u think?
I can make this loading render optionally.
https://github.com/douglasjunior/react-native-recaptcha-that-works/blob/master/src/Recaptcha.js#L183
it's not a bug, only an enhancement.
It's the first time I'm using recaptcha and I have a doubt about what the baseUrl domain should be.
I already set up a key, what else do I need to configure?
Thanks
I am using the configuration below, however, it is not fully invisible. The activity indicator appears on iOS. The StatusBar appears on Android.
I am using the following configuration. modalProps prop not rewrites modalProps props correctly.
<View style={{ display: 'none' }}>
<Recaptcha
style={{ display: 'none' }}
ref={recaptcha}
siteKey="6LcsO5sUAAAAADhfEx8vFSKFS2nP1DjHjaZN"
baseUrl="https://www.trollflix.com"
onVerify={onVerify}
size="invisible"
hideBadge={true}
modalProps={{ visible: false, animationType: 'none', transparent: true, supportedOrientations: ['landscape-right'], statusBarTranslucent: true }}
/>
</View>
I am facing issue while trying to open captcha inside modals. Captcha is not opening.
@douglasjunior Can you help to solve this issue?
const recaptcha = useRef();
<Recaptcha
ref={recaptcha}
siteKey="my site key"
baseUrl="my url"
onVerify={onVerify}
onExpire={onExpire}
size="invisible"
/>
const send = () => {
recaptcha.current.open();
}
const onVerify = token => {
console.log('success!', token);
recaptcha.current.close();
}
Once on Verify is called. THe modal is not getting closed.
On recaptcha.current.open();
Along with activity indicator recaptcha icon coming on right bottom corner, which is looking odd.
Right before the captcha icon loads in the bottom-right corner of the react native app (for both normal and invisible mode), the screen changes momentarily to black. Is there a way to avoid this?
Thank you for this awesome lib that really works :)
The main readme doesn't mention the support of react-native-web .
is this planned in the futur ?
On android, onError is called and error is null. Not using invisible works.
What version of React Native?
react: "^16.13.1",
react-native: "^0.63.4"
What version of React Native WebView?
react-native-webview": "^10.10.2",
react-native-modal: "^11.5.6"
What version of the library?
react-native-recaptcha-that-works: "^1.3.0"
iOS/Android version?
using the iPhone 5s/8/13 simulator + Pixel 3 API 28/Pixel 4 API 30 emulator
Did the problem happen after updating React Native?
haven't upgraded RN since installing the library
Are you using the library for the first time?
yes
It's a bug? Provide a link to a minimal reproduction case.
This might be an issue with the Recaptcha from google itself, since it's being injected into a WebView.
For visuals, the recaptcha works for both android & iOS. The redo button also resets the images correctly.
For the audio,
For the info, it seems to take a few clicks for it to pop up, but the links dont work on either platform.
I looked over the source code of the library and it's just injecting the recaptcha from
<script src="https://${validHost}/recaptcha/api.js?hl={{lang}}" async defer></script>
into
<body>
<div class="container">
<span id="recaptcha-container"></span>
</div>
</body>
I'd expect clicking on the Learn more link (or other similar links in the info messages) to open a web browser in the web view and redirect to said links. But nothing happens on click, or multiple clicks.
Note: I used ref to close but not work
I'm trying to use this library but nothing shows up at all when I trigger it with $recaptcha.current.open
. Does this need the latest version of React Native and react-native-webview
? Because I am on RN 0.63.4 and react-native-webview
= 11.13.0. I would not upgrade for now RN if at all possible.
My code is based on the example/sample, when a button is clicked I call the send
function which should open it. Tried size = compact/normal.
const $recaptcha = useRef();
const send = () => {
console.log('send!');
$recaptcha.current?.open();
};
const onVerify = async (token: string) => {
console.log('success!', token);
await onSubmit();
};
const onExpire = () => {
console.warn('expired!');
};
<Recaptcha
ref={$recaptcha}
siteKey={Config.RECAPTCHA_SITE_KEY}
baseUrl={Config.WEBSITE_BASE_URL}
onVerify={onVerify}
onExpire={onExpire}
theme="light"
size="compact"
/>
<ButtonRegular
title={isSignUp ? trans('buttons.signup') : trans('buttons.login')}
onPress={send}
isLoading={isLoading}
/>
What is the baseUrl prop? The invisible captcha don't seem to work for me. I have added the component but I am not recieving any token.
When it is generating a token, its blocking the UI. The UI becomes unresponsive to touches and scrolling for about 1 second. This happens on both iOS and Android.
Please could you make this non-blocking? Thank you in advance.
This is my setup:
<View style={{ display: 'none' }}>
<Recaptcha
style={{ display: 'none' }}
ref={recaptcha}
loadingComponent={<></>}
siteKey="6LcsO5sUAAAGDSWMFSKLWDnP1DjHjaZN"
baseUrl="https://www.trollflix.com"
onVerify={onVerify}
size="invisible"
hideBadge={true}
modalProps={{ visible: false, animationType: 'none', transparent: true, supportedOrientations: ['landscape-right'], statusBarTranslucent: true }}
/>
</View>
I want to implement this captcha but it should view directly no need for that modal view. Please help me its urgent work request.
Hi!
@douglasjunior I got an error message on Android
[Android] Failed to call method WebViewMessageHandler1.onMessage(). Module has not been registred as callable
.
react-native": "0.71.11
"react-native-webview": "^13.8.6"
Any ideas why it happens?
Thank you for your efforts.
Hi! First of all! Thank you to share this awesome lib. I was trying to use this at Expo SDK 42 "managed workflow" react-native project linking to firebase. Below are my packages related:
"expo": "^42.0.0",
"expo-firebase-recaptcha": "^1.4.2",
"firebase": "8.2.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
"react-native-recaptcha-that-works": "^1.1.0",
"react-native-webview": "11.6.2"
Issue: Since I start reCaptcha flow it invokes onError and console warns "Error: null".
Workaround(?): I use your code as a template to locate where would the issue come from. As a junior, in advance, I want to apologize any misunderstood concept by myself. I tried use your concepts of nesting webview starting from render hello world and adding handlers like yours handleMessage and stuck at this problem at function getTemplate when it acts over "template" string variable. The workaround was just to assign de return from replace() to a new that function scoped variable and return. I will appreciate this issue can help others to use this awesome library and skilled ones help us fixing this behaviour, if it was a issue to anyone.
const getTemplate = useCallback((params) => {
let output;
Object.entries(params).forEach(([key, value]) => {
// template = template.replace( ...
output = template.replace(new RegExp(`{{${key}}}`, 'img'), value); //line change
});
return output;
}, []);
Sorry about my english too. Thank you owner and contributors.
Is it expected to open the recaptcha again with recaptcha.current?.open()
on the onExpire callback? If not, how is the expiration usually handled?
It's not loading google Captcha with an invisible size. It's working fine with normal size.
<Recaptcha
ref={recaptchaRef}
lang="en"
siteKey="key"
baseUrl={CAPTCHA_CUSTOM_DOMAIN_URL}
size="invisible"
theme="light"
onLoad={() => console.log('onLoad event')}
onClose={() => console.log('onClose event')}
onError={(err) => {
console.warn('error', err)
console.log('onError event')
}}
onExpire={() => console.log('onExpire event')}
onVerify={(token) => {
console.log('onVerify event', token)
setKey(token)
}}
hideBadge={true}
/>
I really appreciate any help you can provide!
My code is:
send = () => {
console.log('send!');
this.recaptcha.open(); // Error is showing here to open
}
onVerify = token => {
console.log('success!', token);
}
onExpire = () => {
console.warn('expired!');
}
render() {
return (
<View>
<Recaptcha
ref={ref => this.recaptcha = ref}
siteKey="<your-recaptcha-public-key>"
baseUrl="http://my.domain.com"
onVerify={this.onVerify}
onExpire={this.onExpire}
size="invisible"
/>
<Button title="Send" onPress={this.send} />
</View>
)
}
To create a siteKey for iOS and Android, do we have to do it through here? https://cloud.google.com/recaptcha-enterprise/docs/create-key-mobile
Android app crashes if you press back button instantaneously after calling .open()
There's no logcat. Even the Android Studio logcat is blank.
I am not sure if this is an issue or maybe an expected behaviour for some reason. When I have enterprise set to true, size normal and compact will not work. The modal will appear for a split second and the on error callback runs with null as the error. But it works normally when size is set to inivisible.
I tried to vertically center the Recaptcha challenge window but failed so far, it always stuck on top. On some newer iPhone model (looks like start from iPhone 14 Pro Max and above) it even overlap with the camera.
Tried to wrap with SafeAreaView but didn't work since the library is using a modal and it looks like it occupies the whole screen. Any suggestions what is the easiest way to accomplish this? Wonder wrapping the header component, the web view, and the footer component inside a View and then making the style overridable might help.
Hi,
Thanks for this package "that just works" :-)
We are considering upgrading to reCAPTCHA Enterprise - does this package support it?
how can i modify the width of the recpatcha so that i can occupy the entire width of my div and make it so that when the recaptcha is finished the widget doesn't disappear but stays with the checked one, because any modification i make doesn't change the recaptcha widget.
I don't want to use it as a modal, but rather fit it into a form.
Hi,
I saw in another thread that the default V3 sometimes falls back to recaptcha V2.
I was unable to reproduce it, but I would like to know:
Asking since I wouldn't want to have a state "stuck in between" with a loading modal or whatever I put in place for V3 that behaves differently for V2?
Thank you for your help!
Hello. I don't know if this is the right place to ask since there is no discussion tab. Apologies in advance.
I am testing this tool with hidden mode (size=invisible
) and it seems to be working fine in the normal/positive cases. The app opens the ReCaptcha and validates it seamlessly.
The problem is testing the negative cases. The QA team with automated testing bots on BrowserStack are able to bypass the captcha verification, and the hidden captcha treats them as real users. (Understandable browser stack might be running on real devices in the backend).
Is it possible to add jest tests to sample app? I'm trying to add tests in my application, but i can't mock properly this library.
Thanks.
I am sorry if this is a duplicate of my other issue #31 , but since it was closed without answer I need to clarify:
Is this library using recaptcha v2 or v3?
You stated in issue 31 that this library doesn't work with recaptcha 3, but then my question remains:
Why is the whole process invisible as intended with V3, unlike V2 that asks for questions?
How come my recapatcha v3 key seems to be working with your plugin; and even the backend v3 checking the score is working as expected when sending your plugin generated token?
So did you mean to say that your library doesn't work with V2 rather than V3?
Thank you for your help!
Hi,
I know most google plugins/tools rely on google play services.
Question is: can this plugin be used properly on Huwaei devices?
( I guess yes, since it works on iOS, but unfortunately I have no huwaei to test it on )
I think it could be because the keys are wrapped in single quotes.. other keys in the same object do not have any quote wrappings. I suspect onError is similar not working. Only onVerify gets triggered because I'm able to get the token.
Verified against the doc's that the keys are correct though: https://developers.google.com/recaptcha/docs/display
<Recaptcha
ref={recaptcha}
siteKey={process.env.EXPO_PUBLIC_RECAPTCHAKEY || ''}
baseUrl={process.env.EXPO_PUBLIC_BASE_URL || ''}
onVerify={(token) => {
onSubmit(token);
}}
hideBadge
size="invisible"
/>
EXPO_PUBLIC_RECAPTCHAKEY = realkey
EXPO_PUBLIC_BASE_URL = https://domain.example
Here is how I implemented Recaptcha in my app
import React from 'react';
import RecaptchaV3 from 'react-native-recaptcha-that-works';
import {RECAPTCHA_SECRET, RECAPTCHA_DOMAIN} from '@env';
const Recaptcha = React.forwardRef(({onSuccess}, ref) => {
const onVerifyRecaptcha = token => {
onSuccess(token);
};
const onExpire = () => {
console.warn('expired!');
};
return (
<RecaptchaV3
ref={ref}
siteKey={RECAPTCHA_SECRET}
baseUrl={RECAPTCHA_DOMAIN}
onVerify={onVerifyRecaptcha}
onExpire={onExpire}
size="normal"
/>
);
});
export default Recaptcha;
when I run npm test, I get the following error
React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Anyone was able to solve this issue or have a mock file for the package.
Hi @douglasjunior, thanks for the amazing lib. What about creating a footerComponent prop for this lib? Or at least create a style to then container for using flexDirection: 'column-reverse'.
My app got this warning from playstore:
Firstly, gstatic log_list.json will start returning 404 on 2023-06-07 around 10AM UTC+1.
I assume that this lib uses the above URL? Any solution to be implemented?
Hello,
Thank you for this library 🥇 I would like to propose another interesting feature to this library.
Image the case, when the library is in invisible state and I would like to display the captcha, once user clicked on submit button in the form. When the submission is completed, then we can make an api call to apply the changes. So far I need to handle it using the callback, which is not the cleanest way to do it. Hence I would like to improve it using async/await handle
Create a ref, which will be responsible for storing the promise
const $promiseToken = useRef<{
resolve: (value: GetToken | PromiseLike<GetToken>) => void;
reject: (arg: any) => void;
} | null>();
Move code to the separate method. It will be used in both places
const onOpen = useCallback(() => {
setVisible(true);
setLoading(true);
$isClosed.current = false;
}, []);
Add new async method getToken, which will be responsible for opening the modal and fetching the token
This promise will be stored in the ref called $promiseToken
useImperativeHandle(
ref,
() => ({
open: () => {
onOpen();
},
close: handleClose,
getToken: () => {
onOpen();
return new Promise<GetToken>(
(resolve, reject: (arg: any) => void) => {
$promiseToken.current = { resolve, reject };
}
);
},
}),
[handleClose, onOpen]
);
Handle this promise in handleMessage
method
const handleMessage = useCallback(
(content) => {
try {
const payload = JSON.parse(content.nativeEvent.data);
if (payload.close) {
if (isInvisibleSize) {
handleClose();
}
}
if (payload.load) {
handleLoad(...payload.load);
}
if (payload.expire) {
//@ts-ignore
onExpire?.(...payload.expire);
}
if (payload.error) {
handleClose();
//@ts-ignore
onError?.(...payload.error);
$promiseToken?.current?.reject(payload.error);
}
if (payload.verify) {
handleClose();
//@ts-ignore
onVerify?.(...payload.verify);
const token = payload?.verify?.[0] || '';
$promiseToken?.current?.resolve({ token: token });
}
} catch (err) {
$promiseToken?.current?.reject(err);
}
},
[onVerify, onExpire, onError, handleClose, handleLoad, isInvisibleSize]
);
After everything, we need to clean up a little bit to avoid memory leak
React.useEffect(() => {
return () => {
$promiseToken.current = null;
};
}, []);
const App = () => {
const size = 'normal';
const [key, setKey] = useState('<none>');
const $recaptcha = useRef();
const handleOpenPress = useCallback(() => {
$recaptcha.current.open();
}, []);
const handleClosePress = useCallback(() => {
$recaptcha.current.close();
}, []);
useState(() => {
// handle submit here (api call), which is not the best solution. I would prefer to have it all at one place
},[key])
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView style={styles.safeArea}>
<View
contentInsetAdjustmentBehavior="automatic"
style={styles.container}>
<Button onPress={handleOpenPress} title="Open" />
<Text>Token: {key}</Text>
<Text>Size: {size}</Text>
</View>
<Recaptcha
ref={$recaptcha}
lang="en"
headerComponent={<Button title="Close" onPress={handleClosePress} />}
siteKey="6LejsqwZAAAAAGsmSDWH5g09dOyNoGMcanBllKPF"
baseUrl="http://127.0.0.1"
size={size}
theme="light"
onLoad={() => alert('onLoad event')}
onClose={() => alert('onClose event')}
onError={(err) => {
alert('onError event');
console.warn(err);
}}
onExpire={() => alert('onExpire event')}
onVerify={(token) => {
alert('onVerify event');
setKey(token);
}}
/>
</SafeAreaView>
</>
);
};
const App = () => {
const size = 'normal';
const [key, setKey] = useState('<none>');
const $recaptcha = useRef();
const handleOpenPress = useCallback(() => {
const response = await $recaptcha?.current?.getToken();
if (response?.token) {
// do some api calls etc
} else {
// do some api calls etc
Alert.alert('Title', 'Something went wrong');
} }, []);
const handleClosePress = useCallback(() => {
$recaptcha.current.close();
}, []);
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView style={styles.safeArea}>
<View
contentInsetAdjustmentBehavior="automatic"
style={styles.container}>
<Button onPress={handleOpenPress} title="Open" />
<Text>Token: {key}</Text>
<Text>Size: {size}</Text>
</View>
<Recaptcha
ref={$recaptcha}
lang="en"
headerComponent={<Button title="Close" onPress={handleClosePress} />}
siteKey="6LejsqwZAAAAAGsmSDWH5g09dOyNoGMcanBllKPF"
baseUrl="http://127.0.0.1"
size={size}
theme="light"
onLoad={() => alert('onLoad event')}
onClose={() => alert('onClose event')}
onError={(err) => {
alert('onError event');
console.warn(err);
}}
onExpire={() => alert('onExpire event')}
onVerify={(token) => {
alert('onVerify event');
setKey(token);
}}
/>
</SafeAreaView>
</>
);
};
WDYT about above approach ? Feel free to comment.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.