【问题标题】:In-App Purchase with an IBAction / Button使用 IBAction / 按钮进行应用内购买
【发布时间】:2013-01-05 03:54:08
【问题描述】:

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

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

 + (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];
     }

所以我正在尝试制作一个简单的按钮来触发操作,如下所示:

 - (IBAction)button10Coins:(id)sender {

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

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

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

谢谢!!!

【问题讨论】:

    标签: ios xcode in-app-purchase


    【解决方案1】:

    如果你完成了所有的连接工作并且在代码下面添加框架肯定会起作用:

    define kStoredData @"应用内购买对象"(这是对象声明)

    - (void) requestProductData
    {
        if(countphotoval==2)
        {
            phonetext.text=@"";
            countrycode.text=@"";
            nametext.text=@"";
            Emailtext.text=@"";
            photocounter=0;
            image1.image=[UIImage imageNamed:@"image-box.png"];
            image2.image=[UIImage imageNamed:@"image-box.png"];
            labelimage.text=@"Image";
            addbuttonforpicker.userInteractionEnabled=true;
            addbuttonforpicker2.userInteractionEnabled=false;
            countphotoval=0;
        }
        request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: @"object of inapp purchase"]];
        request.delegate = self;
        
        [request start];
        
          
    }
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    {
        NSArray *myProduct = response.products;
        
        
        // populate UI
      
        }
    
    
    -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
        for (SKPaymentTransaction *transaction in transactions) {
            NSLog(@"transaction array-->%@",transaction.description);
            switch (transaction.transactionState) {
                case SKPaymentTransactionStatePurchasing:
                    
                    // show wait view here
                    //statusLabel.text = @"Processing...";
                    break;
                    
                case SKPaymentTransactionStatePurchased:
                    
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    [NSThread detachNewThreadSelector:@selector(startActivityindicatore) toTarget:self withObject:nil];
                    [self fordataupload];
                    
                    break;
                    
                case SKPaymentTransactionStateRestored:
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    break;
                    
                case SKPaymentTransactionStateFailed:
                    
                    if (transaction.error.code != SKErrorPaymentCancelled) {
                        NSLog(@"Error payment cancelled");
                        UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Sorry" message:@"Please provide correct Userid and Password" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil, nil];
                        [alert show];
                        [alert release];
                        //                    [self dismissModalViewControllerAnimated:YES];
                    }
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    // remove wait view here
                    // statusLabel.text = @"Purchase Error!";
                    break;
                    
                default:
                    break;
            }
        }
    }
    
    
    - (void) failedTransaction: (SKPaymentTransaction *)transaction
    {
        if (transaction.error.code != SKErrorPaymentCancelled)
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Something has went wrong" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
            [alert release];
    
        }
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    }
    
    - (void) restoreTransaction: (SKPaymentTransaction *)transaction
    {
        //If you want to save the transaction
        // [self recordTransaction: transaction];
        
        //Provide the new content
        // [self provideContent: transaction.originalTransaction.payment.productIdentifier];
        
        //Finish the transaction
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        
    }
    
    - (void) completeTransaction: (SKPaymentTransaction *)transaction
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Congrats!!" message:@"Your Transaction Is Completed" delegate:self cancelButtonTitle:@"Thanx!" otherButtonTitles:nil];
        [alert show];
        [alert release];
    
        //If you want to save the transaction
        // [self recordTransaction: transaction];
        
        //Provide the new content
        //[self provideContent: transaction.payment.productIdentifier];
        
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        
    }
    -(void)requestDidFinish:(SKRequest *)request1  
    {  
        [self stopActivityindicatore];
        SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"VirtualBinocularsContest1"];
        NSLog(@"quality --->%d",payment.quantity);
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
        [request release];
    }  
    

    如果它适合你,请通知..:)

    【讨论】:

    • 谢谢,这对我有帮助。我发布了用于创建 IAP 按钮的整个代码。谢谢您的帮助! :)
    【解决方案2】:

    paymentWithProduct: 需要 SKProduct * 参数,而您传递的是 NSString。您需要将您的产品从您的 _products 数组中取出并传递给它。

    【讨论】:

    • 是的,没错。这是一个复制和粘贴问题。但这也不起作用,这不是真正的问题:)
    • @tomDev 你能看到这是否修复了警告吗?
    • 是的,这就是问题所在。我切换到更容易设置的 paymentWithProductIdentifier,它已被弃用但仍然有效。如果有人感兴趣,我发布了整个代码。感谢您的帮助!
    【解决方案3】:

    感谢在这里帮助过我的所有人!我终于成功了。

    我得到了一个不同的代码。我将尝试解释我在这里所做的一切,以便如果有人想做同样的事情。

    首先在 iOS Provisioning Portal 上创建 App ID,并在 iTunes Connect 上创建 IAP 购买。

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

    现在是代码:

    .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];
            }
        }
    } }
    

    请求产品(如果有),或者取消购买(如果没有):

    -(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]);
    }
    

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

    不要忘记在 iTunes Connect 上创建 Consumable 项目,并将 ID“com.IAPID.10coins”更改为您在那里创建的正确 ID。

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

    这是 ARC 准备好了,除了“SFHFKeychainUtils.m”,你可以尝试修复它或在该单个文件上禁用 ARC,这里是教程:http://www.leesilver.net/1/post/2011/8/disabling-arc-on-certain-files-in-xcode.html

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

    对于消耗品,就是这样!对于非消耗品,您必须添加一个 RESTORE 按钮,否则 Apple 会拒绝您。但这很容易:

    // 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 批准它:)

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

    【讨论】:

    • 它还能正常工作吗?希望在我的应用中实现 IAP,但想先检查
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多