Table of Contents
10.9 Apple IAP 服务端通知【未执行,需三方/真实联调】
POST /tieup/api/v1/webhooks/payments/apple-iap
Content-Type: application/json
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
signedPayload |
string | 是 | Apple App Store Server Notification JWS 原文 |
请求体示例:
{
"signedPayload": "apple_app_store_server_notification_jws"
}
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
ack |
boolean | 是否确认收到并处理通知 |
result |
object | 通知业务处理结果,不同通知类型会附带续订、关闭、失败记录或退款字段 |
result.duplicate |
boolean | 是否为重复通知或重复交易 |
result.delivered |
boolean | DID_RENEW/SUBSCRIBED 是否已发放订阅权益 |
result.subscription_no |
string | 续订生成或复用的订阅编号 |
result.expires_at |
string | 本次续订权益到期时间 |
result.im_sync |
object | 续订权益生效后的 IM 成员同步结果 |
result.im_sync.artist_id |
integer | 同步目标艺人 ID |
result.im_sync.synced_count |
integer | 成功同步成员数 |
result.im_sync.failed_count |
integer | 同步失败成员数 |
result.subscription_message |
object | 订阅成功消息登记和异步发送结果 |
result.subscription_message.queued |
boolean | 是否已投递异步发送任务 |
result.subscription_message.message_no |
string/null | 已登记的消息编号 |
result.subscription_message.registration_error |
string/null | 消息登记失败原因 |
result.income |
object | 订阅收入入账结果 |
result.income.duplicate |
boolean | 收入是否为幂等复用 |
result.income.income_no |
string | 收入记录编号 |
result.income.settlement_base_amount |
string | 艺人分成结算基数,单位元,固定两位小数 |
result.income.artist_income_amount |
string | 艺人收入金额,单位元,固定两位小数 |
result.closed_count |
integer | EXPIRED/REFUND/REVOKE 实际关闭的订阅记录数 |
result.auto_renew_updated_count |
integer | 自动续费关闭标记实际更新数量 |
result.manual_review_required |
boolean | 是否因本地交易或权益未匹配而进入补偿重放 |
result.reason |
string | 重复、忽略、失败或人工检查原因 |
result.provider_notification_id |
string | 重复通知对应 Apple notificationUUID |
result.replay_queued |
boolean | 重复投递命中既有失败日志时是否已重新投递补偿任务 |
result.diagnostic |
object | Apple 订阅链最新诊断状态更新结果 |
result.diagnostic.updated |
boolean | 本通知是否按 signedDate 更新为最新诊断状态 |
result.diagnostic.reason |
string | 未更新原因,例如 out_of_order_notification |
result.diagnostic.original_transaction_id |
string | Apple 自动订阅链原始交易 ID |
响应示例:
{
"ack": true,
"result": {
"duplicate": false,
"delivered": true,
"subscription_no": "SUB202607210002",
"expires_at": "2026-09-21 10:01:00",
"im_sync": {
"artist_id": 1,
"synced_count": 1,
"failed_count": 0
},
"subscription_message": {
"queued": true,
"message_no": "MSG202607210002",
"registration_error": null
},
"income": {
"duplicate": false,
"income_no": "IN202607210002",
"settlement_base_amount": "30.00",
"artist_income_amount": "21.00"
},
"diagnostic": {
"updated": true,
"original_transaction_id": "2000001208186444"
}
}
}
相同 notificationUUID 重复投递响应示例:
{
"ack": true,
"result": {
"duplicate": true,
"reason": "apple_notification_duplicate",
"provider_notification_id": "0f08f9a7-75e0-4b48-bc99-06b27a381fc2",
"replay_queued": false
}
}
说明:
- 由 Apple App Store Server Notifications 调用,不面向 APP。
- Apple 自动续订通知按
original_transaction_id找到订阅链;DID_RENEW创建本地续订订单并发放当前已支付周期,auto_renew_status=0只表示后续不再自动续费,不撤销当前周期。 - Apple 自动续订优先使用验签通知中的实付金额;通知缺少金额时回退当前续订商品对应的 iOS 配置价。普通月费或年费同时固化为本周期
settlement_base_amount_cent,后续收入不得再按档位代码查询改价后的普通价格。 -
notificationUUID用于通知幂等;相同通知不会重复创建订单或发放权益。失败通知再次投递时会重新触发原失败日志的补偿重放。 - 回调日志会保留通知 UUID、类型、subtype、交易标识和解码后的诊断字段,但会过滤
signedPayload、signedTransactionInfo、signedRenewalInfo、小票和密钥。 - 最新诊断状态按 Apple
signedDate更新,乱序旧通知不得覆盖更新的自动续费状态和通知类型。 -
DID_CHANGE_RENEWAL_STATUS更新订阅链自动续费标记;字段缺失时保持原状态,不按关闭处理。 -
DID_FAIL_TO_RENEW只记录续费失败和宽限期,不提前关闭仍在有效期内的权益。 -
EXPIRED包含subtype=VOLUNTARY:只把通知交易对应的订阅权益置为过期,同时将同链后续自动续费标记关闭;找不到本地交易或订阅时记录失败并进入回调重放。 -
REFUND、REVOKE继续按被退款或撤销的精确交易关闭权益。 - 验签、载荷解析或未捕获业务异常返回 HTTP 500,响应体为
{"ack":false,"message":"失败原因"};已识别但暂未匹配本地交易的通知返回ack=true、manual_review_required=true,并由内部补偿任务重放。