HarmonyOS掌上记账APP开发实践第64篇:会员订阅的全流程实现 — 购买→支付→服务端验证→权益激活
会员订阅的全流程实现 — 购买→支付→服务端验证→权益激活文章简介会员订阅是付费应用的核心商业闭环。在 MoneyTrack 中用户从会员页面选择商品到最终解锁会员权益经历了一个包含客户端支付、服务端收据验证、本地权益激活在内的完整流程。本文详细拆解这一流程的各个阶段涵盖 createPurchase 购买发起、支付回调处理、finishStatus 状态判断、服务端同步以及到期提醒等关键环节。核心知识点1. 完整购买流程时序图以下时序图清晰展示了从用户点击购买到权益激活的完整交互过程开发者服务端AppGallery ConnectIAP SDKMoneyTrack 客户端用户开发者服务端AppGallery ConnectIAP SDKMoneyTrack 客户端用户alt[FINISHED][CANCELED][ERROR]点击「开通会员」createPurchase(productId)发起支付请求弹出支付确认窗口确认支付/指纹验证返回支付收据(receipt)subscribeCallBack(receipt)判断 finishStatusJWSUtil.decodeJwsObj(receipt)POST /subscribe (收据设备ID)验证 JWS 签名服务端收据验签验证通过返回 isMembertrue更新 MemberShipVM 状态显示「会员已激活」提示「已取消支付」提示「支付失败请重试」2. FinishStatus 完整枚举说明FinishStatus枚举定义在membership/constant/Enum.ets中用于标识支付完成的三种状态export enum FinishStatus { /** 支付成功收据有效可发起服务端验证 */ FINISHED 0, /** 用户主动取消支付 */ CANCELED 1, /** 支付过程发生错误网络异常、余额不足等 */ ERROR 2, }应用需根据不同状态执行不同的 UI 反馈逻辑FINISHED触发权益激活流程CANCELED展示友好提示ERROR提供重试入口。3. 支付失败处理支付失败是移动支付场景中的高频问题MoneyTrack 设计了三级处理策略自动重试对于网络超时等可恢复错误自动重试 1 次重试间隔 3 秒。用户引导重试仍失败时弹窗提示用户检查网络或切换支付方式并提供「重新购买」按钮。优雅降级支付取消不视为失败不弹错误提示仅关闭加载状态。会员页面保持原样用户可以稍后重新尝试。async function handlePaymentError(err: Error, productId: string): Promisevoid { if (isRetryableError(err) retryCount 1) { retryCount; await delay(3000); return buyProduct(productId, iap.ProductType.AUTORENEWABLE); } // 不可恢复错误提示用户 AlertDialog.show({ message: 支付失败请检查网络后重试 }); }4. 服务端同步完整代码支付成功后客户端需要将解码后的收据发送到服务端。服务端验证通过后更新用户会员状态并返回最新信息// 客户端服务端同步 async function syncReceiptToServer(params: iap.PurchaseParams): Promisevoid { try { // 1. 解码 JWS 收据 const decodedReceipt JWSUtil.decodeJwsObj(params.receipt); // 2. 组装请求体 const body { receipt: decodedReceipt, productId: params.productId, purchaseToken: params.purchaseToken, deviceId: await getDeviceId(), }; // 3. 发送到服务端 const response await UserApis.subscribeMembership(body); // 4. 更新本地会员状态 if (response.code 200) { memberShipVM.isMember true; memberShipVM.expiresTime response.data.expiresTime; memberShipVM.isRenewMember true; } } catch (err) { hilog.error(0xFF00, SyncReceipt, sync failed: ${JSON.stringify(err)}); // 收据上传失败存入本地队列等待下次重试 await enqueuePendingReceipt(params); } }5. 订阅到期提醒为了防止用户因忘记续费而失去会员权益MoneyTrack 在会员到期前通过本地通知进行提醒function scheduleExpiryReminder(expiresTime: number): void { const now Date.now(); const daysUntilExpiry Math.floor((expiresTime - now) / 86400000); if (daysUntilExpiry 7 daysUntilExpiry 0) { notificationManager.publish({ id: 2001, content: { notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, normal: { title: 会员即将到期, text: 您的会员将在 ${daysUntilExpiry} 天后到期请及时续费, }, }, }); } }项目代码案例MemberShipPage 中 subscribeCallBack 回调链文件路径components/membership/src/main/ets/pages/MemberShipPage.etsEvent subscribeCallBack: (params: MemberParams) Promisevoid () new Promise(() {}); // 在 aboutToAppear 中注册回调 this.vm.setEvent(this.subscribeCallBack, this.queryExpireTime, this.ownedMemberCallBack);UserApis.subscribeMembership()文件路径commons/lib_network/src/main/ets/https/apis/User.etspublic subscribeMembership(body: Recordstring, object): PromiseBaseResponse { return request.post(RequestUrlMap.USER_MEMBERSHIP, body); }最佳实践收据上传失败处理使用本地队列暂存未上传成功的收据应用下次启动时重试确保不丢失任何有效订单。幂等性设计服务端接口需做幂等处理防止同一笔订单多次验证导致重复激活。到期提醒时机分别在到期前 7 天、3 天、1 天发送三级提醒提醒频率不宜过高避免用户反感。回调超时保护subscribeCallBack 内部设置 10 秒超时超时后释放资源防止内存泄漏。推荐参考文档HarmonyOS IAP Kit 购买与订阅开发指南AppGallery Connect 服务端收据验证文档kit.IAPKit createPurchase APIHarmonyOS notificationManager 通知开发指南