内购——应用内购买

通过苹果应用程序商店有三种主要赚钱的方式:
直接收费(与国内大部分用户的消费习惯相悖)
广告(降低用户体验 应用程序名称带Lite可以添加广告)
O2O -> Online推广 & Offline交易,闭环
不要砍功能,增加内容,而不是增加功能
内购:应用程序本身的增值产品,游戏装备,应用程序中增值功能同样可以内购
第三方支付:跟应用程序无关的
内购分成:三(苹果)七(开发商)开
 
提示:
要做好游戏 & 应用,一定要研究心理,要研究哲学
人人都是产品经理
 
内购的五种产品类别
非消耗品(Nonconsumable)一旦购买,终身拥有
  指的是在游戏中一次性购买并拥有永久访问权的物品或服务。非消耗品物品可以被用户再次下载,并且能够在用户的所有设备上使用
消耗品(Consumable),买了就用,用了就没
  专为支持可消耗的物品或服务设计的,消耗品购买不可被再次下载,根据其特点,消耗品不能在用户的设备之间跨设备使用,除非自定义服务在用户的账号之间共享这些信息
 
以下三种类别在iBooks中使用,目前iBooks不支持大陆市场
ISBN:每本书的一个ID
免费订阅(Free subscriptions)
自动续费订阅(Auto-renewing subscriptions)
非自动续费订阅(Nonrenewing subscriptions)
 

准备工作:

在Itunes  添加应用   设置 apppurese  内购的 道具

并且制定每一个道具的名称跟 产品 ID

bundleID:  唯一的

必须是真机: 要求  不能越狱

添加测试账号:  (不花钱   苹果提供一个 沙盒 专门用来测试内购

注意点: 不能是苹果真的 账号

1> 内购程序的APP ID需要单独指定,因为在开发时,需要独立测试,通过苹果的网站进行交互

2> 在iTunes Connect中添加可以销售的商品

3> 中间有一个审批的过程,之后就可以在应用程序中添加

4> 注册Sandbox(使用测试服务器的)用户,同样具备苹果ID的能力

苹果官方有限定,不能用测试账号在苹果真正市场消费,一旦有消费行为,就会被禁用

5> 在应用程序信息中,填写测试账号和密码,方便审核人员测试!

开发前的注意事项:

1> 要开发内购,必须用真机

2> 真机一定不能越狱

3> BundlID 和服务器上的 App ID要一致,靠AppID来识别具体的消费

对于非消耗品,需要增加一个恢复购买的功能,提示:会一次性恢复所有的购买的非消耗品

要使用内购,需要导入StoreKit框架

内购的常用方法

请求有效的产品代号集合
购买指定产品
验证购买(在购买完成之后,验证)
恢复购买(针对非消耗品)
 
请求有效产品集合

// 1) 实例化产品请求

SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:identifiers];

// 2) 设置代理

[request setDelegate:self];

// 3) 启动请求

[request start];

提示:

1. 实例化请求时,必须指定有效的identifiers集合,之所以如此处理,主要是为了确保提交的内购商品真的通过了苹果的审批,处于可用状态!

2. 要想获取到准确的可用产品集合,需要通过代理方法实现

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

3. 越狱用户无法测试内购,但是可以购买

购买产品

1. 内购的交易过程是通过SKPaymentTransactionObserver监控的,因此需要为IAPHelper添加交易观察者:

// 添加交易观察者对象

[[SKPaymentQueue defaultQueue]addTransactionObserver:sharedInstance];

2. 由于发起交易需要使用SKProduct对象,因此需要使用字典记录所有可用的商品

NSMutableDictionary*_productsDict;

交易队列回调方法

- (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);

}

}

}

}

恢复购买

[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];

验证购买

#if DEBUG

#define ITMS_VERIFY_RECEIPT_URL             @"https://sandbox.itunes.apple.com/verifyReceipt"

#else

#define ITMS_VERIFY_RECEIPT_URL             @"https://buy.itunes.apple.com/verifyReceipt"

#endif

--------------------------------------------------------------------------------------------------------------------

完整步骤代码:

#import "ViewController.h"

#import <StoreKit/StoreKit.h>

@interface ViewController ()<SKProductsRequestDelegate,SKPaymentTransactionObserver>

//产品

@property (nonatomic,strong)NSArray *allProducts;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//1.请求可销售的商品列表

//准备自己需要销售的商品列表

NSString *path = [[NSBundle mainBundle]pathForResource:@"products.json" ofType:nil];

