苹果系统 怎么在出交易原始凭证丢失情况说明情况下不购买内购

内购&&应用内购买  
我所说的内购&&也可以说是应用内购买
大家都知道通过苹果应用程序商店有三种主要赚钱的方式:
1.直接收费(与国内大部分用户的消费习惯相悖,如果要收费,直接收高的,别收6块钱)
2.广告(降低用户体验 应用程序名称带Lite可以添加广告)
至于设计哪些卖钱?产品经理需要认真考虑和调研的。记录用户行为是可以帮助产品经理确认哪些收费!
所以要做好,一定要研究心理,要研究哲学,哈哈。
2.内购的类别有哪几种呢?  
在游戏中我们经常用到的主要由分两种:
非消耗品(Nonconsumable)买了就有,头衔,功能
指的是在游戏中一次性购买并拥有永久访问权的物品或服务。非消耗品物品可以被用户再次下载,并且能够在用户的所有设备上使用
消耗品(Consumable),买了就用,用了就没
专为支持可消耗的物品或服务设计的,消耗品购买不可被再次下载,根据其特点,消耗品不能在用户的设备之间跨设备使用,除非自定义服务在用户的账号之间共享这些信息
3.添加内购功能   
3.1在iTunes Connect中给自己的应用添加消耗品定义  
3.2在iTunes Connect中给自己的应用添加定义的商品 
3.3要使用内购,需要导入StoreKit框架  
&定义好的商品
#define kIAPBomb @"airplay.10bombs"
#define kIAPBullet @"airplay.laserBullet"
1. 实例化请求时,必须指定有效的identifiers集合,之所以如此处理,主要是为了确保提交的内购商品真的通过了苹果的审批,处于可用状态!
2. 要想获取到准确的可用产品集合,需要通过代理方法实现
- (void)oductsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
3. 越狱用户无法测试内购,但是可以购买
1 @interface ITViewController () &SKProductsRequestDelegate, SKPaymentTransactionObserver&
// 产品字典
NSMutableDictionary *_productD
1 - (void)viewDidLoad
[super viewDidLoad];
[self requestProducts];
// 设置购买队列的监听器
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
3.4.询问苹果的服务器能够销售哪些商品 
#pragma mark 询问苹果的服务器能够销售哪些商品
- (void)requestProducts
// 能够销售的商品
NSSet *set = [[NSSet alloc] initWithObjects:kIAPBomb, kIAPBullet, nil];
// "异步"询问苹果能否销售
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
request.delegate =
// 启动请求
[request start];
3.5.获取询问结果,成功采取操作把商品加入可售商品字典里  
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
if (_productDict == nil) {
_productDict = [NSMutableDictionary dictionaryWithCapacity:response.products.count];
for (SKProduct *product in response.products) {
// 激活了对应的销售操作按钮,相当于商店的商品上架允许销售
NSLog(@"%@", product.productIdentifier);
if ([product.productIdentifier isEqualToString:kIAPBullet]) {
_bulletButton.enabled = YES;
if ([product.productIdentifier isEqualToString:kIAPBomb]) {
_bombButton.enabled = YES;
// 填充商品字典
[_productDict setObject:product forKey:product.productIdentifier];
3.6.用户决定购买商品   
1 #pragma mark - 用户决定购买商品
2 - (void)buyProduct:(SKProduct *)product
// 要购买产品(店员给用户开了个小票)
SKPayment *payment = [SKPayment paymentWithProduct:product];
// 设置购买队列的监听器
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// 去收银台排队,准备购买(异步网络)
[[SKPaymentQueue defaultQueue] addPayment:payment];
1 - (IBAction)purchaseProducts
[self buyProduct:_productDict[kIAPBullet]];
6 - (IBAction)purchaseBomb:(id)sender
[self buyProduct:_productDict[kIAPBomb]];
3.7.判断购买状态是否成功  
#pragma mark - SKPaymentTransaction Observer
#pragma mark 购买队列状态变化
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
for (SKPaymentTransaction *transaction in transactions) {
NSLog(@"队列状态变化 %@", transaction);
// 如果小票状态是购买完成
if (SKPaymentTransactionStatePurchased == transaction.transactionState) {
NSLog(@"购买完成 %@", transaction.payment.productIdentifier);
// 更新界面或者数据,把用户购买得商品交给用户
// 验证购买凭据
[self verifyPruchase];
// 将交易从交易队列中删除
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
} else if (SKPaymentTransactionStateRestored == transaction.transactionState) {
NSLog(@"恢复成功 %@", transaction.payment.productIdentifier);
// 更新界面或者数据,把用户购买得商品交给用户
// 将交易从交易队列中删除
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
3.8.给用户提供恢复功能(因为在不同设备上永久性商品可能会出现需要恢复购买的情况)
#pragma mark - 恢复商品
- (void)restorePurchase
// 恢复已经完成的所有交易.(仅限永久有效商品)
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
3.9.验证购买(防止第三方插件漏洞)iOS7新特性  
提示:虽然苹果在iOS7提升了购买凭据的安全性,但是处于金钱考虑,购买完成后,一定要做凭据的验证工作。
1 #pragma mark 验证购买凭据
2 - (void)verifyPruchase
// 验证凭据,获取到苹果返回的交易凭据
// appStoreRecetURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 从沙盒中获取到购买凭据
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 发送网络POST请求,对购买凭据进行验证
NSURL *url = [NSURL URLWithString:ITMS_SANDBOX_VERIFY_RECEIPT_URL];
// 国内访问苹果服务器比较慢,timeoutInterval需要长一点
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
request.HTTPMethod = @"POST";
// 在网络中传输数据,大多情况下是传输的字符串而不是二进制数据
// 传输的是BASE64编码的字符串
BASE64 常用的编码方案,通常用于数据传输,以及加密算法的基础算法,传输过程中能够保证数据传输的稳定性
BASE64是可以编码和解码的
NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = payloadD
// 提交验证请求,并获得官方的验证JSON结果
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// 官方验证结果为空
if (result == nil) {
NSLog(@"验证失败");
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", dict);
if (dict != nil) {
// 比对字典中以下信息基本上可以保证数据安全
// bundle_id&_version&product_id&transaction_id
NSLog(@"验证成功");
3.9.说说整个购买流程结构   
1.苹果APP(商家)&&& 2.告诉苹果Store服务器要卖的商品 &&& 3.苹果审核完(告诉你是否可以卖)
4.用户(买商品)&&&&5.苹果APP(商家)&&&&6.开发票给(用户)&&&&
7.用户(拿着发票去苹果Store服务器付款)&&8.付款成功(用户在APP里获得服务商品)
(注意:如果要模拟测试内购,需要用真机才可以测试)
作者:&清澈Saup出处:本文版权归作者和博客园共有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文连接。
优质网站模板当前位置: >
您的购买无法完成 请联系iTunes支持解决方法
快捷人口:
游戏类型:角色扮演
游戏语言:简体中文96U手游网—最好玩的手机游戏网站!
当前位置:
> 功夫熊猫序篇充值无法购买怎么办?联系iTunes支持处理教程
功夫熊猫序篇充值无法购买怎么办?联系iTunes支持处理教程
类型:角色扮演
平台:安卓
状态:公测
大小:343 MB
功夫序篇充值无法购买怎么办?联系iTunes支持处理教程。功夫熊猫序篇购买不了怎么办?在出现这样的情况的时候,不要急,一起来和小编解决问题吧!
&最近有许多IOS玩家朋友遇到了在游戏内购买时
出现&您的购买无法完成 &请联系iTunes支持&的弹窗 &无法购买游戏内置物品
经官方人员试验,下面奉上该类问题的处理方法
&首先 &请您确保机器处于非非正版状态&
如果机器已经非正版 请您删除iapfree 或 iapcracker 等虚假凭证内购的软件
并确保机器UUID为正常状态而不是编造的或者是他人的&在游戏内尝试购买
如仍旧不能购买,请按以下流程操作以获得支持
&第一步:进入苹果支持中心,选择右下角iTunes图标
苹果支持中心地址:
第二步:选择左下角&联系支持&条框
第三步:选择窗口中央的 联系 iTunes Store支持
第四步:点击&购买/账单与兑换&
第五步:在弹出列表中选择&无法从iTunes购买&
第六步:选择合适您的联络方式以获取支持
本站为防止低俗内容出现,用户发表的评论需经过审核,谢谢 !
查看更多 ↓
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%
新年大礼包剩余:0%大家都知道做iOS开发本身的收入有三种来源:出售应用、内购和广告。国内用户通常很少直接购买应用,因此对于开发者而言(特别是个人开发者),内购和广告收入就成了主要的收入来源。内购营销模式,通常软件本身是不收费的,但是要获得某些特权就必须购买一些道具,而内购的过程是由苹果官方统一来管理的,所以和Game Center一样,在开发内购程序之前要做一些准备工作(下面的准备工作主要是针对真机的,模拟器省略Provisioning Profile配置过程):
前四步和Game Center基本完全一致,只是在选择服务时不是选择Game Center而是要选择内购服务(In-App Purchase)。
到iTuens Connect中设置&App 内购买项目&,这里仍然以上面的&KCTest&项目为例,假设这个足球竞技游戏中有三种道具,分别为&强力手套&(增强防御)、&金球&(增加金球率)和&能量瓶&(提供足够体力),前两者是非消耗品只用一次性购买,后者是消耗品用完一次必须再次购买。In-App_Purchase_Config
到iTunes Connect中找到&协议、税务和银行业务&增加&iOS Paid Applications&协议,并完成所有配置后等待审核通过(注意这一步如果不设置在应用程序中无法获得可购买产品)。
在iOS&设置&中找到&iTunes Store与App Store&,在这里可以选择使用沙盒用户登录或者处于注销状态,但是一定注意不能使用真实用户登录,否则下面的购买测试不会成功,因为到目前为止我们的应用并没有真正通过苹果官方审核只能用沙盒测试用户(如果是模拟器不需要此项设置)。
有了上面的设置之后保证应用程序Bundle ID和iTunes Connect中的Bundle ID(或者说App ID中配置的Bundle ID)一致即可准备开发。
开发内购应用时需要使用StoreKit.framework,下面是这个框架中常用的几个类:
SKProduct:可购买的产品(例如上面设置的能量瓶、强力手套等),其productIdentifier属性对应iTunes Connect中配置的&产品ID&,但是此类不建议直接初始化使用,而是要通过SKProductRequest来加载可用产品(避免出现购买到无效的产品)。
SKProductRequest:产品请求类,主要用于加载产品列表(包括可用产品和不可用产品),通常加载完之后会通过其-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response代理方法获得响应,拿到响应中的可用产品。
SKPayment:产品购买支付类,保存了产品ID、购买数量等信息(注意与其对应的有一个SKMutablePayment对象,此对象可以修改产品数量等信息)。
SKPaymentQueue:产品购买支付队列,一旦将一个SKPayment添加到此队列就会向苹果服务器发送请求完成此次交易。注意交易的状态反馈不是通过代理完成的,而是通过一个交易监听者(类似于代理,可以通过队列的addTransactionObserver来设置)。
SKPaymentTransaction:一次产品购买交易,通常交易完成后支付队列会调用交易监听者的-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction方法反馈交易情况,并在此方法中将交易对象返回。
SKStoreProductViewController:应用程序商店产品展示视图控制器,用于在应用程序内部展示此应用在应用商店的情况。(例如可以使用它让用户在应用内完成评价,注意由于本次演示的示例程序没有正式提交到应用商店,所以在此暂不演示此控制器视图的使用)。
了解了以上几个常用的开发API之后,下面看一下应用内购买的流程:
通过SKProductRequest获得可购买产品SKProduct数组(SKProductRequest会根据程序的Bundle ID去对应的内购配置中获取指定ID的产品对象),这个过程中需要知道产品标识(必须和iTuens Connect中的对应起来),可以存储到沙盒中也可以存储到中(下面的Demo中定义成了宏定义)。
请求完成后可以在SKProductRequest的-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response代理方法中获得SKProductResponse对象,这个对象中保存了products属性表示可用产品对象数组。
给SKPaymentQueue设置一个监听者来获得交易的状态(它类似于一个代理),监听者通过-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction方法反馈交易的变化状态(通常在此方法中可以根据交易成功、恢复成功等状态来做一些处理)。
一旦用户决定购买某个产品(SKProduct),就可以根据SKProduct来创建一个对应的支付对象SKPayment,只要将这个对象加入到SKPaymentQueue中就会触发购买行为(将订单提交到苹果服务器),一旦一个交易发生变化就会触发SKPaymentQueue监听者来反馈交易情况。
交易提交给苹果服务器之后如果不出意外的话通常就会弹出一个确认购买的对话框,引导用户完成交易,最终完成交易后(通常是完成交易,用户点击&好&)会调用交易监听者-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction方法将此次交易的所有交易对象SKPaymentTransaction数组返回,可以通过交易状态判断交易情况。
通常一次交易完成后需要对本次交易进行验证,避免越狱机器模拟苹果官方的反馈造成交易成功假象。苹果官方提供了一个验证的URL,只要将交易成功后的凭证(这个凭证从iOS7之后在交易成功会会存储到沙盒中)传递给这个地址就会给出交易状态和本次交易的详细信息,通过这些信息(通常可以根据交易状态、Bundler ID、ProductID等确认)可以标识出交易是否真正完成。
对于非消耗品,用户在完成购买后如果用户使用其他机器登录或者用户卸载重新安装应用后通常希望这些非消耗品能够恢复(事实上如果不恢复用户再次购买也不会成功)。调用SKPaymentQueue的restoreCompletedTransactions就可以完成恢复,恢复后会调用交易监听者的paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction方法反馈恢复的交易(也就是已购买的非消耗品交易,注意这个过程中如果没有非消耗品可恢复,是不会调用此方法的)。
下面通过一个示例程序演示内购和恢复的整个过程,程序界面大致如下:
主界面中展示了所有可购买产品和售价,以及购买情况。
选择一个产品点&购买&可以购买此商品,购买完成后刷新购买状态(如果是非消耗品则显示已购买,如果是消耗品则显示购买个数)。
程序卸载后重新安装可以点击&恢复购买&来恢复已购买的非消耗品。
In-App_Purchase_Layout
程序代码:
// KCMainTableViewController.m
// Created by Kenshin Cui on 14/4/5.
// Copyright (c) 2015年 cmjstudio. All rights reserved.
#import &KCMainTableViewController.h&
#define kAppStoreVerifyURL @&https://buy./verifyReceipt& //实际购买验证URL
#define kSandboxVerifyURL @&https://sandbox./verifyReceipt& //开发阶段沙盒验证URL
//定义可以购买的产品ID,必须和iTunes Connect中设置的一致
#define kProductID1 @&ProtectiveGloves& //强力手套,非消耗品
#define kProductID2 @&GoldenGlobe& //金球,非消耗品
#define kProductID3 @&EnergyBottle& //能量瓶,消耗品
@interface KCMainTableViewController ()
@property (strong,nonatomic) NSMutableDictionary *//有效的产品
@property (assign,nonatomic) int selectedR//选中行
@implementation KCMainTableViewController
#pragma mark - 控制器视图方法
- (void)viewDidLoad {
[super viewDidLoad];
[self loadProducts];
[self addTransactionObjserver];
#pragma mark - UI事件
//购买产品
- (IBAction)purchaseClick:(UIBarButtonItem *)sender {
NSString *productIdentifier=self.products.allKeys[self.selectedRow];
SKProduct *product=self.products[productIdentifier];
if (product) {
[self purchaseProduct:product];
NSLog(@&没有可用商品.&);
//恢复购买
- (IBAction)restorePurchaseClick:(UIBarButtonItem *)sender {
[self restoreProduct];
#pragma mark - UITableView数据源方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.products.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identtityKey=@&myTableViewCellIdentityKey1&;
UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:identtityKey];
if(cell==nil){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identtityKey];
cell.accessoryType=UITableViewCellAccessoryN
NSString *key=self.products.allKeys[indexPath.row];
SKProduct *product=self.products[key];
NSString *purchaseS
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([product.productIdentifier isEqualToString:kProductID3]) {
purchaseString=[NSString stringWithFormat:@&已购买%i个&,[defaults integerForKey:product.productIdentifier]];
if([defaults boolForKey:product.productIdentifier]){
purchaseString=@&已购买&;
purchaseString=@&尚未购买&;
cell.textLabel.text=[NSString stringWithFormat:@&%@(%@)&,product.localizedTitle,purchaseString] ;
cell.detailTextLabel.text=[NSString stringWithFormat:@&%@&,product.price];
#pragma mark - UITableView代理方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *currentSelected=[tableView cellForRowAtIndexPath:indexPath];
currentSelected.accessoryType=UITableViewCellAccessoryC
self.selectedRow=indexPath.
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *currentSelected=[tableView cellForRowAtIndexPath:indexPath];
currentSelected.accessoryType=UITableViewCellAccessoryN
#pragma mark - SKProductsRequestd代理方法
* 产品请求完成后的响应方法
* @param request 请求对象
* @param response 响应对象,其中包含产品信息
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
//保存有效的产品
_products=[NSMutableDictionary dictionary];
[response.products enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
SKProduct *product=
[_products setObject:product forKey:product.productIdentifier];
//由于这个过程是异步的,加载成功后重新刷新表格
[self.tableView reloadData];
-(void)requestDidFinish:(SKRequest *)request{
NSLog(@&请求完成.&);
-(void)request:(SKRequest *)request didFailWithError:(NSError *)error{
if (error) {
NSLog(@&请求过程中发生错误,错误信息:%@&,error.localizedDescription);
#pragma mark - SKPaymentQueue监听方法
* 交易状态更新后执行
* @param queue 支付队列
* @param transactions 交易数组,里面存储了本次请求的所有交易对象
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
[transactions enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
SKPaymentTransaction *paymentTransaction=
if (paymentTransaction.transactionState==SKPaymentTransactionStatePurchased){//已购买成功
NSLog(@&交易\&%@\&成功.&,paymentTransaction.payment.productIdentifier);
//购买成功后进行验证
[self verifyPurchaseWithPaymentTransaction];
//结束支付交易
[queue finishTransaction:paymentTransaction];
}else if(paymentTransaction.transactionState==SKPaymentTransactionStateRestored){//恢复成功,对于非消耗品才能恢复,如果恢复成功则transaction中记录的恢复的产品交易
NSLog(@&恢复交易\&%@\&成功.&,paymentTransaction.payment.productIdentifier);
[queue finishTransaction:paymentTransaction];//结束支付交易
//恢复后重新写入偏好配置,重新加载UITableView
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:paymentTransaction.payment.productIdentifier];
[self.tableView reloadData];
}else if(paymentTransaction.transactionState==SKPaymentTransactionStateFailed){
if (paymentTransaction.error.code==SKErrorPaymentCancelled) {//如果用户点击取消
NSLog(@&取消购买.&);
NSLog(@&ErrorCode:%i&,paymentTransaction.error.code);
//恢复购买完成
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue{
NSLog(@&恢复完成.&);
#pragma mark - 私有方法
* 添加支付观察者监控,一旦支付后则会回调观察者的状态更新方法:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
-(void)addTransactionObjserver{
//设置支付观察者(类似于代理),通过观察者来监控购买情况
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
* 加载所有产品,注意产品一定是从服务器端请求获得,因为有些产品可能开发人员知道其存在性,但是不经过审核是无效的;
-(void)loadProducts{
//定义要获取的产品标识集合
NSSet *sets=[NSSet setWithObjects:kProductID1,kProductID2,kProductID3, nil];
//定义请求用于获取产品
SKProductsRequest *productRequest=[[SKProductsRequest alloc]initWithProductIdentifiers:sets];
//设置代理,用于获取产品加载状态
productRequest.delegate=
//开始请求
[productRequest start];
* 购买产品
* @param product 产品对象
-(void)purchaseProduct:(SKProduct *)product{
//如果是非消耗品,购买过则提示用户
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([product.productIdentifier isEqualToString:kProductID3]) {
NSLog(@&当前已经购买\&%@\& %i 个.&,kProductID3,[defaults integerForKey:product.productIdentifier]);
}else if([defaults boolForKey:product.productIdentifier]){
NSLog(@&\&%@\&已经购买过,无需购买!&,product.productIdentifier);
//创建产品支付对象
SKPayment *payment=[SKPayment paymentWithProduct:product];
//支付队列,将支付对象加入支付队列就形成一次购买请求
if (![SKPaymentQueue canMakePayments]) {
NSLog(@&设备不支持购买.&);
SKPaymentQueue *paymentQueue=[SKPaymentQueue defaultQueue];
//添加都支付队列,开始请求支付
// [self addTransactionObjserver];
[paymentQueue addPayment:payment];
* 恢复购买,对于非消耗品如果应用重新安装或者机器重置后可以恢复购买
* 注意恢复时只能一次性恢复所有非消耗品
-(void)restoreProduct{
SKPaymentQueue *paymentQueue=[SKPaymentQueue defaultQueue];
//设置支付观察者(类似于代理),通过观察者来监控购买情况
// [paymentQueue addTransactionObserver:self];
//恢复所有非消耗品
[paymentQueue restoreCompletedTransactions];
* 验证购买,避免越狱软件模拟苹果请求达到非法购买问题
-(void)verifyPurchaseWithPaymentTransaction{
//从沙盒中获取交易凭证并且拼接成请求体数据
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//转化为base64字符串
NSString *bodyString = [NSString stringWithFormat:@&{\&receipt-data\& : \&%@\&}&, receiptString];//拼接请求数据
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//创建请求到苹果官方进行购买验证
NSURL *url=[NSURL URLWithString:kSandboxVerifyURL];
NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];
requestM.HTTPBody=bodyD
requestM.HTTPMethod=@&POST&;
//创建连接并发送同步请求
NSError *error=
NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];
if (error) {
NSLog(@&验证购买过程中发生错误,错误信息:%@&,error.localizedDescription);
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@&%@&,dic);
if([dic[@&status&] intValue]==0){
NSLog(@&购买成功!&);
NSDictionary *dicReceipt= dic[@&receipt&];
NSDictionary *dicInApp=[dicReceipt[@&in_app&] firstObject];
NSString *productIdentifier= dicInApp[@&product_id&];//读取产品标识
//如果是消耗品则记录购买数量,非消耗品则记录是否购买过
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([productIdentifier isEqualToString:kProductID3]) {
int purchasedCount=[defaults integerForKey:productIdentifier];//已购买数量
[[NSUserDefaults standardUserDefaults] setInteger:(purchasedCount+1) forKey:productIdentifier];
[defaults setBool:YES forKey:productIdentifier];
[self.tableView reloadData];
//在此处对购买记录进行存储,可以存储到开发商的服务器端
NSLog(@&购买失败,未通过验证!&);
运行效果(这是程序在卸载后重新安装的运行效果,卸载前已经购买&强力手套&,因此程序运行后点击了&恢复购买&):
In_AppPurchase_Effect
扩展--广告
上面也提到做iOS开发另一收益来源就是广告,在iOS上有很多广告服务可以集成,使用比较多的就是苹果的iAd、谷歌的Admob,下面简单演示一下如何使用iAd来集成广告。使用iAd集成广告的过程比较简单,首先引入iAd.framework框架,然后创建ADBannerView来展示广告,通常会设置ADBannerView的代理方法来监听广告点击并在广告加载失败时隐藏广告展示控件。下面的代码简单的演示了这个过程:
// ViewController.m
// Created by Kenshin Cui on 14/4/5.
// Copyright (c) 2015年 cmjstudio. All rights reserved.
#import &ViewController.h&
@interface ViewController ()
@property (weak, nonatomic) IBOutlet ADBannerView *advertiseB//广告展示视图
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置代理
self.advertiseBanner.delegate=
#pragma mark - ADBannerView代理方法
//广告加载完成
-(void)bannerViewDidLoadAd:(ADBannerView *)banner{
NSLog(@&广告加载完成.&);
//点击Banner后离开之前,返回NO则不会展开全屏广告
-(BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave{
NSLog(@&点击Banner后离开之前.&);
return YES;
//点击banner后全屏显示,关闭后调用
-(void)bannerViewActionDidFinish:(ADBannerView *)banner{
NSLog(@&广告已关闭.&);
//获取广告失败
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
NSLog(@&加载广告失败.&);
self.advertiseBanner.hidden=YES;
运行效果:

我要回帖

更多关于 特殊情况扣税凭证 的文章

 

随机推荐