一尘不染

如何将应用内购买添加到iOS应用?

swift

如何将应用内购买添加到iOS应用?所有细节都是什么,是否有示例代码?

这意味着可以将各种应用内购买添加到iOS应用中


阅读 323

收藏
2020-07-07

共1个答案

一尘不染

迅捷的用户

Swift用户可以查看有关此问题的My SwiftAnswer。或者,查看YedidyaReiss的Answer,它将这个Objective-C代码转换为Swift。

Objective-C用户

该答案的其余部分用Objective-C编写

App Store连接

  1. 转到appstoreconnect.apple.com并登录
  2. 点击My Apps然后点击您想要添加购买的应用程序
  3. 单击Features标题,然后In-App Purchases在左侧选择
  4. 点击+中间的图标
  5. 在本教程中,我们将添加应用内购买来删除广告,因此请选择non-consumable。如果您要向用户发送实物商品,或给他们一些可以多次购买的东西,则可以选择consumable
  6. 对于参考名称,请输入您想要的名称(但请确保您知道它是什么)
  7. 对于产品ID,tld.websitename.appname.referencename此方法效果最好,例如,您可以使用com.jojodmo.blix.removeads
  8. 选择cleared for sale,然后选择价格层为1(99¢)。第2层的价格为1.99美元,第3层的价格为2.99美元。如果您单击“ view pricing matrix我建议您使用第1层”,则完整列表可用。因为这通常是任何人为删除广告所付的最高价。
  9. 单击蓝色add language按钮,然后输入信息。这将全部显示给客户,所以不要放任何您不希望他们看到的东西
  10. 对于hosting content with Apple选择
  11. 您可以将复习笔记空白 FOR NOW
  12. 跳过screenshot for review FOR NOW ,一切我们跳过我们会回来。
  13. 点击“保存”

您的产品ID可能要花几个小时才能注册App Store Connect,因此请耐心等待。

设置项目

现在,您已经在App Store
Connect上设置了应用程序内购买信息,进入Xcode项目,然后转到应用程序管理器(方法和头文件位于顶部的蓝色页面状图标),单击将您的应用置于目标下(应该是第一个),然后进入常规状态。在底部,你应该可以看到linked frameworks and libraries单击小加号,并添加框架StoreKit.framework。如果你不这样做,应用程序内购买将
工作!

如果您将Objective-C用作应用程序的语言, 则应跳过这五个步骤
。否则,如果您使用的是Swift,则可以在此处针对我的问题回答“我的斯威夫特”,或者,如果您更喜欢在应用内购买代码中使用Objective-C,但在应用中使用的是Swift,则可以执行以下操作:

  1. 创建一个新.h的打算(头)文件File> New> File...Command ⌘+ N)。.h在本教程的其余部分中,此文件将称为“您的文件”。

  2. 出现提示时,点击 创建桥接标题 。这将是我们的桥接头文件。如果你 提示,请转到步骤3.如果您 提示,请跳过步骤3,直接进入第4步。

  3. 在主项目文件夹中创建另一个.h文件Bridge.h,然后转到“应用程序管理器”(类似于蓝色页面的图标),然后在该Targets部分中选择您的应用程序,然后单击“确定” Build Settings。找到显示“ Swift Compiler-代码生成” 的选项,然后将“ Objective-C桥接头” 选项设置为Bridge.h

  4. 在桥接头文件中,添加line #import "MyObjectiveCHeaderFile.h",其中MyObjectiveCHeaderFile是您在第一步中创建的头文件的名称。因此,例如,如果您将头文件命名为 InAppPurchase.h ,则可以将行添加#import "InAppPurchase.h"到桥头文件中。

  5. 创建一个新的Objective-C的方法(.m通过转到)文件File> New> File...Command ⌘+ N)。将其命名为与在步骤1中创建的头文件相同的名称。例如,如果您在步骤1 InAppPurchase.h中 调用了该文件,则将其命名为这个新文件 InAppPurchase.m.m在本教程的其余部分中,此文件将称为“您的文件”。

编码

现在,我们将开始实际的编码。将以下代码添加到您的.h文件中:

BOOL areAdsRemoved;

- (IBAction)restore;
- (IBAction)tapsRemoveAds;

接下来,您需要将StoreKit框架导入.m文件中,SKProductsRequestDelegateSKPaymentTransactionObserver@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方法中的某处,您将要添加以下代码:

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
}

现在您已经添加了所有代码,进入您的.xibstoryboard文件,并添加了两个按钮,一个表示购买,另一个表示恢复。将挂钩tapsRemoveAds
IBAction到您刚创建的购买按钮,并将挂钩restore
IBAction到恢复按钮。该restore操作将检查用户是否以前购买了应用程序内购买,如果尚未购买,则免费为他们提供应用程序内购买。

提交审查

接下来,进入App Store Connect,单击,Users and Access然后单击Sandbox Testers标题,然后单击+左侧显示的符号Testers。您可以随意输入名字和姓氏,并且电子邮件不一定是真实的-
您只需要能够记住它即可。输入密码(您必须记住该密码)并填写其余信息。我建议您指定Date of Birth一个使用户年满18岁的日期。App Store Territory HAS 是在正确的国家。接下来,注销您现有的iTunes帐户(您可以在本教程后重新登录)。

现在,你的iOS设备上运行应用程序,如果你试图在模拟器上运行它,这次收购将 永远 错误,你
你的iOS设备上运行。应用运行后,点击购买按钮。当提示您登录iTunes帐户时,以我们刚刚创建的测试用户身份登录。接下来,当它要求您确认购买99美分或您设置的价格等级时,请
抓住它的屏幕快照, 这是您打算screenshot for review在App Store Connect上使用的内容。现在取消付款。

现在,进入App Store的连接,然后去My Apps> the app you have the In-app purchase on> In-App Purchases。然后,点击您的应用内购买,然后点击应用内购买详细信息下方的修改。完成此操作后,将刚刚在iPhone上拍摄的照片导入到计算机中,并将其上传为屏幕快照以供审阅,然后在审阅说明中输入您的
TEST USER 电子邮件和密码。这将有助于苹果进行审核。

完成此操作后,返回到iOS设备上的应用程序,仍以测试用户帐户身份登录,然后单击购买按钮。这次,确认付款
不用担心,这不会向您的帐户收取任何费用,测试用户帐户可免费获得所有应用程序内购买。
确认付款后,请确保用户实际购买产品时会发生什么发生。如果不是,那将是您的doRemoveAds方法的错误。同样,我建议您将背景更改为蓝色以测试应用内购买,但是这不应该是您实际的应用内购买。如果一切正常,您一切顺利!将其上传到App
Store Connect时,只需确保将应用程序内购买包括在您的新二进制文件中!


以下是一些常见错误:

已记录: No Products Available

这可能意味着四件事:

  • 您未在代码中输入正确的应用内购买ID(kRemoveAdsProductIdentifier上述代码中的标识符)
  • 您尚未清除要在App Store Connect上出售的应用内购买商品
  • 您没有等待在App Store Connect中注册应用程序内购买ID 。等待创建ID几个小时,您的问题应得到解决。
  • 您尚未完成填写协议,税收和银行信息。

如果第一次无法使用,请不要沮丧!不要放弃!我花了大约5个小时的时间才能完成此工作,大约花了10个小时来寻找正确的代码!如果您完全使用上面的代码,它应该可以正常工作。如有任何疑问
请随时发表评论。

我希望这对希望将应用程序内购买添加到其iOS应用程序的所有人有所帮助。干杯!

2020-07-07