IAP-应用内购买(部分)

前言:自我总结---loadStore(监听交易,请求产品描述:完成交由委托->获取产品描述-.交给fetch自定义委托LB显示)->2,点击购买->激活交易监听进行购买payment->交易监听事件(相当于委托)-主要与store交互实现购买->3,显示购买uialertview购买界面->cancel-正常消失;购买:输入账号view--输入正确时,激发交易监听事件(主要与st
摘要由CSDN通过智能技术生成

前言:自我总结---

loadStore(监听交易,请求产品描述:完成交由委托->获取产品描述-.交给fetch自定义委托LB显示)->

2,点击购买->激活交易监听进行购买payment->交易监听事件(相当于委托)-主要与store交互实现购买->

3,显示购买uialertview购买界面->cancel-正常消失;

购买:输入账号view--输入正确时,激发交易监听事件(主要与store交互实现购买)


一,IAP可以正常更年工作的主要2个步骤:

1,创建及提取产品描述;2,购买产品。

步骤1详细:创建唯一的APP ID->生成及安装新的provisioning profile文件->在Xcode中更新bundle ID及code signing profile->如果还没做的话,请在iTunes Connect中提交你程序相关的metadata和二进制码->为IAP添加新产品->编写提取产品描述的代码.

注:等待几小时,进行后续操作;提取产品描述的代码非常简单,但其他步骤则很容易错;为提取产品描述,并不需要在iTunes Connect中创建IAP测试用户。

详细:

1. 创建唯一的App ID
为支持IAP,你的App ID不能包括通配符(“*”)。为确定你的App Id是否包括通配符,请登录http://developer.apple.com/iphone,在 iPhone Developer Program Portal中选择左边菜单中的 “App IDs”检查你的 App ID。

下面是一个唯一的App ID:

7DW89RZKLY.com.runmonster.runmonsterfree

下面不是一个唯一的 App ID:

7DW89RZKLY.com.runmonster.*

如果你还没有一个唯一的App ID,按如下步骤创建一个:

在developer portal中的 App IDs 部分,选择“New App ID”
填写下列信息:
Display name(显示名): 选取一个不同的App ID的名称。你不能编辑或删除旧的App ID,所以你必须为你的App ID提供一个新名称以避免溷淆。
Prefix(前缀): 生成一个新的前缀,或者如果你的程序是通过Keychain Services API分享数据的系列程序中之一的话,则选用已存在的前缀。
Suffix(后缀): com.companyname.appname (这是通用格式 – 注意没有使用通配符)。
按 “Save”
按 App ID旁的“Configure” 链接
选取 “Enable In App Purchase”选择框
按“Done”
2. 创建一个新的Provisioning Profile文件
在创建了新的App ID后,你需要生成一个指向这个App ID的新provisioning profile。

下面就是令人痛苦的生成和安装新provisioning profile的详细步骤:

在 iPhone Developer Portal中, 选择左边的Provisioning部分
确保你处于Development 标籤下, 按下右上角的 “New Profile”
填入所需信息并指向你刚创建的唯一的App ID
如果你在Actions条目下看到 “Pending”,那麽请按下“Development”标籤标题进行刷新
点击 “Download” 下载新的profile文件
将profile文件拖入到Dock中Xcode图标上进行安装
如果你想在硬盘上保存provisioning profile,那麽你可以按如下步骤手工安装profile:
在Xcode中, 选择 Window > Organizer
选择左边 “Provisioning Profiles” 分类
Ctrl-按下profile > Reveal in Finder
将新profile拖入到 profile Finder 窗口
3. 更新Xcode 设置
在Xcode中安装了 profile 文件后,你需要对使用此provisiong profile的项目进行一些编辑工作:

编辑项目 .plist 文件使其 Bundle ID 与 App ID 匹配。忽略ID开始部分的字母数字序列。例如,在Developer Portal中你的App ID为“7DW89RZKLY.com.runmonster.runmonsterfree”,那麽在Bundle ID中你只需输入“com.runmonster.runmonsterfree” 。
编辑项目的 target 信息以使用新的provisioning profile:
选取 Project > Edit Active Target
选取顶部“Build” 标籤
选取需要的 configuration (通常为 Debug)
在Code Signing Identity中选择新的provisioning profile
在Code Signing Identity之下的行中(可能名为 Any iPhone OS Device)选择新的provisioning profile
4. 添加你的应用程序
如果你的程序已经发表到App Store了,那麽可以略过此步骤。

在你将产品添加到 iTunes Connect之前,你必须添加此产品所需的程序。如果你的程序还没有100%完成也无需担心,你可以先提交具有部分数据的程序,最后再提交真实的程序。

注意: 只有 SKU 和 version(版本)部分是以后不可修改的

登录到 http://developer.apple.com/iphone
点击右边链接进入 iTunes Connect
注意:你必须先登录到developer.apple.com,否则会有不测发生(译者注:具体是什麽不测我也不太清楚,胆大的请自己试一下)
在 iTunes Connect主页点击 “Manage Your Applications”
在右上角点击“Create New Application”
填写程序所需的一切信息。当要求程序二进制码时,请选择稍后上传选项。
5. 提交程序二进制码
Apple的文档中没有任何地方提及详情,但它却是必须的步骤。要成功测IAP功能,你必须提交程序的二进制码。即使你的程序还没有100%完成,你仍然需要提交二进制码。然而,你也可以立即摈弃你的二进制码,使其不会进入审核阶段。

下面这些步骤非常关键,我可是因为少做了某些步骤而度过了一段非常痛苦的时间:

生成App Store发佈版程序
如果你不知怎麽做,请在 iPhone Developer Portal 中点击左方的 Distribution标籤,并选择 “Prepare App” 标籤。然后,根据蓝色链接的指示:
获取iPhone发行许可证
创建并下载在App Store发行所需的iPhone Distribution Provisioning Profile
在Xcode中生成程序的发行版
在iTunes Connect中进入程序页
选择 “Upload Binary”
上传.zip压缩程序
如果你的程序还没有100%完成以进行审核,那麽请点击iTunes Connect中你程序首页中的 “Reject Binary”链接。程序的状态应该更新为 “Developer Rejected”.
不用担心,由于程序的状态是“Developer Rejected”,Apple是不会对其进行审核的。你可以在任何时候提交程序的新版本并使其状态为“Developer Rejected”,这不会对以后程序正式提交的等待时间有任何影响。

6. 添加产品
完成了以上所有步骤后,我们最终可以向iTunes Connect中添加产品了。

确保登录到 http://developer.apple.com/iphone
进入 iTunes Connect 主页
点击“Manage Your Applications”
点击刚建好的程序 点击view details
点击 “Manage in-App Purchases” 链接
点击 “Create New”
填写下列产品信息:
Reference Name(参考名称): 产品的通用名称。比如,我使用的是 “Pro Upgrade”。此名称是不允许进行编辑的,它不会显示于App Store中。
Product ID(产品ID): 你产品的唯一id。通常格式是 com.company.appname.product,但它可以说任何形式。它并不要求以程序的App ID作为前缀。
Type(类型): 有三种选择
Non-consumable(非消耗品): 仅需付费一次 (例如你希望将出现从免费版升级为专业版)
Consumable(消耗品): 每次下载都需要付费
Subscription(预订): 循环反覆
Price Tier(价格等级): 产品价格。参见不同等级的价格列表。
Cleared for Sale(等待销售): 一定要选取此项,否则的话,测试时会发生非法产品ID的错误。
Language to Add(增加的语言): 选一项。下列两项将出现:
Displayed Name(显示名称): 用户看到的产品名称。比如我选择 “Upgrade to Pro”。
Description(描述): 对产品进行描述。此处输入的文本将与Displayed Name 及 Price 一起在你代码中提取 SKProduct时出现。
Screenshot(截屏): 展示你产品的截屏。儘管屏幕上会显示“提交截屏会触发产品审核过程”之类的文字(个人拙见,这是非常糟糕的设计),你还是可以安全地提交截屏而不会使产品进入审核过程。存储后,选择“Submit with app binary” (随程序二进制码一起提交)选项。是产品与程序二进制绑定在一起,所以在你最后正式提交100%完成的程序二进制码时,产品也会随之提交。
点击 “Save”
最后一定不要忘了回到view details  编辑In-App Purchases
选择刚刚添加的iap版本。

Products
产品可以是任意一项你想要出售的特性。产品在iTunes Connect中被组织,这和你添加一个新的App是一样的。支持的产品种类共有四种:
1. 内容型。包括电子书,电子杂志,照片,插图,游戏关卡,游戏角色,和其他的数字内容。
2. 扩展功能。这些功能已经包含在App内部。在未购买之前被锁定。例如,你可以在一个游戏程序中包含若干个小游戏,用户可以分别来购买这些游戏。
3. 服务。允许程序对单次服务收费。比如录音服务。
4. 订阅。支持对内容或服务的扩展访问。例如,你的程序可以每周提供财务信息或游戏门户网站的信息。应该设定一个合理的更新周期,以避免过于频繁的
提示困扰用户。要记住:你将负责跟踪订阅的过期信息,并且管理续费。App Store不会替你监视订阅的周期,也不提供自动收费的机制。


7. 编写代码
下面我们开始编写代码对刚加入到iTunes Connect中的产品信息进行提取。我访问产品数据,我们需要使用 StoreKit framework。

注意: StoreKit 无法在模拟器上工作。你必须在真机上进行测试。

1.添加 StoreKit framework 到你的项目中。
2.添加SKProduct引用到你的 .h 文件中:

  1. // InAppPurchaseManager.h
  2. #import <StoreKit/StoreKit.h>
  3. #define kInAppPurchaseManagerProductsFetchedNotification @"kInAppPurchaseManagerProductsFetchedNotification"
  4. @interface InAppPurchaseManager : NSObject <SKProductsRequestDelegate>
  5. {
  6.     SKProduct *proUpgradeProduct;
  7.     SKProductsRequest *productsRequest;
  8. }
注意: InAppPurchaseManager 是一个单例类,它处理程序中所有IAP任务。它是本文中的示例程序。

3.产品请求,并在相应.m文件中实现代理协议

  • // InAppPurchaseManager.m
  • - (void)requestProUpgradeProductData
  • {
  •     NSSet *productIdentifiers = [NSSet setWithObject:@"com.runmonster.runmonsterfree.upgradetopro" ];
  •     productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
  •     productsRequest.delegate = self;
  •     [productsRequest start];
  •     
  •     // we will release the request object in the delegate callback
  • }
  • #pragma mark -
  • #pragma mark SKProductsRequestDelegate methods
  • - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
  • {
  •     NSArray *products = response.products;
  •     proUpgradeProduct = [products count] == 1 ? [[products firstObject] retain] : nil;
  •     if (proUpgradeProduct)
  •     {
  •         NSLog(@"Product title: %@" , proUpgradeProduct.localizedTitle);
  •         NSLog(@"Product description: %@" , proUpgradeProduct.localizedDescription);
  •         NSLog(@"Product price: %@" , proUpgradeProduct.price);
  •         NSLog(@"Product id: %@" , proUpgradeProduct.productIdentifier);
  •     }
  •     
  •     for (NSString *invalidProductId in response.invalidProductIdentifiers)
  •     {
  •         NSLog(@"Invalid product id: %@" , invalidProductId);
  •     }
  •     
  •     // finally release the reqest we alloc/init’ed in requestProUpgradeProductData
  •     [productsRequest release];
  •     
  •     [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
  • }
  • 上面代码有几点需要注意:

    指定产品id时,你必须使用完整产品id。例如,上例中使用 “com.runmonster.runmonsterfree.upgradetopro”。仅使用 “upgradetopro” 将不会正常工作。
    如果在productsRequest:didReceiveResponse:中response.products 为 nil,而你的产品id出现于 response.invalidProductIdentifers 数组中时,那麽请做好心理准备开始一场徒劳的搜索战吧。 StoreKit API没有提供任何帮助,也没有任何指示关于为什麽你的id是无效的。很可爱,不是吗?
    SKProduct类提供了有关程序标题和描述的本地化版本,但是价格则没有本地化版本。下面是针对此疏忽提供的代码:

    1. // SKProduct+LocalizedPrice.h
    2. #import <Foundation/Foundation.h>
    3. #import <StoreKit/StoreKit.h>
    4. @interface SKProduct (LocalizedPrice)
    5. @property (nonatomic, readonly) NSString *localizedPrice;
    6. @end

    1. // SKProduct+LocalizedPrice.m
    2. #import "SKProduct+LocalizedPrice.h"
    3. @implementation SKProduct (LocalizedPrice)
    4. - (NSString *)localizedPrice
    5. {
    6.     NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    7.     [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    8.     [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    9.     [numberFormatter setLocale:self.priceLocale];
    10.     NSString *formattedString = [numberFormatter stringFromNumber:self.price];
    11.     [numberFormatter release];
    12.     return formattedString;
    13. }
    14. @end
    加入上述代码,测试一下。你应该在控制台窗口中看见产品信息了。然而更大的可能是,你得到了一个无效的产品id。我下一篇文章将介绍怎样对这个问题进行调试。但是,下面的步骤8有可能是阻碍你前进的障碍。

    8. 等待几小时
    遵循了上述所有步骤,但是你的产品仍然是无效的?你是否两次,三次,四次不懈努力地确认你是否遵循了上面提到的每个步骤?你是否已经对网上IAP信息少得可怜而感到绝望?

    那麽,你应该等待。

    你的产品要进入iTunes Connect使得Apple准备好沙箱环境需要一些时间。对于我而言,我是经过了无数次产品无效错误的绝望。而在24小时后,我没有修改任何一行代码,但产品id变为有效。我认为要使产品发佈到Apple的网络系统需要几个小时的时间,但如果你有时间的话,你可以像我一样等上24个小时。

    2,购买产品详细步骤:

    通过步骤1,成功的获取到了产品的SKProduct描述。支持购买实现一下三点即可。

    a,编写代码支持事务(transaction)。

    b,在iTunes Connect中添加程序测试用户。

    c,在设备中登录你的 iTunes Store 帐号。

    详细:

    1. 编写代码支持事务
    首先注意:你将负责开发产品购买的用户界面。StoreKit 未提供任何与用户界面相关的元素。如果你希望你的购买用户界面与App Store一样,那麽你要自己完成。

    下面所有代码都是有关事务处理的后台部分。这是一个单独的类只有一条简单的API以供外部类(比如view controller)调用进行购买。如果你找到将其集成到你程序的购买部分的方法,那麽我推荐你使用类似方桉。

    首先,需要遵循 SKPaymentTransactionObserver 协议:

    1. // InAppPurchaseManager.h
    2. // add a couple notifications sent out when the transaction completes
    3. #define kInAppPurchaseManagerTransactionFailedNotification @"kInAppPurchaseManagerTransactionFailedNotification"
    4. #define kInAppPurchaseManagerTransactionSucceededNotification @"kInAppPurchaseManagerTransactionSucceededNotification"
    5. @interface InAppPurchaseManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
    6. {
    7.     …
    8. }
    9. // public methods
    10. - (void)loadStore;
    11. - (BOOL)canMakePurchases;
    12. - (void)purchaseProUpgrade;
    13. @end
    上面我们定义了两个新的notification,它们将作为购买事务的结果被发送。在上例中我们仍然使用与获取产品描述同一个InAppPurchaseManager类。

    1. // InAppPurchaseManager.m
    2. #define kInAppPurchaseProUpgradeProductId @"com.runmonster.runmonsterfree.upgradetopro"
    3. #pragma -
    4. #pragma Public methods
    5. //
    6. // call this method once on startup
    7. //
    8. - (void)loadStore
    9. {
    10.     // restarts any purchases if they were interrupted last time the app was open
    11.     [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    12.     
    13.     // get the product description (defined in early sections)
    14.     [self requestProUpgradeProductData];
    15. }
    16. //
    17. // call this before making a purchase
    18. //
    19. - (BOOL)canMakePurchases
    20. {
    21.     return [SKPaymentQueue canMakePayments];
    22. }
    23. //
    24. // kick off the upgrade transaction
    25. //
    26. - (void)purchaseProUpgrade
    27. {
    28.     SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId];
    29.     [[SKPaymentQueue defaultQueue] addPayment:payment];
    30. }
    31. #pragma -
    32. #pragma Purchase helpers
    33. //
    34. // saves a record of the transaction by storing the receipt to disk
    35. //
    36. - (void)recordTransaction:(SKPaymentTransaction *)transaction
    37. {
    38.     if ([transaction.payment.productIdentifier isEqualToString:kInAppPurchaseProUpgradeProductId])
    39.     {
    40.         // save the transaction receipt to disk
    41.         [[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:@"proUpgradeTransactionReceipt" ];
    42.         [[NSUserDefaults standardUserDefaults] synchronize];
    43.     }
    44. }
    45. //
    46. // enable pro features
    47. //
    48. - (void)provideContent:(NSString *)productId
    49. {
    50.     if ([productId isEqualToString:kInAppPurchaseProUpgradeProductId])
    51.     {
    52.         // enable the pro features
    53.         [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isProUpgradePurchased" ];
    54.         [[NSUserDefaults standardUserDefaults] synchronize];
    55.     }
    56. }
    57. //
    58. // removes the transaction from the queue and posts a notification with the transaction result
    59. //
    60. - (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
    61. {
    62.     // remove the transaction from the payment queue.
    63.     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    64.     
    65.     NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, @"transaction" , nil];
    66.     if (wasSuccessful)
    67.     {
    68.         // send out a notification that we’ve finished the transaction
    69.         [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo];
    70.     }
    71.     else
    72.     {
    73.         // send out a notification for the failed transaction
    74.         [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo];
    75.     }
    76. }
    77. //
    78. // called when the transaction was successful
    79. //
    80. - (void)completeTransaction:(SKPaymentTransaction *)transaction
    81. {
    82.     [self recordTransaction:transaction];
    83.     [self provideContent:transaction.payment.productIdentifier];
    84.     [self finishTransaction:transaction wasSuccessful:YES];
    85. }
    86. //
    87. // called when a transaction has been restored and and successfully completed
    88. //
    89. - (void)restoreTransaction:(SKPaymentTransaction *)transaction
    90. {
    91.     [self recordTransaction:transaction.originalTransaction];
    92.     [self provideContent:transaction.originalTransaction.payment.productIdentifier];
    93.     [self finishTransaction:transaction wasSuccessful:YES];
    94. }
    95. //
    96. // called when a transaction has failed
    97. //
    98. - (void)failedTransaction:(SKPaymentTransaction *)transaction
    99. {
    100.     if (transaction.error.code != SKErrorPaymentCancelled)
    101.     {
    102.         // error!
    103.         [self finishTransaction:transaction wasSuccessful:NO];
    104.     }
    105.     else
    106.     {
    107.         // this is fine, the user just cancelled, so don’t notify
    108.         [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    109.     }
    110. }
    111. #pragma mark -
    112. #pragma mark SKPaymentTransactionObserver methods
    113. //
    114. // called when the transaction status is updated
    115. //
    116. - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
    117. {
    118.     for (SKPaymentTransaction *transaction in transactions)
    119.     {
    120.         switch (transaction.transactionState)
    121.         {
    122.             case SKPaymentTransactionStatePurchased:
    123.                 [self completeTransaction:transaction];
    124.                 break;
    125.             case SKPaymentTransactionStateFailed:
    126.                 [self failedTransaction:transaction];
    127.                 break;
    128.             case SKPaymentTransactionStateRestored:
    129.                 [self restoreTransaction:transaction];
    130.                 break;
    131.             default:
    132.                 break;
    133.         }
    134.     }
    135. }
    要测试上面的新代码,你还需要编写调用 loadStore, canMakePurchases 以及 purchaseProUpgrade 方法的代码。

    有关上述代码的详细解释,请参考官方 In App Purchase Programming Guide (IAP编程指南)

    上述代码有几个部分是针对我的程序的。例如,在 provideContent:中,NSUserDefaults 中的@”isProUpgradePurchased” BOOL 字段被设定为 YES。程序的其他部分将检查此BOOL值以确定是否需要启动专业版功能。如果你正好也要实现免费升级专业版的功能,那麽你可以使用同样的方法。

    2. 添加测试用户
    为测试上述代码,你需要在 iTunes Connect 中创建测试用户以对IAP功能进行测试。你可以使用测试帐号购买产品而不被Apple收取费用。

    按以下步骤创建测试用户:

    登录到 http://developer.apple.com/iphone
    进入 iTunes Connect
    选择iTunes Connect首页中的 “Manage Users”
    选择 “In App Purchase Test User”
    选择 “Add New User”
    填入用户信息. 所有信息都不必是合法的。建议使用虚假简短的email地址及简短的密码。
    选择 “Save”
    测试时你需要输入这些email地址和密码。

    <1 在添加Test User之前,应该已经设置好ITunes Connect账户中关于Purchase Contract的信息。至少应该点击contract 的request按钮,让contract置于pending in process的状态。
         完成上面的操作后,你才会在刚进入Manage User界面的时候,能选择创建Test User。


      一、在现在的IAP测试中,已经不需要提交程序再让开发者把程序状态设置“Developer Reject”了,只需要程序      到”prepare for upload“就可以了。
    二、在IOS5,已经可以在模拟器中测试,调试IAP这个功能了。


    3. 在你的设备中退出登录
    在进行程序购买功能测试前,你必须在你的设备中退出iTunes Store。遵循以下步骤:

    打开Settings App
    点击 “Store” 行
    点击 “Sign Out”
    4. 购买测试
    现在,终于可以开始进行IAP功能的测试了。测试很简单:

    运行你设备中的程序
    进行购买
    当程序提示输入用户名和密码时,输入参数用户的信息
    如果你使用同一账户进行购买时,系统将提示你已经购买了此产品。按“Yes”就可以再次下载此产品。

    注:向apple服务器提交验证的未证方式:

    NSDictionary *tempDict = [NSDictionary dictionaryWithObject:[transaction transactionReceiptforKey:@"receipt-data"];

    NSString *josnValue = [tempDict JSONRepresentation];

    NSURL *sandboxStoreURL = [[NSURL allocinitWithString@"https://sandbox.itunes.apple.com/verifyReceipt"];

    NSData *postData = [NSData dataWithBytes:[josnValue UTF8Stringlength:[josnValue length]];

    NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:sandboxStoreURL];

    [connectionRequest setHTTPMethod:@"POST"];

    [connectionRequest setTimeoutInterval:120.0];

    [connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];

    [connectionRequest setHTTPBody:postData];

    [[SKPaymentQueue defaultQueuefinishTransaction: transaction];

    NSURLConnection *connection = [[NSURLConnection alloc]

    initWithRequest:connectionRequest

    delegate:self];

    [connection release];

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

    简单地说:
    1. iTunes Connect   ->   Manage Your Applications  ->  Manage In-App Purchases,创建你需要的Product,一般来说分为:消耗型、非消耗型、自动再生订阅、免费订阅、非自动再生订阅几种。消耗型一般适合于游戏里的虚拟物品,以及一次性使用的服务;非消耗型适用于功能解锁等

    2. iTunes Connect 建立一个test user,专门用来测试in-App Purchases的,不会发生实际的购买

    3. 实现IAP有内建模型和服务器模型两种,简单点的话直接内建模型,应用内搞定;要想安全一些,防破解高一些的话,就必须使用服务器模型了。

    应用内建模型:

    In App Purchase为创建产品提供了一种通用的机制,如何操作将由你负责。当你设计程序的时候,有以下几点需要注意:

    1. 你必须提供电子类产品和服务。不要使用In App Purchase 去出售实物和实际服务。
    2. 不能提供代表中介货币的物品,因为让用户知晓他们购买的商品和服务是很重要的。





    服务器模型:

    2. 服务器类型
    使用这终方式,要提供另外的服务器将产品发送给程序。 服务器交付适用于订阅、内容类商品和服务,因为商品可以作为数据发送,而不需改动程序束。 例如,一个游戏提供的新的内容(关卡等)。 Store Kit不会对服务器端的设计和交互做出定义,这方面工作需要你来完成。 而且,Store Kit不提供验证用户身份的机制,你需要来设计。 如果你的程序需要以上功能,例如,纪录特定用户的订阅计划, 你需要自己来设计和实现。

    1. 程序向服务器发送请求,获得一份产品列表。
    2. 服务器返回包含产品标识符的列表。
    3. 程序向App Store发送请求,得到产品的信息。
    4. App Store返回产品信息。
    5. 程序把返回的产品信息显示给用户(App的store界面)
    6. 用户选择某个产品
    7. 程序向App Store发送支付请求
    8. App Store处理支付请求并返回交易完成信息。
    9. 程序从信息中获得数据,并发送至服务器。
    10. 服务器纪录数据,并进行审(我们的)查。
    11. 服务器将数据发给App Store来验证该交易的有效性。
    12. App Store对收到的数据进行解析,返回该数据和说明其是否有效的标识。
    13. 服务器读取返回的数据,确定用户购买的内容。
    14. 服务器将购买的内容传递给程序。

    Apple建议在服务器端存储产品标识,而不要将其存储在plist中。 这样就可以在不升级程序的前提下添加新的产品。

    在服务器模式下, 你的程序将获得交易(transaction)相关的信息,并将它发送给服务器。服务器可以验证收到的数据,并将其解码以确定需要交付的内容。 这个流程将在“验证store收据”一节讨论。

    对于服务器模式,我们有安全性和可靠性方面的顾虑。 你应该测试整个环境来避免威胁。《Secure Coding Guide》文档中有相关的提示说明。

    虽然非消耗性商品可以用内置模式来恢复,订阅类商品必须通过服务器来恢复。你要负责纪录订阅信息、恢复数据。 
    消耗类商品也可以通过服务器方式来纪录。例如,由服务器提供的一项服务, 你可能需要用户在多个设备上重新获得结果。


    首先确保项目链接了StoreKit.framework,应用中添加Store的详细步骤如下:

    1. 定义应用需要递送的products。
    Store Kit对products有一些限制,不允许应用对自己打补丁,或者下载额外的代码。products要么已经在应用的现有代码中,要么从远程服务器下载数据文件来实现。如果应用增加特性需要修改现有代码,必须发布一个新版本的应用。

    2. 在iTunes Connect中为每个product注册详细信息
    每次应用Store要增加一个新的product,都需要先在iTunes Connect中进行注册。每个product都需要一个唯一的ID字符串。App Store使用这个字符串来查找product信息以及处理支付请求。product ID特定于iTunes Connect账号,注册的方式与注册应用类似。
    3. 确定系统能够处理支付
    用户可以禁止应用内购买,因此你的应用需要先检查当前是否支持应用内购买。应用可以在显示Store给用户之前,或者在实际发起购买请求之前,进行这项检查。后者允许用户查看能够购买的products,即使应用内购买当前被禁止。
    if ([SKPaymentQueue canMakePayments])
    {
        ... // 向用户显示Store
    }
    else
    {
        ... // 警告用户当前禁止应用内购买
    }

    4. 获取products的信息
    应用创建一个SKProductsRequest对象,并初始化为一组你想要销售的product ID,添加一个delegate处理请求返回结果,然后就可以发起这个请求。响应结果保存了所有合法的products的本地化信息。应用必须首先获得product的信息,然后才能创建payment请求。

    SKProductsResponse对象为App Store返回的响应信息。里面包含两个列表(当然是NSArray了):一是经过验证有效的商品,
    @property(nonatomic, readonly) NSArray *products
    另外一个是无法被识别的商品信息:
    @property(nonatomic, readonly) NSArray * invalidProductIdentifiers
    有几种原因将造成商品标识无法被识别,如拼写错误(当然),被标记为不可出售(unavailable for sale),或是对商品信息的改变没有传送到所有App Store的服务器。(这个原因不是很清楚,再议)。


    - ( void ) requestProductData
    {
        SKProductsRequest *request= [[SKProductsRequest alloc]
    initWithProductIdentifiers: [ NSSet setWithObject:
    kMyFeatureIdentifier]];
        request.delegate = self ;
        [request start];
    }
    - ( void )productsRequest:(SKProductsRequest *)request
    didReceiveResponse:(SKProductsResponse *)response
    {
         NSArray *myProduct = response.products;
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值