使用IBAction / Button进行应用程序内购买 [英] In-App Purchase with an IBAction / Button

查看:102
本文介绍了使用IBAction / Button进行应用程序内购买的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Ray Wenderlich教程创建IAP(http://www.raywenderlich.com/23266/),一切正常,但我不想在我的应用程序上使用表视图,我想使用只需一个简单的IBAction按钮即可购买。

I'm using Ray Wenderlich tutorial to create IAP (http://www.raywenderlich.com/23266/) , everything works well, but I don't want to use table view on my app, I want to use just a simple IBAction button to make the purchase.

所以基本上这就是它在表格视图中的工作方式。首先确定产品:

So basically this is the way it works on the table view. First identify the products:

 + (RageIAPHelper *)sharedInstance {
     static dispatch_once_t once;
     static RageIAPHelper * sharedInstance;
     dispatch_once(&once, ^{
         NSSet * productIdentifiers = [NSSet setWithObjects:
                                       @"com.companyname.10coins",
                                       @"com.companyname.20coins",
                                       nil];
         sharedInstance = [[self alloc] initWithProductIdentifiers:productIdentifiers];
     });
     return sharedInstance;
 }

然后触发行动:

 - (void)buyButtonTapped:(id)sender {

        UIButton *buyButton = (UIButton *)sender;
        SKProduct *product = _products[buyButton.tag];

        NSLog(@"Buying %@...", product.productIdentifier);
        [[RageIAPHelper sharedInstance] buyProduct:product]; }


     - (void)buyProduct:(SKProduct *)product {

         NSLog(@"Buying %@...", product.productIdentifier);

         SKPayment * payment = [SKPayment paymentWithProduct:product];
         [[SKPaymentQueue defaultQueue] addPayment:payment];
     }

所以我试图制作一个简单的按钮来触发动作,比如这个:

So I'm trying to make a simple button to trigger the action, like this:

 - (IBAction)button10Coins:(id)sender {

     SKPayment * payment = [SKPayment paymentWithProduct:@"com.companyname.10coins"];
     [[SKPaymentQueue defaultQueue] addPayment:payment];
 }

但我收到警告不兼容的指针类型。

But I get a warning "Incompatible Pointer types".

启动后代码运行良好,我能够完成购买,唯一的问题是正确创建IBAction。有什么想法吗?

After the it starts the code works great and I'm able to finalize the purchase, the only problem is creating the IBAction properly. Any ideas?

谢谢!!!

推荐答案

感谢大家这对我有所帮助!我终于成功了。

Thanks to everyone that helped me here! I finally made it work.

我推出了不同的代码。我将尝试解释我在这里所做的一切,如果有人想要这样做。

I came out with a different code. I will try to explain everything I did here so if anyone wants to do the same.

Fist在iOS Provisioning Portal上创建一个App ID并在iTunes Connect上创建IAP Purchase 。

Fist create an App ID on iOS Provisioning Portal and create the IAP Purchase on iTunes Connect.

然后,得到这个项目: http://xcodenoobies.blogspot.com.br/2012/04/implementing-inapp-purchase-in-xcode.html 并导入SFHFKeychainUtils.h和.m文件。不要忘记将SFHFKeychainUtils.m添加到编译源(项目 - >构建阶段 - >编译源)。

Then, get this project: http://xcodenoobies.blogspot.com.br/2012/04/implementing-inapp-purchase-in-xcode.html and import the "SFHFKeychainUtils.h" and .m files. Don't forget to add the SFHFKeychainUtils.m to your Compile Sources (Project -> Build Phases - > Compile Sources).

现在代码:

.h

#import <StoreKit/StoreKit.h>

(...)

<SKProductsRequestDelegate, SKPaymentTransactionObserver, UIAlertViewDelegate> {
IBOutlet UIButton *feature2Btn;
IBOutlet UILabel *featureLabel, *statusLabel;
UIAlertView *askToPurchase;

int64_t coins;
IBOutlet UILabel * coinsLabel;

}

@property (nonatomic, retain)  UIButton *feature2Btn;
@property (nonatomic, retain)  UILabel *featureLabel, *statusLabel;
@property (nonatomic, assign)  int64_t coins;

-(IBAction)button10Coins:(id)sender;
-(BOOL)IAPItemPurchased;

.m

#import "SFHFKeychainUtils.h"

@synthesize feature2Btn, featureLabel, statusLabel, coins;
#define kStoredData @"com.IAPID.10coins"

按钮:

-(IBAction)button10Coins:(id)sender {

    askToPurchase = [[UIAlertView alloc]
                     initWithTitle:@"IAP"
                     message:@"Would you like to buy 10 coins?"
                     delegate:self
                     cancelButtonTitle:nil
                     otherButtonTitles:@"Yes", @"No", nil];
    askToPurchase.delegate = self;
    [askToPurchase show];
}

检查IAP是否可用:

#pragma mark AlertView Delegate

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {

if (alertView==askToPurchase) {
    if (buttonIndex==0) {
        // user tapped YES, but we need to check if IAP is enabled or not.
        if ([SKPaymentQueue canMakePayments]) {

            NSLog(@"IAP: Checking if IAP Available");

            SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"com.IAPID.10coins"]];

            request.delegate = self;
            [request start];


        } else {
            UIAlertView *tmp = [[UIAlertView alloc]
                                initWithTitle:@"Prohibited"
                                message:@"Parental Control is enabled, cannot make a purchase!"
                                delegate:self
                                cancelButtonTitle:nil
                                otherButtonTitles:@"Ok", nil];
            [tmp show];
        }
    }
} }

