帮你快速理解、总结文档立即下载

HarmonyOS 接入

最近更新时间:2026-08-07 17:59:42
我的收藏

接入前提

Demo 工程使用 Stage 模型:
根工程 modelVersion: 5.0.2
entry 模块 apiType: stageMode
Demo 产品 compatibleSdkVersion: 5.0.0(12)
SDK HAR compatibleSdkVersion: 12
SDK HAR 包名:kycnfcsdk
埋点依赖 HAR 包名:analytics
建议业务工程使用 HarmonyOS API 12 及以上版本,并在真机上验证 NFC 能力。读卡流程需要设备支持 NFC,且系统 NFC 开关处于开启状态。

接入步骤

步骤1:SDK 文件和依赖配置

Demo 的 SDK 文件位于根目录 libs
libs/KycNfcSdk-v1.0.0-b3e74971.har
libs/WAAnalytics-2.3.4-ce3e09a.har
KycNfcSdk-v1.0.0-b3e74971.har 内部依赖 JLReaderD-1.1.5.har,并依赖 analytics@2.3.4。业务工程需要同时提供 WAAnalytics-2.3.4-ce3e09a.har,并保证 analytics 依赖解析到该本地 HAR。

根工程 oh-package.json5 增加 analytics override:
{
"modelVersion": "5.0.2",
"dependencies": {},
"overrides": {
"analytics": "file:./libs/WAAnalytics-2.3.4-ce3e09a.har"
}
}
entry 模块 entry/oh-package.json5 增加 SDK 依赖:
{
"name": "entry",
"version": "1.0.0",
"dependencies": {
"kycnfcsdk": "file:../libs/KycNfcSdk-v1.0.0-b3e74971.har",
"analytics": "file:../libs/WAAnalytics-2.3.4-ce3e09a.har"
}
}
配置完成后执行依赖同步或 ohpm install。依赖锁中应能看到:
kycnfcsdk@1.0.0
analytics@2.3.4
jlreader@1.1.5
libjlreader.so

步骤2:module.json5 配置

2.1 网络权限

Demo 的 entry 模块显式声明了网络权限:
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" }
]
SDK HAR 自身声明了:
[
{ "name": "ohos.permission.INTERNET" },
{ "name": "ohos.permission.GET_NETWORK_INFO" },
{ "name": "ohos.permission.SET_NETWORK_INFO" },
{ "name": "ohos.permission.NFC_TAG" }
]
外部工程接入时,entry 模块至少保留 ohos.permission.INTERNET。如果业务工程的权限合并或合规扫描要求所有权限必须在 entry 模块显式出现,请同步确认 SDK HAR 中声明的网络/NFC 权限没有被裁剪。

2.2 NFC Tag 分发配置

承载 NFC 流程的 UIAbility 需要配置 ohos.nfc.tag.action.TAG_FOUND,并声明 SDK 需要识别的 Tag 技术类型:NfcBIsoDep

核心新增配置如下:
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"exported": true,
"skills": [
{
"actions": [
"ohos.nfc.tag.action.TAG_FOUND"
],
"uris": [
{ "type": "tag-tech/NfcB" },
{ "type": "tag-tech/IsoDep" }
]
}
]
}
]
}
}
如果该 Ability 同时作为桌面入口,保留原有的 entity.system.homeaction.system.home 配置。Demo 将桌面入口 action 与 NFC TAG_FOUND action 放在同一个 skill 中。

步骤3:EntryAbility 必须初始化 JLElementName

注意:
该配置为必接项,不是可选配置。
SDK 底层读卡能力需要当前 Ability 的 ElementName。必须在 EntryAbility.onCreate() 中初始化,否则 NFC 前台分发注册会失败。
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { JLElementName } from 'kycnfcsdk';

export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
JLElementName.elementName = {
bundleName: want.bundleName as string,
abilityName: want.abilityName as string,
moduleName: want.moduleName as string
};
}
}

步骤4:SDK 初始化参数

业务侧通过 NfcInitDataMap 向 SDK 传入初始化参数。Demo 使用的核心类型如下:
import {
InputData,
NfcInitDataMap,
WbCloudNfcSDK
} from 'kycnfcsdk';

