写点什么

如何实现应用内支付零掉单?

作者:HarmonyOS SDK
  • 2025-04-21
    贵州
  • 本文字数:3700 字

    阅读完需:约 12 分钟

在电子商务的快速发展中,用户体验成为了衡量平台服务质量的重要标准。当用户完成商品购买后,开发者需要及时发放相关权益。但在实际应用场景中,由于网络波动、进程被中止等异常因素,可能会出现支付状态无法及时确认的情况,从而无法及时发放权益,即出现"掉单"情况。


掉单不仅会严重影响用户支付体验,还可能引发退款、投诉等,容易产生负面舆情,从而增加开发者和运营人员额外的操作成本。


HarmonyOS SDK应用内支付服务(IAP Kit)为了确保权益发放,需要在以下 2 种场景检查用户是否存在已购未发货的商品,以防止掉单情况。


1.应用启动时。


2.购买请求(createPurchase)返回iap.IAPErrorCode.PRODUCT_OWNEDiap.IAPErrorCode.SYSTEM_ERROR时


如果存在已购未发货商品,则发放相关权益,然后向 IAP Kit 确认发货,完成购买。

业务流程

开发步骤

1.应用客户端向 IAP Kit 发起 queryPurchases 请求,获取用户已购买但未确认发货的订单信息。


2.在请求参数 QueryPurchasesParameter 中指定对应的 productType,同时指定 queryType 为 iap.PurchaseQueryType.UNFINISHED。当接口请求成功时,IAP Kit 将返回一个 QueryPurchaseResult 对象,该对象包含承载了订单信息的 PurchaseData 的列表。


3.对 purchaseData.jwsPurchaseOrder 进行解码验签。建议应用客户端将 purchaseData 发送至应用服务器,在应用服务器执行此操作。


4.验证成功可得到对应的 PurchaseOrderPayload 的 JSON 字符串,如果 PurchaseOrderPayload.purchaseOrderRevocationReasonCode 为空,则代表购买成功,需要进行补发货处理。


5.建议先检查此笔订单权益的发放状态,未发放则发放权益,成功后记录 PurchaseOrderPayload 等信息,用于后续检查权益发放状态。


6.发货成功后,应用需调用 finishPurchase 接口确认发货,以此通知 IAP 服务器更新商品的发货状态,完成购买流程。


7.发起请求时,需在请求参数 FinishPurchaseParameter 中携带 PurchaseOrderPayload 中的 productType、purchaseToken、purchaseOrderId。


请求成功后,IAP 服务器会将相应商品标记为已发货状态。对于消耗型商品,IAP 服务器会将相应商品重新设置为可购买状态,用户即可再次购买该商品。对于非消耗型商品,用户购买后永久拥有,无法再次购买该商品。


