这次我的问题是,我确实创建了一个应用内购买方法,购买 2 个产品,这是我第一次,我确实从 raywenderlich [1] 的教程中学习:http ://www.raywenderlich.com/21081 /introduction-to-in-app-purchases-in-ios-6-tutorial,[2]:http://xcodenoobies.blogspot.com/2012/04/implementing-inapp-purchase-in-xcode.html和[ _ 3]:http ://www.techotopia.com/index.php/An_iPhone_iOS_6_In-App_Purchase_Tutorial,问题是在开发我的应用程序时,我在模拟器测试器中创建了帐户并完美运行,没有任何错误我在真实设备中进行了测试并且运行完美,但是当我的应用程序进入应用商店并获得批准时,我确实下载了应用程序,我确实将它安装到我的 iphone 并且两种方法都不起作用,不让我购买或恢复,甚至没有显示“使用苹果 ID”、“创建新苹果 ID”、“取消”等消息对话框,按照教程制作它的代码是:
//--- in viewcontroller---//
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray * productIdentifiers = [[NSArray alloc] initWithObjects:INAPP1_ID,INAPP2_ID, nil];
NSMutableArray * inAppPurchases = [InAppPurchase initWithProductIdentifiers:productIdentifiers delegate:self];
NSString * msg = nil;
if (inAppPurchases != nil)
{
NSLog(@"created %d in-app-purchase objects...", inAppPurchases.count);
inAppPurchase_ProductPRIMERO = [inAppPurchases objectAtIndex:0];
[inAppPurchase_ProductPRIMERO setVerbose:FALSE];
inAppPurchase_ProductPRIMERO.progressUploadPurchase = [[MBProgressHUD alloc]initWithView:self.view];
[self.view addSubview: inAppPurchase_ProductPRIMERO.progressUploadPurchase];
inAppPurchase_ProductPRIMERO.progressUploadPurchase.mode = MBProgressHUDModeIndeterminate;
inAppPurchase_ProductPRIMERO.progressUploadPurchase.labelText = @"Buying...";
msg = [NSString stringWithFormat:@"Product One productId: %@", inAppPurchase_ProductPRIMERO.productId];
NSLog(@"%@", msg);
inAppPurchase_ProductSEGUNDO = [inAppPurchases objectAtIndex:1];
[inAppPurchase_ProductSEGUNDO setVerbose:FALSE];
inAppPurchase_ProductSEGUNDO.progressUploadPurchase = [[MBProgressHUD alloc]initWithView:self.view];
[self.view addSubview: inAppPurchase_ProductSEGUNDO.progressUploadPurchase];
inAppPurchase_ProductSEGUNDO.progressUploadPurchase.mode = MBProgressHUDModeIndeterminate;
inAppPurchase_ProductSEGUNDO.progressUploadPurchase.labelText = @"Buying...";
msg = [NSString stringWithFormat:@"Product Two productId %@", inAppPurchase_ProductSEGUNDO.productId];
NSLog(@"%@", msg);
} else {
msg = @"Error creating in-app purchases objects!";
}
NSLog(@"in ViewDidLoad doYouDidBuyPRIMERO %s", doYouDidBuyPRIMERO ? "true" : "false");
NSLog(@"in ViewDidLoad doYouDidBuySEGUNDO %s", doYouDidBuySEGUNDO ? "true" : "false");
}
-(IBAction)BuyPRIMERO:(id)sender
{
alreadyPurchased = [inAppPurchase_ProductPRIMERO alreadyPurchased];
NSLog(@"%c",alreadyPurchased);
if (!alreadyPurchased)
[inAppPurchase_ProductPRIMERO purchaseProduct];
}
-(IBAction)RestoreBuyPRIMERO:(id)sender
{
[inAppPurchase_ProductPRIMERO restorePurchase];
}
-(IBAction)BuySEGUNDO:(id)sender
{
alreadyPurchased = [inAppPurchase_ProductSEGUNDO alreadyPurchased];
NSLog(@"%c",alreadyPurchased);
if (!alreadyPurchased)
[inAppPurchase_ProductSEGUNDO purchaseProduct];
}
-(IBAction)RestoreBuySEGUNDO:(id)sender
{
[inAppPurchase_ProductSEGUNDO restorePurchase];
}
- (void)requestedProduct:(InAppPurchase *)iap identifier:(NSString*)productId name:(NSString*)productName price:(NSString*)productPrice description:(NSString*)productDescription {
NSString * _msg = nil;
if (iap == inAppPurchase_ProductPRIMERO)
{
_msg = [NSString stringWithFormat:@"Product One is valid %@ price: %@", productName, [iap getValidProductLocalizedPrice]];
NSLog(@"localized price is %@ (id is %@)", [iap getValidProductLocalizedPrice], [iap getValidProductId]);
NSString *PRIMERO =[iap getValidProductLocalizedTitle];
NSLog(@"Title: %@",PRIMERO);
NSString *pricePRIMERO = [iap getValidProductLocalizedPrice];
NSString *titlePRIMERO = [NSString stringWithFormat:@"Buy %@ %@",PRIMERO,pricePRIMERO];
PRIMEROFunctionButton.titleLabel.text = titlePRIMERO;
} else if (iap == inAppPurchase_ProductSEGUNDO)
{
_msg = [NSString stringWithFormat:@"Product Two is valid %@ price: %@", productName, [iap getValidProductLocalizedPrice]];
NSLog(@"localized price is %@ (id is %@)", [iap getValidProductLocalizedPrice], [iap getValidProductId]);
NSString *SEGUNDO =[iap getValidProductLocalizedTitle];
NSLog(@"Title: %@",SEGUNDO);
NSString *priceIcons = [iap getValidProductLocalizedPrice];
NSString *titleIcons = [NSString stringWithFormat:@"Buy %@ %@",SEGUNDO,priceSEGUNDO];
SEGUNDOButton.titleLabel.text = titleSEGUNDO
;
} else {
}
}
- (void)successfulPurchase:(InAppPurchase*)iap restored:(bool)isRestore identifier:(NSString*)productId receipt:(NSData*)transactionReceipt
{
NSString * statusMsg = nil;
if (iap == inAppPurchase_ProductPRIMERO)
{
if (isRestore)
{
statusMsg = [NSString stringWithFormat:@"Restored purchase of Product One productId: %@", productId];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"Purchase Restore Completed" message:statusMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
if ([iap isPurchased])
{
doYouDidBuyPRIMERO = YES;
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DO_YOU_DID_BUY_PRIMERO"];
NSLog(@"doYouDidBuyPRIMERO %s", doYouDidBuyPRIMERO ? "true" : "false");
[self HideCancelBuyPRIMERO];
}
[inAppPurchase_ProductPRIMERO.progressUploadPurchase hide:YES];
} else {
statusMsg = [NSString stringWithFormat:@"Purchased Product One productId: %@", productId];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"Purchase Completed" message:statusMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
if ([iap isPurchased])
{
doYouDidBuyPRIMERO = YES;
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DO_YOU_DID_BUY_PRIMERO"];
NSLog(@"doYouDidBuyPRIMERO %s", doYouDidBuyPRIMERO ? "true" : "false");
[self HideCancelBuyPRIMERO];
}
[inAppPurchase_ProductPRIMERO.progressUploadPurchase hide:YES];
}
} else if (iap == inAppPurchase_ProductSEGUNDO) {
if (isRestore)
{
statusMsg = [NSString stringWithFormat:@"Restored purchase of Product Two productId: %@", productId];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"Purchase Restore Completed" message:statusMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
if ([iap isPurchased])
{
doYouDidBuySEGUNDO = YES;
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DO_YOU_DID_BUY_SEGUNDO"];
NSLog(@"doYouDidBuySEGUNDO %s", doYouDidBuySEGUNDO ? "true" : "false");
[self HideCancelBuySEGUNDO];
}
[inAppPurchase_ProductSEGUNDO.progressUploadPurchase hide:YES];
} else {
statusMsg = [NSString stringWithFormat:@"Purchased Product Two productId: %@", productId];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"Purchase Completed" message:statusMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
if ([iap isPurchased])
{
doYouDidBuySEGUNDO = YES;
[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DO_YOU_DID_BUY_SEGUNDO"];
NSLog(@"doYouDidBuySEGUNDO %s", doYouDidBuySEGUNDO ? "true" : "false");
[self HideCancelBuySEGUNDO];
}
[inAppPurchase_ProductSEGUNDO.progressUploadPurchase hide:YES];
}
} else {
}
}
- (void)failedPurchase:(InAppPurchase*)iap error:(NSInteger)errorCode message:(NSString*)errorMessage {
NSString * statusMsg = nil;
if (iap == inAppPurchase_ProductPRIMERO)
{
statusMsg = [NSString stringWithFormat:@"Failed purchased for Product One!\Error code: %d Error message: %@", errorCode, errorMessage];
NSLog(@"%@",statusMsg);
}else if (iap == inAppPurchase_ProductSEGUNDO) {
statusMsg = [NSString stringWithFormat:@"Failed purchased for Product Two!\nError code: %d Error message: %@", errorCode, errorMessage];
NSLog(@"%@",statusMsg);
} else {
}
}
- (void)incompleteRestore:(InAppPurchase*)iap {
NSString * statusMsg = nil;
if (iap == inAppPurchase_ProductPRIMERO) {
statusMsg = @"Incomplete restore for Product One!";
NSLog(@"%@",statusMsg);
} else if (iap == inAppPurchase_ProductSEGUNDO) {
statusMsg = @"Incomplete restore for Product Two!";
NSLog(@"%@",statusMsg);
} else {
}
}
- (void)failedRestore:(InAppPurchase*)iap error:(NSInteger)errorCode message:(NSString*)errorMessage {
NSString * statusMsg = nil;
if (iap == inAppPurchase_ProductPRIMERO) {
statusMsg = @"Failed restore for Product One";
NSLog(@"%@",statusMsg);
} else if (iap == inAppPurchase_ProductSEGUNDO) {
statusMsg = @"Failed restored for Product Two!";
NSLog(@"%@",statusMsg);
} else {
}
}
// AND IN APP PURCHASE HELPER .m
#import "InAppPurchase.h"
@implementation InAppPurchase
@synthesize delegate;
@synthesize validProduct;
@synthesize productId;
@synthesize progressUploadPurchase;
+ (NSMutableArray *)initWithProductIdentifiers:(NSArray *)productIdentifiers delegate:(id<InAppPurchaseDelegate>)_delegate {
NSMutableArray * iapPurchaseArray = nil;
if (productIdentifiers != nil) {
InAppPurchase * purchase = nil;
NSString * productIdentifier = nil;
iapPurchaseArray = [[NSMutableArray alloc] initWithCapacity:productIdentifiers.count];
for (int i = 0; i < productIdentifiers.count; i++) {
productIdentifier = [productIdentifiers objectAtIndex:i];
purchase = [[InAppPurchase alloc] initWithProductId:productIdentifier delegate:_delegate];
[iapPurchaseArray addObject:purchase];
}
}
return iapPurchaseArray;
}
+ (InAppPurchase *)initWithProductIdentifier:(NSString *)productIdentifier delegate:(id<InAppPurchaseDelegate>)_delegate {
InAppPurchase * purchase = nil;
if (productIdentifier != nil)
purchase = [[InAppPurchase alloc] initWithProductId:productIdentifier delegate:_delegate];
return purchase;
}
+ (InAppPopoverView *)showPurchasePopover:(NSArray *)purchases atPoint:(CGPoint)point inView:(UIView *)view withTitle:(NSString *)title includeRestore:(BOOL)includeRestore delegate:(id<InAppPopoverViewDelegate>)delegate {
InAppPopoverView * inAppPopoverView = nil;
if (purchases != nil && purchases.count > 0) {
NSMutableArray * stringArray = [[NSMutableArray alloc] init];
InAppPurchase * inAppPurchase = nil;
NSString * _productTitle = nil;
NSString * localizedPrice = nil;
BOOL wrongClassObject = FALSE;
BOOL alreadyPurchased = FALSE;
for (int i = 0; i < purchases.count; i++) {
inAppPurchase = [purchases objectAtIndex:i];
if ([inAppPurchase isKindOfClass:InAppPurchase.class])
{
if ([inAppPurchase isValidProduct] == FALSE) {
NSLog(@"Your purchases NSArray contains some non InAppPurchase that has not been validated! Please check!");
_productTitle = [NSString stringWithFormat:@"%@ not validated yet!", inAppPurchase.productId];
} else {
_productTitle = [inAppPurchase getValidProductLocalizedTitle];
alreadyPurchased = [inAppPurchase alreadyPurchased];
if (alreadyPurchased) {
localizedPrice = [inAppPurchase getValidProductLocalizedPrice];
if ([InAppPurchase isRunningIPad])
_productTitle = [_productTitle stringByAppendingFormat:@" (already purchased for %@)", localizedPrice];
else
_productTitle = [_productTitle stringByAppendingFormat:@" (%@)", localizedPrice];
} else
_productTitle = [NSString stringWithFormat:@"Buy %@", [inAppPurchase getValidProductLocalizedTitle]];
}
[stringArray addObject:_productTitle];
} else
wrongClassObject = TRUE;
}
if (wrongClassObject)
NSLog(@"Your purchases NSArray contains some non InAppPurchase class objects! Please check!");
else {
if (includeRestore) {
// last add 'Restore Purchase' which is required by Apple AppStore so good idea to add or have available elsewhere
[stringArray addObject:@"Restore Purchases"];
}
inAppPopoverView = [InAppPopoverView showPopoverAtPoint:point inView:view withTitle:title withStringArray:stringArray delegate:delegate];
}
} else {
NSLog(@"nil InAppPurchases array provided!");
}
return inAppPopoverView;
}
+ (BOOL)hasAlreadyPurchased:(NSString *)productId {
BOOL result = FALSE;
if (productId != nil)
result = [[NSUserDefaults standardUserDefaults] boolForKey:productId];
return result;
}
- (id)initWithProductId:(NSString *)_productId delegate:(id<InAppPurchaseDelegate>)_delegate {
if ((self = [super init])) {
self.productId = _productId;
self.delegate = _delegate;
purchased = FALSE;
restored = FALSE;
verbose = FALSE;
NSLog(@"purchased %s", purchased? "true" : "false");
[self requestProduct:self.productId];
purchased = [[NSUserDefaults standardUserDefaults] boolForKey:self.productId];
NSLog(@"purchased %s", purchased? "true" : "false");
if (purchased)
NSLog(@"The product %@ is already purchased.", self.productId);
NSLog(@"purchased %s", purchased? "true" : "false");
}
return self;
}
- (void)setVerbose:(BOOL)_verbose {
verbose = _verbose;
}
- (BOOL)canMakePayments {
return [SKPaymentQueue canMakePayments];
}
- (BOOL)alreadyPurchased {
return [self isPurchased];
NSLog(@"purchased %s", purchased? "true alreadyPurchased" : "false alreadyPurchased");
}
- (BOOL)isPurchased
{
return purchased;
NSLog(@"purchased %s", purchased? "true" : "false");
}
- (BOOL)isRestored {
return restored;
}
- (BOOL)isValidProduct {
BOOL result = FALSE;
if (self.validProduct != nil)
result = TRUE;
return result;
}
- (NSString *)getProductId {
return self.productId;
}
- (SKProduct *)getValidProduct {
return self.validProduct;
}
- (NSString *)getValidProductId {
NSString * _id = nil;
if ([self isValidProduct])
_id = [self.validProduct productIdentifier];
return _id;
}
- (NSString *)getValidProductLocalizedDescription {
NSString * description = nil;
if ([self isValidProduct])
description = [self.validProduct localizedDescription];
return description;
}
- (NSString *)getValidProductLocalizedTitle {
NSString * title = nil;
if ([self isValidProduct])
title = [self.validProduct localizedTitle];
return title;
}
- (NSString *)getValidProductLocalizedPrice {
NSString * priceStr = nil;
if ([self isValidProduct]) {
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:self.validProduct.priceLocale];
priceStr = [numberFormatter stringFromNumber:self.validProduct.price];
}
return priceStr;
}
- (BOOL)requestProduct:(NSString *)_id {
if (_id != nil)
{
if (verbose)
NSLog(@"InAppPurchase requestProduct: %@", _id);
if ([SKPaymentQueue canMakePayments])
{
SKProductsRequest * prodRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:_id]];
prodRequest.delegate = self;
[prodRequest start];
return YES;
} else {
if (verbose)
NSLog(@"InAppPurchase requestProduct: IAP Disabled");
return NO;
}
} else {
if (verbose)
NSLog(@"InAppPurchase requestProduct: productId = NIL");
return NO;
}
}
- (BOOL)purchaseProduct {
return [self purchaseProduct:self.validProduct];
}
- (BOOL)purchaseProduct:(SKProduct*)requestedProduct
{
NSLog(@"InAppPurchase purchaseProduct: %@", requestedProduct.productIdentifier);
if (requestedProduct != nil)
{
if (verbose)
NSLog(@"InAppPurchase purchaseProduct: %@", requestedProduct.productIdentifier);
if ([SKPaymentQueue canMakePayments])
{
SKPayment *paymentRequest = [SKPayment paymentWithProduct:requestedProduct];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:paymentRequest];
return YES;
} else {
if (verbose)
NSLog(@"InAppPurchase purchaseProduct: IAP Disabled");
return NO;
}
} else {
if (verbose)
NSLog(@"InAppPurchase purchaseProduct: SKProductis nil");
return NO;
}
}
- (BOOL)restorePurchase {
if (verbose)
NSLog(@"InAppPurchase restorePurchase");
if ([SKPaymentQueue canMakePayments])
{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
return YES;
} else {
return NO;
}
}
- (void)clearUserDefaultsSetting {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:self.productId];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
self.validProduct = nil;
int count = [response.products count];
if (count > 0) {
self.validProduct = [response.products objectAtIndex:0];
if (verbose)
NSLog(@"got valid product %@ for product id %@", self.validProduct, productId);
}
if (self.validProduct) {
if ([delegate respondsToSelector:@selector(requestedProduct:identifier:name:price:description:)])
[delegate requestedProduct:self identifier:self.validProduct.productIdentifier name:self.validProduct.localizedTitle price:[self.validProduct.price stringValue] description:self.validProduct.localizedDescription];
} else {
if ([delegate respondsToSelector:@selector(requestedProduct:identifier:name:price:description:)])
[delegate requestedProduct:self identifier:nil name:nil price:nil description:nil];
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
NSLog(@"1");
[self.progressUploadPurchase show:YES];
break;
case SKPaymentTransactionStatePurchased:
purchased = TRUE;
NSLog(@"2");
NSLog(@"purchased %s", purchased? "true" : "false");
purchased product.
if ([delegate respondsToSelector:@selector(successfulPurchase:restored:identifier:receipt:)])
[delegate successfulPurchase:self restored:NO identifier:transaction.payment.productIdentifier receipt:transaction.transactionReceipt];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:transaction.payment.productIdentifier];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
case SKPaymentTransactionStateRestored:
purchased = TRUE;
NSLog(@"3");
NSLog(@"purchased %s", purchased? "true" : "false");
if (!restored && [delegate respondsToSelector:@selector(successfulPurchase:restored:identifier:receipt:)])
[delegate successfulPurchase:self restored:YES identifier:transaction.payment.productIdentifier receipt:transaction.transactionReceipt];
restored = TRUE;
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:transaction.payment.productIdentifier];
[[NSUserDefaults standardUserDefaults] synchronize];
break;
case SKPaymentTransactionStateFailed:
NSLog(@"4");
[self.progressUploadPurchase hide:YES];
if (transaction.error.code != SKErrorPaymentCancelled)
{
if ([delegate respondsToSelector:@selector(failedPurchase:error:message:)])
[delegate failedPurchase:self error:transaction.error.code message:transaction.error.localizedDescription];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions {
if (verbose)
NSLog(@"InAppPurchase removedTransactions");
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
if (verbose)
NSLog(@"InAppurchase paymentQueueRestoreCompletedTransactionsFinished");
if ([queue.transactions count] == 0) {
if (verbose)
NSLog(@"InAppPurchase restore queue.transactions count == 0");
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
if ([delegate respondsToSelector:@selector(incompleteRestore:)])
[delegate incompleteRestore:self];
} else {
if (verbose)
NSLog(@"InAppPurchase restore queue.transactions available");
for (SKPaymentTransaction *transaction in queue.transactions) {
if (verbose)
NSLog(@"InAppPurchase restore queue.transactions - transaction data found");
if (!restored && [delegate respondsToSelector:@selector(successfulPurchase:restored:identifier:receipt:)])
[delegate successfulPurchase:self restored:YES identifier:transaction.payment.productIdentifier receipt:transaction.transactionReceipt];
restored = TRUE;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
if (verbose)
NSLog(@"InAppPurchase restoreCompletedTransactionsFailedWithError");
if ([delegate respondsToSelector:@selector(failedRestore:error:message:)])
[delegate failedRestore:self error:error.code message:error.localizedDescription];
}
#pragma mark - Internal Methods & Events
+ (BOOL)isRunningIPad {
if ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)]) {
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
}
return NO;
}
@end
请帮帮我,如果我的代码错误或不完整,请告诉我在哪里!!,我确实从 stackoverflow 看到了另一个答案,但是,等待 48 小时,或者重置我的设备,我找不到错误,或者找不到对这个问题的任何解释,在登上 apsstore 之前工作同一个项目似乎很奇怪,如果它是同一个工作项目,当我下载应用程序时你注意到的差异再次感谢来自玻利维亚的家伙和 GRETTINGS ROCK ON!