我想在当前处于活动状态且未过期的自动续订订阅中兑换订阅优惠。
我在Xcode 10.2上设置了一个Store Kit演示项目,以测试新的订阅优惠。在遵循WWDC 2019主题演讲和大量故障排除之后,我能够实现以下目标:
每当我尝试申领订阅优惠并且我的自动续订订阅仍处于活动状态时,都会从StoreKit中收到以下错误消息:
Error Domain=SKErrorDomain Code=0 "Cannot connect to iTunes Store" UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store}
但是,令人惊讶的是,尽管在日志中收到了上述错误消息,但试图索要要约的消息时弹出一个警告框,提示“您已准备就绪。您的购买已成功。[环境:沙箱]”。
根据SKErrorDomain上的Apple文档(链接:https://developer.apple.com/documentation/storekit/skerror/code),代码0为“未知错误”。这是我碰到的砖墙。
在此演示项目的开发过程中,我收到了其他错误代码,例如ErrorCode = 12,这意味着我解决了“无效签名”,因此,我确定签名没有问题。在下面查看我的设置以获取更多背景信息。
我敦促您在这里忽略我的非最佳编码实践。我把这些作为概念证明,而不是用于生产。
这是点击“索赔奖励”按钮的操作,该按钮试图兑现订阅优惠:
// PrimaryVC.swift
@IBAction func aClaimReward(_ sender: UIButton) {
// Hard code offer information
let username = "mail@mysandbox.com" // sandbox username
guard let usernameData = username.data(using: .utf8) else { return }
let usernameHash = usernameData.md5().toHexString()
// Enums for simplifying the product identifiers.
let productIdentifier = IAPProduct.autoRenewable.rawValue
let offerIdentifier = IAPProduct.reward.rawValue
// Call prepare offer method and get discount in completion block
IAPService.shared.prepareOffer(usernameHash: usernameHash, productIdentifier: productIdentifier, offerIdentifier: offerIdentifier) { (discount) in
// Find the autorenewable subscription in products set
guard let product = IAPService.shared.products.filter({ $0.productIdentifier == IAPProduct.autoRenewable.rawValue }).first else {
return
}
// Complete transaction
self.buyProduct(product: product, forApplicationUsername: usernameHash, withOffer: discount)
}
}
这是在上述操作结束时使用的buyProduct()方法的代码:
// PrimaryVC.swift
func buyProduct(product: SKProduct, forApplicationUsername usernameHash: String, withOffer offer: SKPaymentDiscount) {
// Create payment object
let payment = SKMutablePayment(product: product)
// Apply username and offer to the payment
payment.applicationUsername = usernameHash
payment.paymentDiscount = offer
// Add payment to paymentQueue
IAPService.shared.paymentQueue.add(payment)
}
我创建了一个应用内购买服务类,其中许多应用内购买逻辑都存在。该单例用于上面详细介绍的按钮操作中,其使用的方法如下:
// IAPService.swift
import SwiftyJSON
import Alamofire
// ...
func prepareOffer(usernameHash: String, productIdentifier: String, offerIdentifier: String, completion: @escaping (SKPaymentDiscount) -> Void) {
// Create parameters dictionary
let parameters: Parameters = [
"appBundleID": "my.bundle.id",
"productIdentifier": productIdentifier, // "my.product.id",
"offerID": offerIdentifier, // "REFERRALBONUSMONTH"
"applicationUsername": usernameHash
]
// Generate new signature by making get request to local server.
// I used the starter code from the wwdc2019 lecture on subscription offers
AF.request("https://mylocalserver/offer", parameters: parameters).responseJSON { response in
var signature: String?
var keyID: String?
var timestamp: NSNumber?
var nonce: UUID?
switch response.result {
case let .success(value):
let json = JSON(value)
// Get required parameters for creating offer
signature = json["signature"].stringValue
keyID = json["keyID"].stringValue
timestamp = json["timestamp"].numberValue
nonce = UUID(uuidString: json["nonce"].stringValue)
case let .failure(error):
print(error)
return
}
// Create offer
let discountOffer = SKPaymentDiscount(identifier: offerIdentifier, keyIdentifier: keyID!, nonce: nonce!, signature: signature!, timestamp: timestamp!)
// Pass offer in completion block
completion(discountOffer)
}
}
结论:
根据WWDC2019订阅优惠讲座,即使在活跃订阅期间,用户也应该能够兑换订阅优惠,但是当我尝试在活跃订阅期间兑换订阅优惠时,我仍然得到SKErrorCode = 0。我可以在自动续订的订阅到期后兑换该订阅,并且已经验证了收据并在收据上看到了订阅优惠的数据。
关于我可能要去哪里的任何想法?还是这是苹果方面的问题?