import { iap } from '@kit.IAPKit';import { common } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';// JWTUtil为自定义类,可参见示例代码import { JWSUtil } from '../common/JWSUtil';
queryPurchases() { const param: iap.QueryPurchasesParameter = { productType: iap.ProductType.CONSUMABLE, queryType: iap.PurchaseQueryType.UNFINISHED }; const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.queryPurchases(context, param).then((res: iap.QueryPurchaseResult) => { console.info('Succeeded in querying purchases.'); const purchaseDataList: string[] = res.purchaseDataList; if (purchaseDataList === undefined || purchaseDataList.length <= 0) { return; } for (let i = 0; i < purchaseDataList.length; i++) { const jwsPurchaseOrder: string = JSON.parse(purchaseDataList[i]).jwsPurchaseOrder; if (!jwsPurchaseOrder) { continue; } const purchaseStr = JWSUtil.decodeJwtObj(jwsPurchaseOrder); // 需自定义PurchaseOrderPayload类,包含的信息请参见PurchaseOrderPayload const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload; // 处理发货 // ... // 发货成功后向IAP Kit发送finishPurchase请求,确认发货,完成购买 this.finishPurchase(purchaseOrderPayload); } }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query purchases. Code is ${err.code}, message is ${err.message}`); });}
finishPurchase(purchaseOrder: PurchaseOrderPayload) { const finishPurchaseParam: iap.FinishPurchaseParameter = { productType: purchaseOrder.productType, purchaseToken: purchaseOrder.purchaseToken, purchaseOrderId: purchaseOrder.purchaseOrderId }; const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.finishPurchase(context, finishPurchaseParam).then(() => { // 请求成功 console.info('Succeeded in finishing purchase.'); }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query purchases. Code is ${err.code}, message is ${err.message}`); });}
复制代码

单机应用权益发放(非消耗型商品)

用户在购买非消耗型商品后,将永久拥有该商品的权益。应用需要在用户购买非消耗型商品后,始终为其发放相关权益。


请在以下场景获取用户已购非消耗型商品的信息,并发放相关权益。


1.应用启动时。


2.购买请求(createPurchase)返回 iap.IAPErrorCode.PRODUCT_OWNED 或 iap.IAPErrorCode.SYSTEM_ERROR 时。

开发步骤

1.应用客户端向 IAP Kit 发起 queryPurchases 请求,获取用户已购非消耗型商品的订单状态信息。


在请求参数 QueryPurchasesParameter 中指定 productType 为 iap.ProductType.NONCONSUMABLE,同时指定 queryType 为 iap.PurchaseQueryType.CURRENT_ENTITLEMENT。当接口请求成功时,IAP Kit 将返回一个 QueryPurchaseResult 对象,该对象包含承载了订单信息的 PurchaseData 的列表。


2.对每个 PurchaseData.jwsPurchaseOrder 进行解码验签。


3.验证成功可得到对应的 PurchaseOrderPayload 的 JSON 字符串,需要发放相关权益。


4.发放权益后,应用需调用 finishPurchase 接口确认发货,以此通知 IAP 服务器更新商品的发货状态,完成购买流程。


发起请求时,需在请求参数 FinishPurchaseParameter 中携带 PurchaseOrderPayload 中的 productType、purchaseToken、purchaseOrderId。请求成功后,IAP 服务器会将相应商品标记为已发货。对于非消耗型商品,用户购买后永久拥有,无法再次购买该商品。


import { iap } from '@kit.IAPKit';import { common } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';// JWTUtil为自定义类,可参见示例代码import { JWSUtil } from '../common/JWSUtil';
queryPurchases() { const param: iap.QueryPurchasesParameter = { productType: iap.ProductType.NONCONSUMABLE, queryType: iap.PurchaseQueryType.CURRENT_ENTITLEMENT }; const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.queryPurchases(context, param).then((res: iap.QueryPurchaseResult) => { console.info('Succeeded in querying purchases.'); const purchaseDataList: string[] = res.purchaseDataList; if (purchaseDataList === undefined || purchaseDataList.length <= 0) { return; } for (let i = 0; i < purchaseDataList.length; i++) { const jwsPurchaseOrder: string = JSON.parse(purchaseDataList[i]).jwsPurchaseOrder; if (!jwsPurchaseOrder) { continue; } // 对jwsPurchaseOrder进行解码验签 const purchaseStr = JWSUtil.decodeJwtObj(jwsPurchaseOrder); // 需自定义PurchaseOrderPayload类,包含的信息请参见PurchaseOrderPayload const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload; // 处理权益发放 // ... // 发放权益后向IAP Kit发送finishPurchase请求,确认发货,完成购买 if (purchaseOrderPayload && purchaseOrderPayload.finishStatus !== '1') { this.finishPurchase(purchaseOrderPayload); } } }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query purchases. Code is ${err.code}, message is ${err.message}`); });}
finishPurchase(purchaseOrder: PurchaseOrderPayload) { const finishPurchaseParam: iap.FinishPurchaseParameter = { productType: purchaseOrder.productType, purchaseToken: purchaseOrder.purchaseToken, purchaseOrderId: purchaseOrder.purchaseOrderId }; const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.finishPurchase(context, finishPurchaseParam).then(() => { // 请求成功 console.info('Succeeded in finishing purchase.'); }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query purchases. Code is ${err.code}, message is ${err.message}`); });}
复制代码


了解更多详情>>


访问应用内支付服务联盟官网


获取权益发放的开发指导文档

用户头像

HarmonyOS SDK

关注

HarmonyOS SDK 2022-06-16 加入

HarmonyOS SDK通过将HarmonyOS系统级能力对外开放,支撑开发者高效打造更纯净、更智能、更精致、更易用的鸿蒙应用,和开发者共同成长。

评论

发布
暂无评论
如何实现应用内支付零掉单?_harmoyos_HarmonyOS SDK_InfoQ写作社区