NSData *data = [NSData dataWithContentsOfFile:path];

NSArray *arrayList = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];

NSArray *arrayIdList = [arrayList valueForKeyPath:@"productId"];

NSLog(@"%@",arrayIdList);

NSSet *set = [NSSet setWithArray:arrayIdList];

//创建一个请求对象

SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];

request.delegate = self;

[request start];

//6.创建监听对象 来监听交易队列中的交易对象的交易状态

[[SKPaymentQueue defaultQueue]addTransactionObserver:self];

}

- (void)dealloc

{

//移除监听对象

[[SKPaymentQueue defaultQueue]removeTransactionObserver:self];

}

#pragma mark - SKProductsRequestDelegate

/**

*  返回可销售的商品列表

*

*  @param request  请求对象

*  @param response 返回数据

*/

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

{

for (SKProduct *product in response.products) {

NSLog(@"%@  %@  %@ %@",product.localizedTitle,product.localizedDescription,product.price,product.productIdentifier);

}

self.allProducts = response.products;

//刷新表格

[self.tableView reloadData];

}

/**

*      //2.展示可销售的商品

*

*  @param tableView <#tableView description#>

*  @param section   <#section description#>

*

*  @return <#return value description#>

*/

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

return  self.allProducts.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *ID = @"cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

if (cell == nil) {

cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

}

//取模型

SKProduct *product = self.allProducts[indexPath.row];

cell.textLabel.text = product.localizedTitle;

cell.detailTextLabel.text = [NSString stringWithFormat:@"%@元",product.price];

return cell;

}

//3.点击购买

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

//4.开具小票

SKProduct *pro = self.allProducts[indexPath.row];

//小票 创建一个交易

SKPayment *payment = [SKPayment paymentWithProduct:pro];

//5.创建交易对象并添加到交易队列

[[SKPaymentQueue defaultQueue]addPayment:payment];

}

#pragma mark -SKPaymentTransactionObserver

/**

*  监听到交易队列中交易状态改变的时候就会调用

*

*  @param queue        队列

*  @param transactions 在队列交易

*/

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

{

//非消耗品  才能被恢复购买

/*

SKPaymentTransactionStatePurchasing,    交易正在被添加到交易队列

SKPaymentTransactionStatePurchased,     //交易已经在队列,用户已经付钱,客户端需要完成交易

SKPaymentTransactionStateFailed,        //还没添加到队列中就取消或者失败了

SKPaymentTransactionStateRestored,      // 交易被恢复购买,客户端需要完成交易

SKPaymentTransactionStateDeferred NS_ENUM_AVAILABLE_IOS(8_0),   交易在队列中,交易状态不确定依赖别的参数参与

*/

//7.如果交易状态购买成功  提供特殊服务

for (SKPaymentTransaction *t in transactions) {

if (t.transactionState == SKPaymentTransactionStatePurchased) {

NSLog(@"购买成功提供增值");

//结束交易完成

[[SKPaymentQueue defaultQueue]finishTransaction:t];

}else if (t.transactionState == SKPaymentTransactionStateRestored) {

NSLog(@"恢复购买成功!");

//结束交易完成

[[SKPaymentQueue defaultQueue]finishTransaction:t];

}

}

//测试账户

//huijidazhan@126.com

//密码

//Yinuohanlei001

}

/**

*  恢复 非消耗品的购买  从用户的交易记录

*

*  @param sender <#sender description#>

*/

- (IBAction)retoreProduct:(UIBarButtonItem *)sender {

[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];

}

@end

-------------------------------------------------------------------------------------------------------------

广告:

广告收益三七开
添加 iAd.framework 框架
添加 ADBannerView 视图,并设置代理方法
广告条加载完成之前最好隐藏

