045-IAP Kit应用内支付
045 — IAP Kit 应用内支付会员订阅全流程实现简介付费会员是记账应用实现商业闭环的重要途径。MoneyTrack 通过 IAP Kit 实现了完整的应用内购买功能支持自动续费订阅AUTORENEWABLE和非续费订阅NONRENEWABLE两种商品类型。从商品信息配置、购买流程发起、收银台拉起、收据验签到会员状态管理形成了一条完整的支付链路。MemberSubscriptionPage 作为订阅入口页面通过 ProductInfo 配置商品列表结合 JWSUtil 对支付平台返回的 JWS 收据进行解码验证。完整购买流程IAP Kit 的完整购买流程分为五个关键步骤自有服务端应用市场IAP KitMoneyTrack用户自有服务端应用市场IAP KitMoneyTrack用户进入会员订阅页1. queryProductInfo() 查询商品返回 ProductInfo 列表展示商品月度/年度选择商品点击购买2. createPurchase() 创建订单返回 PurchaseResult3. purchase() 拉起收银台调用系统支付能力支付完成返回收据返回 JWS 收据4. JWSUtil 解码验证5. 发送收据到服务端验签验证签名 解析 payload返回激活结果提示会员已激活商品配置ProductInfo 完整定义商品信息通过iap.ProductInfo对象定义在查询商品时由系统返回import{iap}fromkit.IAPKit;// 查询商品信息asyncfunctionqueryProducts():Promiseiap.ProductInfo[]{constproductIds[moneytrack_monthly,moneytrack_yearly];constresultawaitiap.queryProductInfo({productIds:productIds,type:iap.ProductType.AUTORENEWABLE});returnresult.productInfoList;}// ProductInfo 包含以下完整字段interfaceProductInfo{productId:string;// 商品唯一 ID在 AGC 控制台配置type:iap.ProductType;// 商品类型title:string;// 商品名称本地化description:string;// 商品描述price:string;// 显示价格如 ¥12.00microPrice:number;// 微单位价格如 1200单位分currency:string;// 货币代码如 CNYstatus:number;// 商品状态0正常1下架subscriptionPeriod:string;// 订阅周期如 P1M 表示每月freeTrialPeriod:string;// 免费试用期如 P7D 表示 7 天}订阅状态管理会员订阅不是一次性操作需要持续管理会员状态、检测过期、处理续费import{iap}fromkit.IAPKit;exportclassMembershipManager{// 检测当前会员状态staticasynccheckMembershipStatus():PromiseMembershipStatus{try{constreceiptsawaitiap.getPurchaseRecords({type:iap.ProductType.AUTORENEWABLE});if(receipts.length0){return{isActive:false,level:none,expireDate:null};}// 取最新的收据constlatestReceiptreceipts[0];constdecodedJWSUtil.decode(latestReceipt.receipt);constpayloaddecoded.payload;constexpireDatenewDate(payload.expirationDate);constnownewDate();return{isActive:expireDatenow,level:this.getProductLevel(payload.productId),expireDate:expireDate,autoRenew:payload.autoRenewStatus1,daysRemaining:Math.ceil((expireDate.getTime()-now.getTime())/86400000)};}catch(error){console.error(Check membership failed:,error);return{isActive:false,level:none,expireDate:null};}}// 处理续费提醒staticasynchandleRenewReminder(){conststatusawaitthis.checkMembershipStatus();if(status.isActivestatus.daysRemaining7status.daysRemaining0){// 会员即将过期推送续费提醒this.showRenewPrompt(status.daysRemaining);}elseif(!status.isActivestatus.level!none){// 会员已过期引导重新订阅this.showExpiredPrompt();}}// 恢复购买跨设备同步staticasyncrestorePurchases(){constreceiptsawaitiap.getPurchaseRecords({type:iap.ProductType.AUTORENEWABLE});// 将收据列表发送到服务端验证并激活for(constreceiptofreceipts){awaitthis.verifyOnServer(receipt.receipt);}}}支付安全JWS 解码验签与服务端验证支付安全是应用内购买的核心。IAP Kit 返回的收据采用 JWSJSON Web Signature格式需要在服务端完成签名验证后才能激活会员权益// 客户端解析 JWS 收据exportclassJWSUtil{// JWS 格式为header.payload.signaturestaticdecode(jwsString:string):DecodedJWS{constpartsjwsString.split(.);if(parts.length!3){thrownewError(Invalid JWS format);}return{header:JSON.parse(this.base64UrlDecode(parts[0])),payload:JSON.parse(this.base64UrlDecode(parts[1])),signature:parts[2],// 客户端仅解析验证由服务端完成verify():boolean{returnfalse;// 客户端不做签名验证}};}privatestaticbase64UrlDecode(str:string):string{// Base64 URL 解码实现constbase64str.replace(/-/g,).replace(/_/g,/);returndecodeURIComponent(Array.from(atob(base64),c%(00c.charCodeAt(0).toString(16)).slice(-2)).join());}}// 服务端验证逻辑Node.js 示例/* async function verifyReceipt(receipt: string) { // 1. 获取 IAP Kit 公钥从华为 IAP 服务端获取 const publicKey await getIAPPublicKey(); // 2. 使用 JWS 库验证签名 const jws jose.generalVerify(receipt, publicKey); // 3. 验证 payload 中的关键字段 const payload jws.payload; if (payload.productId ! expectedProductId) throw new Error(Product mismatch); if (payload.purchaseTime 3600000 Date.now()) throw new Error(Receipt expired); // 4. 检查 purchaseToken 是否已被使用防止重放攻击 if (await isTokenUsed(payload.purchaseToken)) throw new Error(Token already used); // 5. 标记 token 已使用并激活会员 await markTokenUsed(payload.purchaseToken); await activateMembership(payload); } */安全要点说明客户端可以解析 JWS 查看收据内容但绝不能仅凭客户端解析结果就激活会员。签名验证必须在自有服务端完成以防止伪造收据。服务端还需校验purchaseToken的唯一性防止重放攻击。最佳实践服务端强制验签所有会员激活逻辑必须在服务端完成客户端仅做展示和收据透传。支持恢复购买提供恢复购买按钮通过getPurchaseRecords获取历史收据确保用户在不同设备间已购权益同步。处理收据重复回调purchase操作可能因网络原因收到重复回调需通过purchaseToken去重。订阅状态本地缓存定期检测会员状态并缓存到本地避免每次打开应用都调用网络接口。提前 7 天续费提醒在会员到期前 7 天开始提示续费降低流失率。测试商品与正式商品隔离开发阶段使用 AGC 控制台配置的测试商品价格为零上架前切换为正式商品。项目代码案例文件路径feature_membership/ProductInfo.etsimport{iap}fromkit.IAPKit;exportconstPRODUCTS:iap.ProductInfo[][{productId:moneytrack_monthly,type:iap.ProductType.AUTORENEWABLE,title:月度会员,description:解锁所有高级功能按月订阅,price:¥12.00,microPrice:1200,currency:CNY,status:0,subscriptionPeriod:P1M,freeTrialPeriod:P7D},{productId:moneytrack_yearly,type:iap.ProductType.AUTORENEWABLE,title:年度会员,description:解锁所有高级功能按年订阅享优惠,price:¥98.00,microPrice:9800,currency:CNY,status:0,subscriptionPeriod:P1Y,freeTrialPeriod:P7D}];文件路径feature_membership/MemberSubscriptionPage.etsimport{iap}fromkit.IAPKit;asyncfunctionstartPurchase(productId:string){try{// 1. 创建订单constpurchaseResultawaitiap.createPurchase({productId});// 2. 拉起收银台awaitiap.purchase(purchaseResult);// 3. 获取 JWS 收据constjwsReceiptpurchaseResult.inAppPurchaseResponse.receipt;// 4. 客户端解码查看constdecodedJWSUtil.decode(jwsReceipt);console.info(Purchase payload:,decoded.payload);// 5. 发送到服务端验证constverifiedawaitverifyOnServer(jwsReceipt);if(verified){awaitactivateLocalMembership(decoded.payload);showSuccessPrompt();}}catch(error){console.error(Purchase failed:,error);showErrorPrompt(error.message);}}推荐参考文档IAP Kit 应用内支付指南IAP Kit 服务端验签指南JWS 解码与验签规范

