我尝试在我的应用中实施应用内购买。我按照教程https://www.youtube.com/watch?v=dwPFtwDJ7tc&index=12&list=WL进行了操作,但是当我尝试运行它时,如果按下按钮,则不会弹出警报。 Sample项目工作得非常好但是在进入我自己的购买后没有任何作用。
这是我的代码:
import UIKit
import SwiftyStoreKit
import StoreKit
var sharedSecret = "919a706ee42143df8571a316f14531c8"
enum RegisteredPurchase : String {
case Dolla10 = "10Dolla"
case RemoveAds = "RemoveAds"
case autoRenewable = "autoRenewable"
}
class NetworkActivityIndicatorManager : NSObject {
private static var loadingCount = 0
class func NetworkOperationStarted() {
if loadingCount == 0 {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
loadingCount += 1
}
class func networkOperationFinished(){
if loadingCount > 0 {
loadingCount -= 1
}
if loadingCount == 0 {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
class ViewController: UIViewController {
@IBOutlet var MoneyLbl: UILabel!
var Money = Int()
let bundleID = "com.KonradLoecher.inAppPurchase"
var Dolla10 = RegisteredPurchase.Dolla10
var RemoveAds = RegisteredPurchase.RemoveAds
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.MoneyLbl.text = "\(self.Money)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func Consumable1(_ sender: Any) {
purchase(purchase: Dolla10)
}
@IBAction func Consumable2(_ sender: Any) {
purchase(purchase: RemoveAds)
}
@IBAction func Renewable(_ sender: Any) {
}
@IBAction func NonRenewable(_ sender: Any) {
}
func getInfo(purchase : RegisteredPurchase) {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.retrieveProductsInfo([bundleID + "." + purchase.rawValue], completion: {
result in
NetworkActivityIndicatorManager.networkOperationFinished()
self.showAlert(alert: self.alertForProductRetrievalInfo(result: result))
})
}
func purchase(purchase : RegisteredPurchase) {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.purchaseProduct(bundleID + "." + purchase.rawValue, completion: {
result in
NetworkActivityIndicatorManager.networkOperationFinished()
if case .success(let product) = result {
if product.productId == self.bundleID + "." + "10Dolla"{
self.Money += 10
self.MoneyLbl.text = "\(self.Money)"
}
if product.productId == self.bundleID + "." + "RemoveAds" {
self.Money += 100
self.MoneyLbl.text = "\(self.Money)"
}
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
self.showAlert(alert: self.alertForPurchaseResult(result: result))
}
})
}
func restorePurchases() {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.restorePurchases(atomically: true, completion: {
result in
NetworkActivityIndicatorManager.networkOperationFinished()
for a product in a result.restoredProducts {
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
}
self.showAlert(alert: self.alertForRestorePurchases(result: result))
})
}
func verifyReceipt() {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.verifyReceipt(password: sharedSecret, completion: {
result in
NetworkActivityIndicatorManager.networkOperationFinished()
self.showAlert(alert: self.alertForVerifyReceipt(result: result))
if case .error(let error) = result {
if case .noReceiptData = error {
self.refreshReceipt()
}
}
})
}
func verifyPurcahse(product : RegisteredPurchase) {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.verifyReceipt(password: sharedSecret, completion: {
result in
NetworkActivityIndicatorManager.networkOperationFinished()
switch result{
case .success(let receipt):
let productID = self.bundleID + "." + product.rawValue
if product == .autoRenewable {
let purchaseResult = SwiftyStoreKit.verifySubscription(productId: productID, inReceipt: receipt, validUntil: Date())
self.showAlert(alert: self.alertForVerifySubscription(result: purchaseResult))
}
else {
let purchaseResult = SwiftyStoreKit.verifyPurchase(productId: productID, inReceipt: receipt)
self.showAlert(alert: self.alertForVerifyPurchase(result: purchaseResult))
}
case .error(let error):
self.showAlert(alert: self.alertForVerifyReceipt(result: result))
if case .noReceiptData = error {
self.refreshReceipt()
}
}
})
}
func refreshReceipt() {
SwiftyStoreKit.refreshReceipt(completion: {
result in
self.showAlert(alert: self.alertForRefreshRecepit(result: result))
})
}
}
extension ViewController {
func alertWithTitle(title : String, message : String) -> UIAlertController {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
return alert
}
func showAlert(alert : UIAlertController) {
guard let _ = self.presentedViewController else {
self.present(alert, animated: true, completion: nil)
return
}
}
func alertForProductRetrievalInfo(result : RetrieveResults) -> UIAlertController {
if let product = result.retrievedProducts.first {
let priceString = product.localizedPrice!
return alertWithTitle(title: product.localizedTitle, message: "\(product.localizedDescription) - \(priceString)")
}
else if let invalidProductID = result.invalidProductIDs.first {
return alertWithTitle(title: "Could not retreive product info", message: "Invalid product identifier: \(invalidProductID)")
}
else {
let errorString = result.error?.localizedDescription ?? "Unknown Error. Please Contact Support"
return alertWithTitle(title: "Could not retreive product info" , message: errorString)
}
}
func alertForPurchaseResult(result : PurchaseResult) -> UIAlertController {
switch result {
case .success(let product):
print("Purchase Succesful: \(product.productId)")
return alertWithTitle(title: "Thank You", message: "Purchase completed")
case .error(let error):
print("Purchase Failed: \(error)")
switch error {
case .failed(let error):
if (error as NSError).domain == SKErrorDomain {
return alertWithTitle(title: "Purchase Failed", message: "Check your internet connection or try again later.")
}
else {
return alertWithTitle(title: "Purchase Failed", message: "Unknown Error. Please Contact Support")
}
case.invalidProductId(let productID):
return alertWithTitle(title: "Purchase Failed", message: "\(productID) is not a valid product identifier")
case .noProductIdentifier:
return alertWithTitle(title: "Purchase Failed", message: "Product not found")
case .paymentNotAllowed:
return alertWithTitle(title: "Purchase Failed", message: "You are not allowed to make payments")
}
}
}
func alertForRestorePurchases(result : RestoreResults) -> UIAlertController {
if result.restoreFailedProducts.count > 0 {
print("Restore Failed: \(result.restoreFailedProducts)")
return alertWithTitle(title: "Restore Failed", message: "Unknown Error. Please Contact Support")
}
else if result.restoredProducts.count > 0 {
return alertWithTitle(title: "Purchases Restored", message: "All purchases have been restored.")
}
else {
return alertWithTitle(title: "Nothing To Restore", message: "No previous purchases were made.")
}
}
func alertForVerifyReceipt(result: VerifyReceiptResult) -> UIAlertController {
switch result {
case.success(let receipt):
return alertWithTitle(title: "Receipt Verified", message: "Receipt Verified Remotely")
case .error(let error):
switch error {
case .noReceiptData:
return alertWithTitle(title: "Receipt Verification", message: "No receipt data found, application will try to get a new one. Try Again.")
default:
return alertWithTitle(title: "Receipt verification", message: "Receipt Verification failed")
}
}
}
func alertForVerifySubscription(result: VerifySubscriptionResult) -> UIAlertController {
switch result {
case .purchased(let expiryDate):
return alertWithTitle(title: "Product is Purchased", message: "Product is valid until \(expiryDate)")
case .notPurchased:
return alertWithTitle(title: "Not purchased", message: "This product has never been purchased")
case .expired(let expiryDate):
return alertWithTitle(title: "Product Expired", message: "Product is expired since \(expiryDate)")
}
}
func alertForVerifyPurchase(result : VerifyPurchaseResult) -> UIAlertController {
switch result {
case .purchased:
return alertWithTitle(title: "Product is Purchased", message: "Product will not expire")
case .notPurchased:
return alertWithTitle(title: "Product not purchased", message: "Product has never been purchased")
}
}
func alertForRefreshRecepit(result : RefreshReceiptResult) -> UIAlertController {
switch result {
case .success(let receiptData):
return alertWithTitle(title: "Receipt Refreshed", message: "Receipt refreshed successfully")
case .error(let error):
return alertWithTitle(title: "Receipt refresh failed", message: "Receipt refresh failed")
}
}
}
编辑: 固定 而不是使用bundleID +"。" + purchase.rawValue id我使用iTunes中的产品ID连接(com.KonradLoecher.inAppPurchase.UnlockPremiumVersion)我将这些ID存储在enum RegisteredPurchase中。