HarmonyOS NEXT 实战:QQ 图文分享功能完整实现
在 HarmonyOS NEXT 应用开发中,集成 QQ 分享功能需严格遵循腾讯开放平台的签名校验机制与参数规范。本文基于华为开发者联盟官方实战指南,详细拆解 QQ 图文分享的前置准备、签名生成、代码实现及错误处理,确保开发者按步骤即可实现稳定分享功能,规避 “签名错误”“发送失败” 等高频问题。
一、核心前提与环境准备
1.1 前置条件
- 已完成 QQ HarmonyOS SDK 环境搭建(参考腾讯官方文档,确保 SDK 版本≥v1.0.4);
- 已在腾讯开放平台创建鸿蒙应用,获取
AppID和AppKey(AppKey需妥善保管,建议仅存储在后端); - 鸿蒙应用已完成
module.json5配置(含querySchemes、skills等 Scheme 相关配置,确保 QQ 回调正常)。
1.2 依赖导入(关键步骤)
分享功能需通过 CryptoJS 实现 HMAC-SHA1 签名生成,需在项目中添加依赖:
- 打开鸿蒙项目的
oh-package.json5文件,新增以下依赖:
"dependencies": {
"@tencent/qq-open-sdk": "^1.0.4", // QQ SDK 核心依赖
"@ohos/crypto-js": "^2.0.4" // 签名生成工具
}
- 执行
ohpm install命令安装依赖,安装完成后验证node_modules目录下是否存在@ohos/crypto-js文件夹。
二、核心原理:分享签名生成规范(报错重灾区)
腾讯 QQ 分享接口为保证数据安全性,要求对分享参数进行签名校验,签名生成错误是导致 “发送失败(901310)” 的主要原因,需严格遵循以下两步流程:
2.1 签名原文拼接规则(不可修改)
签名原文需按固定格式拼接,顺序、字段均不可自定义,格式如下:
请求方法 + 请求域名 + 请求路径 + ? + 请求字符串 + 分享内容json字符串
各部分说明:
- 请求方法:固定为
POST(全大写,不可小写); - 请求域名:固定为
connect.qq.com(无协议头,不可加https://); - 请求路径:固定为
/share; - 请求字符串:按字典序拼接
appid、nonce(随机自然数)、ts(时间戳,秒级),格式为appid=xxx&nonce=xxx&ts=xxx; - 分享内容 json 字符串:需与实际分享的标题、链接等参数完全一致,不可额外添加字段。
2.2 签名计算流程
- 使用
AppKey对拼接后的签名原文执行 HMAC-SHA1 加密; - 将加密结果通过 Base64 编码,得到最终签名串(
shareJsonSign); - 签名串需与分享参数一同传入 SDK,否则会被接口校验拒绝。
2.3 签名示例(直观参考)
假设以下参数:
- AppID:22222222
- nonce:1234(随机自然数)
- ts:1618924373(秒级时间戳)
- 分享内容 JSON:
{"msg_style": 0, "title":"标题", "summary":"内容", "brief":"互联分享","url":"https://www.qq.com","picture_url":"../images/2026/0130/babyhome.htm"}
拼接后的签名原文:
POSTconnect.qq.com/share?appid=222222&nonce=1234&ts=1618924373&{"msg_style": 0, "title":"标题", "summary":"内容", "brief":"互联分享", "url":"https://www.qq.com", "picture_url":"../images/2026/0130/babyhome.htm"}
若 AppKey 为 fakeAppKey,最终 Base64 编码后的签名串为:Ngyk0JS5pQR8ffygeeMHFUNFQQA=
三、完整代码实现(逐行对照官方示例)
3.1 配置常量类(统一管理敏感参数)
创建 AppConfigs.ets 文件,集中管理 AppID、AppKey 等参数,便于维护:
// AppConfigs.ets
export class AppConfigs {
// 替换为你的腾讯开放平台 AppID(纯数字)
static readonly qqsdkAppId = 222222;
// 替换为你的腾讯开放平台 AppKey(仅用于签名生成,建议后端提供)
static readonly qqsdkAppKey = "fakeAppKey";
}
3.2 封装 QQ 分享工具类(QQUtil.ets)
创建工具类统一处理分享逻辑,包含签名生成、参数组装、SDK 调用等核心步骤,可直接复用:
// QQUtil.ets
import { CryptoJS } from '@ohos/crypto-js';
import { IQQOpenApi, QQOpenApiFactory, ShareData, ShareResult, ShareResultType } from '@tencent/qq-open-sdk';
import { AppConfigs } from './AppConfigs';
import promptAction from '@ohos.promptAction';
import Logger from '../utils/Logger'; // 可自定义日志工具,也可使用 console
export class QQUtil {
// 获取 QQ SDK 实例(单例模式,避免重复创建)
private static getQQOpenApi(): IQQOpenApi {
return QQOpenApiFactory.createApi(AppConfigs.qqsdkAppId.toString());
}
/**
* QQ 图文分享核心方法
* @param title 分享标题(长度≤50字)
* @param summary 分享摘要(长度≤100字)
* @param brief QQ 消息列表显示的小尾巴(建议固定为“互联分享”)
* @param imageUrl 封面图片链接(仅支持网络图片,尺寸≤1MB)
* @param url 点击跳转链接(需备案,支持 https/http)
*/
static async share(
title: string,
summary: string,
brief: string = "互联分享",
imageUrl: string,
url: string
) {
try {
// 1. 组装分享内容 JSON(msg_style 固定为 0,不可修改)
const shareContent = {
msg_style: 0,
title: title,
summary: summary,
brief: brief,
url: url,
picture_url: imageUrl
};
const shareJson = JSON.stringify(shareContent);
// 2. 生成签名所需参数
const timestamp = Math.floor(Date.now() / 1000); // 秒级时间戳
const nonce = Math.floor(Math.random() * 100000000 + 100); // 随机自然数(100-100000099 之间)
// 3. 拼接签名原文(严格按规则,不可调整顺序或格式)
const signContent =
`POSTconnect.qq.com/share?appid=${AppConfigs.qqsdkAppId}&nonce=${nonce}&ts=${timestamp}&${shareJson}`;
// 4. 生成 HMAC-SHA1 + Base64 签名
const hmac = CryptoJS.HmacSHA1(signContent, AppConfigs.qqsdkAppKey);
const shareJsonSign = hmac.toString(CryptoJS.enc.Base64);
// 5. 组装分享参数(ShareData 为 SDK 内置类型,字段不可增减)
const shareData: ShareData = {
shareJson: shareJson,
timestamp: timestamp,
nonce: nonce,
shareJsonSign: shareJsonSign
};
// 6. 调用 QQ SDK 分享接口(type=2 为图文分享,固定值)
const qqOpenApi = QQUtil.getQQOpenApi();
const result: ShareResult = await qqOpenApi.share(2, shareData);
// 7. 处理分享结果
switch (result.resultType) {
case ShareResultType.Success:
promptAction.showToast({ message: "分享成功" });
Logger.info(`QQ分享成功:${JSON.stringify(result)}`);
break;
case ShareResultType.Cancel:
const cancelMsg = result.message ?? "用户取消分享";
promptAction.showToast({ message: cancelMsg });
break;
case ShareResultType.Error:
const errorMsg = result.message ?? "分享失败";
promptAction.showToast({ message: errorMsg });
Logger.error(`QQ分享失败:错误码=${result.code},消息=${errorMsg}`);
break;
}
} catch (error) {
const errMsg = error instanceof Error ? error.message : "未知错误";
promptAction.showToast({ message: `分享异常:${errMsg}` });
Logger.error(`QQ分享异常:${errMsg}`);
}
}
}
3.3 调用分享功能(页面中使用)
在需要触发分享的页面(如按钮点击事件)中,直接调用 QQUtil.share 方法即可:
// 示例:分享按钮点击事件
import { QQUtil } from '../utils/QQUtil';
handleShareClick() {
QQUtil.share(
"HarmonyOS NEXT 实战教程", // 标题
"详解 QQ 图文分享功能实现,包含签名生成与 SDK 调用", // 摘要
"互联分享", // 小尾巴
"https://tangram-1251316161.file.myqcloud.com/files/20200722/example.png", // 封面图片
"https://developer.huawei.com/consumer/cn/blog/topic/03186421393814079" // 跳转链接
);
}
四、关键注意事项(避坑核心)
- AppKey 安全:
AppKey是签名生成的核心,建议由后端生成签名后返回给客户端,客户端避免直接存储AppKey(防止泄露); - 参数格式校验:
- 分享标题、摘要不可为空,且长度不超过限制(标题≤50 字,摘要≤100 字);
- 图片链接必须是合法网络地址(支持 https/http),本地图片需先上传至服务器获取链接;
- 跳转链接需完成备案,否则会被 QQ 拦截。
- 签名原文不可修改:请求方法、域名、路径均为固定值,拼接时不可添加额外字符(如空格、换行);
- 时间戳与随机数:
timestamp必须为秒级(毫秒级会导致签名失效),nonce每次分享需生成新值(不可重复使用); - SDK 实例一致性:调用
share方法的IQQOpenApi实例,需与初始化、回调处理的实例一致(建议单例模式)。
五、常见报错与解决方案
5.1 报错 “发送失败(901310)”
- 原因:签名生成错误(拼接格式错误、AppKey 错误、加密方式不对);
- 解决方案:
- 逐行核对签名原文拼接格式,确保与官方规则一致;
- 确认
AppKey为腾讯开放平台鸿蒙应用的专属密钥(不可复用 Android/iOS 平台 AppKey); - 验证加密方式为 HMAC-SHA1 + Base64(不可用 MD5 或其他加密方式)。
5.2 报错 “参数错误(-4035)”
- 原因:
shareData缺少必填字段(如shareJsonSign、timestamp)或shareJson格式错误; - 解决方案:
- 确保
shareData包含shareJson、timestamp、nonce、shareJsonSign四个字段; - 使用
JSON.stringify生成shareJson,避免手动拼接导致格式错误。
- 确保
5.3 分享无回调 / 无法唤起 QQ
- 原因:
module.json5中 Scheme 配置错误; - 解决方案:
- 确认
querySchemes包含https和qqopenapi; skills中的uris配置中,scheme为qqopenapi,host为纯数字 AppID,pathRegex包含share。
- 确认
总结
HarmonyOS NEXT 平台集成 QQ 图文分享的核心在于严格遵循签名生成规范与参数格式要求。通过本文提供的工具类封装,开发者可直接复用代码,只需替换 AppID、AppKey 及分享内容即可快速实现功能。若需扩展分享类型(如大图、空间分享),可参考腾讯官方接口文档,核心签名逻辑与图文分享一致,仅需调整 shareJson 字段与 type 参数。








