WWDC Quick Look 💓 By SwiftGGTeam
Meet the App Store Server Library

Meet the App Store Server Library

元の動画を見る

ハイライト

Apple は、WWDC23 で、Swift、Java、Node.js、Python の 4 つの言語をサポートする App Store Server Library オープンソース ライブラリをリリースしました。 JWT 生成、JWS 署名データ検証、レシート移行、プロモーション オファー署名の 4 つのコア機能を提供し、App Store サーバー API の統合しきい値を大幅に下げます。

主な内容

なぜこのライブラリが必要なのでしょうか?

(00:34) 2021 年、Apple は StoreKit 2、App Store Server API、および App Store Server Notices V2 をリリースしました。これらのツールは、古い verifyReceipt よりも安全で柔軟な JWS (JSON Web Signature) 形式を使用して、署名されたトランザクション データを提供します。ただし、JWS の検証プロセスには、証明書チェーン検証、OCSP 失効チェック、署名検証などの複数の複雑な手順が含まれるため、暗号化プロトコルに詳しくない開発者にとっては敷居が高くなります。

(01:33) App Store サーバー ライブラリは、この問題を解決するために生まれました。JWT 生成、署名検証、レシート解析などの複雑な操作を単純な API 呼び出しにカプセル化し、開発者がビジネス ロジックに集中できるようにします。

4 つのコア コンピテンシー

02:07

1. App Store サーバー API 呼び出し

ライブラリは JWT 生成を自動的に処理します。issuerId、keyId、秘密キー、bundleId、および環境 (サンドボックス/プロダクション) を指定するだけで、API クライアントを作成し、すべてのサーバー API エンドポイントを直接呼び出すことができます。

2. JWS署名データの検証

App Store から受け取った署名付きデータが本物で有効であることを確認します。これには、証明書チェーンの検証、証明書失効ステータスの確認、署名の確認、アプリケーション識別子と環境が一致することの確認が含まれます。

3.レシート移行ツール

古いアプリレシートからtransactionIdを抽出すると、非推奨のverifyReceiptエンドポイントをバイパスして、サーバーAPIを使用してトランザクション情報を直接取得できるようになります。

4.プロモーションオファーの署名

アプリ内購入の秘密キーを使用すると、サブスクリプションのプロモーション オファーの署名が自動的に生成され、署名ロジックを手動で実装する手間が省けます。

クイックスタート

(04:22) ライブラリを使用する前に、App Store Connect および Apple PKI Web サイトから次の情報を収集する必要があります。

  1. Issuer ID:App Store Connect → Users and Access → Keys → In-App Purchase
  2. キー ID と秘密キー: 同じページで新しい秘密キーを生成し、秘密キー ファイルをダウンロードします (ダウンロードは 1 回のみ)
  3. Apple ルート証明書: Apple PKI Web サイトからルート証明書をダウンロードします。
  4. バンドル ID: アプリケーションのバンドル識別子

##詳細

Java の例: API クライアントの作成

(05:34) Java を例として、ライブラリを使用して App Store サーバー API を呼び出す方法を示します。

Gradle の依存関係:

dependencies {
    implementation 'com.apple.itunes.storekit:app-store-server-library:1.0.0'
}

クライアントを作成して API を呼び出します:

import com.apple.itunes.storekit.client.AppStoreServerAPIClient;
import com.apple.itunes.storekit.model.Environment;

public class ExampleApp {
    public static void main(String[] args) throws Exception {
        String issuerId = "YOUR_ISSUER_ID";
        String keyId = "YOUR_KEY_ID";
        String privateKey = "-----BEGIN EC PRIVATE KEY-----\n...";
        String bundleId = "com.example.yourapp";
        Environment environment = Environment.SANDBOX;

        // 创建 API 客户端
        AppStoreServerAPIClient client = new AppStoreServerAPIClient(
            privateKey, keyId, issuerId, bundleId, environment
        );

        // 请求测试通知
        var response = client.requestTestNotification();
        System.out.println("Test notification token: " + response.getTestNotificationToken());
    }
}

キーポイント:

  • AppStoreServerAPIClientJWT の生成と更新を自動的に処理する
  • すべてのサーバー API エンドポイントには対応するメソッドがあります
  • 環境パラメータによりサンドボックスと本番環境が区別されます

JWS 署名データの検証

(07:29) JWS データには、ドットで区切られた 3 つの Base64URL エンコードされた部分 (ヘッダー、ペイロード、署名) が含まれています。

ヘッダーにはアルゴリズム (ES256 に固定) と証明書チェーン (x5c) が含まれています。検証プロセスには次のものが含まれます。

  1. 証明書チェーン内の各証明書が前の証明書によって署名されていることを確認します。
  2. 証明書の有効期間と形式を確認する
  3. OCSP を使用して証明書が失効していないか確認します。
  4. リーフ証明書が App Store のレシート署名に使用されていることを確認します。
  5. リーフ証明書の公開キーを使用して JWS 署名を検証する
  6. ペイロード内の appAppleId と BundleId がアプリケーションと一致するかどうかを確認します

(13:52) ライブラリ内SignedDataVerifierこのクラスは、次のすべての手順をカプセル化します。

