Send a verification request from your app

更新时间:
复制 MD 格式

This tutorial explains how to use the client-side V2 architecture to send a verification request from your app and return the result to the H5 page. Demo projects are also provided.

Important
  • For this integration method, we recommend using interactive verification types such as the slider or jigsaw puzzle. Silent verification is not supported. Silent verification requires collecting user behavior information on the page and an action to trigger the verification process. In this scenario, developers often use JavaScript to trigger the verification automatically, which can cause the silent verification to fail but still be billed as a verification attempt.

  • This method is only applicable to the client-side V2 architecture.

Integrate CAPTCHA 2.0 in iOS using WKWebView

In an iOS application, you can use the window.webkit.messageHandlers interface of WKWebView to enable JavaScript interaction with an H5 page. This interface allows you to send messages to native code and retrieve the results of the native code's processing. This interaction is typically asynchronous because it relies on native code processing and callbacks. However, window.webkit.messageHandlers does not natively support Promise or async/await. Message sending is typically one-way, from JavaScript to native code, and the response from the native code requires a separate mechanism. To use await for this interaction, you need to create a Promise and resolve it after the native code finishes processing. This is typically done by using a callback function to resolve the Promise. The following is a simple example to illustrate how to achieve this.

Modify captchaVerifyCallback as follows:

// Define a function on the H5 page to send a message to native code and return a Promise.
async function sendMessageToNative(action, data) {
  return new Promise((resolve, reject) => {
    // Create a unique callback function name.
    const callbackName = `cb_${Math.random().toString(36).substring(2)}`;

    // Attach the callback function to the window object so that native code can call it.
    window[callbackName] = (response) => {
      // Process or display the result returned from the iOS side.
      console.log('Verification result from iOS:', response);
      resolve(JSON.parse(response)); // Note the format conversion.
      // Remove the attached callback function to prevent a memory leak.
      delete window[callbackName];
    };

    console.log(action, data, window.webkit);
    // Call the JavaScript interface to send a message to the native code.
    window.webkit && window.webkit.messageHandlers[action].postMessage(JSON.stringify({
      data,
      callback: callbackName,
    }));
  });
}

// Use an async function to call sendMessageToNative and wait for the reply from the native code.
// Business request (with CAPTCHA validation) callback function.
async function captchaVerifyCallback(captchaVerifyParam) {
  // 1. Call the sendMessageToNative method to get the verification result.
  let result = {};
  try {
    console.log(captchaVerifyParam);
    result = await sendMessageToNative('getVerifyResult', captchaVerifyParam);
    console.log('Verification result from iOS:', result);
  } catch (error) {
    console.error('An error occurred:', error);
    // Error handling/fallback logic.
    result = {
      captchaResult: false,
      bizResult: false,
    };
  }
  // If the verification logic is executed on the client-side, the following return value is not needed. You can close the H5 page directly.
  return {
    captchaResult: result.captchaResult, // Indicates whether the CAPTCHA verification passed. A boolean value. Required.
    bizResult: result.bizResult, // Indicates whether the business validation passed. A boolean value. Optional. This can be null if business validation is not performed.
  };
}

Modify your Swift code as follows to return the verification result to the H5 page. You can then decide whether to execute custom business logic on the client-side or on the H5 side based on your requirements.

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "getVerifyResult", let messageBody = message.body as? String {
        if let data = messageBody.data(using: .utf8) {
            do {
                if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                    // Parse the JSON.
                    let captchaVerifyParam = jsonObject["data"]as! String;
                    let callbackName = jsonObject["callback"] as! String;
                    // Use captchaVerifyParam to request the backend API and get the result.
                    let response: [String: Any] = [
                        "captchaResult": true,
                        "bizResult": true
                    ]; // The result is converted to a JSON string. The H5 page must parse this string back into an object.
                    do {
                        let jsonData = try JSONSerialization.data(withJSONObject: response, options: []);
                        // Convert the JSON data to a string.
                        if let verifyResult = String(data: jsonData, encoding: .utf8) {
                            // Execute the callback to pass the result back to the H5 page.
                            sendJSONToWebView(jsonString: verifyResult, callbackName: callbackName);
                            // Execute custom business logic on the client-side based on the result. The onBizResultCallback in H5 can be an empty function.
                        }
                    } catch {
                        print("Error serializing JSON: \(error)")
                    }
                }
            } catch {
                print("Failed to parse JSON: \(error)")
            }
        }
    }
    // Close the webview.
    if message.name == "closeWebView" {
        webView.removeFromSuperview();
    }
}
// Call the JavaScript function.
func sendJSONToWebView(jsonString: String, callbackName: String) {
    let javascriptFunction = "\(callbackName)('\(jsonString)');"
    
    webView.evaluateJavaScript(javascriptFunction) { (result, error) in
        if let error = error {
            print("Error calling JavaScript function: \(error)")
        } else {
            print("Sent JSON to WebView")
        }
    }
}

