文档管理中心

服务端关键事件通知

如果接入了IAP Kit订单/订阅功能,建议在AppGallery Connect网站配置通知接收地址,用于接收IAP服务器发送的关键事件通知。IAP关键事件通知版本只支持v3。

说明

建议所有提供消耗型/非消耗型/自动续期订阅/非续期订阅商品的App均配置该通知接收地址,以便接收关键事件通知,为用户提供更好、更及时的服务。另外,通知接收地址必须基于HTTPS并且配置有商业域名机构颁发的证书。

功能介绍

用户购买消耗型/非消耗型/自动续期订阅/非续期订阅商品后,IAP服务器调用此接口向开发者服务器发送关键事件通知。

场景描述

如果在AppGallery Connect申请支付服务时提前配置通知接收地址,并且通知版本设置为v3,用户购买消耗型/非消耗型/自动续期订阅/非续期订阅商品后,IAP服务器会在某些关键事件发生时调用此接口通知已配置的服务器。

消耗型/非消耗型/非续期订阅商品主要涉及的场景如下:

  • 支付成功。

  • 退款成功。

自动续期订阅商品主要涉及的场景如下:

  • 用户第一次订阅成功。

  • 已过期的订阅自动续期成功。

  • 用户主动恢复一个已过期的自动续期订阅商品。

  • 用户调整为相同等级的自动续期订阅商品,如果订阅商品的周期相同,则新订阅立即生效。

  • 用户调整为相同等级的自动续期订阅商品,如果订阅商品的周期不相同,则新订阅在下个续期日生效。

  • 用户调整为更高等级的自动续期订阅商品,则新订阅立即生效,原订阅的剩余金额将折算成新订阅的天数,延长新订阅的有效期。

  • 用户调整为更低等级的自动续期订阅商品,则新订阅在下个续期日生效

  • 用户主动或者App取消一个自动续期订阅商品,已经收费的服务仍然有效,但是后续续期会停止。

  • 一个自动续期订阅商品成功续期。

  • 一个到期的自动续期订阅商品进入账号保留期。

  • 订阅的续期时间已延期。

若开发者服务器返回结果为非成功响应(请求返回的HTTP状态码不为200),IAP服务器将对本次关键事件的通知进行周期性重发。建议在收到通知后立即返回成功响应,避免通知消息堆积。

说明

为保证可靠性,系统具备补偿机制,所以可能出现重发的通知比预期的多。

沙盒测试场景下通知失败不会进行重发。

关键事件通知处理建议

  1. 开发者服务器收到IAP服务器的关键事件通知(下文简称事件通知)时,建议根据通知内容中的购买Token,请求IAP服务器校验购买Token获取当前购买Token关联订单/订阅的最新状态,并根据订单/订阅最新状态决定是否需要提供商品服务。

  2. 事件通知仅作为订单/订阅状态发生变化的一个事件通知,由于网络延迟等导致服务器收到通知事件有延迟,通知中携带的信息可能与IAP服务器的最新的状态不一致,建议不要根据事件通知来决定是否提供商品服务。

  3. 收到DID_NEW_TRANSACTION通知类型后,建议根据如下通知处理流程进行业务逻辑处理,提供商品服务。

关键事件通知处理流程建议如下:

  1. IAP服务器发送订单/订阅关键事件通知。

  2. 应用服务器收到通知请求后,从通知中获取购买Token。

  3. 调用IAP服务器提供的订单状态查询/订阅状态查询接口,查询购买数据及其签名数据。

  4. IAP服务器返回购买数据及其签名数据。

  5. 校验订单/订阅状态提供商品服务。消耗型/非消耗型/非续期订阅商品请根据订单状态查询接口获取消耗型/非消耗型/非续期订阅的订单最新状态,再根据订单状态调用订单确认发货接口执行发货操作。自动续期订阅商品请根据订阅状态查询接口响应经JWS解码之后SubGroupStatusPayload中的status字段决定是否发货。若status为1,则调用订阅确认发货接口执行发货操作。

  6. 应用服务器返回通知响应给IAP服务器。

接口约束

不允许开发者服务器设置IP允许清单用于限制华为侧的出口IP地址。IP允许清单本身并不能提高安全性且会给业务发展带来约束,在消息层面已有更安全的JWS签名机制条件下,没有存在价值。不遵守该约定而导致的后果将由开发者自行承担。

