如何将应用内购买添加到 iOS 应用?详细信息是什么,是否有示例代码?
这意味着如何将应用内购买添加到 iOS 应用程序的所有类型
Swift 用户可以查看[My Swift Answer的这个问题。 或者,查看Yedidya Reiss 的答案,它将这个 Objective-C 代码翻译成 Swift。
只需将 Jojodmo 代码翻译成 Swift:
class InAppPurchaseManager: NSObject , SKProductsRequestDelegate, SKPaymentTransactionObserver{ //If you have more than one in-app purchase, you can define both of //of them here. So, for example, you could define both kRemoveAdsProductIdentifier //and kBuyCurrencyProductIdentifier with their respective product ids // //for this example, we will only use one product let kRemoveAdsProductIdentifier = "put your product id (the one that we just made in iTunesConnect) in here" @IBAction func tapsRemoveAds() { NSLog("User requests to remove ads") if SKPaymentQueue.canMakePayments() { NSLog("User can make payments") //If you have more than one in-app purchase, and would like //to have the user purchase a different product, simply define //another function and replace kRemoveAdsProductIdentifier with //the identifier for the other product let set : Set<String> = [kRemoveAdsProductIdentifier] let productsRequest = SKProductsRequest(productIdentifiers: set) productsRequest.delegate = self productsRequest.start() } else { NSLog("User cannot make payments due to parental controls") //this is called the user cannot make payments, most likely due to parental controls } } func purchase(product : SKProduct) { let payment = SKPayment(product: product) SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().addPayment(payment) } func restore() { //this is called when the user restores purchases, you should hook this up to a button SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } func doRemoveAds() { //TODO: implement } ///////////////////////////////////////////////// //////////////// store delegate ///////////////// ///////////////////////////////////////////////// // MARK: - store delegate - func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { if let validProduct = response.products.first { NSLog("Products Available!") self.purchase(validProduct) } else { NSLog("No products available") //this is called if your product id is not valid, this shouldn't be called unless that happens. } } func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) { NSLog("received restored transactions: \(queue.transactions.count)") for transaction in queue.transactions { if transaction.transactionState == .Restored { //called when the user successfully restores a purchase NSLog("Transaction state -> Restored") //if you have more than one in-app purchase product, //you restore the correct product for the identifier. //For example, you could use //if(productID == kRemoveAdsProductIdentifier) //to get the product identifier for the //restored purchases, you can use // //NSString *productID = transaction.payment.productIdentifier; self.doRemoveAds() SKPaymentQueue.defaultQueue().finishTransaction(transaction) break; } } } func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .Purchasing: NSLog("Transaction state -> Purchasing") //called when the user is in the process of purchasing, do not add any of your own code here. case .Purchased: //this is called when the user has successfully purchased the package (Cha-Ching!) self.doRemoveAds() //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads SKPaymentQueue.defaultQueue().finishTransaction(transaction) NSLog("Transaction state -> Purchased") case .Restored: NSLog("Transaction state -> Restored") //add the same code as you did from SKPaymentTransactionStatePurchased here SKPaymentQueue.defaultQueue().finishTransaction(transaction) case .Failed: //called when the transaction does not finish if transaction.error?.code == SKErrorPaymentCancelled { NSLog("Transaction state -> Cancelled") //the user cancelled the payment ;( } SKPaymentQueue.defaultQueue().finishTransaction(transaction) case .Deferred: // The transaction is in the queue, but its final status is pending external action. NSLog("Transaction state -> Deferred") } } } }
这个答案的其余部分是用 Objective-C 编写的
My Apps
Features
In-App Purchases
+
non-consumable
consumable
tld.websitename.appname.referencename
com.jojodmo.blix.removeads
cleared for sale
view pricing matrix
add language
hosting content with Apple
screenshot for review
注册您的产品 ID 可能需要几个小时App Store Connect,因此请耐心等待。
App Store Connect
现在您已经在 App Store Connect 上设置了您的应用内购买信息,进入您的 Xcode 项目,然后转到应用程序管理器(方法和头文件所在位置顶部的蓝色页面状图标)单击您的应用程序在目标下(应该是第一个)然后转到一般。在底部,您应该会看到linked frameworks and libraries单击小加号并添加框架StoreKit.framework如果您不这样做,则应用内购买将 不起作用 !
linked frameworks and libraries
StoreKit.framework
如果您使用 Objective-C 作为您的应用程序的语言,您 应该跳过这五个步骤 。否则,如果您使用的是 Swift,您可以在此处关注我的 Swift 答案,或者,如果您更喜欢使用 Objective-C 作为应用内购买代码但在您的应用程序中使用 Swift,您可以执行以下操作:
.h
File
New
File...
Bridge.h
Targets
Build Settings
#import "MyObjectiveCHeaderFile.h"
MyObjectiveCHeaderFile
#import "InAppPurchase.h"
.m
现在我们将进入实际的编码。将以下代码添加到您的.h文件中:
BOOL areAdsRemoved; - (IBAction)restore; - (IBAction)tapsRemoveAds;
接下来,您需要将StoreKit框架导入到您的.m文件中,并在声明之后添加SKProductsRequestDelegate和:SKPaymentTransactionObserver``@interface
StoreKit
SKProductsRequestDelegate
SKPaymentTransactionObserver``@interface
#import <StoreKit/StoreKit.h> //put the name of your view controller in place of MyViewController @interface MyViewController() <SKProductsRequestDelegate, SKPaymentTransactionObserver> @end @implementation MyViewController //the name of your view controller (same as above) //the code below will be added here @end
现在将以下内容添加到您的.m文件中,这部分变得复杂,所以我建议您阅读代码中的注释:
//If you have more than one in-app purchase, you can define both of //of them here. So, for example, you could define both kRemoveAdsProductIdentifier //and kBuyCurrencyProductIdentifier with their respective product ids // //for this example, we will only use one product #define kRemoveAdsProductIdentifier @"put your product id (the one that we just made in App Store Connect) in here" - (IBAction)tapsRemoveAds{ NSLog(@"User requests to remove ads"); if([SKPaymentQueue canMakePayments]){ NSLog(@"User can make payments"); //If you have more than one in-app purchase, and would like //to have the user purchase a different product, simply define //another function and replace kRemoveAdsProductIdentifier with //the identifier for the other product SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kRemoveAdsProductIdentifier]]; productsRequest.delegate = self; [productsRequest start]; } else{ NSLog(@"User cannot make payments due to parental controls"); //this is called the user cannot make payments, most likely due to parental controls } } - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ SKProduct *validProduct = nil; int count = [response.products count]; if(count > 0){ validProduct = [response.products objectAtIndex:0]; NSLog(@"Products Available!"); [self purchase:validProduct]; } else if(!validProduct){ NSLog(@"No products available"); //this is called if your product id is not valid, this shouldn't be called unless that happens. } } - (void)purchase:(SKProduct *)product{ SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; [[SKPaymentQueue defaultQueue] addPayment:payment]; } - (IBAction) restore{ //this is called when the user restores purchases, you should hook this up to a button [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; } - (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { NSLog(@"received restored transactions: %i", queue.transactions.count); for(SKPaymentTransaction *transaction in queue.transactions){ if(transaction.transactionState == SKPaymentTransactionStateRestored){ //called when the user successfully restores a purchase NSLog(@"Transaction state -> Restored"); //if you have more than one in-app purchase product, //you restore the correct product for the identifier. //For example, you could use //if(productID == kRemoveAdsProductIdentifier) //to get the product identifier for the //restored purchases, you can use // //NSString *productID = transaction.payment.productIdentifier; [self doRemoveAds]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; } } } - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ for(SKPaymentTransaction *transaction in transactions){ //if you have multiple in app purchases in your app, //you can get the product identifier of this transaction //by using transaction.payment.productIdentifier // //then, check the identifier against the product IDs //that you have defined to check which product the user //just purchased switch(transaction.transactionState){ case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing"); //called when the user is in the process of purchasing, do not add any of your own code here. break; case SKPaymentTransactionStatePurchased: //this is called when the user has successfully purchased the package (Cha-Ching!) [self doRemoveAds]; //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; NSLog(@"Transaction state -> Purchased"); break; case SKPaymentTransactionStateRestored: NSLog(@"Transaction state -> Restored"); //add the same code as you did from SKPaymentTransactionStatePurchased here [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; case SKPaymentTransactionStateFailed: //called when the transaction does not finish if(transaction.error.code == SKErrorPaymentCancelled){ NSLog(@"Transaction state -> Cancelled"); //the user cancelled the payment ;( } [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; break; } } }
现在你想添加你的代码,当用户完成交易时会发生什么,在本教程中,我们使用删除添加,你必须添加你自己的代码,当横幅视图加载时会发生什么。
- (void)doRemoveAds{ ADBannerView *banner; [banner setAlpha:0]; areAdsRemoved = YES; removeAdsButton.hidden = YES; removeAdsButton.enabled = NO; [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"]; //use NSUserDefaults so that you can load whether or not they bought it //it would be better to use KeyChain access, or something more secure //to store the user data, because NSUserDefaults can be changed. //You're average downloader won't be able to change it very easily, but //it's still best to use something more secure than NSUserDefaults. //For the purpose of this tutorial, though, we're going to use NSUserDefaults [[NSUserDefaults standardUserDefaults] synchronize]; }
如果您的应用程序中没有广告,您可以使用任何其他您想要的东西。例如,我们可以将背景的颜色设为蓝色。为此,我们希望使用:
- (void)doRemoveAds{ [self.view setBackgroundColor:[UIColor blueColor]]; areAdsRemoved = YES //set the bool for whether or not they purchased it to YES, you could use your own boolean here, but you would have to declare it in your .h file [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"]; //use NSUserDefaults so that you can load wether or not they bought it [[NSUserDefaults standardUserDefaults] synchronize]; }
现在,在您的方法的某处viewDidLoad,您将要添加以下代码:
viewDidLoad
areAdsRemoved = [[NSUserDefaults standardUserDefaults] boolForKey:@"areAdsRemoved"]; [[NSUserDefaults standardUserDefaults] synchronize]; //this will load wether or not they bought the in-app purchase if(areAdsRemoved){ [self.view setBackgroundColor:[UIColor blueColor]]; //if they did buy it, set the background to blue, if your using the code above to set the background to blue, if your removing ads, your going to have to make your own code here }
现在您已经添加了所有代码,进入您的.xiborstoryboard文件,并添加两个按钮,一个表示购买,另一个表示恢复。将tapsRemoveAds IBAction连接到您刚刚制作的购买按钮,然后连接restore IBAction到恢复按钮。该restore操作将检查用户之前是否购买过应用内购买,如果他们还没有应用内购买,则免费为他们提供应用内购买。
.xib
storyboard
tapsRemoveAds
IBAction
restore
接下来,进入App Store Connect,然后单击Users and Access然后单击Sandbox Testers标题,然后单击+左侧显示的符号Testers。您可以随意输入名字和姓氏,电子邮件不必是真实的 - 您只需要能够记住它即可。输入密码(您必须记住)并填写其余信息。我建议您将Date of Birth日期设为用户年满 18 岁或以上。App Store Territory 必须 在正确的国家。接下来,注销您现有的 iTunes 帐户(您可以在完成本教程后重新登录)。
Users and Access
Sandbox Testers
Testers
Date of Birth
App Store Territory
现在,在你的 iOS 设备上运行你的应用程序,如果你尝试在模拟器上运行它,购买 总是* 会 出错,你必须在你的 iOS 设备上运行它。应用程序运行后,点击购买按钮。当系统提示您登录 iTunes 帐户时,请以我们刚刚创建的测试用户身份登录。接下来,当它要求您确认购买 99 或任何您设置的价格等级时,请对其进行 屏幕 截图,这就是您要在 App Store Connect 上使用的内容。现在取消付款。 ***screenshot for review
现在,前往App Store Connect,然后前往My Apps> the app you have the In-app purchase on> In-App Purchases。然后单击您的应用内购买,然后单击应用内购买详细信息下的编辑。完成后,将您刚刚在 iPhone 上拍摄的照片导入计算机,并将其作为屏幕截图上传以供审核,然后在审核备注中输入您的 TEST USER 电子邮件和密码。这将有助于苹果在审查过程中。
the app you have the In-app purchase on
完成此操作后,返回 iOS 设备上的应用程序,仍以测试用户帐户登录,然后单击购买按钮。这次,确认付款 别担心,这不会向您的帐户收取任何费用,测试用户帐户免费获得所有应用内购买 确认付款后,请确保用户实际购买您的产品时会发生什么发生。如果没有,那么这将是您的doRemoveAds方法的错误。同样,我建议使用将背景更改为蓝色来测试应用内购买,但这不应该是您实际的应用内购买。如果一切正常,你就可以开始了!只需确保在将新二进制文件上传到 App Store Connect 时将应用内购买包含在其中!
doRemoveAds
记录: No Products Available
No Products Available
这可能意味着四件事:
kRemoveAdsProductIdentifier
如果它第一次不起作用,请不要沮丧!不要放弃!我花了大约 5 个小时才可以让它工作,大约 10 个小时寻找正确的代码!如果您完全使用上面的代码,它应该可以正常工作。 如果您有任何问题, 请随时发表评论。
我希望这对所有希望在他们的 iOS 应用程序中添加应用内购买的人有所帮助。干杯!