In App Purchases(IAP 应用程序内购买)完全攻略.doc_第1页
In App Purchases(IAP 应用程序内购买)完全攻略.doc_第2页
In App Purchases(IAP 应用程序内购买)完全攻略.doc_第3页
In App Purchases(IAP 应用程序内购买)完全攻略.doc_第4页
In App Purchases(IAP 应用程序内购买)完全攻略.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

In App Purchases(IAP 应用程序內购买): 完全攻略 原文:/blog/2010/01/in-app-purchases-a-full-walkthrough/参考:/bbs/read.php?tid-11357.html第一印象觉得In-App Purchase(简称IAP)非常简单。Apple提供的大量文档应该让开发者很快熟悉地熟悉。那麽,为什麽在你的应用中集成IAP特性就如此令人生厌呢?这是因为在开发过程中不可避免会出现一些错误。而但这些错误发生的时候,你就抓瞎了。虽然Apple提供了有关IAP的大量文档,但他们并未提及集成IAP的详细步骤。而且对StoreKit集成过程中出现的问题也没有一个核对清单。另外对于为什麽诸如产品ID非法之类的问题也没有提供NSError之类的对象来告诉你原因。在试用了各种可能的解决方桉后,你只能身心疲惫,彷徨无助。为了提高你的效率和减少你的痛苦,我觉定利用此文来介绍一下实现IAP的详细步骤。本文很详细,有点长。甚至可能太长了,但不像Apple的文档,它提供了为实现IAP的每一个步骤。废话少说,我们直入主题吧。概况IAP能正常工作的秘诀:分成两个步骤:创建及提取产品描述购买产品第一个步骤是你可能遇到问题的部分。一旦你在代码中成功地获取了产品描述,编写购买产品的代码不过是小菜一碟。我们先看看步骤1。创建及提取产品描述下面是有关创建产品及提取其描述的非常粗略的步骤:创建唯一的App ID生成及安装新的provisioning profile文件在Xcode中更新 bundle ID 及 code signing profile如果还没做的话,请在iTunes Connect中提交有关你程序的 metadata如果还没做的话,请在iTunes Connect中提交你程序的二进制码为IAP添加新产品编写提取产品描述的代码等待几小时提取产品描述的代码非常简单,但其他步骤则很容易错。注意: 为提取产品描述,你并不需要在iTunes Connect中创建IAP测试用户。1. 创建唯一的App ID为支持IAP,你的App ID不能包括通配符(“*”)。为确定你的App Id是否包括通配符,请登录/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(后缀): panyname.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 profile4. 添加你的应用程序如果你的程序已经发表到App Store了,那麽可以略过此步骤。在你将产品添加到 iTunes Connect之前,你必须添加此产品所需的程序。如果你的程序还没有100%完成也无需担心,你可以先提交具有部分数据的程序,最后再提交真实的程序。注意: 只有 SKU 和 version(版本)部分是以后不可修改的登录到 /iphone点击右边链接进入 iTunes Connect注意:你必须先登录到,否则会有不测发生(译者注:具体是什麽不测我也不太清楚,胆大的请自己试一下)在 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中添加产品了。确保登录到 /iphone进入 iTunes Connect 主页点击 “Manage Your in App Purchases” 链接点击 “Create New”选择你的程序填写下列产品信息:Reference Name(参考名称): 产品的通用名称。比如,我使用的是 “Pro Upgrade”。此名称是不允许进行编辑的,它不会显示于App Store中。Product ID(产品ID): 你产品的唯一id。通常格式是 duct,但它可以说任何形式。它并不要求以程序的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”7. 编写代码下面我们开始编写代码对刚加入到iTunes Connect中的产品信息进行提取。我访问产品数据,我们需要使用 StoreKit framework。注意: StoreKit 无法在模拟器上工作。你必须在真机上进行测试。1.添加 StoreKit framework 到你的项目中。2.添加SKProduct引用到你的 .h 文件中:1 复制代码/ InAppPurchaseManager.h2 #import 3 #define kInAppPurchaseManagerProductsFetchedNotification kInAppPurchaseManagerProductsFetchedNotification4 interface InAppPurchaseManager : NSObject 5 6 SKProduct *proUpgradeProduct;7 SKProductsRequest *productsRequest;8 注意: InAppPurchaseManager 是一个单例类,它处理程序中所有IAP任务。它是本文中的示例程序。3.产品请求,并在相应.m文件中实现代理协议:9 复制代码/ InAppPurchaseManager.m10 - (void)requestProUpgradeProductData11 12 NSSet *productIdentifiers = NSSet setWithObject:com.runmonster.runmonsterfree.upgradetopro ;13 productsRequest = SKProductsRequest alloc initWithProductIdentifiers:productIdentifiers;14 productsRequest.delegate = self;15 productsRequest start;16 17 / we will release the request object in the delegate callback18 19 #pragma mark -20 #pragma mark SKProductsRequestDelegate methods21 - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response22 23 NSArray *products = ducts;24 proUpgradeProduct = products count = 1 ? products firstObject retain : nil;25 if (proUpgradeProduct)26 27 NSLog(Product title: % , proUpgradeProduct.localizedTitle);28 NSLog(Product description: % , proUpgradeProduct.localizedDescription);29 NSLog(Product price: % , proUpgradeProduct.price);30 NSLog(Product id: % , proUpgradePductIdentifier);31 32 33 for (NSString *invalidProductId in response.invalidProductIdentifiers)34 35 NSLog(Invalid product id: % , invalidProductId);36 37 38 / finally release the reqest we alloc/inited in requestProUpgradeProductData39 productsRequest release;40 41 NSNotificationCenter defaultCenter postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil;42 上面代码有几点需要注意:指定产品id时,你必须使用完整产品id。例如,上例中使用 “com.runmonster.runmonsterfree.upgradetopro”。仅使用 “upgradetopro” 将不会正常工作。如果在productsRequest:didReceiveResponse:中ducts 为 nil,而你的产品id出现于 response.invalidProductIdentifers 数组中时,那麽请做好心理准备开始一场徒劳的搜索战吧。 StoreKit API没有提供任何帮助,也没有任何指示关于为什麽你的id是无效的。很可爱,不是吗?SKProduct类提供了有关程序标题和描述的本地化版本,但是价格则没有本地化版本。下面是针对此疏忽提供的代码:43 复制代码/ SKProduct+LocalizedPrice.h44 #import 45 #import 46 interface SKProduct (LocalizedPrice)47 property (nonatomic, readonly) NSString *localizedPrice;48 end49 复制代码/ SKProduct+LocalizedPrice.m50 #import SKProduct+LocalizedPrice.h51 implementation SKProduct (LocalizedPrice)52 - (NSString *)localizedPrice53 54 NSNumberFormatter *numberFormatter = NSNumberFormatter alloc init;55 numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4;56 numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle;57 numberFormatter setLocale:self.priceLocale;58 NSString *formattedString = numberFormatter stringFromNumber:self.price;59 numberFormatter release;60 return formattedString;61 62 end加入上述代码,测试一下。你应该在控制台窗口中看见产品信息了。然而更大的可能是,你得到了一个无效的产品id。我下一篇文章将介绍怎样对这个问题进行调试。但是,下面的步骤8有可能是阻碍你前进的障碍。8. 等待几小时遵循了上述所有步骤,但是你的产品仍然是无效的?你是否两次,三次,四次不懈努力地确认你是否遵循了上面提到的每个步骤?你是否已经对网上IAP信息少得可怜而感到绝望?那麽,你应该等待。你的产品要进入iTunes Connect使得Apple准备好沙箱环境需要一些时间。对于我而言,我是经过了无数次产品无效错误的绝望。而在24小时后,我没有修改任何一行代码,但产品id变为有效。我认为要使产品发佈到Apple的网络系统需要几个小时的时间,但如果你有时间的话,你可以像我一样等上24个小时。购买产品至此你应该已经成功地获取了 SKProduct 描述。比较而言,支持购买产品相对简单些。仅需下面三个步骤:编写代码支持事务(transaction)在iTunes Connect中添加程序测试用户在设备中登录你的 iTunes Store 帐号购买测试我们从编写支持事务所需代码开始。1. 编写代码支持事务首先注意:你将负责开发产品购买的用户界面。StoreKit 未提供任何与用户界面相关的元素。如果你希望你的购买用户界面与App Store一样,那麽你要自己完成。下面所有代码都是有关事务处理的后台部分。这是一个单独的类只有一条简单的API以供外部类(比如view controller)调用进行购买。如果你找到将其集成到你程序的购买部分的方法,那麽我推荐你使用类似方桉。首先,需要遵循 SKPaymentTransactionObserver 协议:63 复制代码/ InAppPurchaseManager.h64 / add a couple notifications sent out when the transaction completes65 #define kInAppPurchaseManagerTransactionFailedNotification kInAppPurchaseManagerTransactionFailedNotification66 #define kInAppPurchaseManagerTransactionSucceededNotification kInAppPurchaseManagerTransactionSucceededNotification67 68 interface InAppPurchaseManager : NSObject 69 70 71 72 / public methods73 - (void)loadStore;74 - (BOOL)canMakePurchases;75 - (void)purchaseProUpgrade;76 end上面我们定义了两个新的notification,它们将作为购买事务的结果被发送。在上例中我们仍然使用与获取产品描述同一个InAppPurchaseManager类。77 复制代码/ InAppPurchaseManager.m78 #define kInAppPurchaseProUpgradeProductId com.runmonster.runmonsterfree.upgradetopro79 80 #pragma -81 #pragma Public methods82 /83 / call this method once on startup84 /85 - (void)loadStore86 87 / restarts any purchases if they were interrupted last time the app was open88 SKPaymentQueue defaultQueue addTransactionObserver:self;89 90 / get the product description (defined in early sections)91 self requestProUpgradeProductData;92 93 /94 / call this before making a purchase95 /96 - (BOOL)canMakePurchases97 98 return SKPaymentQueue canMakePayments;99 100 /101 / kick off the upgrade transaction102 /103 - (void)purchaseProUpgrade104 105 SKPayment *payment = SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId;106 SKPaymentQueue defaultQueue addPayment:payment;107 108 #pragma -109 #pragma Purchase helpers110 /111 / saves a record of the transaction by storing the receipt to disk112 /113 - (void)recordTransaction:(SKPaymentTransaction *)transaction114 115 if (ductIdentifier isEqualToString:kInAppPurchaseProUpgradeProductId)116 117 / save the transaction receipt to disk118 NSUserDefaults standardUserDefaults setValue:transaction.transactionReceipt forKey:proUpgradeTransactionReceipt ;119 NSUserDefaults standardUserDefaults synchronize;120 121 122 /123 / enable pro features124 /125 - (void)provideContent:(NSString *)productId126 127 if (productId isEqualToString:kInAppPurchaseProUpgradeProductId)128 129 / enable the pro features130 NSUserDefaults standardUserDefaults setBool:YES forKey:isProUpgradePurchased ;131 NSUserDefaults standardUserDefaults synchronize;132 133 134 /135 / removes the transaction from the queue and posts a notification with the transaction result136 /137 - (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful138 139 / remove the transaction from the payment queue.140 SKPaymentQueue defaultQueue finishTransaction:transaction;141 142 NSDictionary *userInfo = NSDictionary dictionaryWithObjectsAndKeys:transaction, transaction , nil;143 if (wasSuccessful)144 145 / send out a notification that weve finished the transaction146 NSNotificationCenter defaultCenter postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo;147 148 else149 150 / send out a notification for the failed transaction151 NSNotificationCenter defaultCenter postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo;152 153 154 /155 / called when the transaction was successful156 /157 - (void)completeTransaction:(SKPaymentTransaction *)transaction158 159 self recordTransaction:transaction;160 self provideContent:ductIdentifier;161 self finishTransaction:transaction wasSuccessful:YES;162 163 /164 / called when a transaction has been restored and and successfully completed165 /166 - (void)restoreTransaction:(SKPaymentTransaction *)transaction167 168 self recordTransaction:transaction.originalTransaction;169 self provideContent:transaction.originalTductIdentifier;170 self finishTransaction:transaction wasSuccessful:YES;171 172 /173 / called when a transaction has failed174 /175 - (void)failedTransaction:(SKPaymentTransaction *)transaction176 177 if (transaction.error.code != SKErrorPaymentCancelled)178 179 / error!180 self finishTransaction:transaction wasSuccessful:NO;181 182 else183 184 / this is fine, the user just cancelled, so dont notify185 SKPaymentQueue defaultQueue finishTransaction:transaction;186 187 188 #pragma mark -189 #pragma mark SKPaymentTransactionObserver methods190 /191 / called when the transaction status is updated192 /193 - (void)p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论