4.1 InputData 构造参数

SDK 导出的 InputData 字段:
参数
说明
类型
长度
是否必填
orderNo
订单号
String
32
必填,合作方订单的唯一标识,字母/数字组成的字符串
openApiAppId
业务流程唯一标识,即 wbappid,可参考 获取 WBappid 指引在人脸核身控制台内申请
String
8
必填
openApiAppVersion
接口版本号
String
20
必填,默认填 1.0.0
openApiNonce
32位随机字符串
String
32
必填,每次请求需要的一次性 nonce
openApiUserId
User Id
String
30
必填,每个用户唯一的标识
openApiSign
合作方后台服务器通过 ticket 计算出来的签名信息
String
40
必填
openApiOcrCertId
合作方后台服务器通过 ticket 计算出来的 ocrCertId
String
40
必填
构造顺序必须与 Demo 一致:
const inputData = new InputData(
orderNo,
openApiAppId,
openApiAppVersion,
openApiNonce,
openApiUserId,
openApiSign,
ocrCertId
);

4.2 初始化 Map

import {
InputData,
NfcInitDataMap,
TRAVEL_CARD_BIRTH,
TRAVEL_CARD_NO,
TRAVEL_CARD_VALIDATE,
WbCloudNfcSDK
} from 'kycnfcsdk';

const data: NfcInitDataMap = {};

data[WbCloudNfcSDK.INPUT_DATA] = new InputData(
orderNo,
openApiAppId,
openApiAppVersion,
openApiNonce,
openApiUserId,
openApiSign,
ocrCertId
);

// 单位:毫秒。Demo 传入 20000。
data[WbCloudNfcSDK.NFC_TIME] = 20000;

// Demo 中:'1' 表示身份证;'3' 表示回乡证/旅行证件类流程。
data[WbCloudNfcSDK.NFC_TYPE] = nfcType;

if (nfcType === '3') {
data[TRAVEL_CARD_NO] = travelCardNo;
data[TRAVEL_CARD_BIRTH] = travelBirth;
data[TRAVEL_CARD_VALIDATE] = travelValidate;
}
Demo 也直接使用过以下字符串 key:
data.travel_card_no = travelCardNo;
data.travel_card_birth = travelBirth;
data.travel_card_validate = travelValidate;
外部接入建议优先使用 SDK 导出的常量,避免后续 SDK 升级时 key 发生变化。

4.3 初始化调用

import common from '@ohos.app.ability.common';
import {
NfcLoginListener,
WbCloudNfcSDK
} from 'kycnfcsdk';

class LoginListener implements NfcLoginListener {
onLoginSuccess(): void {
// 初始化和 SDK 登录成功后,再启动读卡。
}

onLoginFailed(errorCode: string, errorMsg: string): void {
// 初始化失败,业务侧提示或上报。
}
}

const context = getContext() as common.UIAbilityContext;
WbCloudNfcSDK.getInstance().init(context, data, new LoginListener());
init() 完成后会通过 NfcLoginListener 返回结果。只有收到 onLoginSuccess() 后才调用读卡接口。

步骤5:SDK 读卡调用

带 UI 模式由 SDK 展示内置 NFC 引导、协议、读卡和完成页面。业务侧只需要在 init() 成功后调用 startActivityForNfc()
import common from '@ohos.app.ability.common';
import {
NfcResultListener,
WBNfcResult,
WbCloudNfcSDK
} from 'kycnfcsdk';

class ResultListener implements NfcResultListener {
onFinish(result: WBNfcResult): void {
if (result.code === '0') {
// 读卡成功。可使用 result.reqId/orderNo 查询最终业务结果。
return;
}

// 读卡失败或取消。展示 result.message,并按业务需要上报。
}
}

