Apple App Store 服务器 Swift 库
适用于 App Store 服务器 API 和 App Store 服务器通知 的 Swift 服务器库。还提供 Java、Python 和 Node.js 版本。
目录
安装
Swift 包管理器
添加以下依赖
.package(url: "https://github.com/apple/app-store-server-library-swift.git", .upToNextMinor(from: "2.3.0")),
文档
从 App Store Connect 获取应用内购买密钥
要使用 App Store 服务器 API 或创建促销优惠签名,需要从 App Store Connect 下载签名密钥。要获取此密钥,您必须拥有管理员角色。转到"用户与访问" > "集成" > "应用内购买"。在这里,您可以创建和管理密钥,以及找到您的发行者 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! 仅用于示例目的
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() // 具体实现可能有所不同
let appAppleId: Int64? = nil // 对于生产环境,必须提供 appAppleId
let enableOnlineChecks = true
let environment = Environment.sandbox
// try! 仅用于示例目的
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! 仅用于示例目的
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:
// 处理失败
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! 仅用于示例目的
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)
支持
只有最新的主要版本库会收到更新,包括安全更新。因此,建议更新到新的主要版本。