readdle/app-store-receipt-verification

无需调用App Store API,纯PHP应用程序商店收据解析/验证/验证库。

1.6.2 2024-09-11 14:48 UTC

README

这是一个无依赖项*纯PHP库,允许在不调用App Store Server API的情况下进行收据解析/验证/验证。

然而,到App Store Server API的桥梁也已经实现,因此可以更进一步,使用API扩展收据数据。

* 无依赖项意味着这个库不依赖于任何第三方库。同时,这个库依赖于一些基本的PHP扩展,如jsonopenssl

注意

如果您需要处理App Store Server API而不是(或与)收据解析/验证,请查看这个库

安装

这里没有特别之处,只需使用composer安装包即可

composer install readdle/app-store-receipt-verification

用法

解析base64编码的收据数据,并验证其是否由Apple根证书签名

$appleIncRootCertificate = \Readdle\AppStoreReceiptVerification\Utils::DER2PEM(
    file_get_contents('https://www.apple.com/appleca/AppleIncRootCertificate.cer')
);

$serializedReceipt = \Readdle\AppStoreReceiptVerification\AppStoreReceiptVerification::verifyReceipt(
    $receiptData,
    $appleIncRootCertificate
);

使用到readdle/app-store-server-api包的桥梁扩展收据的最新信息

try {
    $serverApi = new \Readdle\AppStoreServerAPI\AppStoreServerAPI(
        'Production',
        '1a2b3c4d-1234-4321-1111-1a2b3c4d5e6f',
        'com.readdle.MyBundle',
        'ABC1234DEF',
        "-----BEGIN PRIVATE KEY-----\n<base64-encoded private key goes here>\n-----END PRIVATE KEY-----"
    );
} catch (\Readdle\AppStoreServerAPI\Exception\WrongEnvironmentException $e) {
    exit($e->getMessage());
}

$receiptExtender = new \Readdle\AppStoreReceiptVerification\ReceiptExtender\AppStoreServerAPIReceiptExtender($serverApi);
$mergeNewEntries = true;

try {
    $extendedReceipt = $receiptExtender->extend($serializedReceipt, $mergeNewEntries);
} catch (\Exception $e) {
    exit($e->getMessage());
}

自签名StoreKit收据

从版本1.4.0开始,也支持自签名的StoreKit收据。请注意,与沙盒/生产收据相比,此类收据包含的数据非常有限,并且**无法验证,因此请仅在开发模式下解析它们(见下文)**。

关于收据的内容

不幸的是,App Store收据不包含其中由已弃用的App Store Receipt Verification API返回的所有信息。

同时,它们包含一些可能不太有用的额外字段,但既然它们已经存在,您也会在结果集中获得它们。

应用内购买收据中缺少的字段列表

  • app_account_token
  • in_app_ownership_type
  • offer_code_ref_name
  • subscription_group_identifier

应用收据中的额外字段列表

  • age_rating
  • opaque_value
  • sha1_hash

扩展收据

有点有趣令人烦恼的是,App Store Server API返回的并非像在App Store Receipt Verification API响应中找到的那样详细的信息集 ¯_(ツ)_/¯

因此,使用来自App Store Server API的信息扩展的收据包含最多的信息。

合并收据中的新条目

$receiptExtender->extend()方法的第二个参数是一个布尔标志,表示您是否想将条目合并到in_app/latest_receipt_info数组中。

意味着那些不在收据中但通过API可用的交易(例如,处理过时的收据)。在这种情况下,关于每个新交易的信息集仅限于API中可用的信息。

开发模式

您可以使用此调用打开开发模式

\Readdle\AppStoreReceiptVerification\AppStoreReceiptVerification::devMode();

在开发模式下,**不会执行收据容器检查**,因此**仅**用于开发目的或测试。

在应用和内购收据中也将有一个名为unknown的属性。该属性将包含在二进制数据中找到的所有未识别字段。

如果您知道其中任何一项的含义,请与我联系,我将更新库 :)

测试

tests/目录中您可以找到一些测试。

对你最有用的将是 tests/Functional/AppStoreReceiptVerificationTest.php

这个测试会查找 tests/playground/ 目录中的四个文件(你不需要创建所有四个,只需要你需要的那些):production.jsonsandbox.jsonxcode.jsonunknown.json。所有这些文件的结构预期是相同的

[
    {
        "name": "any name for your receipt",
        "base64": "...base64-encoded receipt data..."
    },
    {
        "name": "any name for your receipt",
        "base64": "...base64-encoded receipt data..."
    },
    ...
]

注意:每个哈希可以包含任何额外的键/值对,这两个是唯一使用的

每个文件可以包含你想要的条目数量。对 production/sandbox/xcode/unknown 的分离只是为了使测试收据的管理更方便。然而,有一个区别,xcodeunknown 列表将在开发模式下解析(因为无法验证自签名收据,而 unknown,正如其名称所示,也可以包含自签名收据)。

此测试将生成 production.parsed.jsonsandbox.parsed.jsonxcode.parser.jsonunknown.parsed.json。每个文件都将包含一个哈希,其中键将是收据的名称(源文件中的 name 或者在 name 被省略的情况下为 unknown_X,其中 X 是源文件中收据的索引号),值将是解析后的收据数据(与从 AppStoreReceipVerification::verifyReceipt() 获得的数据相同)。

外部链接

在设备上验证收据

收据验证编程指南

ASN.1 的通俗易懂指南,ASN.1 是什么?

ASN.1 简化版 — ASN.1 是什么?

信息技术 – ASN.1 编码规则:基本编码规则(BER)、规范编码规则(CER)和选择编码规则(DER)的规范

PKCS7 模块(X.420:06/1999)

认证框架模块(X.509:08/1997)