HarmonyOS 6.1 开源生态实战:从“自用”到“贡献”的三方库开发
系列生态共建篇·第53篇。跨端篇后,有开源爱好者问:“我在电商Demo里写了很多通用组件(如SKU选择器、地址联动),能不能抽离出来给社区用?怎么做成标准的OpenHarmony三方库?” 这正是开源生态的魅力。今天我们将电商Demo中的通用支付模块和SKU选择组件抽离、封装,发布为一个标准的OpenHarmony三方库(HAR包),并上架到OHPM(OpenHarmony Package Manager)仓库。我们将覆盖库工程搭建、API设计、文档撰写、单元测试、CI发布全流程。全程基于API23,含官方文档未涉及的“多目标构建”和“语义化版本控制”技巧。
一、前言:为什么“造轮子”也要讲姿势?
很多开发者写过“工具类”,但那只是“代码片段”。真正的三方库需要具备:
-
独立性:不依赖具体业务(如电商Demo),可独立编译和运行。
-
通用性:API设计抽象,能适应多种场景(如支付模块支持支付宝、微信、银联)。
-
稳定性:经过充分测试,版本迭代不破坏兼容性。
-
易用性:文档齐全,示例清晰,一键集成。
OHPM是OpenHarmony的官方包管理器,类似于npm(Node.js)或Maven(Android)。今天,我们将把电商Demo中的“支付功能”提炼成一个名为@harmony/payment-kit的高质量三方库,并贡献给开源社区。
二、核心概念辨析(代码片段 vs 三方库)
|
维度 |
代码片段 (Utils/Snippets) |
三方库 (Library/HAR) |
|---|---|---|
|
复用性 |
低,需复制粘贴修改 |
高,一键集成 ( |
|
维护性 |
差,分散在各项目中 |
好,集中维护,版本化管理 |
|
测试 |
无或简陋 |
完善,包含单元测试、集成测试 |
|
文档 |
注释为主 |
独立文档、API参考、示例工程 |
|
依赖 |
隐式依赖项目环境 |
显式声明依赖,自动解决 |
|
发布 |
口头分享 |
OHPM中央仓库,可检索 |
三、代码实现:从“业务代码”到“开源库”
3.1 创建HAR库工程
步骤1:新建Library Module
在DevEco Studio中:File -> New -> Module -> Static Library (HAR)。
命名为payment-kit。
步骤2:工程结构规划
payment-kit/
├── src/main/ets/
│ ├── components/ # UI组件(如支付密码弹窗)
│ │ └── PayPasswordDialog.ets
│ ├── core/ # 核心逻辑
│ │ ├── PaymentManager.ets
│ │ └── ChannelAdapter.ets
│ ├── models/ # 数据模型
│ │ └── PaymentInfo.ets
│ ├── utils/ # 工具类
│ │ └── SignUtil.ets
│ ├── index.ets # 对外暴露的API入口(关键!)
│ └── resources/ # 资源文件
├── src/test/ets/ # 单元测试
├── oh-package.json5 # 库配置文件(类似package.json)
└── README.md # 项目说明文档
3.2 抽离核心逻辑:支付管理器
创建src/main/ets/core/PaymentManager.ets:
// 定义支付渠道枚举
export enum PayChannel {
ALIPAY = 'alipay',
WECHAT = 'wechat',
UNIONPAY = 'unionpay',
HUAWEI_IAP = 'huawei_iap' // 华为IAP
}
// 定义支付结果回调
export interface PaymentCallback {
onSuccess?(result: PaymentResult): void
onFailed?(code: number, msg: string): void
onCancel?(): void
}
// 支付管理器(单例)
export class PaymentManager {
private static instance: PaymentManager
private channels: Map<PayChannel, ChannelAdapter> = new Map()
private currentCallback: PaymentCallback | null = null
static getInstance(): PaymentManager {
if (!PaymentManager.instance) {
PaymentManager.instance = new PaymentManager()
}
return PaymentManager.instance
}
/**
* 注册支付渠道适配器
*/
registerChannel(channel: PayChannel, adapter: ChannelAdapter): void {
this.channels.set(channel, adapter)
console.log(`支付渠道注册成功: ${channel}`)
}
/**
* 发起支付
*/
pay(info: PaymentInfo, callback: PaymentCallback): void {
this.currentCallback = callback
const adapter = this.channels.get(info.channel)
if (!adapter) {
callback.onFailed?.(-1, `支付渠道 ${info.channel} 未注册`)
return
}
// 参数校验
if (!this.validateParams(info)) {
callback.onFailed?.(-2, '支付参数校验失败')
return
}
// 调用具体渠道的支付逻辑
adapter.pay(info, {
onSuccess: (result) => {
this.handleSuccess(result)
},
onFailed: (code, msg) => {
this.handleFailed(code, msg)
},
onCancel: () => {
this.handleCancel()
}
})
}
/**
* 参数校验
*/
private validateParams(info: PaymentInfo): boolean {
if (!info.orderId || !info.amount || info.amount <= 0) {
return false
}
return true
}
private handleSuccess(result: PaymentResult): void {
console.log('支付成功:', result)
this.currentCallback?.onSuccess?.(result)
}
private handleFailed(code: number, msg: string): void {
console.error('支付失败:', code, msg)
this.currentCallback?.onFailed?.(code, msg)
}
private handleCancel(): void {
console.log('支付取消')
this.currentCallback?.onCancel?.()
}
}
// 渠道适配器接口(策略模式)
export interface ChannelAdapter {
pay(info: PaymentInfo, callback: PaymentCallback): void
}
3.3 实现具体渠道:华为IAP适配器
创建src/main/ets/core/adapters/HuaweiIAPAdapter.ets:
import { iap } from '@kit.IAPKit'
import { PaymentCallback, ChannelAdapter, PaymentInfo, PaymentResult } from '../PaymentManager'
export class HuaweiIAPAdapter implements ChannelAdapter {
async pay(info: PaymentInfo, callback: PaymentCallback): Promise<void> {
try {
// 1. 创建订单
const order = await iap.createPurchaseOrder({
productId: info.productId!,
quantity: info.quantity || 1
})
// 2. 发起支付
const payResult = await iap.pay(order)
// 3. 处理支付结果
if (payResult.returnCode === 0) {
const result: PaymentResult = {
orderId: info.orderId,
transactionId: payResult.inAppPurchaseData?.inAppPurchaseData?.orderId || '',
channel: 'huawei_iap',
rawData: JSON.stringify(payResult)
}
callback.onSuccess?.(result)
} else {
callback.onFailed?.(payResult.returnCode, payResult.errMsg || '支付失败')
}
} catch (err) {
console.error('华为IAP支付异常:', err)
callback.onFailed?.(-3, '支付过程发生异常')
}
}
}
3.4 定义对外API(入口文件)
关键:src/main/ets/index.ets 是库的“脸面”,必须清晰、简洁。
// 核心类
export { PaymentManager } from './core/PaymentManager'
export { HuaweiIAPAdapter } from './core/adapters/HuaweiIAPAdapter'
// 导出枚举和接口,方便使用者
export { PayChannel } from './core/PaymentManager'
export type { PaymentCallback, PaymentResult } from './core/PaymentManager'
export type { PaymentInfo } from './models/PaymentInfo'
// 提供便捷的初始化函数
import { PaymentManager } from './core/PaymentManager'
import { HuaweiIAPAdapter } from './core/adapters/HuaweiIAPAdapter'
export function initPaymentKit(): PaymentManager {
const manager = PaymentManager.getInstance()
// 默认注册华为IAP渠道
manager.registerChannel(PayChannel.HUAWEI_IAP, new HuaweiIAPAdapter())
return manager
}
3.5 配置库信息(oh-package.json5)
{
"name": "@harmony/payment-kit",
"version": "1.0.0",
"description": "A universal payment kit for HarmonyOS, supporting multiple channels.",
"main": "src/main/ets/index.ets",
"author": "listening777",
"license": "Apache-2.0",
"keywords": ["harmonyos", "payment", "iap", "alipay", "wechat"],
"repository": {
"type": "git",
"url": "https://gitee.com/your_repo/payment-kit.git"
},
"dependencies": {
"@ohos/iap": "^1.0.0" // 声明对IAP Kit的依赖
},
"devDependencies": {
"@ohos/hypium": "^1.0.0" // 单元测试框架
},
"ohos": {
"minAPIVersion": 11, // 支持的最低API版本
"targetAPIVersion": 12 // 目标API版本
}
}
3.6 编写README.md(门面担当)
# @harmony/payment-kit
一个用于HarmonyOS的通用支付聚合库,旨在简化多支付渠道的集成流程。
## 特性
- 🚀 **一键集成**:一行代码初始化,支持链式调用。
- 🔌 **可扩展**:通过适配器模式轻松接入新支付渠道。
- 🛡️ **类型安全**:完整的TypeScript类型定义。
- 📱 **跨端支持**:基于ArkUI-X,支持HarmonyOS、Android、iOS。
## 安装
bash
ohpm install @harmony/payment-kit
## 快速开始
typescript
import { initPaymentKit, PayChannel, PaymentInfo } from '@harmony/payment-kit'
// 1. 初始化
const paymentKit = initPaymentKit()
// 2. 构建支付信息
const info: PaymentInfo = {
orderId: 'ORDER_123456',
amount: 99.8,
currency: 'CNY',
channel: PayChannel.HUAWEI_IAP,
productId: 'product_001', // 华为IAP商品ID
subject: '测试商品'
}
// 3. 发起支付
paymentKit.pay(info, {
onSuccess: (result) => {
console.log('支付成功:', result.transactionId)
},
onFailed: (code, msg) => {
console.error('支付失败:', code, msg)
},
onCancel: () => {
console.log('用户取消支付')
}
})
## API文档
### PaymentManager
- `registerChannel(channel: PayChannel, adapter: ChannelAdapter)`: 注册支付渠道。
- `pay(info: PaymentInfo, callback: PaymentCallback)`: 发起支付。
### PaymentInfo
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | string | 是 | 商户订单号 |
| amount | number | 是 | 支付金额 |
| channel | PayChannel | 是 | 支付渠道 |
| productId | string | 否 | 商品ID(IAP需要) |
## 贡献指南
欢迎PR!请确保:
1. 代码通过`ohpm run lint`检查。
2. 新增功能包含单元测试。
3. 更新README文档。
## 许可证
Apache License 2.0
四、踩坑记录(官方文档没写的开源细节)
-
API设计的“洁癖”:三方库的API一旦发布,修改成本极高。原则:宁缺毋滥。不要在1.0.0版本暴露过多的内部方法。使用
export严格控制对外API,内部类使用internal或文件夹隔离。 -
资源命名的“隔离”:如果库中使用了图片、字符串等资源,务必添加前缀(如
pk_),防止与主工程资源冲突。例如$r('app.media.pk_pay_icon')。 -
多目标构建(Multi-target Build):如果库需要支持HarmonyOS和OpenHarmony(社区版),需要注意API差异。使用条件编译:
// 条件编译:仅HarmonyOS支持 // @ts-ignore if (canIUse('SystemCapability.ArkUI.ArkUI.Full')) { // HarmonyOS特有逻辑 } -
版本号的“敬畏”:严格遵守语义化版本(SemVer):
主版本.次版本.修订号。-
主版本:不兼容的API修改(如重构了支付流程)。
-
次版本:向后兼容的功能新增(如增加了新的支付渠道)。
-
修订号:向后兼容的问题修正(如修复了某个NullPointerException)。
-
-
OHPM发布的“门槛”:首次发布需要实名认证(个人或企业)。包名(
name)必须全局唯一,且不能以@ohos/开头(那是官方包)。建议使用@组织名/包名的格式。
更多推荐



所有评论(0)