请求产品,如果可用,或取消购买,如果没有:

Request the product, if available, or cancel the purchase if not:

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{

NSLog(@"IAP: Received Response");

// remove wait view here
statusLabel.text = @"";

SKProduct *validProduct = nil;
int count = [response.products count];

if (count>0) {

    NSLog(@"IAP: Available, starting transaction");

    validProduct = [response.products objectAtIndex:0];


    SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.IAPID.10coins"];
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];


} else {

    NSLog(@"IAP: Item not found");

    UIAlertView *tmp = [[UIAlertView alloc]
                        initWithTitle:@"Internet Connection Required"
                        message:@"You must connect to a Wi-Fi  or cellular data network to perform an In-App Purchase."
                        delegate:self
                        cancelButtonTitle:nil
                        otherButtonTitles:@"Ok", nil];
    [tmp show];
} }

最后,行动:

#pragma mark StoreKit Delegate

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {

for (SKPaymentTransaction *transaction in transactions) {
    switch (transaction.transactionState) {
        case SKPaymentTransactionStatePurchasing: {

            // show wait view here
            NSLog(@"IAP: Processing...");}
            break;

        case SKPaymentTransactionStatePurchased:{

            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            // remove wait view and unlock feature 2
            statusLabel.text = @"Done!";
            UIAlertView *tmp = [[UIAlertView alloc]
                                initWithTitle:@"Completet"
                                message:@"The purchase has been completed!"
                                delegate:self
                                cancelButtonTitle:nil
                                otherButtonTitles:@"Ok", nil];

            [tmp show];


            NSError *error = nil;
            [SFHFKeychainUtils storeUsername:@"IAPNoob01" andPassword:@"whatever" forServiceName:kStoredData updateExisting:YES error:&error];

            // apply purchase action  - hide lock overlay and
            [feature2Btn setBackgroundImage:nil forState:UIControlStateNormal];

            // Get The Coins, rock, favor points, whatever:

            self.coins = coins +10;
            coinsLabel.text = [NSString stringWithFormat: @"%lld", self.coins];

        }
            break;

        case SKPaymentTransactionStateRestored:{
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            // remove wait view here
            statusLabel.text = @"";}
            break;

        case SKPaymentTransactionStateFailed:{

            if (transaction.error.code != SKErrorPaymentCancelled) {
                NSLog(@"Error payment cancelled");
            }
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            // remove wait view here
            statusLabel.text = @"Purchase Error!";}
            break;

        default:
            break;
    }
} }