必须在开发前在AppGallery Connect中配置开发者服务器的回调地址,地址必须支持HTTPS协议且具有合法商用证书,出于安全考虑,cipher需要支持ECDHE-RSA-AES128-GCM-SHA256、ECDHE-ECDSA-AES128-GCM-SHA256、ECDHE-RSA-AES256-GCM-SHA384或ECDHE-ECDSA-AES256-GCM-SHA384中至少一种,否则无法正常接收通知消息。

华为IAP关键事件通知仅通过IPv4链路发送,请确保回调地址支持IPv4访问。若回调地址仅支持IPv6,将无法正常接收通知消息。

接口原型

  • 承载协议: HTTPS POST

  • 接口方向: IAP服务器 -> 开发者服务器

  • 接口URL: URL由开发者在申请支付服务时配置

  • 数据格式:

    请求消息:Content-Type: application/json; charset=UTF-8

    响应消息:Content-Type: application/json; charset=UTF-8

请求参数

Request Body

展开
参数 是否必选 参数类型 描述
jwsNotification 是 String

通知内容信息,对通知内容NotificationPayload签名后的字符串。具体请参见表NotificationPayload。

需要参见对返回结果验签使用JWS签名方式对NotificationPayload消息体进行验签。

NotificationPayload

展开
参数 是否必选 参数类型 描述
notificationType 是 String 通知主类型,具体请参见表NotificationType说明。
notificationSubtype 否 String 通知子类型,具体请参见表NotificationSubtype说明。后续子类型会增加,开发者需要设计相应的处理机制。
notificationRequestId 是 String 通知唯一请求ID。
notificationMetaData 是 Object 通知元数据,具体请参见表NotificationMetaData说明。
notificationVersion 是 String 通知版本:v3。
signedTime 是 Long 通知签名时间,UTC时间戳,以ms为单位。
注意

服务端关键事件通知可能会在后续版本中新增参数和取值。开发者在处理通知时应保留兼容性,避免因收到非预期的类型而导致程序异常或中断。

NotificationType

展开
取值 取值说明
DID_NEW_TRANSACTION 订单已购买/订阅已购买/订阅续订成功。
DID_CHANGE_RENEWAL_STATUS 订阅状态发生改变。
REVOKE

消耗型/非消耗型/非续期订阅商品:订单退款。

自动续期订阅商品:撤销订阅。

RENEWAL_TIME_MODIFIED 订阅过期时间调整。
EXPIRE 订阅已过期。
TEST

测试服务端通知,仅开发者调用测试服务端通知接口才会发送此类型通知。

此场景下无notificationSubtype。

NotificationSubtype

展开
取值 取值说明
INITIAL_BUY

消耗型/非消耗型/非续期订阅商品购买成功。

自动续期订阅商品的第一次购买成功。

使用主类型:DID_NEW_TRANSACTION

DID_RENEW

续期成功。

使用主类型:DID_NEW_TRANSACTION

RESTORE

用户主动恢复了一个订阅型商品,续期恢复正常。

使用主类型:DID_NEW_TRANSACTION

AUTO_RENEW_ENABLED

自动续期功能开启。

使用主类型:DID_CHANGE_RENEWAL_STATUS

AUTO_RENEW_DISABLED

自动续期功能关闭。

使用主类型:DID_CHANGE_RENEWAL_STATUS

DOWNGRADE

用户调整自动续期订阅商品降级或跨级且在下个续订生效。

使用主类型:DID_CHANGE_RENEWAL_STATUS或DID_NEW_TRANSACTION

UPGRADE

用户调整自动续期订阅商品升级或跨级且立即生效。

使用主类型:DID_NEW_TRANSACTION

REFUND_TRANSACTION

消耗型/非消耗型/非续期订阅商品:订单退款成功。

自动续期订阅商品:订单退款成功且撤销对应订阅成功,订阅权益会立即取消。

使用主类型:REVOKE

BILLING_RETRY

一个到期的自动续期订阅商品进入账号保留期。

使用主类型:EXPIRE

PRICE_INCREASE

用户同意了涨价。

使用主类型:DID_CHANGE_RENEWAL_STATUS

BILLING_RECOVERY

订阅重试扣费成功。

使用主类型:DID_NEW_TRANSACTION

VOLUNTARY

主动退订后订阅过期。

使用主类型:EXPIRE

PRODUCT_NOT_FOR_SALE

商品不存在。

