内购——应用内购买
准备工作:
在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];
}
}
//测试账户
//密码
//Yinuohanlei001
}
/**
* 恢复 非消耗品的购买 从用户的交易记录
*
* @param sender <#sender description#>
*/
- (IBAction)retoreProduct:(UIBarButtonItem *)sender {
[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
}
@end
-------------------------------------------------------------------------------------------------------------
广告:
- (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