最近做了iOS程序内购买,封装了一下给上层调用,现在介绍下流程和简单的实现。具体可以看我上传到Github的代码ZInAppPurchase,或者直接在CocoaPods拉取ZInAppPurchase。(第一次试试上传到CocoaPods,还没加demo)
程序内购买要做的话要考虑很多,像漏单处理、重新购买处理等等,对于游戏App来说更需要考虑。下面只介绍最简单的流程和处理。
iOS程序内购买流程主要分几步:
iTunes Connect商品配置添加沙箱技术测试员App内获取购买商品验证receipt主要是填写完整信息和添加商品。
登录iTunes Connect,进入”协议、税务和银行业务“。
如果Contracts In PRocess下有All(See Contract)和Contact Info、Bank Info、Tax Info三列,则表示已填写;否则点击Request按照提示进行操作。之后就会出现Contact Info、Bank Info、Tax Info三列,分别Set Up(需要同公司财务人员一起填写)。
(如果没有填写完整只能添加免费订阅商品)
登录iTunes Connect,进入我的App——功能——App内购买项目,点击+号。可以添加的类型有:消耗型项目、非消耗型项目、自动续订订阅、免费订阅、非续订订阅。商品添加完屏幕快照就会变成准备提交状态。
注意:产品 ID不可重复,如果删除某个商品,以后这个产品的ID也不可用,即使它已经被删除了;另外类型也不能改,选错了只能重新增加一个商品。
登录iTunes Connect,进入用户和职能——沙箱技术测试员,点击+号。(必须是未注册的Apple账号,用于测试购买)
根据productId获取商品信息(可以获取多个):
let productRequest = SKProductsRequest(productIdentifiers: Set<String>(arrayLiteral: productId))productRequest.delegate = selfproductRequest.start()实现SKProductsRequestDelegate:
func productsRequest(request: SKProductsRequest, didReceiveResponse response: SKProductsResponse) { if let product = response.products.first {// 获取返回的商品 }}购买商品购买获取的商品product:
if SKPaymentQueue.canMakePayments() {// 是否能且允许支付 let payment = SKPayment(product: product) SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().addPayment(payment)}实现SKPaymentTransactionObserver:
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .Purchased: // Transaction is in queue, user has been charged. Client should complete the transaction. if let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL, let receiptData = NSData(contentsOfURL: receiptUrl) { let receiptString = receiptData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) // 将receiptString发给服务器 } SKPaymentQueue.defaultQueue().finishTransaction(transaction) case .Failed: // Transaction was cancelled or failed before being added to the server queue. if let errorCode = transaction.error?.code { } SKPaymentQueue.defaultQueue().finishTransaction(transaction) default: break } }}receipt验证可以本地验证,也可以提交给App Store验证。
参考链接:Validating Receipts With the App Store
我们是将receipt进行base64编码后,传给服务器,服务器判断凭证是否已经存在或验证过,再去POST给Apple服务器验证。
沙箱环境POST的URLhttps://sandbox.itunes.apple.com/verifyReceipt
正式环境POST的URLhttps://buy.itunes.apple.com/verifyReceipt
验证后Apple会返回数据,从中可以获取product_id、quantity等,下面是正确时的返回数据:
{ "status": 0, "environment": "Sandbox", "receipt": { "receipt_type": "ProductionSandbox", "adam_id": 0, "app_item_id": 0, "bundle_id": "com.xxx.xxxxxx", "application_version": "999", "download_id": 0, "version_external_identifier": 0, "receipt_creation_date": "2016-05-26 04:35:08 Etc/GMT", "receipt_creation_date_ms": "1464237308000", "receipt_creation_date_pst": "2016-05-25 21:35:08 America/Los_Angeles", "request_date": "2016-05-26 06:40:32 Etc/GMT", "request_date_ms": "1464244832729", "request_date_pst": "2016-05-25 23:40:32 America/Los_Angeles", "original_purchase_date": "2013-08-01 07:00:00 Etc/GMT", "original_purchase_date_ms": "1375340400000", "original_purchase_date_pst": "2013-08-01 00:00:00 America/Los_Angeles", "original_application_version": "1.0", "in_app": [ { "quantity": "1", "product_id": "000000", "transaction_id": "1000000213676495", "original_transaction_id": "1000000213676495", "purchase_date": "2016-05-26 04:35:08 Etc/GMT", "purchase_date_ms": "1464237308000", "purchase_date_pst": "2016-05-25 21:35:08 America/Los_Angeles", "original_purchase_date": "2016-05-26 04:35:08 Etc/GMT", "original_purchase_date_ms": "1464237308000", "original_purchase_date_pst": "2016-05-25 21:35:08 America/Los_Angeles", "is_trial_period": "false" } ] }}下面是在沙箱环境下的真机测试截图(“测试”是所填写的产品名称,未登录Apple ID时会提示登录,已登录时会提示输入密码/Touch ID):
IMG_6816.PNGIMG_6814.PNG在iTunes Connect添加完App版本后,在App 内购买项目处添加该版本新增的App内购买项目。
新闻热点
疑难解答