使用主类型:EXPIRE

APPLICATION_DELETE_SUBSCRIPTION_HOSTING

撤销订阅成功,订阅权益会立即取消。

使用主类型:REVOKE

RENEWAL_EXTENDED

延迟订阅续订日期成功,订阅的下一个续订日期将推迟。

使用主类型:RENEWAL_TIME_MODIFIED

NotificationMetaData

展开
参数 是否必选 参数类型 描述
environment 是 String

环境类型。

- NORMAL:正式环境

- SANDBOX:沙盒环境

applicationId 是 String 应用Id。
packageName 是 String 应用包名。
type 是 Integer

商品类型。

0:消耗型商品

1:非消耗型商品

2:自动续期订阅商品

3:非续期订阅商品

currentProductId 否 String 最近一个有效订阅的商品ID。仅自动续期订阅商品场景下存在值。
subGroupId 否 String 订阅组ID。仅自动续期订阅商品场景下存在值。
subGroupGenerationId 否 String

订阅组的代ID。

- 用户切换订阅商品时,此ID不会改变。

- 订阅失效且超出保留期后,用户重新购买商品时,此ID会改变。

subscriptionId 否 String

商品的订阅ID。以下场景,此ID会发生改变:

- 用户切换订阅商品时。

- 订阅失效且超出保留期后,用户重新购买商品时。

purchaseToken 是 String 商品的购买Token,发起购买和查询订阅信息均会返回。最大长度256。
purchaseOrderId 否 String

具体一笔订单中对应的购买订单号。当NotificationType为DID_CHANGE_RENEWAL_STATUS且NotificationSubtype为DOWNGRADE时不返回purchaseOrderId。

最大长度256。

请求示例

POST /notify/address
Content-Type: application/json;charset=UTF-8
Accept: application/json
{
  "jwsNotification": "***"
}

NotificationPayload样例(消耗型/非消耗型)

{
  "notificationType": "DID_NEW_TRANSACTION",
  "notificationSubtype": "INITIAL_BUY",
  "notificationRequestId": "7f67e39aa72d1a55f36293047f9769c0aa47a467ffb110eaeeeb888def9f9713",
  "notificationMetaData": {
    "environment": "NORMAL",
    "applicationId": "***",
    "packageName": "***",
    "type": 0,
    "purchaseToken": "***.*.***",
    "purchaseOrderId": "***.***"
  },
  "notificationVersion": "v3",
  "signedTime": 1702607152698
}

NotificationPayload样例(非续期订阅商品)

{
  "notificationType": "DID_NEW_TRANSACTION",
  "notificationSubtype": "INITIAL_BUY",
  "notificationRequestId": "7f67e39aa72d1a55f36293047f9769c0aa47a467ffb110eaeeeb888def9f9713",
  "notificationMetaData": {
    "environment": "NORMAL",
    "applicationId": "***",
    "packageName": "***",
    "type": 3,
    "purchaseToken": "***.*.***",
    "purchaseOrderId": "***.***"
  },
  "notificationVersion": "v3",
  "signedTime": 1702607152698
}

NotificationPayload样例(自动续期订阅商品)

{
  "notificationType": "DID_NEW_TRANSACTION",
  "notificationSubtype": "INITIAL_BUY",
  "notificationRequestId": "6d5882d55c8e5136f2348b8e13b4aaad6d0938898b7e5efdc13f7c7130286f8c",
  "notificationMetaData": {
    "environment": "NORMAL",
    "applicationId": "***",
    "packageName": "***",
    "type": 2,
    "currentProductId": "1701072721154732",
    "subGroupId": "1701072721154732",
    "subGroupGenerationId": "f7967e2439769fbb3c155a50d2cdd6a8cc8f7750cac7bf78b6f5d65c97c34deb",
    "subscriptionId": "1701072722814.ADE66B39.4732",
    "purchaseToken": "***.*.***",
    "purchaseOrderId": "***.*.***"
  },
  "notificationVersion": "v3",
  "signedTime": 1701072726860
}

响应参数

通过HTTP状态码来标识IAP服务器通知开发者服务器是否发送成功:

  • 如果通知发送成功,则发送HTTP 200,不需要返回响应体。

  • 如果通知发送失败,则通过发送HTTP 40X或者HTTP 50X,告知IAP服务器进行重试,IAP服务器会在一段时间内重试多次。

响应示例

HTTP/1.2 200 OK