一、前提条件
2. 单击新建验证,根据业务场景需求,设置验证名称、客户端类型、验证方式等参数。
3. 单击确定,完成新建验证,即可在验证列表中查看验证码 CaptchaAppId 及 AppSecretKey。
二、接入步骤
注意:App 客户端(Android/iOS/Harmony)当前仅支持通过 WebView 引入 H5页面进行接入。
三、Harmony 接入主要流程
1. 在 Harmony 端利用 WebView 引入 H5页面。H5 页面接入验证码,详情请参见 Web 客户端接入。
2. 在 H5 页面中,通过调用验证码 JS,渲染验证页面,并将 JS 返回的参数值传到 Harmony App 业务端。
3. Harmony App 业务端把相关参数(票据 ticket、随机数等)传入业务侧后端服务进行票据验证,详情请参见 接入票据校验(Web及App)。
4. 体验完整接入示例 Harmony Next Demo。
四、Harmony 接入详细步骤
1. 在项目的工程中,新建一个 View 视图。导入 WebView 组件所需的包并进行初始化。
// src/main/ets/view/Login.etsimport router from '@ohos.router';import web_webview from '@ohos.web.webview';import { CaptchaCbParams,CaptchaRetData } from '../viewmodel/ParamsItem';import Logger from '../common/utils/Logger';import JSBridge from '../common/utils/JsBridge';@Componentexport struct LoginComponent { controller: web_webview.WebviewController = new web_webview.WebviewController(); aboutToAppear() { // 配置web开启调试模式 web_webview.WebviewController.setWebDebuggingAccess(true); } ports: web_webview.WebMessagePort[] = []; // 初始化JS事件交互 private jsBridge: JSBridge = new JSBridge(this.controller, this); // 在build方法之外定义关闭WebView的方法 closeWebView(param: string) { Logger.info("接收的回调数据", param) const jsonObj: CaptchaCbParams = JSON.parse(param) const retObj: CaptchaRetData = JSON.parse(jsonObj.data) if (retObj.ret == 0) { // 验证成功有票据 router.pushUrl({ url: CommonConstants.SUCCESS_PAGE_URL, params: retObj }) } else { // 验证失败或者主动关闭验证码无票据 Logger.info("主动关闭验证码") } this.showWebView = false; } build() { Stack() { Web({ src: $rawfile('captcha.html'), // 本地HTML文件路径 controller: this.controller }) .domStorageAccess(true) .javaScriptAccess(true) .javaScriptProxy(this.jsBridge.javaScriptProxy) .onPageBegin(() => { this.jsBridge.initJsBridge(); }) .width('360vp') .height('360vp') .backgroundColor(Color.Transparent) .alignSelf(ItemAlign.Center) } }}
2. 添加验证码 HTML 页面文件,放置于src/main/resources/rawfile/captcha.html中,WebView 需要从这个路径加载文件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { background-color: transparent; margin: 0; padding: 0; } </style> <title>Tencent Captcha</title> <script src="https://turing.captcha.qcloud.com/TCaptcha.js"></script></head><body> <script type="text/javascript"> function getAppIdParam() { let params = {}; let queryString = window.location.search.slice(1); // 获取URL参数字符串 if (queryString) { queryString = queryString.split('&'); // 分割成参数数组 queryString.forEach(item => { let arr = item.split('='); // 分割每个参数键值对 params[arr[0]] = decodeURIComponent(arr[1]); // decodeURIComponent用于解码URI }); } return params['appid'] || null; // 返回'appid'参数,如果不存在则返回null } function globalCallback(res) { // 与鸿蒙webview通信 if (window.ohosCallNative && window.ohosCallNative.callNative) { window.ohosCallNative.callNative('postMessage', JSON.stringify(res)); } } // captcha js error callback function errorCallback() { globalCallback({ ret: -1, randstr: '@' + Math.random().toString(36).substr(2), ticket: '', errorCode: 1001, errorMessage: 'jsload_error', }); } window.onload = function () { try { const sdkOptions = { isMobile: true, needFeedBack: false, enableDarkMode: false, // 是否需要loading和mask蒙层 loading: false, ready: function (size) { console.log('ready size:', JSON.stringify(size)); } }; const captcha = new TencentCaptcha('你的CatchaAppid', globalCallback, sdkOptions); // 调用方法,显示验证码 captcha.show(); } catch (error) { errorCallback(); } } </script></body></html>
3. 编写 WebView 页面与 App 端进行事件通信的方法。
// src/main/ets/common/utils/JsBridge.etsimport WebView from '@ohos.web.webview';import { code } from '../constants/CodeConstant';import { ParamsItem } from '../../viewmodel/ParamsItem';import { JavaScriptItem } from '../../viewmodel/JavaScriptItem';import Logger from './Logger';import { LoginComponent } from '../../view/LoginComponent';/** * JS事件层 连接 WebView 和 ArkTS通信. */export default class JsBridge { controller: WebView.WebviewController; private componentInstance: LoginComponent; constructor(controller: WebView.WebviewController,componentInstance: LoginComponent) { this.controller = controller; this.componentInstance = componentInstance; } get javaScriptProxy(): JavaScriptItem { let result: JavaScriptItem = { object: { call: this.call }, name: "JSBridgeHandle", methodList: ['call'], controller: this.controller } return result; } initJsBridge(): void { this.controller.runJavaScript(code); } postMessage = (params:string): Promise<string> => { // 可以在此将获取的票据传给页面,执行票据二次验证操作 Logger.info("验证码回调数据,",params) this.componentInstance.closeWebView(params); return new Promise((resolve) => { resolve(params); }) } call = (func: string, params: string): void => { const paramsObject: ParamsItem = JSON.parse(params); let result: Promise<string> = new Promise((resolve) => resolve('')); switch (func) { case 'postMessage': result = this.postMessage(params); break; default: break; } result.then((data: string) => { this.callback(paramsObject?.callID, data); }) } callback = (id: number, data: string): void => { this.controller.runJavaScript(`JSBridgeCallback("${id}", ${JSON.stringify(data)})`); }}
4. 在 H5 业务页面中接入验证码,详情请参见 Web 客户端接入 文档,并使用 JSBridge 传回验证数据给具体业务端。
注意:业务客户端完成验证码接入后,服务端需二次核查验证码票据结果(未接入票据校验,会导致黑产轻易伪造验证结果,失去验证码人机对抗效果),详情参见 接入票据校验 (Web 及 App)。
五、常见问题
详情参见 接入相关问题。
六、更多信息
你可以登录 验证码控制台,在页面右下角单击快速咨询,了解更多详细信息。