http://yarin.blog.51cto.com/1130898/549141php
1、In App Purchase概览json
Store Kit表明App和App Store之间进行通讯。程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买。
当用户须要购买某件产品时,程序调用StoreKit来收集购买信息。下图即为基本的store kit 模型:安全
Store Kit的API只是为程序添加In App Purchase功能的一小部分。你须要决定如何去记录那些你想要提交的产品,如何在程序中将商店功能展示给用户,
还要考虑如何将用户购买的产品提交。本章的剩余部分会展现整个流程。服务器
Products
产品能够是任意一项你想要出售的特性。产品在iTunes Connect中被组织,这和你添加一个新的App是同样的。支持的产品种类共有四种:
1. 内容型。包括电子书,电子杂志,照片,插图,游戏关卡,游戏角色,和其余的数字内容。
2. 扩展功能。这些功能已经包含在App内部。在未购买以前被锁定。例如,你能够在一个游戏程序中包含若干个小游戏,用户能够分别来购买这些游戏。
3. 服务。容许程序对单次服务收费。好比录音服务。
4. 订阅。支持对内容或服务的扩展访问。例如,你的程序能够每周提供财务信息或游戏门户网站的信息。应该设定一个合理的更新周期,以免过于频繁的
提示困扰用户。要记住:你将负责跟踪订阅的过时信息,而且管理续费。App Store不会替你监视订阅的周期,也不提供自动收费的机制。并发
In App Purchase为建立产品提供了一种通用的机制,如何操做将由你负责。当你设计程序的时候,有如下几点须要注意:app
1. 你必须提供电子类产品和服务。不要使用In App Purchase 去出售实物和实际服务。
2. 不能提供表明中介货币的物品,由于让用户知晓他们购买的商品和服务是很重要的。curl
2. 服务器类型
使用这终方式,要提供另外的服务器将产品发送给程序。 服务器交付适用于订阅、内容类商品和服务,由于商品能够做为数据发送,而不需改动程序束。 例如,一个游戏提供的新的内容(关卡等)。 Store Kit不会对服务器端的设计和交互作出定义,这方面工做须要你来完成。 并且,Store Kit不提供验证用户身份的机制,你须要来设计。 若是你的程序须要以上功能,例如,纪录特定用户的订阅计划, 你须要本身来设计和实现。异步
图1-3 展现了服务器类型的购买过程。ide
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》文档中有相关的提示说明。
虽然非消耗性商品能够用内置模式来恢复,订阅类商品必须经过服务器来恢复。你要负责纪录订阅信息、恢复数据。
消耗类商品也能够经过服务器方式来纪录。例如,由服务器提供的一项服务, 你可能须要用户在多个设备上从新得到结果。
(这段翻译的比较生硬,由于我我的也没有机会把各类类型的服务跑一遍,后续会检查并修改。但愿你们一块儿来看看,欢迎补充。)
取得产品信息
要在程序内部显示“商店”,须要从App Store获得信息来购建界面。 本章详细讲解如何从App Store获取产品信息。
向App Store发送请求
Store Kit提供了从App Store上请求数据的通用机制。 程序能够建立并初始化一个request对象, 为其附加delegate, 而后启动请求过程。请求将被发送到App Store,在那里被处理。 处理完成时, request对象的delegate方法将被异步调用,以得到请求的结果。 图2-1显示了请求的数据模型。
若是程序在请求期间退出,则须要从新发送请求。
下面讲解请求过程当中用到的类:
SKRequest
SKRequest为request的抽象根类。
SKRequestDelegate
SKRequestDelegate是一个protocol, 实现用以处理请求结果的方法,好比请求成功,或请求失败。
发送得到产品信息的请求
程序使用products request来得到产品的信息。 要完成这一过程,程序需建立一个request对象,其中会包含一个产品标识的列表。以前提到过,你的程序既能够内置产品列表,又能够经过外部服务器来得到。
当发送请求时,产品标识会传送到App Store,App Store将会返回本地化信息(这些信息事先已经在iTunes Connect中设置好了),你将使用这些信息来购建内置商店的界面(显示商品名,描述,等等)。 图2-2显示了请求的过程。
SKProductsRequest
用来请求商品的信息。 建立时,咱们将须要显示的商品列表加入该对象。
SKProductsRequestDelegate
该protocol定义了处理App Store响应的方法。
SKProductsResponse
SKProductsResponse对象为App Store返回的响应信息。里面包含两个列表(固然是NSArray了):一是通过验证有效的商品,
@property(nonatomic, readonly) NSArray *products
另一个是没法被识别的商品信息:
@property(nonatomic, readonly) NSArray * invalidProductIdentifiers
有几种缘由将形成商品标识没法被识别,如拼写错误(固然),被标记为不可出售(unavailable for sale),或是对商品信息的改变没有传送到全部App Store的服务器。(这个缘由不是很清楚,再议)。
SKProduct
SKProduct对象包含了在App Store上注册的商品的本地化信息。
购买商品
当用户准备购买商品时,程序向App Store请求支付信息,而后App Store将会建立持久化的交易信息,并继续处理支付流程,即便用户重启程序,这个过程亦是如此。App Store同步待定交易的列表到程序中,并在交易状态发生改变时向程序发送更新的数据。
收集支付信息
要收集支付信息, 你的程序能够建立一个payment的对象,将它放到支付队列中,如图3-1所示。
1. 一个SKPayment的对象,包含了"Sword"的商品标识,而且制定购买数量为1。
2. 使用addPayment:方法将SKPayment的对象添加到SKPaymentQueue里。
3. SKPaymentmentQueue包含的全部请求商品,
4. 使用SKPaymentTransactionObserver的paymentQueue: updatedTransactions: 方法来检测全部完成的购买,并发送购买的商品。
5. 最后,使用finishTransaction:方法完成交易。
当payment的对象被添加到支付队列中的时候, 会建立一个持久保存的transaction对象来存放它。 当支付被处理后,transaction被更新。 程序中将实现一个观察者(observer)对象来获取transaction更新的消息。 观察者应该为用户提供购买的商品,而后将transaction从队列中移除。
下面介绍在购买过程当中用到的几个类:
SKPayment
要收集支付信息,先要了解一下支付对象。 支付对象包含了商品的标识(identifier)和要购买商品的数量(quantity)(数量可选)。你能够把同一个支付对象重复放入支付队列,,每一次这样的动做都至关于一次独立的支付请求。
用户能够在Settings程序中禁用购买的功能。 所以在请求支付以前,程序应该首先检查支付是否能够被处理。 调用SKPaymentQueue的canMakePayments方法来检查。
SKPaymentQueue
支付队列用以和App Store之间进行通讯。 当新的支付对象被添加到队列中的时候, Store Kit向App Store发送请求。 Store Kit将会弹出对话框询问用户是否肯定购买。 完成的交易将会返回给程序的observer对象。
SKPaymentTransaction
transaction对象在每次添加新的payment到队列中的时候被建立。 transaction对象包含了一些属性,可让程序肯定当前的交易状态。
程序能够从支付队列那里获得一份审核中的交易列表,但更经常使用的作法仍是等待支付队列告知交易状态的更新。
SKPaymentTransactionObserver
在程序中实现SKPaymentTransactionObserver的协议,而后把它做为SKPaymentQueue对象的观察者。该观察者的主要职责是:检查完成的交易,交付购买的内容,和把完成后的交易对象从队列中移除。
在程序一启动,就应该为支付队列指定对应的观察者对象,而不是等到用户想要购买商品的时候。 Transaction对象在程序退出时不会丢失。程序重启时, Store Kit继续执行未完成的交易。 在程序初始化的时候添加观察者对象,能够保证全部的交易都被程序接收(也就时说,若是有未完成的transaction,若是程序重启,就从新开始了,若是稍候再添加观察者,就可能会漏掉部分交易的信息)。
恢复交易信息(Transactions)
当transaction被处理并从队列移除以后,正常状况下,程序就再也看不到它们了。 若是你的程序提供的是非消耗性的或是订阅类的商品,就必须提供restore的功能,使用户能够在其余设备上从新存储购买信息。
Store Kit提供内建的功能来从新存储非消耗商品的交易信息。 调用SKPaymentQueue的restoreCompletedTransactions的方法来从新存储。对于那些以前已经完成交易的非消耗性商品,Apple Store生成新的,用于恢复的交易信息。 它包含了原始的交易信息。你的程序能够拿到这个信息,而后继续为购买的功能解锁。 当以前全部的交易都被恢复时, 就会调用观察者对象的paymentQueueRestoreCompletedTransactionsFinished方法。
若是用户试图购买已经买过的非消耗性商品,程序会收到一个常规的交易信息,而不是恢复的交易信息。可是用户不会被再次收费。程序 应把这类交易和原始的交易同等对待。
订阅类服务和消耗类商品不会被Store Kit自动恢复。 要恢复这些商品,你必须在用户购买这些商品时,在你本身的服务器上记录这些交易信息, 而且为用户的设备提供恢复交易信息的机制。
在程序中添加Store功能
本章为添加购买功能的指导
详细流程:
准备工做固然是添加StoreKit.framework了。
而后是具体的步骤:
1. 决定在程序内出售的商品的类型。
以前提到过,程序内能够出售的新feature类型是有限制的。 Store Kit不容许咱们下载新的代码。 你的商品要么能够经过当前的代码工做(bundle类型),要么能够经过服务器下载(固然,这里下载的为数据文件,代码是不能够的)。 若是要修改源代码,就只能老实的升级了。
2. 经过iTunes Connect注册商品
每次添加新商品的时候都须要执行这一步骤。 每一个商品都须要一个惟一的商品标识。 App Store经过这个标识来查找商品信息并处理支付流程。 注册商品标识的方法和注册程序的方法相似。
要了解如何建立和注册商品信息,请参考“iTunes Connect Developer Guide”文档。
3. 检测是否能够进行支付
用户能够禁用在程序内部支付的功能。在发送支付请求以前,程序应该检查该功能是否被开启。程序可在显示商店界面以前就检查该设置(没启用就不显示商店界面了),也能够在用户发送支付请求前再检查,这样用户就能够看到可购买的商品列表了。
例子:
4. 得到商品的信息
程序建立SKProductsRequest对象,用想要出售的商品的标识来初始化, 而后附加上对应的委托对象。 该请求的响应包含了可用商品的本地化信息。
5. 添加一个展现商品的界面
Store Kit不提供界面的类。 这个界面须要咱们本身来设计并实现。
6. 为支付队列(payment queue)注册一个观察者对象
你的程序须要初始化一个transaction observer对象并把它指定为payment queue的观察者。
上代码:
应该在程序启动的时候就添加好观察者,缘由前面说过,重启后程序会继续上次未完的交易,这时就添加观察者对象就不会漏掉以前的交易信息。
7. 在MyStoreObserver类中执行paymentQueue: updatedTransactions: 方法。
这个方法会在有新的交易被建立,或者交易被更新的时候被调用。
上面的函数针对不一样的交易返回状态,调用对应的处理函数。
8. 观察者对象在用户成功购买一件商品时,提供相应的内容,如下是在交易成功后调用的方法
交易成功的信息包含transactionIdentifier和transactionReceipt的属性。其中,transactionReceipt记录了支付的详细信息,这个信息能够帮助你跟踪、审(咱们的)查交易,若是你的程序是用服务器来交付内容,transactionReceipt能够被传送到服务器,而后经过App Store验证交易。(以前提到的server模式,能够参考之前的图)
9. 若是交易是恢复过来的(restore),咱们用这个方法来处理:
这个过程完成购买的过程相似。 恢复的购买内容提供一个新的交易信息,这个信息包含了新的transaction的标识和receipt数据。 若是须要的话,你能够把这些信息单独保存下来,供追溯审(咱们的)查之用。但更多的状况下,在交易完成时,你可能须要覆盖原始的transaction数据,并使用其中的商品标识。
10. 交易过程失败的话,咱们调用以下的方法:
一般状况下,交易失败的缘由是取消购买商品的流程。 程序能够从error中读出交易失败的详细信息。
显示错误信息不是必须的,但在上面的处理方法中,须要将失败的交易从支付队列中移除。 通常来讲,咱们用一个对话框来显示错误信息,这时就应避免将用户取消购买这个error显示出来。
11. 组织好程序内“商店”的UI。当用户选择一件商品时, 建立一个支付对象,并放到队列中。
若是你的商店支持选择同一件商品的数量,你能够设置支付对象的quantity属性
下一步:
本章中所示代码可用于内置型商品模式(Built-in)。 若是你的程序要使用服务器来发布商品,你须要负责设计和执行iPhone程序和你的服务器之间的通讯。服务器应该验证数据并为程序提供内容。
验证store的收据
使用服务器来交付内容,咱们还须要作些额外的工做来验证从Store Kit发送的收据信息。
重要信息:来自Store的收据信息的格式是专用的。 你的程序不该直接解析这类数据。可以使用以下的机制来取出其中的信息。
验证App Store返回的收据信息
当交易完成时,Store Kit告知payment observer这个消息,并返回完成的transaction。 SKPaymentTransaction的transactionReceipt属性就包含了一个通过签名的收据信息,其中记录了交易的关键信息。你的服务器要负责提交收据信息来肯定其有效性,并保证它未通过篡改。 这个过程当中,信息被以JSON数据格式发送给App Store,App Store也以JSON的格式返回数据。
(你们能够先了解一下JSON的格式)
验证收据的过程:
1. 从transaction的transactionReceipt属性中获得收据的数据,并以base64方式编码。
2. 建立JSON对象,字典格式,单键值对,键名为"receipt-data", 值为上一步编码后的数据。效果为:
3. 发送HTTP POST的请求,将数据发送到App Store,其地址为:
https://buy.itunes.apple.com/verfyReceipt
4. App Store的返回值也是一个JSON格式的对象,包含两个键值对, status和receipt:
若是status的值为0, 就说明该receipt为有效的。 不然就是无效的。
App Store的收据
发送给App Store的收据数据是经过对transaction中对应的信息编码而建立的。 当App Store验证收据时, 将从其中解码出数据,并以"receipt"的键返回。 返回的响应信息是JSON格式,被包含在SKPaymentTransaction的对象中(transactionReceipt属性)。Server可经过这些值来了解交易的详细信息。 Apple建议只发送receipt数据到服务器并使用receipt数据验证和得到交易详情。 由于App Store可验证收据信息,返回信息,保证信息不被篡改,这种方式比同时提交receipt和transaction的数据要安全。(这段得再看看)
表5-1为交易信息的全部键,不少的键都对应SKPaymentTransaction的属性。
备注:一些键取决于你的程序是连接到App Store仍是测试用的Sandbox环境。更多关于sandbox的信息,请查看"Testing a Store"一章。
Table 5-1 购买信息的键:
键名 | 描述 |
quantity | 购买商品的数量。对应SKPayment对象中的quantity属性 |
product_id | 商品的标识,对应SKPayment对象的productIdentifier属性。 |
transaction_id | 交易的标识,对应SKPaymentTransaction的transactionIdentifier属性 |
purchase_date | 交易的日期,对应SKPaymentTransaction的transactionDate属性 |
original_-transaction_id | 对于恢复的transaction对象,该键对应了原始的transaction标识 |
original_purchase_-date | 对于恢复的transaction对象,该键对应了原始的交易日期 |
app_item_id | App Store用来标识程序的字符串。一个服务器可能须要支持多个server的支付功能,能够用这个标识来区分程序。连接sandbox用来测试的程序的不到这个值,所以该键不存在。 |
version_external_-identifier | 用来标识程序修订数。该键在sandbox环境下不存在 |
bid | iPhone程序的bundle标识 |
bvrs | iPhone程序的版本号 |
测试Store功能
开发过程当中,咱们须要测试支付功能以保证其工做正常。然而,咱们不但愿在测试时对用户收费。 Apple提供了sandbox的环境供咱们测试。
备注:Store Kit在模拟器上没法运行。 当在模拟器上运行Store Kit的时候,访问payment queue的动做会打出一条警告的log。测试store功能必须在真机上进行。
Sandbox环境
使用Sandbox环境的话,Store Kit并无连接到真实的App Store,而是连接到专门的Sandbox环境。 SandBox的内容和App Store一致,只是它不执行真实的支付动做。 它会返回交易成功的信息。 Sandbox使用专门的iTunes Connect测试 帐户。不能使用正式的iTunes Connect帐户来测试。
要测试程序,须要建立一个专门的测试帐户。你至少须要为程序的每一个区域建立至少一个测试帐户。详细信息,请查看iTunes Connect Developer Guide文档。
在Sandbox环境中测试
步骤:
1. 在测试的iPhone上退出iTunes帐户
Settings中可能会记录以前登陆的帐户,进入并退出。
重要信息:不能在Settings 程序中经过测试帐户登陆。
2. 运行程序
当你在程序的store中购买商品后,Store kit提示你去验证交易。用测试帐户登陆,并批准支付。 这样虚拟的交易就完成了。
后台php代码示例:
注:支付订单中并无玩家相关标识,若是CP方服务器须要将购买道具从后台发送到玩家帐户,则能够经过Get或Post的方式传递其余字段信息到服务器。
如:
另外,订单协议中只有玩家购买的道具信息,没有这次该玩家消费的金额,须要CP方服务器于后台自行兑帐。
在Sandbox中验证收据
验证的URL不一样了: