zhun#1.通過蘋果應(yīng)用程序商店有三種主要賺錢的方式:
(1)直接收費(fèi)(與國內(nèi)大部分用戶的消費(fèi)習(xí)慣相悖)
(2)廣告
O2O -> Online推廣 & Offline交易,閉環(huán)
不要砍功能议双,增加內(nèi)容,而不是增加功能
(3)內(nèi)購:應(yīng)用程序本身的增值產(chǎn)品,游戲裝備,應(yīng)用程序中增值功能同樣可以內(nèi)購
第三方支付:跟應(yīng)用程序無關(guān)的
內(nèi)購:三(蘋果)七(開發(fā)商)開
2.內(nèi)購的五種產(chǎn)品類別
(1)非消耗品(Nonconsumable)一旦購買肺素,終身擁有
指的是在游戲中一次性購買并擁有永久訪問權(quán)的物品或服務(wù)。非消耗品物品可以被用戶再次下載宇驾,并且能夠在用戶的所有設(shè)備上共享
(2)消耗品(Consumable)倍靡,買了就用,用了就沒
消耗品購買不可被再次下載课舍,根據(jù)其特點(diǎn)菌瘫,消耗品不能在用戶的設(shè)備之間跨設(shè)備使用,除非自定義服務(wù)在用戶的賬號(hào)之間共享這些信息
以下三種類別在iBooks中使用布卡,目前iBooks不支持大陸市場
ISBN:每本書的一個(gè)ID
(3)免費(fèi)訂閱(Free subscriptions)
(4)自動(dòng)續(xù)費(fèi)訂閱(Auto-renewing subscriptions)
(5)非自動(dòng)續(xù)費(fèi)訂閱(Nonrenewing subscriptions)
3.內(nèi)購流程
4.要使用內(nèi)購雨让,需要導(dǎo)入StoreKit框架
5.內(nèi)購的常用方法
(1)請求有效的產(chǎn)品代號(hào)集合
// 1) 實(shí)例化產(chǎn)品請求
SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:identifiers];
// 2) 設(shè)置代理
[request setDelegate:self];
// 3) 啟動(dòng)請求
[request start];
提示:
- 實(shí)例化請求時(shí),必須指定有效的identifiers集合忿等,之所以如此處理栖忠,主要是為了確保提交的內(nèi)購商品真的通過了蘋果的審批,處于可用狀態(tài)贸街!
- 要想獲取到準(zhǔn)確的可用產(chǎn)品集合庵寞,需要通過代理方法實(shí)現(xiàn)
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
3 . 越獄用戶無法測試內(nèi)購,但是可以購買
(2)購買指定產(chǎn)品
- 內(nèi)購的交易過程是通過SKPaymentTransactionObserver監(jiān)控的薛匪,因此需要為IAPHelper添加交易觀察者:
// 添加交易觀察者對象
[[SKPaymentQueue defaultQueue]addTransactionObserver:sharedInstance];
- 由于發(fā)起交易需要使用SKProduct對象捐川,因此需要使用字典記錄所有可用的商品
NSMutableDictionary *_productsDict;
(3)驗(yàn)證購買(在購買完成之后,驗(yàn)證)
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
// 購買完成
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
NSLog(@"購買完成 %@", transaction.payment.productIdentifier);
[queue finishTransaction:transaction];
} else if (transaction.transactionState == SKPaymentTransactionStateFailed) {
if (transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"交易失斠菁狻: %@", transaction.error.localizedDescription);
}
}
}
}
(4)恢復(fù)購買(針對非消耗品)
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
購買數(shù)據(jù)記錄問題——系統(tǒng)偏好
[[NSUserDefaults standardUserDefaults]setBool:isPurchased forKey:productId];
[[NSUserDefaults standardUserDefaults]synchronize];
案例
#import "ViewController.h"
#import <StoreKit/StoreKit.h>
@interface ViewController () <SKProductsRequestDelegate, UITableViewDataSource, UITableViewDelegate, SKPaymentTransactionObserver>
/** 所有的商品的數(shù)組 */
@property (nonatomic, strong) NSArray *products;
- (IBAction)restore:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 去自己的服務(wù)器請求所有想賣商品的ProductIds
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"iapdemo.plist" ofType:nil];
NSArray *productArray = [NSArray arrayWithContentsOfFile:filePath];
NSArray *productIdArray = [productArray valueForKeyPath:@"productId"];
// 去蘋果服務(wù)器請求可賣的商品
NSSet *productIdSet = [NSSet setWithArray:productIdArray];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdSet];
request.delegate = self;
[request start];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// 3.添加觀察者(代理是一對一的關(guān)系/觀察者一對多)
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 移除觀察者
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
#pragma mark - 實(shí)現(xiàn)SKProductsRequest的代理方法
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
// 展示商品
self.products = [response.products sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(SKProduct *obj1, SKProduct *obj2) {
return [obj1.price compare:obj2.price];
}];
// 2.刷新表格
[self.tableView reloadData];
}
#pragma mark - 實(shí)現(xiàn)tableView的數(shù)據(jù)源和代理方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.products.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"ProductCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
// 1.取出模型
SKProduct *product = self.products[indexPath.row];
// 2.給cell設(shè)置數(shù)據(jù)
cell.textLabel.text = product.localizedTitle;
cell.detailTextLabel.text = [NSString stringWithFormat:@"價(jià)格:%@", product.price];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.取出模型
SKProduct *product = self.products[indexPath.row];
// 2.購買商品
[self buyProduct:product];
}
#pragma mark - 購買商品
- (void)buyProduct:(SKProduct *)product
{
// 1.創(chuàng)建票據(jù)
SKPayment *payment = [SKPayment paymentWithProduct:product];
// 2.將票據(jù)加入到交易隊(duì)列中
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
#pragma mark - 實(shí)現(xiàn)SKPaymentQueue的回調(diào)方法
/*
隊(duì)列中的交易發(fā)生改變時(shí),就會(huì)調(diào)用該方法
*/
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
/*
SKPaymentTransactionStatePurchasing, 正在購買
SKPaymentTransactionStatePurchased, 已經(jīng)購買(購買成功)
SKPaymentTransactionStateFailed, 購買失敗
SKPaymentTransactionStateRestored, 恢復(fù)購買
SKPaymentTransactionStateDeferred 未決定
*/
for (SKPaymentTransaction *transation in transactions) {
switch (transation.transactionState) {
case SKPaymentTransactionStatePurchasing:
NSLog(@"用戶正在購買");
break;
case SKPaymentTransactionStatePurchased:
NSLog(@"購買成功,將對應(yīng)的商品給用戶");
// 將交易從交易隊(duì)列中移除
[queue finishTransaction:transation];
break;
case SKPaymentTransactionStateFailed:
NSLog(@"購買失敗,告訴用戶沒有付錢成功");
// 將交易從交易隊(duì)列中移除
[queue finishTransaction:transation];
break;
case SKPaymentTransactionStateRestored:
NSLog(@"恢復(fù)商品,將對應(yīng)的商品給用戶");
// transation.payment.productIdentifier
// 將交易從交易隊(duì)列中移除
[queue finishTransaction:transation];
break;
case SKPaymentTransactionStateDeferred:
NSLog(@"未決定");
break;
default:
break;
}
}
}
#pragma mark - 恢復(fù)購買
- (IBAction)restore:(id)sender {
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
@end