Apple App Store 服务器 Swift 库

用于 App Store 服务器 APIApp Store 服务器通知 的 Swift 服务器库。 同样也提供 Java, Python, 和 Node.js 版本。

目录

  1. 安装
  2. 文档
  3. 使用
  4. 支持

安装

Swift 包管理器

添加以下依赖项

.package(url: "https://github.com/apple/app-store-server-library-swift.git", .upToNextMinor(from: "2.3.0")),

文档

文档

WWDC 视频

从 App Store Connect 获取 App 内购买项目密钥

要使用 App Store 服务器 API 或创建促销优惠签名,需要从 App Store Connect 下载签名密钥。 要获取此密钥,您必须具有管理员角色。 转到“用户和访问”>“集成”>“App 内购买项目”。 在这里,您可以创建和管理密钥,以及查找您的发行者 ID。 使用密钥时,您还需要密钥 ID 和发行者 ID。

获取 Apple 根证书

下载并存储 Apple PKI 站点“Apple 根证书”部分中找到的根证书。 将这些证书作为数组提供给 SignedDataVerifier,以允许验证签名数据来自 Apple。

使用

API 使用

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = Environment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let response = await client.requestTestNotification()
switch response {
case .success(let response):
    print(response.testNotificationToken)
case .failure(let errorCode, let rawApiError, let apiError, let errorMessage, let causedBy):
    print(errorCode)
    print(rawApiError)
    print(apiError)
    print(errorMessage)
    print(causedBy)
}

验证使用

import AppStoreServerLibrary

let bundleId = "com.example"
let appleRootCAs = loadRootCAs() // Specific implementation may vary
let appAppleId: Int64? = nil // appAppleId must be provided for the Production environment
let enableOnlineChecks = true
let environment = Environment.sandbox

// try! used for example purposes only
let verifier = try! SignedDataVerifier(rootCertificates: appleRootCAs, bundleId: bundleId, appAppleId: appAppleId, environment: environment, enableOnlineChecks: enableOnlineChecks)

let notificationPayload = "ey..."
let notificationResult = await verifier.verifyAndDecodeNotification(signedPayload: notificationPayload)
switch notificationResult {
case .valid(let decodedNotificaiton):
    ...
case .invalid(let error):
    ...
}

收据使用

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = Environment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let appReceipt = "MI..."
let transactionIdOptional = ReceiptUtility.extractTransactionId(appReceipt: appReceipt)
if let transactionId = transactionIdOptional {
    var transactionHistoryRequest = TransactionHistoryRequest()
    transactionHistoryRequest.sort = TransactionHistoryRequest.Order.ascending
    transactionHistoryRequest.revoked = false
    transactionHistoryRequest.productTypes = [TransactionHistoryRequest.ProductType.autoRenewable]

    var response: HistoryResponse?
    var transactions: [String] = []
    repeat {
        let revisionToken = response?.revision
        let apiResponse = await client.getTransactionHistory(transactionId: transactionId, revision: revisionToken, transactionHistoryRequest: transactionHistoryRequest, version: .v2)
        switch apiResponse {
        case .success(let successfulResponse):
            response = successfulResponse
        case .failure:
            // Handle Failure
            throw
        }
        if let signedTransactions = response?.signedTransactions {
            transactions.append(contentsOf: signedTransactions)
        }
    } while (response?.hasMore ?? false)
    print(transactions)
}

促销优惠签名创建

import AppStoreServerLibrary

let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")

let productId = "<product_id>"
let subscriptionOfferId = "<subscription_offer_id>"
let applicationUsername = "<application_username>"

// try! used for example purposes only
let signatureCreator = try! PromotionalOfferSignatureCreator(privateKey: encodedKey, keyId: keyId, bundleId: bundleId)

let nonce = UUID()
let timestamp = Int64(Date().timeIntervalSince1970) * 1000
let signature = signatureCreator.createSignature(productIdentifier: productIdentifier, subscriptionOfferID: subscriptionOfferID, applicationUsername: applicationUsername, nonce: nonce, timestamp: timestamp)
print(signature)

支持

只有该库的最新主要版本才会收到更新,包括安全更新。 因此,建议更新到新的主要版本。