const context = getContext() as common.UIAbilityContext;
WbCloudNfcSDK.getInstance().startActivityForNfc(context, new ResultListener());
注意:
不要在一次识别未结束时重复调用 startActivityForNfc()。SDK 内部会拦截重复调用。
如果业务需要重试,等待 onFinish() 回调后重新走初始化/启动流程;SDK 也导出了 resetCanDoNfcSdkRecognise() 用于重置识别状态。
生产环境建议关闭 SDK 内部日志,见“可选配置项”。

步骤6:结果回调和结果查询

6.1 WBNfcResult

SDK 通过 NfcResultListener.onFinish()NfcResultWithStateListener.onFinish() 回调 WBNfcResult
参数
说明
type
NFC 类型,Demo 使用 '1''3'
code
SDK 结果码,Demo 以 '0' 判断成功
message
结果描述
orderNo
业务订单号
ocrCertId
OCR/NFC 凭证 ID
reqId
本次请求 ID,后续查询结果使用
guidePageTime
SDK 引导页耗时
nfcPreDoTime
NFC 前置处理耗时
nfcDetectTime
NFC 检测耗时
netRequestTime
网络请求耗时
端侧读卡成功不等于业务已经拿到全部证件信息。业务侧通常需要使用 appIdnoncereqIdorderNo 到服务端查询最终结果。

6.2 Demo 中的签名接口

Demo 为了演示,在端侧直接请求:
GET https://kyc1.qcloud.com/ems-partner/cert/nfc/getocrcertid
请求参数:
参数
说明
appId
OpenAPI AppId
nonce
随机串
userId
用户 ID
orderNo
订单号
nfcType
NFC 类型
Demo 期望返回:
class SignResponse {
sign: string = '';
ocrCertId: string = '';
code: string = '';
msg: string = '';
}
生产接入建议由业务后端负责签名和敏感参数处理,端侧只接收启动 SDK 所需的 signocrCertId 等参数。

6.3 Demo 中的结果查询接口

Demo 读卡成功后请求:
GET https://kyc1.qcloud.com/ems-partner/cert/nfc/queryrecord

请求参数:
参数
说明
appId
OpenAPI AppId
nonce
随机串
reqId
SDK 回调中的 result.reqId
orderNo
业务订单号
Demo 解析的主要结果字段:
字段
说明
code / msg
查询接口结果
reqId / orderNo
请求 ID 和订单号
name / enName
姓名/英文名
sex / nation / birth
性别、民族、出生日期
address
地址
idcard
证件号
signingOrganization
签发机关
validDateBegin / validDateEnd
有效期
frontPhoto / backPhoto / portraitPhoto
图片 Base64 或 data URL
结果查询接口不是端侧 SDK 的公共 API,实际生产方案以业务方服务端和腾讯云接口约定为准。

步骤7:可选配置项

SDK 导出配置单例 WbCloudNfcConfig
import { WbCloudNfcConfig } from 'kycnfcsdk';

const config = WbCloudNfcConfig.getInstance();

// 是否使用 SIT 环境。生产环境不要打开。
config.setSitEnv(false);

// 是否打开 SDK 内部日志。Demo 打开;生产环境建议 false。
config.setEnableLog(false);
SDK 还导出以下配置方法:
方法
说明
setIpv6(boolean) / isIpv6()
IPv6 相关配置
setRetCrop(boolean) / isRetCrop()
裁剪结果相关配置
setWbUrl(boolean) / isWbUrl()
URL 相关配置
setCheckWarnings(boolean) / isCheckWarnings()
告警检查相关配置
Demo 未使用这些扩展配置。外部接入如需启用,应以 SDK 版本说明或商务/服务端配置要求为准。

NFC 能力检测

SDK 导出:
const availability = WbCloudNfcSDK.getInstance().getNfcAvailability();
返回结构:
interface NfcAvailabilityState {
status: NfcAvailabilityStatus; // ready / unsupported / disabled
code: string;
message: string;
canRead: boolean;
}
无 UI 模式建议在启动 enableReaderMode() 前检测 canRead。带 UI 模式下 SDK 内部会处理 NFC 不支持或未开启等状态,但业务侧仍可提前检测并做自定义提示。

步骤8:混淆配置