相关新闻

基于TI TDAx DSP的ADAS环视系统:从鱼眼畸变校正到3D视图的工程实现

基于TI TDAx DSP的ADAS环视系统:从鱼眼畸变校正到3D视图的工程实现

1. 项目概述:从鱼眼畸变到上帝视角的工程实现在汽车智能化浪潮中,泊车一直是让新手司机头疼、老司机也难免失手的场景。传统的倒车影像只能看到车尾一隅,车身两侧和车头的盲区依然存在。高级驾驶辅助系统(ADAS)中的环视…

2026/10/17 15:42:13 阅读更多 →
AIGC应用Prompt Injection防护:多层防御框架与实战方案

AIGC应用Prompt Injection防护:多层防御框架与实战方案

你的 AIGC 应用即将上线,但有没有想过:用户输入的一段看似普通的文本,可能让整个系统"叛变"?这不是危言耸听。最近一项研究显示,未经防护的 RAG 系统在面对 Prompt Injection 攻击时,平均攻击成功…

2026/10/17 15:42:12 阅读更多 →
XMove Studio体感管理系统架构与插件化开发实践

XMove Studio体感管理系统架构与插件化开发实践

1. XMove Studio管理系统概述 XMOVE体感方案作为一套完整的动作捕捉与交互系统,其PC端管理中枢XMove Studio基于XFrmWork框架构建,实现了对分布式体感节点的集中管控。这套系统最显著的特点是采用了"通信-节点-应用"三级架构设计,将…