- (void)bannerViewDidLoadAd:(ADBannerView *)banner {

self.bannerBottomConstraint.constant = 20.0;

[UIView animateWithDuration:0.5 animations:^{

[self.view layoutIfNeeded];

}];

NSLog(@"加载广告成功");

}

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {

NSLog(@"加载广告失败 %@", error);

---------------------------------------------------------------------------------------------------

广告完整代码

#import "ViewController.h"

#import <iAd/iAd.h>

@interface ViewController ()<ADBannerViewDelegate>

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *cons;

@end

@implementation ViewController

- (void)bannerViewDidLoadAd:(ADBannerView *)banner

{

self.cons.constant = 50;

//显示完整广告条

[UIView animateWithDuration:2.0 animations:^{

[self.view layoutIfNeeded];

}];

}

- (void)viewDidLoad {

[super viewDidLoad];

//1>3    7

//2>根据用户的应用的分类  //自动推送

//广告什么时候加载完毕

}

@end

IOS,苹果内购和添加广告的更多相关文章

  1. ios 苹果内购订单验证 --- php实现

    验证函数: function appleVerify($receipt_data,$orderId = 0) { /* * 21000 App Store不能读取你提供的JSON对象 * 21002 ...

  2. ios 苹果内购订单验证 --- nodejs实现

    实现代码 function IosPlayVerify(data,orderid,cb) { itunesPost(data,function (error,responseData) { if (e ...

  3. iOS:苹果内购实践

    iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发 ...

  4. iOS开发苹果内购的介绍与实现

    1.iOS开发苹果内购的介绍 1.1 介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝 ...

  5. Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解

    这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结 ...

  6. 苹果内购服务器验证之receipt返回多组in_app思考

    最近有部分用户反映,苹果内购充值失败,经过测试总结有几个关键点出现问题 1.app购买成功苹果没有返回票据,属于票据遗漏(取决于苹果服务器的响应状况),只能客户端进行监听刷新等处理 2.app连续购买 ...

  7. ios IAP 内购验证

    参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...

  8. 苹果内购和 Apple Pay

    作者:CC老师_MissCC链接:http://www.jianshu.com/p/e3bc47e81785來源:简书 苹果内购 1.什么是内购? 如果你购买的商品,是在本app中使用和消耗的,就一定 ...

  9. apicloud含有微信支付。支付宝支付和苹果内购的代码

    apicloud含有微信支付.支付宝支付和苹果内购的代码 <!DOCTYPE html> <html> <head> <meta charset=" ...

随机推荐

  1. 【Foreign】猜测 [费用流]

    猜测 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 3 1 1 1 2 2 1 Samp ...

  2. 【BZOJ1468】Tree [点分治]

    Tree Time Limit: 10 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距 ...

  3. 【BZOJ】1770 [Usaco2009 Nov]lights 燈

    [算法]高斯消元-异或方程组 [题解]良心简中题意 首先开关顺序没有意义. 然后就是每个点选或不选使得最后得到全部灯开启. 也就是我们需要一种确定的方案,这种方案使每盏灯都是开启的. 异或中1可以完美 ...

  4. bzoj 1834

    网络流的模板题 首先第一问我们直接用dinic搞就行了,费用直接存为0(时间上界非常松,这道题是能过),然后第二问我们只需要在第一问 的残余网络上加一个源点,源点指向1号点,容量为k,费用为0,然后对 ...

  5. bzoj 1192 二进制

    原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1192 继续刷水题,二进制思想 //By BLADEVIL var x :longint; ...

  6. 【bzoj3924&&luogu3345】幻想乡战略游戏

    这题可以用线段树做,不过正解恐怕是动态点分治?(点分树) 简单介绍下动态点分治的概念:在点分治的过程中,一般我们面对的问题都是静态的.如果涉及到修改这类的操作,我们就希望找到我们是如何处理到当前的修改 ...

  7. BZOJ1003: [ZJOI2006] 物流运输 trans

    物流运输--看了神犇的题解,就是dp+最短路,设f[i]为1~i天的最少花费,那么 dp[i]=min(cost[1,i],min{dp[j]+cost[j+1,i]+K,1≤j<i}) 就是从 ...

  8. 使用WindowManager添加View——悬浮窗口的基本原理

    Android系统中的“窗口”类型虽然很多,但只有两大类是经常使用的:一是由系统进程管理的,称之为“系统窗口”:第二个就是由应用程序产生的,用于显示UI界面的“应用窗口”.如果大家熟悉WindowMa ...

  9. 《Java编程思想》笔记 第十五章 泛型

    1 泛型 “泛型”意思就是适用于许多类型. 使用泛型的目的之一: 指定容器持有什么类型,让编译器确保正确性,而不是在运行期发现错误. 这个容器可以看成是有其他类型对象作为成员的类,而不单单只是JDK中 ...

  10. 《Java编程思想》笔记 第五章 初始化与清理

    1.构造器 因为创建一个类的对象构造器就会自动执行,故初始化某些东西特好 2.方法重载 方法名相同,参数列表不同. 2.1 区分重载方法 方法重载后区别不同方法的就是方法签名 -->参数类型和个 ...