与来自 Apple 的 verifyReceipt 端点的响应文档不一致

Inconsistencies with documentation in response from Apple's verifyReceipt endpoint

我正在我们的服务器上为 Apple 的自动续订订阅设置收据验证,发现与官方 documentation 存在一些不一致。使用沙盒 verifyReceipt 端点验证沙盒收据时,响应如下所示:

{  
  "auto_renew_status": 1,  
  "status": 0,  
  "auto_renew_product_id": "app.xxx",  
  "receipt": {  
    "original_purchase_date_pst": "2020-03-18 01:11:45 America/Los_Angeles",  
    "quantity": "1",  
    "unique_vendor_identifier": "6D2xxx194",  
    "bvrs": "2",  
    "expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",  
    "is_in_intro_offer_period": "false",  
    "purchase_date_ms": "1584703627636",  
    "expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
    "is_trial_period": "false",  
    "item_id": "15xxx27",  
    "unique_identifier": "cd5xxx424",  
    "original_transaction_id": "100xxx735",  
    "subscription_group_identifier": "20xxx02",  
    "transaction_id": "100xxx439",  
    "web_order_line_item_id": "100xxx419",  
    "version_external_identifier": "0",  
    "purchase_date": "2020-03-20 11:27:07 Etc/GMT",  
    "product_id": "app.xxx",  
    "expires_date": "1584707227636",  
    "original_purchase_date": "2020-03-18 08:11:45 Etc/GMT",  
    "purchase_date_pst": "2020-03-20 04:27:07 America/Los_Angeles",  
    "bid": "app.xxx",  
    "original_purchase_date_ms": "1584519105000"  
  },  
  "latest_receipt_info": {  
    "original_purchase_date_pst": "2020-03-18 01:11:45 America/Los_Angeles",  
    "quantity": "1",  
    "unique_vendor_identifier": "6D2xxx194",  
    "bvrs": "2",  
    "expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",  
    "is_in_intro_offer_period": "false",  
    "purchase_date_ms": "1584703627000",  
    "expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
    "is_trial_period": "false",  
    "item_id": "15xxx27",  
    "unique_identifier": "cd5xxx424",  
    "original_transaction_id": "100xxx735",  
    "subscription_group_identifier": "20xxx02",  
    "transaction_id": "100xxx439",  
    "bid": "app.xxx",  
    "web_order_line_item_id": "100xxx419",  
    "purchase_date": "2020-03-20 11:27:07 Etc/GMT",  
    "product_id": "app.xxx",  
    "expires_date": "1584707227000",  
    "original_purchase_date": "2020-03-18 08:11:45 Etc/GMT",  
    "purchase_date_pst": "2020-03-20 04:27:07 America/Los_Angeles",  
    "original_purchase_date_ms": "1584519105000"  
  },  
  "latest_receipt": "xxx"  
} 

我特别想指出该回复的以下字段:

{  
    ...  
  "latest_receipt_info": {  
      ...  
    "expires_date": "1584707227000",  
    "expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",  
    "expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
    "subscription_group_identifier": "20xxx02",  
    "bid": "app.xxx",  
      ...  
  },  
  "receipt": {  
      ...  
    "expires_date": "1584707227636",  
    "expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",  
    "expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
    "subscription_group_identifier": "20xxx02",  
    "bid": "app.xxx",  
      ...  
  },  
    ...  
} 

与官方不一致的地方documentation有:

  1. latest_receipt_infodocumented 数组,但是,它是单个 json 对象。
  2. latest_receipt_info 中,expires_date 并不像 documentation 所说的那样在 "date-time format similar to the ISO 8601" 中,但看起来它是从纪元开始的毫秒数(应该是expires_date_ms)。但是,我们可以找到日期时间格式的键expires_date_formatted
  3. 与 (2) 中相同的字段也可以在收据中找到,但是,documentation 仅声明一个键 expiration_date(类似于 expires_date latest_receipt_info 日期时间格式)和 expiration_date_ms(自纪元以来的毫秒数)。
  4. 记录的 bundle_id 密钥 (here and here) 不存在,但存在一个密钥 bid,它包含包 ID。
  5. 密钥 subscription_group_identifer 不包含在 AppStoreConnect 中作为订阅组标识符输入的确切字符串,如记录的那样 (here and here),但包含一些整数值。

所以根据文档,对我来说响应应该是这样的:

{  
    ...  
  "latest_receipt_info": [  
    {  
        ...  
      "expires_date": "2020-03-20 12:27:07 Etc/GMT",  
      "expires_date_ms": "1584707227000",  
      "expires_date_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
      "subscription_group_identifier": "MY_SUBSCRIPTION_GROUP_ID",  
      "bundle_id": "app.xxx",  
        ...  
    }  
  ],  
  "receipt": {  
      ...  
    "expiration_date": "2020-03-20 12:27:07 Etc/GMT",  
    "expiration_date_ms": "1584707227636",  
    "expiration_date_pst": "2020-03-20 05:27:07 America/Los_Angeles",  
    "subscription_group_identifier": "MY_SUBSCRIPTION_GROUP_ID",  
    "bundle_id": "app.xxx",  
      ...  
  },  
    ...  
}  

提前致谢!

你从哪里得到那个收据例子?这是来自 verifyReceipt endint 的正确收据示例:https://gist.github.com/ren6/3da2d14ea629ab9add489c0e6df1917c

我还可以推荐您阅读我们博客中的文章:https://blog.apphud.com/receipt-validation/

关于 Apple 服务器到服务器的通知,它们现在是统一的,即数据以与 verifyReceipt 端点相同的结构返回。

对于面临同样问题的每个人:我们向后端发送了错误的收据数据,因为我们通过已弃用的 transactionReceipt and not via appStoreReceiptURL 请求收据。