2026/10/15 19:10:07 阅读更多 →

最新新闻

Qt界面美化实战:基于JSON主题配置的通用UI架构设计

Qt界面美化实战:基于JSON主题配置的通用UI架构设计

简介:本资源是一套基于Qt开发的高颜值、跨平台通用界面示例工程,面向Qt初学者与中阶开发者,聚焦GUI设计实战,解决传统界面风格单一、适配性差、代码复用率低等常见痛点。压缩包共41个文件(294KB)&#xff0…

2026/10/17 15:42:09 阅读更多 →
OpenStack网络实战:Neutron模型、VXLAN与排错全解析

OpenStack网络实战:Neutron模型、VXLAN与排错全解析

简介:《OpenStack网络实战精讲》是一份面向云计算工程师与网络架构师的PDF电子书,系统讲解Neutron在OpenStack云平台中的核心作用。内容覆盖虚拟网络架构、SDN原理、ML2插件、Open vSwitch、安全组与分布式路由,并延伸至VLAN感知虚拟机、BGP动…

2026/10/17 15:42:09 阅读更多 →
viewer.min.js实现高效图片预览:配置、API与多场景实战指南

viewer.min.js实现高效图片预览:配置、API与多场景实战指南

简介:viewer.min.js 是一款专为前端开发者打造的轻量级图像查看器 JavaScript 库,核心解决网页中高分辨率图片的交互预览需求,支持缩放、旋转、平移、全屏查看等常用操作,并可在 Vue、React 或原生 JS 项目中无缝集成。这份 zip 压…

2026/10/17 15:42:09 阅读更多 →
智能音频播放器组件网页模板:架构设计与状态机实现

智能音频播放器组件网页模板:架构设计与状态机实现

简介:这是一套面向前端开发者与网页设计学习者的智能音频播放器组件网页模板,适用于音乐分享、在线教育、播客等需要嵌入音频播放功能的场景。资源围绕HTML5 audio标签、JavaScript控制与Audio API接口展开,涵盖播放暂停、音量调节、进度控制…

2026/10/17 15:42:09 阅读更多 →
红黑树删除全解析:双黑节点、修复分支与工程实现

红黑树删除全解析:双黑节点、修复分支与工程实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 15:42:09 阅读更多 →
Codex 作为 AI 编程工具,普通人可用 TaoToken 处理哪些日常任务?

Codex 作为 AI 编程工具,普通人可用 TaoToken 处理哪些日常任务?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 15:41:08 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →