场景介绍
在接入消耗型/非消耗型商品购买能力前,需在华为AppGallery Connect网站配置商品,录入商品ID和商品价格等信息。用户在开发者应用内发起购买时,应用需要调用createPurchase接口来拉起IAP Kit收银台,收银台会展示商品名称、商品价格等信息,用户可在收银台完成商品购买。
业务流程
说明
当前流程对单机应用同样适用,只需要将流程图中服务端的处理放在客户端即可。
- 用户发起购买后,应用客户端向IAP Kit发起createPurchase购买请求,携带商品ID、商品类型等信息。IAP Kit创建订单并展示收银台。
- 用户完成支付后,IAP Kit返回包含订单信息的PurchaseData数据。
- 应用客户端向应用服务器上报PurchaseData数据。
- 应用服务器可参见对返回结果验签对PurchaseData.jwsPurchaseOrder进行解码验签,成功后可得到PurchaseOrderPayload的JSON字符串。
- (建议)若对安全性要求较高,可从PurchaseOrderPayload中解析出purchaseToken和purchaseOrderId信息,并通过服务端订单状态查询接口向IAP服务器查询最新的订单信息,进一步确认订单的准确性。
- (建议)IAP服务器返回订单信息jwsPurchaseOrder。
- (建议)应用服务器可参见对返回结果验签对jwsPurchaseOrder进行解码验签,成功后可得到PurchaseOrderPayload的JSON字符串。
- 检查当前PurchaseOrderPayload是否已发货。
- 若未发货,应用服务器需发放相关权益,并记录对应的订单信息(PurchaseOrderPayload)。
- 应用客户端向应用服务器查询订单的发货状态。
- 应用服务器返回对应的发货状态以及订单信息(PurchaseOrderPayload)。
- 发货成功后应用客户端向IAP Kit发送finishPurchase请求,以此通知IAP服务器更新商品的发货状态,完成购买流程。
可使用服务端订单确认发货接口代替IAP Kit客户端finishPurchase接口。
注意
确保在发货成功之后再执行finishPurchase操作,否则可能导致IAP服务器已经确认发货但是应用没有发货的问题。
-
IAP Kit向应用返回确认发货结果。应用成功执行finishPurchase之后,IAP服务器会将相应商品标记为已发货状态。对于消耗型商品,IAP服务器会将相应商品重新设置为可购买状态,用户即可再次购买该商品。
开发步骤
- 判断当前登录的华为账号所在的服务地是否支持应用内支付。
在使用应用内支付之前,应用需要向IAP Kit发送queryEnvironmentStatus请求,以此判断用户当前登录的华为账号所在的服务地是否在IAP Kit支持结算的国家/地区中。
说明
当前IAP Kit支持结算的国家/地区仅包括中国大陆。
import { iap } from '@kit.IAPKit'; import { common } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; queryEnvironmentStatus() { const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.queryEnvironmentStatus(context).then(() => { // 请求成功 console.info('Succeeded in querying environment status.'); }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query environment status. Code is ${err.code}, message is ${err.message}`); }); }
查询商品信息。
通过queryProducts来获取在AppGallery Connect上配置的商品信息。发起请求时,需在请求参数QueryProductsParameter中携带相关的商品ID,并根据实际配置指定其productType。
当接口请求成功时,IAP Kit将返回商品信息Product的列表。 应用可以使用Product包含的商品价格、名称和描述等信息,向用户展示可供购买的商品列表。
说明
queryProducts每次只能查询一种类型的商品。
import { iap } from '@kit.IAPKit'; import { BusinessError } from '@kit.BasicServicesKit'; queryProducts() { const queryProductParam: iap.QueryProductsParameter = { // iap.ProductType.CONSUMABLE:消耗型商品; // iap.ProductType.NONCONSUMABLE:非消耗型商品; productType: iap.ProductType.CONSUMABLE, // 查询的商品必须是开发者在AppGallery Connect网站配置的商品 productIds: ['ohos_consume_001'] }; const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.queryProducts(context, queryProductParam).then((result) => { // 请求成功 console.info('Succeeded in querying products.'); // 展示商品信息 // ... }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to query products. Code is ${err.code}, message is ${err.message}`); }); }
发起购买。
用户发起购买时,应用可通过向IAP Kit发送createPurchase请求来拉起IAP Kit收银台。发起请求时,需在请求参数PurchaseParameter中携带此前已在华为AppGallery Connect网站上配置并生效的商品ID,并根据实际配置指定其productType。
- 当用户购买成功时,应用将接收到一个CreatePurchaseResult对象,其purchaseData字段包括了此次购买的结果信息。可参见对返回结果验签对purchaseData.jwsPurchaseOrder进行解码验签,验证成功可得到PurchaseOrderPayload的JSON字符串。
- 当用户购买失败时,需要针对code为iap.IAPErrorCode.PRODUCT_OWNED和iap.IAPErrorCode.SYSTEM_ERROR的场景,检查是否需要补发货,确保权益发放,具体请参见权益发放。
import { iap } from '@kit.IAPKit'; import { BusinessError } from '@kit.BasicServicesKit'; // JWTUtil为自定义类,可参见Sample Code工程。 import { JWTUtil } from '../commom/JWTUtil'; createPurchase() { const createPurchaseParam: iap.PurchaseParameter = { // 购买的商品必须是开发者在AppGallery Connect网站配置的商品 productId: 'ohos_consume_001', // iap.ProductType.CONSUMABLE:消耗型商品; // iap.ProductType.NONCONSUMABLE:非消耗型商品; productType: iap.ProductType.CONSUMABLE } const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; iap.createPurchase(context, createPurchaseParam).then(async (result) => { console.info('Succeeded in creating purchase.'); const jwsPurchaseOrder: string = JSON.parse(result.purchaseData).jwsPurchaseOrder; const purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder); // 需自定义PurchaseOrderPayload类,包含的信息请参见PurchaseOrderPayload const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload; // 处理发货 // ... // 发货成功后向IAP Kit发送finishPurchase请求,确认发货,完成购买 // finishPurchase请求的参数来源于purchaseOrderPayload // ... }).catch((err: BusinessError) => { // 请求失败 console.error(`Failed to create purchase. Code is ${err.code}, message is ${err.message}`); if (err.code === iap.IAPErrorCode.PRODUCT_OWNED || err.code === iap.IAPErrorCode.SYSTEM_ERROR) { // 参见权益发放检查是否需要补发货,确保权益发放 // ... } }) }
说明
消耗型商品请务必按照确保权益发放处理发货,避免掉单问题发生。
-
完成购买
注意
请务必确保发货成功后再调用本步骤。
对PurchaseData.jwsPurchaseOrder解码验签成功后,如果PurchaseOrderPayload.purchaseOrderRevocationReasonCode为空,则代表购买成功,即可发放相关权益。如果开发者同时接入了服务端关键事件通知,为了避免重复发货,建议先检查此笔订单是否已发货,未发货再发放相关权益。发货成功后记录PurchaseOrderPayload等信息,用于后续检查是否已发货。
发货成功后,应用需要发送finishPurchase请求确认发货,以此通知IAP服务器更新商品的发货状态,完成购买流程。发送finishPurchase请求时,需在请求参数FinishPurchaseParameter中携带PurchaseOrderPayload中的productType、purchaseToken、purchaseOrderId。请求成功后,IAP服务器会将相应商品标记为已发货。
对于消耗型商品,应用成功执行finishPurchase之后,IAP服务器会将相应商品重新设置为可购买状态,用户即可再次购买该商品。
import { iap } from '@kit.IAPKit'; import { BusinessError } from '@kit.BasicServicesKit'; /** * 确认发货,完成购买 * * @param purchaseOrder 购买数据,来源于购买请求 */ 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 finish purchase. Code is ${err.code}, message is ${err.message}`); }); }