HarmonyOS掌上记账APP开发实践第63篇:鸿蒙 IAP 商品配置与管理 — 从订阅商品到权益验证
鸿蒙 IAP 商品配置与管理 — 从订阅商品到权益验证

文章简介
HarmonyOS 应用内支付(IAP,In-App Purchases)是鸿蒙生态中实现应用商业化的核心能力。MoneyTrack 作为一款记账应用,提供了会员订阅功能,允许用户购买自动续费订阅商品以解锁高级特性。本文从 IAP 商品配置的角度出发,详细介绍商品从 AGC 配置到客户端查询、本地缓存的完整链路,帮助开发者理解鸿蒙 IAP 商品管理的全流程。
核心知识点
1. IAP 商品配置完整流程
IAP 商品配置涉及三个关键环节:AppGallery Connect 后台配置、客户端 SDK 查询、本地缓存管理。以下流程图展示了完整链路:
2. iap.Product 的完整字段说明
鸿蒙 IAP 的 iap.Product 接口定义了商品的完整信息,开发者可通过这些字段向用户展示统一的商品信息界面:
| 字段 | 类型 | 说明 |
|---|---|---|
productId |
string |
商品唯一标识,需与 AGC 后台一致 |
price |
string |
格式化后的价格字符串,如 “¥6.00” |
microPrice |
number |
价格微单位,单位为分(1 元 = 100) |
description |
string |
商品描述文本,支持多语言 |
title |
string |
商品名称标题 |
type |
ProductType |
商品类型:CONSUMABLE / NONCONSUMABLE / AUTORENEWABLE |
status |
ProductStatus |
商品状态:ACTIVE / INACTIVE |
subPeriod |
string |
订阅周期描述,仅 AUTORENEWABLE 类型有效 |
在 MoneyTrack 中,ProductInfo 类封装了 IAP 商品与本地权益模型的映射关系,确保商品信息在 UI 层以统一格式展示:
export class ProductInfo {
type: iap.ProductType = iap?.ProductType.AUTORENEWABLE;
productId: string = '';
privileges: MemberShipPrivilege[] = [];
privacyName?: string = '';
privacyContent?: string = '';
}
3. 商品价格格式化
不同地区的用户看到的货币符号不同,鸿蒙 IAP SDK 已自动处理本地化格式。iap.Product.price 返回的字符串已包含正确的货币符号和格式,开发者可直接用于 UI 展示。如果需要在本地自行格式化,可参照以下逻辑:
function formatPrice(microPrice: number, currency: string): string {
const price = (microPrice / 100).toFixed(2);
// 根据 currency 添加对应货币符号
const symbolMap: Record<string, string> = {
'CNY': '¥', 'USD': '$', 'JPY': '¥', 'EUR': '€',
};
return `${symbolMap[currency] || ''}${price}`;
}
4. 商品缓存策略
为了避免频繁调用 IAP SDK 查询商品列表(网络请求耗时且可能失败),MoneyTrack 采用「先缓存、兜底读」的策略。首次查询成功后,将商品信息序列化后写入本地首选项(Preferences),后续启动时先读缓存展示,再异步刷新:
// 商品缓存管理
async function cacheProducts(products: iap.Product[]): Promise<void> {
const prefs = await preferences.getPreferences(getContext(), 'iap_cache');
const json = JSON.stringify(products.map(p => ({
productId: p.productId,
price: p.price,
title: p.title,
description: p.description,
})));
await prefs.put('products', json);
await prefs.flush();
}
async function getCachedProducts(): Promise<iap.Product[] | null> {
const prefs = await preferences.getPreferences(getContext(), 'iap_cache');
const json = await prefs.get('products', '');
return json ? JSON.parse(json) : null;
}
项目代码案例
MemberShipVM 的完整商品管理代码
MemberShipVM 是会员模块的核心 ViewModel,管理商品列表的查询、缓存和购买入口。其 productInfoList: iap.Product[] 属性存储 IAP SDK 查询返回的商品信息,视图层据此渲染会员卡片:
@ObservedV2
export class MemberShipVM {
@Trace productInfoList: iap.Product[] = [];
@Trace isMember: boolean = false;
@Trace expiresTime: number = 0;
// 查询 IAP 商品并缓存
async queryProducts(): Promise<void> {
try {
const products = await iap.getProducts(['membership_monthly', 'membership_yearly']);
this.productInfoList = products;
await cacheProducts(products);
} catch (err) {
hilog.error(0xFF00, 'MemberShipVM', `queryProducts err: ${JSON.stringify(err)}`);
// 兜底:读取本地缓存
const cached = await getCachedProducts();
if (cached) this.productInfoList = cached;
}
}
// 发起购买
buyProduct(productId: string, type: iap.ProductType): void {
// 购买前可加入安全环境检测
iap.createPurchase({
productId,
type,
subscribeCallBack: (params: iap.PurchaseParams) => {
if (params.finishStatus === iap.FinishStatus.FINISHED) {
// 支付成功,进行服务端验证
this.handlePurchaseSuccess(params);
}
},
});
}
private async handlePurchaseSuccess(params: iap.PurchaseParams): Promise<void> {
// 将收据解码后发送至服务端验证
const payload = JWSUtil.decodeJwsObj(params.receipt);
await UserApis.subscribeMembership({ receipt: payload });
}
}
最佳实践
- 商品 ID 命名规范:建议采用
功能_类型_周期格式,如membership_autorenewable_monthly,便于后期扩展多商品。 - 缓存兜底策略:网络异常时从本地缓存读取商品信息,保证页面不白屏。同时设置缓存过期时间(如 24 小时)。
- 价格展示一致性:直接使用 IAP SDK 返回的
price字段,不做额外格式化,避免汇率和本地化问题。 - 商品状态校验:每次展示商品前检查
status字段,避免显示已下架商品。
推荐参考文档
- HarmonyOS IAP Kit 开发指南
- AppGallery Connect IAP 商品配置文档
- @kit.IAPKit API 参考
- 鸿蒙首选项(Preferences)数据存储指南
更多推荐



所有评论(0)