我正在使用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。有什么想法吗?
感谢!!!
答案 0 :(得分:3)
如果您已完成所有连接工作,并且在代码下面添加框架肯定会起作用:
- (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];
}
如果它适用于您,请通知.. :)
答案 1 :(得分:2)
paymentWithProduct:
需要一个SKProduct *
参数,而您传递的是NSString
。您需要从_products
数组中取出产品并将其传递出来。
答案 2 :(得分:2)
感谢所有帮助过我的人!我终于成功了。
我出来了一个不同的代码。我将尝试解释我在这里所做的一切,如果有人想要这样做的话。
Fist在iOS Provisioning Portal上创建一个App ID,并在iTunes Connect上创建IAP Purchase。
然后,获取此项目: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]);
}
这是有史以来最简单的代码。不确定苹果是否会批准,但它正在运作。这适用于iOS 4.3及更高版本,我认为它很棒,但没有实现收据,所以一些聪明的孩子将能够免费获得硬币。
不要忘记在iTunes Connect上创建耗材项目,并使用您在那里创建的正确ID更改ID“com.IAPID.10coins”。
“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和Security框架添加到您的项目中。
对于消费品而言,就是这样!对于非消耗品,您必须添加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上完美无缺地进行测试和工作。