Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Example.App.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React, { useState, useRef } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import ConfirmHcaptcha from '@hcaptcha/react-native-hcaptcha';
// import ConfirmHcaptcha, { initJourneyTracking } from '@hcaptcha/react-native-hcaptcha';

// demo sitekey
const siteKey = '00000000-0000-0000-0000-000000000000';
const baseUrl = 'https://hcaptcha.com';

// Uncomment to enable automatic User Journeys collection for this example app.
// initJourneyTracking();

const App = () => {
const [code, setCode] = useState(null);
const captchaForm = useRef(null);
Expand Down Expand Up @@ -38,6 +42,8 @@ const App = () => {
baseUrl={baseUrl}
languageCode="en"
onMessage={onMessage}
// Uncomment to attach the buffered User Journey to each verification request.
// userJourney={true}
/>
<TouchableOpacity
onPress={() => {
Expand Down
113 changes: 113 additions & 0 deletions Example.UserJourneys.App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useRef, useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import ConfirmHcaptcha, { initJourneyTracking } from '@hcaptcha/react-native-hcaptcha';

// demo sitekey
const siteKey = '00000000-0000-0000-0000-000000000000';
const baseUrl = 'https://hcaptcha.com';

initJourneyTracking({
debug: true,
onStats: (stats) => {
console.log('[journey-stats]', JSON.stringify(stats));
},
});

const App = () => {
const [code, setCode] = useState(null);
const [warmups, setWarmups] = useState(0);
const captchaForm = useRef(null);

const onMessage = (event) => {
if (!event?.nativeEvent?.data) {
return;
}

if (event.nativeEvent.data === 'open') {
console.log('Visual challenge opened');
return;
}

if (event.success) {
setCode(event.nativeEvent.data);
captchaForm.current.hide();
event.markUsed();
console.log('Verified code from hCaptcha', event.nativeEvent.data);
return;
}

if (event.nativeEvent.data === 'challenge-expired') {
event.reset();
console.log('Visual challenge expired, reset...', event.nativeEvent.data);
return;
}

setCode(event.nativeEvent.data);
captchaForm.current.hide();
console.log('Verification failed', event.nativeEvent.data);
};

return (
<View style={styles.container}>
<ConfirmHcaptcha
ref={captchaForm}
baseUrl={baseUrl}
languageCode="en"
onMessage={onMessage}
siteKey={siteKey}
userJourney={true}
/>
<TouchableOpacity
nativeID="warmup-touch"
onPress={() => {
setWarmups((value) => value + 1);
}}
testID="warmup-touch"
>
<Text style={styles.paragraph}>Preverify: {warmups} taps here</Text>
</TouchableOpacity>
<TouchableOpacity
nativeID="launch-captcha"
onPress={() => {
captchaForm.current.show();
}}
testID="launch-captcha"
>
<Text style={styles.paragraph}>Tap to launch</Text>
</TouchableOpacity>
{code && (
<Text style={styles.codeContainer}>
{'passcode or status: '}
<Text style={styles.codeText}>
{code}
</Text>
</Text>
)}
</View>
);
};

const styles = StyleSheet.create({
codeContainer: {
alignSelf: 'center',
},
codeText: {
color: 'darkviolet',
fontSize: 6,
fontWeight: 'bold',
},
container: {
backgroundColor: '#ecf0f1',
flex: 1,
justifyContent: 'center',
padding: 8,
},
paragraph: {
fontSize: 18,
fontWeight: 'bold',
margin: 24,
textAlign: 'center',
},
});

export default App;
18 changes: 16 additions & 2 deletions Hcaptcha.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import React from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import { WebViewMessageEvent } from 'react-native-webview';

type HcaptchaProps = {
export type HCaptchaVerifyParams = {
rqdata?: string;
phonePrefix?: string;
phoneNumber?: string;
};

export type HcaptchaProps = {
/**
* The callback function that runs after receiving a response, error, or when user cancels.
*/
onMessage?: (event: CustomWebViewMessageEvent) => void;
onMessage: (event: CustomWebViewMessageEvent) => void;
/**
* The size of the checkbox.
*/
Expand Down Expand Up @@ -52,6 +58,10 @@ type HcaptchaProps = {
* Hcaptcha execution options (see Enterprise docs)
*/
rqdata?: string;
/**
* Verification payload overrides. Values here take precedence over deprecated top-level fields.
*/
verifyParams?: HCaptchaVerifyParams;
/**
* Enable / Disable sentry error reporting.
*/
Expand Down Expand Up @@ -99,6 +109,10 @@ type HcaptchaProps = {
* Optional full phone number in E.164 format ("+44123..."), for use in MFA.
*/
phoneNumber?: string;
/**
* Enable automatic user journey injection.
*/
userJourney?: boolean;
}

interface CustomWebViewMessageEvent extends WebViewMessageEvent {
Expand Down
Loading
Loading