2013-01-05 5 views
2

IAP (http://www.raywenderlich.com/23266/)를 만들기 위해 Ray Wenderlich 튜토리얼을 사용하고 있습니다. 모든 것이 잘 작동하지만 테이블을 사용하고 싶지는 않습니다. 내 앱에서보기, 구매를 위해 간단한 IBAction 버튼 만 사용하고 싶습니다.IBAction/버튼으로 인앱 구매

기본적으로 이것이 테이블보기에서 작동하는 방식입니다. 먼저 제품을 확인 :이 같은 액션을 트리거하는 간단한 버튼을 만들려고 해요 그래서

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

:

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

그런 다음 동작을 트리거

- (IBAction)button10Coins:(id)sender { 

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

그러나 "호환되지 않는 포인터 유형"이라는 경고 메시지가 나타납니다.

코드가 시작된 후 코드가 작동하고 구매를 완료 할 수있는 유일한 문제는 제대로 IBAction을 만드는 것입니다. 어떤 아이디어?

감사합니다 !!!

답변

2

나를 도와 주신 모든 분들께 감사드립니다! 나는 마침내 그것을 일하게 만들었다.

다른 코드가 나왔습니다. 나는 누군가가 똑같이하기를 원한다면 내가 여기 한 모든 것을 설명하려고 노력할 것이다.

주먹은 iOS 프로비저닝 포털에 앱 ID를 만들고 iTunes 연결에서 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" 

버튼 :

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

요청 제품을 사용할 수있는 경우, 또는 구매를하지 않을 경우 취소 :

-(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를 사용할 수있는 경우

-(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 이상에서 작동합니다. 그러나 영리하다고 생각하는 아이들은 무료로 동전을 얻을 수 있습니다.

iTunes Connect에서 Consumable 항목을 생성하고 "com.IAPID.10coins"id를 거기에서 생성 한 올바른 ID로 변경하는 것을 잊지 마십시오.

"paymentWithProductIdentifier"는 더 이상 사용되지 않지만 여전히 "paymentWithProduct"로 변경하고 IAP ID를 추가하는 방법을 찾기 위해 계속 작동합니다. 나는 시도했지만 성공하지 못했습니다. http://www.leesilver.net/1/post/2011/8/disabling-arc-on-certain-files-in-xcode.html

당신은 또한 ScoreKit 및 보안 프레임 워크를 추가해야합니다

이것은 "SFHFKeychainUtils.m"을 제외한 ARC 준비, 당신은 그것을 해결하거나 하나의 파일에 ARC를 비활성화하려고 할 수있다, 여기에 튜토리얼 귀하의 프로젝트에.

소모품 인 경우 그게 다! 소모품이 아닌 경우 RESTORE 버튼을 추가해야합니다. 그렇지 않으면 Apple에서 거부합니다. 애플이 승인 및 판매, 그냥 벌금 아이폰 OS 4.3, 5, 6 개 판매오고있다 :이 사람에게 유용하고 애플이 :)

UPDATE를 승인 할 수 있기를 바랍니다

// 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]; 

} 

:하지만 꽤 쉽게 작동 중 :) UPDATE2 : Xcode 4.6 및 iOS 6.1.2에서 완벽하게 작동하고 테스트를 마쳤습니다.

+0

아직도 잘 작동합니까? 내 앱에 IAP를 구현하려하지만 처음 확인하고 싶었습니다. – BrownEye

2

paymentWithProduct:SKProduct * 인수를 필요로하며 NSString을 전달합니다. 귀하의 제품을 _products 어레이에서 꺼내서 대신 전달해야합니다. 모든 연결 작업으로 수행하고 코드 아래에 추가 프레임 워크가 확실히 작동하는 경우

+0

네, 맞습니다. 복사 및 붙여 넣기 문제였습니다. 그러나 그것도 작동하지 않습니다, 이것은 진짜 문제가되지 않습니다 :) – tomDev

+0

@ tomDev 내 대답 –

+1

@ tomDev 편집이 당신이 경고를 수정하면 볼 수 있었나요? –

3

:

는 @ kStoredData 정의 "인앱 구매의 목적"

- (void) requestProductData 
{ 
    if(countphotoval==2) 
    { 
     [email protected]""; 
     [email protected]""; 
     [email protected]""; 
     [email protected]""; 
     photocounter=0; 
     image1.image=[UIImage imageNamed:@"image-box.png"]; 
     image2.image=[UIImage imageNamed:@"image-box.png"]; 
     [email protected]"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]; 
} 

(이 객체 선언입니다) :)

+0

고마워, 이것이 나를 도왔다. IAP 버튼을 만들 때 사용한 전체 코드를 게시했습니다. 도와 주셔서 감사합니다! :) – tomDev

+0

도움이 되었다면 내 자동 응답을위한 체크 버튼을 표시하십시오 – Ashutosh