Integrate CAPTCHA 2.0 in Android using WebView

In an Android application, you can use a custom Java interface named testJsInterface to interact with JavaScript on an H5 page. You can use this interface to send messages to native code and retrieve the results of the processing. This interaction is typically asynchronous because it relies on native code processing and callbacks. However, window.testInterface itself does not directly support the Promise or async/await mechanism. Message sending is typically one-way, from JavaScript to native code, and replies from the native code must be implemented by using a separate mechanism. To use await for this interaction, you need to create a Promise and resolve this Promise by using a method, such as a callback function, after the native code completes processing. The following is a simple example that illustrates how to achieve this.

Modify captchaVerifyCallback as follows:

// Define a function on the H5 page to send a message to native code and return a Promise.
async function sendMessageToNative(action, data) {
  return new Promise((resolve, reject) => {
    // Create a unique callback function name.
    const callbackName = 'cb_' + Math.random().toString(36).substring(2);

    // Attach the callback function to the window object so that native code can call it.
    window[callbackName] = (response) => {
      // Process or display the result returned from the Android side.
    	console.log('Verification result from Android:', response);
      resolve(JSON.parse(response)); // Note the format conversion.
      // Remove the attached callback function to prevent a memory leak.
      delete window[callbackName];
    };

    // Call the JavaScript interface defined in Java to send a message to the native code.
    window.testInterface && window.testInterface[action](JSON.stringify({
      data: data,
      callback: callbackName
    }));
  });
}

// Use an async function to call sendMessageToNative and wait for the reply from the native code.
// Business request (with CAPTCHA validation) callback function.
async function captchaVerifyCallback(captchaVerifyParam) {
  // 1. Call the sendMessageToNative method to get the verification result.
  let result = {};
  try {
    console.log(captchaVerifyParam);
    result = await sendMessageToNative('getVerifyResult', captchaVerifyParam);
    console.log('Verification result from Android:', result);
  } catch (error) {
    console.error('An error occurred:', error);
    // Error handling/fallback logic.
    result = {
      captchaResult: false,
      bizResult: false,
    };
  }
  // If the verification logic is executed on the client-side, the following return value is not needed. You can close the H5 page directly.
  const verifyResult = {
    captchaResult: result.captchaResult, // Indicates whether the CAPTCHA verification passed. A boolean value. Required.
    bizResult: result.bizResult, // Indicates whether the business validation passed. A boolean value. Optional. This can be null if business validation is not performed.
  };

  return verifyResult;
}

Modify your Java code as follows to return the verification result to the H5 page. You can then decide whether to execute custom business logic on the client-side or on the H5 side based on your requirements.

import android.webkit.JavascriptInterface;
import android.webkit.WebView;

public class testJsInterface {
    private WebView webView;

    // Constructor that passes the WebView object.
    public testJsInterface(WebView webView) {
        this.webView = webView;
    }

    // Expose this method to JavaScript through the @JavascriptInterface annotation.
    @JavascriptInterface
    public void getVerifyResult(String jsonString) {
        try {
            // Convert the JSON string to a JSONObject.
            JSONObject jsonObject = new JSONObject(jsonString);
            String captchaVerifyParam = jsonObject.getString("data");
            String callbackName = jsonObject.getString("callback");
    
            // Use captchaVerifyParam to request the backend API and get the result.
            // JSONObject verifyResult = requestAPI(captchaVerifyParam);
    
            JSONObject result = new JSONObject();
            // Simulate the returned result.
            result.put("captchaResult", true);
            result.put("bizResult", true);
    
            String resultString = result.toString(); // The result is converted to a JSON string. The H5 page must parse this string back into an object.
            System.out.println(resultString);
    
            // After processing the data, pass the result back to the H5 page.
            // Ensure that this operation is executed on the main thread (UI thread).
            webView.post(new Runnable() {
                @Override
                public void run() {
                    // Send the callback to the H5 page by using evaluateJavascript.
                    webView.evaluateJavascript("javascript:" + callbackName + "('" + escapeJavaScriptString(resultString) + "')", null);
                    // Execute custom business logic on the client-side based on the result. The onBizResultCallback in H5 can be an empty function.
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Escape the JavaScript string to prevent JavaScript injection issues.
    private String escapeJavaScriptString(String string) {
        // This is a simple escape example. For more complex cases, a more robust escape method is required.
        return string.replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\\\"");
    }

}

Download app integration demos