Demo 当前 entry/obfuscation-rules.txt 已开启 release 混淆,配置如下:
-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation
当前 Demo 未额外配置 -keep-* 规则。外部工程可以先按上述配置验证 release 包;如果业务工程还有自定义反射、动态字段访问、运行时按字符串调用方法、JSON 字段直接映射、router routeName 等场景,请按业务代码实际情况补充 keep 规则。

重点关注以下跨运行时边界:
SDK 回调方法:onLoginSuccessonLoginFailedonFinishonTagDiscoveredonStart
JLElementName 相关字段:elementNamebundleNameabilityNamemoduleName
SDK 初始化和结果字段:INPUT_DATANFC_TIMENFC_TYPEorderNoappIdnonceuserIdsignocrCertIdreqIdtypecodemessage
回乡证参数字段:TRAVEL_CARD_NOTRAVEL_CARD_BIRTHTRAVEL_CARD_VALIDATEtravel_card_notravel_card_birthtravel_card_validate
业务结果查询 JSON 字段:resultdatanamesexnationbirthaddressidcardfrontPhotobackPhotoportraitPhoto

步骤9:接入验证清单

接入完成后按以下顺序验证:
1. ohpm install 或 DevEco 依赖同步成功。
2. entry 模块可以正常 import:
import { WbCloudNfcSDK, InputData } from 'kycnfcsdk';
3. HAP 构建成功,未出现 kycnfcsdkanalyticsjlreaderlibjlreader.so 解析失败。
4. EntryAbility.onCreate() 已设置 JLElementName.elementName
5. module.json5 中 NFC TAG_FOUND skill 包含 tag-tech/NfcBtag-tech/IsoDep
6. 真机 NFC 已开启,设备支持 NFC。
7. 业务后端能返回有效 signocrCertId
8. init() 能回调 onLoginSuccess()
9. 带 UI 模式能进入 SDK 页面并最终回调 onFinish();无 UI 模式能收到 onTagDiscovered()onStart()onFinish()
10. 成功时 WBNfcResult.code === '0',并能使用 reqIdorderNo 查询业务结果。
11. release 包开启混淆后仍能正常回调,字段未被混淆破坏。

常见问题排查

init() 失败

检查:
InputData 构造参数顺序是否正确。
signocrCertId 是否为空。
appIdnonceuserIdorderNo 是否与服务端签名一致。
网络权限和网络连通性是否正常。
setSitEnv() 是否错误地指向了非目标环境。

无法检测到 NFC 卡片

检查:
真机是否支持 NFC,系统 NFC 开关是否打开。
module.json5 是否配置 ohos.nfc.tag.action.TAG_FOUND
uris 是否包含 tag-tech/NfcBtag-tech/IsoDep
JLElementName.elementName 是否在 EntryAbility.onCreate() 中初始化。
无 UI 模式页面隐藏或后台时是否过早调用了 disableReaderMode()

日志出现 reader elementName 缺失或前台分发注册失败

优先检查 EntryAbility.onCreate() 中的:
JLElementName.elementName = {
bundleName: want.bundleName as string,
abilityName: want.abilityName as string,
moduleName: want.moduleName as string
};
该配置缺失会导致底层 SDK NFC 注册失败。

带 UI 模式重复调用无反应

SDK 会防止一次识别流程中重复调用 startActivityForNfc()。等待 onFinish() 后再发起下一次识别;必要时调用:
WbCloudNfcSDK.getInstance().resetCanDoNfcSdkRecognise();

release 包回调方法不执行

优先确认 release 包使用的混淆规则是否与 Demo 一致。若业务工程在 Demo 配置之外增加了更严格的混淆,或存在按字符串调用回调方法的代码,再补充 -keep-property-name 保留 onLoginSuccessonLoginFailedonFinishonTagDiscoveredonStart 等回调名。

结果页查不到证件信息

SDK 的 onFinish() 返回的是 NFC 读卡流程结果。证件详情需要通过服务端结果查询接口获取。请确认:
result.code === '0'
result.reqId 非空
查询时使用的 appIdnonceorderNo 与启动 SDK 时一致
查询接口环境与 SDK 登录环境一致