Reputation: 810
I am learning about In-App Purchase provided by Apple. So I was following this tutorial : http://www.appcoda.com/in-app-purchase-tutorial/
I followed all the steps in this tutorial. Firstly, I created an app id,and then created an app in iTunes using that app id. Then I created two In-App purchase with product id as "com.outlines.feature1" and "com.outlines.feature2", both of them consumable. The rest of the code I simply followed the steps from the above tutorial
import UIKit
import StoreKit
protocol IAPurchaceViewControllerDelegate {
func didBuyColorsCollection(collectionIndex: Int)
}
class IAPurchaceViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SKProductsRequestDelegate, SKPaymentTransactionObserver {
@IBOutlet weak var tblProducts: UITableView!
var delegate: IAPurchaceViewControllerDelegate!
var selectedProductIndex: Int!
var transactionInProgress = false
let productIdentifiers = NSSet(array: ["com.outlines.feature1", "com.outlines.feature2"])
var product: SKProduct?
var productsArray = Array<SKProduct>()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tblProducts.delegate = self
tblProducts.dataSource = self
//checks whether the In-App feature is activated or not
requestProductInfo()
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
}
func requestProductInfo(){
if SKPaymentQueue.canMakePayments() {
let request = SKProductsRequest(productIdentifiers:
productIdentifiers as! Set<String>)
print("This is the request to be sent \(request)")
request.delegate = self
request.start()//calls productsRequest() function
}
else {
print("Cannot perform In App Purchases.")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: IBAction method implementation
@IBAction func dismiss(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
// MARK: UITableView method implementation
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productsArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("idCellProduct", forIndexPath: indexPath) as UITableViewCell
let product = productsArray[indexPath.row]
cell.textLabel?.text = product.localizedTitle
cell.detailTextLabel?.text = product.localizedDescription
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedProductIndex = indexPath.row
showActions()
tableView.cellForRowAtIndexPath(indexPath)?.selected = false
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 80.0
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) {
if response.products.count != 0 {
for product in response.products {
productsArray.append(product as SKProduct)
}
tblProducts.reloadData()
}
else {
print("There are no products.")
}
if response.invalidProductIdentifiers.count != 0 {
print("Invalid "+response.invalidProductIdentifiers.description)
}
}
func showActions() {
if transactionInProgress {
return
}
let actionSheetController = UIAlertController(title: "IAPDemo", message: "What do you want to do?", preferredStyle: UIAlertControllerStyle.ActionSheet)
let buyAction = UIAlertAction(title: "Buy", style: UIAlertActionStyle.Default) { (action) -> Void in
let payment = SKPayment(product: self.productsArray[self.selectedProductIndex] as SKProduct)
SKPaymentQueue.defaultQueue().addPayment(payment)
self.transactionInProgress = true
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (action) -> Void in
}
actionSheetController.addAction(buyAction)
actionSheetController.addAction(cancelAction)
presentViewController(actionSheetController, animated: true, completion: nil)
}
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions as [SKPaymentTransaction] {
switch transaction.transactionState {
case SKPaymentTransactionState.Purchased:
print("Transaction completed successfully.")
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
transactionInProgress = false
delegate.didBuyColorsCollection(selectedProductIndex)
case SKPaymentTransactionState.Failed:
print("Transaction Failed");
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
transactionInProgress = false
default:
print(transaction.transactionState.rawValue)
}
}
}
}
There are no errors, but the when I run it on iPhone, the console shows:
This is the request to be sent <SKProductsRequest: 0x15d86210>
There are no products.
Invalid ["com.outlines.feature1", "com.outlines.feature2"]
The console shows no products, however I have added two in-app features in my iTunes id. Here is the screenshot:
Can anyone tell me what I am doing wrong??
Upvotes: 10
Views: 15626
Reputation: 624
The accepted answer is correct.
But I want to point out, in my scenario, the reason was that I had recently renewed my Apple Developer membership, and after renewing, I had not updated the contract.
After agreeing and resubmitting the contract, my product SKUs started showing as before.
Apparently, the paid-app contract must be signed by you and Apple. This can keep the SKProductsRequest
from validating the identifiers.
Upvotes: 0
Reputation: 47348
You need to have the complete string com.product.productID in the productID field. The interface makes you believe you only need the last part : productID, but it did not work for me until I re-created new in app purchases with the entire explicit ID :(
Could be related to accepting the tax/banking on the previous day.
Upvotes: 1
Reputation: 810
I solved it finally. There were no errors in the code nor in the In-App purchase making process. The earlier solution mentioned to upload a snapshot was also not the issue.
The issue was the contract in the Agreements, Tax and Baking. It was not mentioned in the tutorial, but we need to complete a contract in the Agreements, Tax and Banking in the iTunes, which I had not done. After filling up the forms for the contract, it will be processed. Then the contract will be in effect and then the In-App Purchases created in the iTunes will be recognized.
Upvotes: 51
Reputation: 1088
For testing IAP on your device you dont need screenshot to submit. It is only needed when you are submitting app.
Make sure you can answer “Yes” to each of these questions:
If you answered “No” to any one of these questions, there’s your problem.
You are using tableView, make sure also you have set right parameters to be loaded in cell. May your problem is in connection releated to tableview.
Upvotes: 18
Reputation: 2176
Your In-App Purchases aren't fully set, as you see, they have status "Waiting for screenshot":
Before you submit your In-App Purchase for review, you must upload a screenshot. This screenshot will be for review purposes only. It will not be displayed on the App Store. Screenshots must be at least 312x390 pixels and at least 72 DPI.
Usually I make a screenshot with alert of In-App purchase suggestion, cut it and upload it ti iTunesConnect.
After doing that, you current purchases should have status Ready for Submit:
P.S. It takes some time to take new changes an effect, so be patient:)
Upvotes: 0