应用内购买不起作用,显示无产品
In-App Purchase not working, showing No Products
我正在了解 Apple 提供的应用内购买。所以我正在关注本教程:
http://www.appcoda.com/in-app-purchase-tutorial/
我遵循了本教程中的所有步骤。首先,我创建了一个应用程序 ID,然后使用该应用程序 ID 在 iTunes 中创建了一个应用程序。然后我创建了两个产品 ID 为 "com.outlines.feature1" 和 "com.outlines.feature2" 的应用内购买,它们都是消耗品。
其余代码我只是按照上面教程的步骤
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)
}
}
}
}
没有错误,但是当我 运行 它在 iPhone 上时,控制台显示:
This is the request to be sent <SKProductsRequest: 0x15d86210>
There are no products.
Invalid ["com.outlines.feature1", "com.outlines.feature2"]
控制台未显示任何产品,但我在我的 iTunes id 中添加了两个应用程序内功能。这是屏幕截图:
谁能告诉我我做错了什么??
您的应用内购买尚未完全设置,如您所见,它们的状态为 "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.
通常我会制作带有应用内购买建议提示的屏幕截图,将其剪切并上传到 iTunesConnect。
完成后,您当前购买的状态应为“准备提交”:
P.S。新的更改需要一些时间才能生效,所以请耐心等待:)
要在您的设备上测试 IAP,您不需要提交屏幕截图。只有在提交应用程序时才需要它。
确保您可以对以下每个问题回答“是”:
- 您是否为您的 App ID 启用了应用内购买?
- 您是否检查过您的产品是否已获准销售?
- 您项目的 .plist Bundle ID 与您的 App ID 匹配吗?
- 您是否为新的 App ID 生成并安装了新的配置文件?
- 您是否已将您的项目配置为使用此新配置文件进行代码签名?
- 您在发出 SKProductRequest 时是否使用了完整的产品 ID?
- 将您的产品添加到 iTunes Connect 后,您等待了几个小时了吗?
- 您是否尝试过从您的设备中删除该应用程序并重新安装?
- 您的设备是否已越狱?如果是这样,您需要恢复越狱以使 IAP 正常工作。
如果您对这些问题中的任何一个回答“否”,那就是您的问题。
您正在使用 tableView,请确保您还设置了要在单元格中加载的正确参数。可能您的问题与表视图有关。
我终于解决了。代码和应用内购买制作过程都没有错误。之前提到的上传快照的解决方案也不是问题。
问题是协议、税收和烘焙中的合同。教程中没有提到,但我们需要在iTunes中的Agreements, Tax and Banking中完成一份合同,我没有做过。填写合同表格后,将对其进行处理。然后合同将生效,然后在 iTunes 中创建的应用程序内购买将被识别。
您需要在 productID 字段中包含完整的字符串 com.product.productID。该界面让您相信您只需要最后一部分:productID,但它对我不起作用,直到我使用整个显式 ID 重新创建新的应用内购买:(
可能与前一天接受tax/banking有关。
我正在了解 Apple 提供的应用内购买。所以我正在关注本教程: http://www.appcoda.com/in-app-purchase-tutorial/
我遵循了本教程中的所有步骤。首先,我创建了一个应用程序 ID,然后使用该应用程序 ID 在 iTunes 中创建了一个应用程序。然后我创建了两个产品 ID 为 "com.outlines.feature1" 和 "com.outlines.feature2" 的应用内购买,它们都是消耗品。 其余代码我只是按照上面教程的步骤
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)
}
}
}
}
没有错误,但是当我 运行 它在 iPhone 上时,控制台显示:
This is the request to be sent <SKProductsRequest: 0x15d86210>
There are no products.
Invalid ["com.outlines.feature1", "com.outlines.feature2"]
控制台未显示任何产品,但我在我的 iTunes id 中添加了两个应用程序内功能。这是屏幕截图:
谁能告诉我我做错了什么??
您的应用内购买尚未完全设置,如您所见,它们的状态为 "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.
通常我会制作带有应用内购买建议提示的屏幕截图,将其剪切并上传到 iTunesConnect。
完成后,您当前购买的状态应为“准备提交”:
P.S。新的更改需要一些时间才能生效,所以请耐心等待:)
要在您的设备上测试 IAP,您不需要提交屏幕截图。只有在提交应用程序时才需要它。
确保您可以对以下每个问题回答“是”:
- 您是否为您的 App ID 启用了应用内购买?
- 您是否检查过您的产品是否已获准销售?
- 您项目的 .plist Bundle ID 与您的 App ID 匹配吗?
- 您是否为新的 App ID 生成并安装了新的配置文件?
- 您是否已将您的项目配置为使用此新配置文件进行代码签名?
- 您在发出 SKProductRequest 时是否使用了完整的产品 ID?
- 将您的产品添加到 iTunes Connect 后,您等待了几个小时了吗?
- 您是否尝试过从您的设备中删除该应用程序并重新安装?
- 您的设备是否已越狱?如果是这样,您需要恢复越狱以使 IAP 正常工作。
如果您对这些问题中的任何一个回答“否”,那就是您的问题。
您正在使用 tableView,请确保您还设置了要在单元格中加载的正确参数。可能您的问题与表视图有关。
我终于解决了。代码和应用内购买制作过程都没有错误。之前提到的上传快照的解决方案也不是问题。
问题是协议、税收和烘焙中的合同。教程中没有提到,但我们需要在iTunes中的Agreements, Tax and Banking中完成一份合同,我没有做过。填写合同表格后,将对其进行处理。然后合同将生效,然后在 iTunes 中创建的应用程序内购买将被识别。
您需要在 productID 字段中包含完整的字符串 com.product.productID。该界面让您相信您只需要最后一部分:productID,但它对我不起作用,直到我使用整个显式 ID 重新创建新的应用内购买:(
可能与前一天接受tax/banking有关。