如何实现多消耗品内购
how to implement multiple consumable products in-app purchase
我已经成功实施了一种消费品,但是我不知道实施多种消费品。我想添加更多产品标识符,例如 com.lalala.20batteries,com.lalala.30batteries
谁能给我一些指导
这是我的单耗品代码
@interface ViewController () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@end
@implementation ViewController
#define ProductIdentifier @"com.lalala.10batteries"
- (IBAction)taps10batteries{
NSLog(@"User requests to get 10 batteries");
if([SKPaymentQueue canMakePayments]){
NSLog(@"User can make payments");
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ProductIdentifier]];
productsRequest.delegate = self;
[productsRequest start];
}
else{
NSLog(@"User cannot make payments due to parental controls");
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct *validProduct = nil;
int count = [response.products count];
if(count > 0){
validProduct = [response.products objectAtIndex:0];
NSLog(@"Products Available!");
[self purchase:validProduct];
}
else if(!validProduct){
NSLog(@"No products available");
}
}
- (IBAction)purchase:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSLog(@"received restored transactions: %i", queue.transactions.count);
for(SKPaymentTransaction *transaction in queue.transactions){
if(transaction.transactionState == SKPaymentTransactionStateRestored){
//called when the user successfully restores a purchase
NSLog(@"Transaction state -> Restored");
[self get10Batteries];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for(SKPaymentTransaction *transaction in transactions){
switch(transaction.transactionState){
case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
break;
case SKPaymentTransactionStatePurchased:
[self get10Batteries];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSLog(@"Transaction state -> Purchased");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"Transaction state -> Restored");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
if(transaction.error.code == SKErrorPaymentCancelled){
NSLog(@"Transaction state -> Cancelled");
//the user cancelled the payment ;(
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)get10Batteries{
NSUbiquitousKeyValueStore *cloudstore1 = [NSUbiquitousKeyValueStore defaultStore];
//load cloud integer
coins = [cloudstore1 doubleForKey:@"yo" ];
coins = [[NSUserDefaults standardUserDefaults]
integerForKey:@"com.lalala.10batteries"];
coins += 10;
[[NSUserDefaults standardUserDefaults] setInteger:coins
forKey:@"com.lalala.10batteries"];
[[NSUserDefaults standardUserDefaults] synchronize];
_coinLabel.text = [NSString stringWithFormat:@"%li", (long)coins];
//save icloud
[cloudstore1 setDouble:coins forKey:@"yo"];
[cloudstore1 synchronize];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSUbiquitousKeyValueStore *cloudstore1 = [NSUbiquitousKeyValueStore defaultStore];
_coinLabel.text = [cloudstore1 stringForKey:@"yo" ];
NSUserDefaults *coinsdefaults = [NSUserDefaults standardUserDefaults];
if([coinsdefaults objectForKey:@"com.lalala.10batteries"] != nil) {
coins = [[NSUserDefaults standardUserDefaults] integerForKey:@"com.lalala.10batteries"];
coins = [coinsdefaults integerForKey:@"com.lalala.10batteries"];
_coinLabel.text = [NSString stringWithFormat:@"%li", (long)coins];
}
}
查看创建 SKProductsRequest 对象的行:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ProductIdentifier]];
NSSet 是一个袋子,里面有未排序的对象,袋子里只允许一种(没有欺骗)。
你所要做的就是像这样改变它:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:
@"com.blahblah.unlockall",
@"com.blahblah.sounds",
@"com.blahblah.alarms",
@"com.blahblah.wallpapers",
nil]];
那么你应该有一个自定义包装器 class (CustomIAPHelper),就像教程中那样。
在视图控制器中,假设您有一个 tableView,那么代码如下所示:
- (void)reload {
_products = nil;
[self.tableView reloadData];
[CustomIAPHelper sharedInstance].delegate = self;
[[CustomIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
// Sort the products array (by price)
_products = [products sortedArrayUsingComparator:^(id a, id b) {
NSDecimalNumber *first = [(SKProduct*)a price];
NSDecimalNumber *second = [(SKProduct*)b price];
return [second compare:first];
}];
[self.tableView reloadData];
}
[refreshControl endRefreshing];
[activity stopAnimating];
[activity setHidden:YES];
}];
}
记得设置和实施 iAPHelper 的协议方法。
您的代码可以轻松支持多种产品,就像它支持一种...
首先,像声明一个产品 ID 一样声明您的其他产品 ID:
#define ProductIdentifier1 @"com.lalala.10batteries"
#define ProductIdentifier2 @"com.lalala.20batteries"
然后,创建一个 loadAllProducts
方法,它与 taps10batteries
方法完全一样,只是您使用所有产品 ID 声明 SKProductsRequest
,就像您对一个产品 ID 所做的一样:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:ProductIdentifier1, ProductIdentifier2, nil]];
除非您更喜欢单独加载每个产品,否则您需要为每个产品创建一个方法,即 taps20batteries
,您可以忽略我回答的下一部分...
回调方法可以 return 多个产品,就像它可以 return 一个一样。按照您认为合适的方式处理响应,就像您处理响应一样:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
int count = [response.products count];
if(count > 0){
_products = [response.products sortedArrayUsingComparator:^(id a, id b) { //sort all products by price
NSDecimalNumber *first = [(SKProduct*)a price];
NSDecimalNumber *second = [(SKProduct*)b price];
return [second compare:first];
}];
for (SKProduct *product in _products) {
NSLog(@"Product Available: %@", product.productIdentifier);
//do something with the product..
//perhaps gather the products into an array and present it somehow to the user so s/he can select what to buy?
}
}
else {
NSLog(@"No products available");
}
}
如果您想要可以使用的完整实现,请尝试 this one
我已经成功实施了一种消费品,但是我不知道实施多种消费品。我想添加更多产品标识符,例如 com.lalala.20batteries,com.lalala.30batteries
谁能给我一些指导
这是我的单耗品代码
@interface ViewController () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@end
@implementation ViewController
#define ProductIdentifier @"com.lalala.10batteries"
- (IBAction)taps10batteries{
NSLog(@"User requests to get 10 batteries");
if([SKPaymentQueue canMakePayments]){
NSLog(@"User can make payments");
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ProductIdentifier]];
productsRequest.delegate = self;
[productsRequest start];
}
else{
NSLog(@"User cannot make payments due to parental controls");
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct *validProduct = nil;
int count = [response.products count];
if(count > 0){
validProduct = [response.products objectAtIndex:0];
NSLog(@"Products Available!");
[self purchase:validProduct];
}
else if(!validProduct){
NSLog(@"No products available");
}
}
- (IBAction)purchase:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSLog(@"received restored transactions: %i", queue.transactions.count);
for(SKPaymentTransaction *transaction in queue.transactions){
if(transaction.transactionState == SKPaymentTransactionStateRestored){
//called when the user successfully restores a purchase
NSLog(@"Transaction state -> Restored");
[self get10Batteries];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for(SKPaymentTransaction *transaction in transactions){
switch(transaction.transactionState){
case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
break;
case SKPaymentTransactionStatePurchased:
[self get10Batteries];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSLog(@"Transaction state -> Purchased");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"Transaction state -> Restored");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
if(transaction.error.code == SKErrorPaymentCancelled){
NSLog(@"Transaction state -> Cancelled");
//the user cancelled the payment ;(
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)get10Batteries{
NSUbiquitousKeyValueStore *cloudstore1 = [NSUbiquitousKeyValueStore defaultStore];
//load cloud integer
coins = [cloudstore1 doubleForKey:@"yo" ];
coins = [[NSUserDefaults standardUserDefaults]
integerForKey:@"com.lalala.10batteries"];
coins += 10;
[[NSUserDefaults standardUserDefaults] setInteger:coins
forKey:@"com.lalala.10batteries"];
[[NSUserDefaults standardUserDefaults] synchronize];
_coinLabel.text = [NSString stringWithFormat:@"%li", (long)coins];
//save icloud
[cloudstore1 setDouble:coins forKey:@"yo"];
[cloudstore1 synchronize];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSUbiquitousKeyValueStore *cloudstore1 = [NSUbiquitousKeyValueStore defaultStore];
_coinLabel.text = [cloudstore1 stringForKey:@"yo" ];
NSUserDefaults *coinsdefaults = [NSUserDefaults standardUserDefaults];
if([coinsdefaults objectForKey:@"com.lalala.10batteries"] != nil) {
coins = [[NSUserDefaults standardUserDefaults] integerForKey:@"com.lalala.10batteries"];
coins = [coinsdefaults integerForKey:@"com.lalala.10batteries"];
_coinLabel.text = [NSString stringWithFormat:@"%li", (long)coins];
}
}
查看创建 SKProductsRequest 对象的行:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:ProductIdentifier]];
NSSet 是一个袋子,里面有未排序的对象,袋子里只允许一种(没有欺骗)。
你所要做的就是像这样改变它:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:
@"com.blahblah.unlockall",
@"com.blahblah.sounds",
@"com.blahblah.alarms",
@"com.blahblah.wallpapers",
nil]];
那么你应该有一个自定义包装器 class (CustomIAPHelper),就像教程中那样。
在视图控制器中,假设您有一个 tableView,那么代码如下所示:
- (void)reload {
_products = nil;
[self.tableView reloadData];
[CustomIAPHelper sharedInstance].delegate = self;
[[CustomIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
// Sort the products array (by price)
_products = [products sortedArrayUsingComparator:^(id a, id b) {
NSDecimalNumber *first = [(SKProduct*)a price];
NSDecimalNumber *second = [(SKProduct*)b price];
return [second compare:first];
}];
[self.tableView reloadData];
}
[refreshControl endRefreshing];
[activity stopAnimating];
[activity setHidden:YES];
}];
}
记得设置和实施 iAPHelper 的协议方法。
您的代码可以轻松支持多种产品,就像它支持一种... 首先,像声明一个产品 ID 一样声明您的其他产品 ID:
#define ProductIdentifier1 @"com.lalala.10batteries"
#define ProductIdentifier2 @"com.lalala.20batteries"
然后,创建一个 loadAllProducts
方法,它与 taps10batteries
方法完全一样,只是您使用所有产品 ID 声明 SKProductsRequest
,就像您对一个产品 ID 所做的一样:
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObjects:ProductIdentifier1, ProductIdentifier2, nil]];
除非您更喜欢单独加载每个产品,否则您需要为每个产品创建一个方法,即 taps20batteries
,您可以忽略我回答的下一部分...
回调方法可以 return 多个产品,就像它可以 return 一个一样。按照您认为合适的方式处理响应,就像您处理响应一样:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
int count = [response.products count];
if(count > 0){
_products = [response.products sortedArrayUsingComparator:^(id a, id b) { //sort all products by price
NSDecimalNumber *first = [(SKProduct*)a price];
NSDecimalNumber *second = [(SKProduct*)b price];
return [second compare:first];
}];
for (SKProduct *product in _products) {
NSLog(@"Product Available: %@", product.productIdentifier);
//do something with the product..
//perhaps gather the products into an array and present it somehow to the user so s/he can select what to buy?
}
}
else {
NSLog(@"No products available");
}
}
如果您想要可以使用的完整实现,请尝试 this one