With the new Swift 4 support, ReCaptcha has finally reached a stable release! Now you can safely use Google’s Invisible ReCaptcha in your app!
Using the JS API, ReCaptcha tries to validate the challenge automatically and retrieve a token, however, if the API can’t ensure the user is human, a challenge may be presented.
Setup
Register a new site to use Invisible reCaptcha at the admin page. Make sure to add correct domain owned by you or your company!
This will return you two keys: a Site key and a Secret key. The former is the public key which will be used in your frontend to start the validation. This is the key must be used in the app. DO NOT USE THE SECRET KEY!
The Secret key is for the validation in the server side of the application!
Warning ⚠️
Beware that this library only works for Invisible ReCaptcha keys! Make sure to check the Invisible reCAPTCHA option when creating your API Key.
Installation
You can install ReCaptcha using CocoaPods, Carthage or as a submodule. The library comes with a RxSwift extension.
CocoaPods
Add the following to your Podfile:
pod "ReCaptcha", '~> 1.0'
# or
pod "ReCaptcha/RxSwift", '~> 1.0'
Carthage
github "fjcaetano/ReCaptcha" ~> 1.0
If you decide to use the reactive extension, be sure to link both frameworks
ReCaptcha
and ReCaptcha_RxSwift
to your project. The latter, simply contains
the reactive extension for the ReCaptcha
class.
iOS Setup
Open your project’s Info.plist
file and add two entries:
- ReCaptchaKey: The Site key created in the previous step.
- ReCaptchaDomain: A valid domain registered with the key in the previous step.
These values may also be sent as parameters to ReCaptcha()
init. In this case,
the parameters will override the values in the Info.plist
.
Code
Before starting the validation, you must call the configureWebView(_:)
method.
This is for when the webview needs to be presented for the user to complete the
ReCaptcha challenge. If this method is not called, the validation may fail.
recaptcha.configureWebView { [weak self] (webview: WKWebView) in
// Configure webview for presentation
// Make sure its frame is not CGRect.zero
}
This is the moment to add AutoLayout constraints and store a reference to the webview, which will already have a superview that is provided when starting the validation.
The configureWebView(_:)
won’t necessarily be called. Only if the invisible
validation is not possible.
Validation
To start the validation, per se, you must call the validate(on:)
method.
recaptcha.validate(on: view) { [weak self] (result: ReCaptchaResult) in
print(try? result.dematerialize())
}
The view
given as parameter, must be visible, i.e. be in the active window
hierarchy, its bounds must be valid and it can’t be marked as hidden
. This view
will contain the ReCaptcha webview as a subview.
By default, ReCaptcha won’t remove the webview from its superview, so it may be interesting to have some clean up after the closure is called.
Error Handling
ReCaptcha may throw you some errors if incorrectly configured or when execution
fails. In any case, you can always try calling recaptcha.reset()
on errors or
providing resetOnError: true
to the validate
method.
ReCaptchaError.htmlLoadError
: If by some reason, the library’s bundle is unreachable, the template HTML won’t be loaded.ReCaptchaError.apiKeyNotFound
: No API key has been provided to the library. Either set aReCaptchaKey
entry in the app’sInfo.plist
or pass it as argument toReCaptcha
’s init.ReCaptchaError.baseURLNotFound
: No domain has been provided to the library. Either set aReCaptchaDomain
entry in the app’sInfo.plist
or pass it as argument toReCaptcha
’s init.ReCaptchaError.wrongMessageFormat
: This means the JS context provided an unexpected message to the API. Shouldn’t happen, so, if it does, be sure to open an issue.ReCaptchaError.unexpected(Error)
: 💩 happens ¯\_(ツ)_/¯. The only moment this error could be thrown is if JavaScript sends an error. Shouldn’t happen, but if it does, don’t be shy and open an issue.
Firewall bypass
If your firewall is blocking Google’s ReCaptcha, or if you’re behind the Great
Firewall of China, you may use an alternate endpoint for the JS API that points
to https://www.recaptcha.net/recaptcha/api.js
:
try ReCaptcha(endpoint: .alternate)
The default value for the endpoint
parameter points the API to https://www.google.com/recaptcha/api.js