不确定是否必须添加:

-(void)requestDidFinish:(SKRequest *)request {
}

-(void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"Failed to connect with error: %@", [error localizedDescription]);
}

这是有史以来最简单的代码。不确定苹果是否会批准,但它正在运作。这适用于iOS 4.3及更高版本,我认为它很棒,但没有实现收据,所以一些聪明的孩子将能够免费获得硬币。

This is the easiest code ever. Not sure if Apple will approve, but it is working. This works on iOS 4.3 and higher which I think it is great, but doesn't implement the Receipts so some smart kids will be able to get coins for free.

Don不要忘记在iTunes Connect上创建耗材项目,并使用您在那里创建的正确ID更改IDcom.IAPID.10coins。

Don't forget to create the Consumable item on iTunes Connect and change the id "com.IAPID.10coins" with the correct ID created created by you over there.

paymentWithProductIdentifier 已弃用但仍然有效,要修复它,请将其更改为paymentWithProduct并找到添加IAP ID的方法。我试过但没有成功。

"paymentWithProductIdentifier" is deprecated but still works, to fix it change it for "paymentWithProduct" and find a way to add the IAP ID. I tried but didn't succeed.

这是ARC就绪,除了SFHFKeychainUtils.m,您可以尝试修复它或禁用该单个文件上的ARC,这是教程: http://www.leesilver.net/1/post/2011/8/disabling-arc-on-certain-files-in-xcode.html

This is ARC ready, except the "SFHFKeychainUtils.m", you can try to fix it or disable ARC on that single file, here is the tutorial: http://www.leesilver.net/1/post/2011/8/disabling-arc-on-certain-files-in-xcode.html

您还必须将ScoreKit和Security框架添加到您的项目中。

You also must add the ScoreKit and Security framework to your project.

对于耗材itens,就是这样!对于非消耗品,您必须添加RESTORE按钮,否则Apple会拒绝您。但这很简单:

For consumable itens, thats it! For non-consumable you must add a RESTORE button or Apple will give you a rejection. But that's pretty easy:

// RESTORE

 - (IBAction)IAPRestore:(id)sender
 {
     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
     [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
 }


 - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
 {
     NSLog(@"Restore completed transactions finished.");
     NSLog(@" Number of transactions in queue: %d", [[queue transactions] count]);
     for (SKPaymentTransaction *trans in [queue transactions])
     {
         NSLog(@" transaction id %@ for product %@.", [trans transactionIdentifier], [[trans payment] productIdentifier]);
         NSLog(@" original transaction id: %@ for product %@.", [[trans originalTransaction] transactionIdentifier],
          [[[trans originalTransaction] payment]productIdentifier]);


    if ([[[trans payment] productIdentifier] isEqual: @"com.AppID.IAPID"]) {

        NSLog(@"Purchase Restored");

        // Do your stuff to unlock

          }

     }
     UIAlertView *tmp = [[UIAlertView alloc]
                         initWithTitle:@"Purchases Restored"
                         message:@"Your previously purchased products have been restored!"
                         delegate:self 
                         cancelButtonTitle:nil 
                         otherButtonTitles:@"OK", nil]; 

                 [tmp show];

 }

我希望这对某人有用,并且Apple批准它:)

I hope this is useful to someone and that Apple approves it :)

更新:Apple批准了它并且销售情况良好,iOS 4.3,5和6销售正在运行:)
UPDATE2:经过测试和工作在Xcode 4.6和iOS 6.1.2上完美无瑕。

UPDATE: Apple approved it and sales are coming in just fine, iOS 4.3, 5 and 6 sales are working :) UPDATE2: Tested and working flawlessly on Xcode 4.6 and iOS 6.1.2.

这篇关于使用IBAction / Button进行应用程序内购买的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