内购其实真的不难,不信你往下看
首先我们来总体看下内购的流程
- 资料填写 (协议,税务,银行业务,联系信息)
- App Store 配置(内购账号及产品ID) 及Xcode配置
3.项目主要代码及二次验证
完成以上几个步骤内购你就了解的差不多了。
一. 资料填写
你需要准备的资料
1.联系地址(英文)
2.银行账户(公司名称,账号,账户持有人姓名,账户类型(公司/个人),CNAPS)
3.一个没有与 App ID 有关联的邮箱(差不多就是添加测试账号的时候去注册App ID)
按照步骤填写就行。《不懂点这里》
二. 添加沙盒测试账户及内购产品ID。
现在添加内购产品。创建的产品会保存在苹果的服务器上面。请求购买的时候会需要带上这个产品ID。
App Store Connect ->我的App ->App 内购项目 -> 管理
1.这里根据你们app自己的产品选择合适的项目。
2.接下来进行产品ID的设置。
到这里内购信息,沙盒测试账号及产品ID就填写完成了。
Xcode项目设置,添加 In-App Purchase。
三。项目主要代码
项目主要用到StoreKit 框架。继承协议 SKProductsRequestDelegate ,SKPaymentTransactionObserver实现代理方法。
1.根据产品ID去苹果服务器请求产品。
let requset = SKProductsRequest.init(productIdentifiers: NSSet(object: productId) as! Set )
requset.delegate = self
requset.start()
// 请求到产品会调用这个代理方法
// MARK : ==== SKProductsRequest Delegate ====
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
if response.products.isEmpty {
delegate?.failurePurchaseWithError("无法获取产品信息")
return
}
myProducts = response.products
delegate?.receiveProduct(myProducts[0])
}
2.根据请求到的产品进行支付请求。
if SKPaymentQueue.canMakePayments() {
let payment = SKPayment(product: skProduct)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
}else {
print("用户禁止应用内购买")
}
3.之后会走支付回调方法
// MARK : ==== SKPaymentTransactionObserver Delegate ====
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print(transactions.count)
for transaction in transactions {
switch transaction.transactionState {
case .purchasing: // 商品添加进列表
print("商品:被添加进购买列表")
case .purchased:// 交易成功
completeTransaction(transaction)
finishedTransaction()
case .failed:// 交易失败
failedTransaction(transaction)
case .restored: // 已购买过该商品
restorePurchase()
case .deferred: // 交易延迟
break
@unknown default: break
}
}
}
// 当你的订单完成或者失败。需要手动完成该订单。不然会一直在苹果的支付队列里面。
func finishedTransaction() {
SKPaymentQueue.default().finishTransaction(self.currentTransaction)
print("该订单已结束")
}
没事可以多看看《文档》
四。为了确保支付成功。苹果提供了二次验证。
我这里就在本地通过AppStore进行验证,(验证的这个过程都是通过服务器去验证,然后再给我们返回支付结果)
沙盒:"https://sandbox.itunes.apple.com/verifyReceipt"
正式 :"https://buy.itunes.apple.com/verifyReceipt"
func verfyIAPurchase() {
print("购买成功---验证")
// MARK : 从沙盒中获取交易凭据
let receiptUrl = Bundle.main.appStoreReceiptURL
let receiptData = NSData(contentsOf: receiptUrl!)
let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
// MARK : 拼接请求数据
let bodyStr = "{\"receipt-data\" : \"\(String(describing: receiptString!))\"}"
let bodyData = bodyStr.data(using: .utf8)!
let session : URLSession = URLSession.shared
let url = URL(string: ViewController.url_verify_test)
let request : NSMutableURLRequest = NSMutableURLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = bodyData
let dataTask : URLSessionDataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
do {
let dict = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : Any]
let receiptDic = dict["receipt"] as! [String:Any]
let inApp = receiptDic["in_app"] as! [[String:Any]]
let transaction_id = inApp.last!["transaction_id"] as! String
let transaction_id2 = IAPManager.shared.currentTransaction.transactionIdentifier!
print(transaction_id,transaction_id2)
// MARK : 验证
if transaction_id == transaction_id2 {
print("验证成功")
}else {
print("验证失败")
}
} catch {}
}
dataTask.resume()
}
ps: 我们在测试过程中,返回的in_app里面有时候会有多个数据,之前提到的,没有结束的支付队列都会在这个数组里面,所以当支付失败/完成的时候需要客户端手动去完成这个transaction。
如果没有请求到订单信息可以用下面的这种方法去重新请求
// MARK : 刷新凭证
func refreshReceipt() {
let request = SKReceiptRefreshRequest()
request.delegate = self
request.start()
}
给大家看下效果图
识别沙盒环境下收据的方法有2种:
1.根据返回的字段 environment = sandbox
2.根据返回的状态码,如果你请求正式环境返回的状态码是21007则表示为沙盒环境
到这里,内购(非订阅)的东西差不多就这么多。其实真的不难。非订阅没有做过,不过应该也差不太多。
最后附上demo