import com.apple.itunes.storekit.verification.SignedDataVerifier;
import com.apple.itunes.storekit.model.Environment;
import java.util.Set;

// 加载 Apple 根证书
Set<String> rootCertificates = Set.of(
    Files.readString(Path.of("AppleRootCA-G3.cer")),
    Files.readString(Path.of("AppleRootCA-G2.cer"))
);

// 创建验证器
SignedDataVerifier verifier = new SignedDataVerifier(
    rootCertificates,      // Apple 根证书集合
    null,                  // appAppleId,sandbox 环境传 null
    bundleId,              // 你的 bundle ID
    environment,           // SANDBOX 或 PRODUCTION
    true                   // 是否执行在线吊销检查
);

// 验证通知
var result = verifier.verifyAndDecodeNotification(signedPayload);
System.out.println("Notification type: " + result.getNotificationType());

キーポイント:

  • onlineChecksパラメータ: 受信したばかりの通知については、次のように設定します。true、数か月前の履歴データの場合は、次のように設定します。false(証明書の有効期限が切れている可能性があります)
  • バリデーターは、appAppleId、bundleId、および環境が一致するかどうかを自動的にチェックします。
  • 検証後、ペイロード内のデータは安全に信頼できる

レシートからtransactionIdを抽出します

(16:52) ReceiptUtility クラスは、古いアプリのレシートからtransactionIdを抽出し、verifyReceiptからサーバーAPIへの移行を実装するのに役立ちます。

import com.apple.itunes.storekit.util.ReceiptUtility;

// 从设备或 V1 通知获取的 app receipt
String appReceipt = "MII...";  // base64 编码的收据

ReceiptUtility utility = new ReceiptUtility();
String transactionId = utility.extractTransactionIdFromAppReceipt(appReceipt);

if (transactionId != null) {
    // 使用 transactionId 调用 Get Transaction History
    var request = new TransactionHistoryRequest();
    request.setProductType(ProductType.CONSUMABLE);
    request.setRevoked(false);
    request.setSort(SortOrder.DESCENDING);

    List<TransactionInfo> transactions = new ArrayList<>();
    String revision = null;

    do {
        var response = client.getTransactionHistory(transactionId, revision, request);
        transactions.addAll(response.getSignedTransactions());
        revision = response.getRevision();
    } while (Boolean.TRUE.equals(response.getHasMore()));

    System.out.println("Found " + transactions.size() + " transactions");
}

キーポイント:

  • すべてのレシートにtransactionIdが含まれているわけではありません(ユーザーは購入記録を持っていない可能性があります)
  • 抽出されたtransactionIdは、originalTransactionIdに限定されず、任意のtransactionIdにすることができます。
  • サーバー API のトランザクション履歴の取得などのエンドポイントは、パラメータとして任意のトランザクション ID をサポートするようになりました。
  • 返されたものを保存するrevisionトークン。次のクエリ中にこのトークンを渡して、新しいトランザクションを段階的に取得できます。

重要ポイント

  1. 手書きの JWT と検証ロジックを公式ライブラリに置き換えます
  • 何をすべきか: JWT を手動で生成し、JWS を検証するサーバー上のコードを App Store サーバー ライブラリに置き換えます。
  • 実行する価値がある理由: ライブラリの検証ロジックは Apple によって正式にレビューされており、手書きの実装よりも信頼性が高く、プロトコルの更新を自動的にフォローアップします。
  • 開始方法: バックエンド言語に応じて対応するライブラリ (Swift/Java/Node.js/Python) を選択し、README の例に従って既存のコードを置き換えます。
  1. サーバー側のトランザクション検証パイプラインを確立します
  • やるべきこと: 通知の受信、署名の検証、ユーザー権限の更新など、完全なトランザクション検証プロセスをサーバーに展開します。
  • 実行する価値がある理由: JWS 署名データによりサーバー側の検証が標準化され、ReceiptUtility により古いデバイスを新しいシステムに接続できるようになります。
  • 開始方法: SignedDataVerifier を使用してクライアントと通知から受信したすべての署名データを検証し、ReceiptUtility を使用して古いレシートを処理し、統合されたトランザクション処理プロセスを確立します。
  1. verifyReceipt 移行ロードマップを計画する
  • 内容: 新旧デバイスの共存をサポートするために、verifyReceipt から App Store サーバー API への移行計画を作成します。
  • 実行する価値がある理由: verifyReceipt は廃止され、新しい関数は JWS システムでのみリリースされます。 ReceiptUtility はスムーズな移行ソリューションを提供します
  • 開始方法: 新しいコードはサーバー API を直接使用し、古いコードは ReceiptUtility を通じてtransactionId を抽出してからサーバー API を呼び出し、verifyReceipt を段階的に段階的に廃止します。
  1. 統合されたプロモーション オファー署名の生成
  • 内容: ライブラリのプロモーション オファー署名機能を使用して、サブスクリプション オファーの実装を簡素化します。
  • 実行する価値がある理由: シグネチャを手動で実装するとエラーが発生しやすくなります。ライブラリは実証済みの実装を提供します。
  • 開始方法: プロモーション オファーを生成するときにライブラリの署名メソッドを呼び出し、製品 ID、オファー ID、および秘密キーを渡します。

関連セッション

コメント

GitHub Issues · utterances