因?yàn)橹白龅亩际腔緦?shí)體的物品在自己的項(xiàng)目做交易的流程,所以之前也沒(méi)有接觸過(guò)蘋(píng)果的內(nèi)購(gòu),都是用的支付寶和微信,但是這次的項(xiàng)目是做虛擬幣的交易,所以前期開(kāi)會(huì)的時(shí)候,公司又想利益最大化,就想避開(kāi)蘋(píng)果那30%的稅,前面的思路是不集成支付寶和微信的sdk做safari的跳轉(zhuǎn)看能不能避開(kāi)蘋(píng)果的抽成,效果是做出來(lái),不集成支付寶的sdk,通過(guò)外部的跳轉(zhuǎn)到支付寶支付然后在調(diào)回自己的app(我下一篇文章說(shuō)支付寶攔截h5調(diào)回自己的app)但是查看了蘋(píng)果指南發(fā)現(xiàn)還是不行就改內(nèi)購(gòu)嗎,但是第一次做,這里就總結(jié)一下自己踩過(guò)的坑和解決辦法
前面的和蘋(píng)果簽署的一系列的賣(mài)身契約我這里就不詳細(xì)的講解
先說(shuō)遇到的坑
- 第一個(gè)坑:獲取不到訂單的信息
- 第二個(gè)坑:總是鏈接不到iTunes Store,錯(cuò)誤內(nèi)容
Optional(Error Domain=SKErrorDomain Code=0 "無(wú)法連接到 iTunes Store" UserInfo={NSLocalizedDescription=無(wú)法連接到 iTunes Store})
- 第三個(gè)坑:因?yàn)槭堑谝淮巫霾恢烙猩澈袦y(cè)試賬號(hào),寫(xiě)好之后測(cè)試的時(shí)候用自己的賬號(hào)測(cè)試提示該賬號(hào)沒(méi)有權(quán)限
- 第四個(gè)坑:創(chuàng)建沙盒測(cè)試賬號(hào)的時(shí)候不允許創(chuàng)建已經(jīng)有的AppleID
1、Xcode工程配置

開(kāi)啟此選項(xiàng)App Strore中APP的介紹界面顯示內(nèi)購(gòu)的相關(guān)項(xiàng)目,關(guān)閉則不顯示
2、iTunesconnect創(chuàng)建產(chǎn)品
(1).開(kāi)發(fā)者中心->App Store Connect->我的App->創(chuàng)建需要上線的App
這里解決第一個(gè)坑,因?yàn)檫@個(gè)項(xiàng)目是團(tuán)隊(duì)開(kāi)發(fā)的,我在測(cè)試的時(shí)候始終拿不到訂單的信息,后面才發(fā)現(xiàn),隊(duì)友在項(xiàng)目中把BundleID給我改了,強(qiáng)調(diào)一點(diǎn)在你確定你的代碼沒(méi)有錯(cuò)的時(shí)候,你必須保證你的BundleID和需要提價(jià)的App信息的BundleID一直
(2).選擇你希望創(chuàng)建APP內(nèi)購(gòu)買(mǎi)項(xiàng)目
App信息->功能->App內(nèi)購(gòu)買(mǎi)項(xiàng)目


在這里創(chuàng)建你在APP項(xiàng)目
- 產(chǎn)品名稱(chēng):隨便寫(xiě),但是最好還是寫(xiě)成和你項(xiàng)目向管理的
- 產(chǎn)品ID:也可以隨便寫(xiě),如果你的項(xiàng)目里面不止一個(gè)內(nèi)購(gòu)商品,那么最好就命名規(guī)范一下,這樣可以由后臺(tái)來(lái)控制
- 價(jià)格:蘋(píng)果果然霸道,價(jià)格都給你定好了,最低消費(fèi)都是6塊起步
- 本地化版本:顯示的名稱(chēng)和描述就是訂單的信息也就是顯示在你購(gòu)買(mǎi)的時(shí)候提示用戶(hù)的信息
- App Strore 推廣:標(biāo)明的是可選,準(zhǔn)備一張1024*1024的推廣圖就可以了
-
審核信息:必須上傳一張屏幕的截圖,如果不是就提交不上去,我開(kāi)始是用的截圖然后通過(guò)qq發(fā)過(guò)來(lái)壓縮了一下,結(jié)果失敗了,后面通過(guò)設(shè)備傳過(guò)來(lái)的,如果沒(méi)有上傳的話(huà),保存之后會(huì)提示元數(shù)據(jù)丟失
8862B2B8-3A36-498A-AA97-60D3F9C00EAE.png
注意:每個(gè)開(kāi)發(fā)人員帳戶(hù)可在該帳戶(hù)的所有 App 中創(chuàng)建最多 10,000 個(gè) App 內(nèi)購(gòu)買(mǎi)項(xiàng)目產(chǎn)品。App 內(nèi)購(gòu)買(mǎi)項(xiàng)目共有四種類(lèi)型:消耗型、非消耗型、自動(dòng)續(xù)期訂閱和非續(xù)期訂閱。
3、實(shí)現(xiàn)步驟主要包括三步
1、首先在項(xiàng)目工程中加入StoreKit.framework
2、加入頭文件#import <StoreKit/StoreKit.h>
3、遵守代理SKPaymentTransactionObserver,SKProductsRequestDelegate
4、代碼實(shí)現(xiàn),我這里直接寫(xiě)的一個(gè)PayManager類(lèi)
1)判斷用戶(hù)是否具備支付權(quán)限
if SKPaymentQueue.canMakePayments(){
pay(productId:productId,order_id:order_id)
}else{
let alertView = CCarAlertView.init(iconImage: nil, message: "您的手機(jī)沒(méi)有打開(kāi)程序內(nèi)付費(fèi)購(gòu)買(mǎi)")
alertView.block = {}
}
2)、注冊(cè)通知
SKPaymentQueue.default().add(self as SKPaymentTransactionObserver)
3)、創(chuàng)建一個(gè)商品查詢(xún)的請(qǐng)求,productIdentifiers指需要查詢(xún)的“產(chǎn)品ID”的數(shù)組,并且實(shí)現(xiàn)代理
func payMoeny(productId:String){
addSKPaymentQueue()
if productId.count == 0{
if requestErrorBlock != nil{
requestErrorBlock()
}
return
}
removeAllUncompleteTransactionsBeforeNewPurchase()
let skpay = SKProductsRequest(productIdentifiers: NSSet(object: productId) as! Set<String>)
self.productId = productId
skpay.delegate = self
skpay.start()
}
/// 結(jié)束上次未完成的交易,防止漏單的其中一種解決方案
private func removeAllUncompleteTransactionsBeforeNewPurchase(){
let transactions:NSArray = SKPaymentQueue.default().transactions as NSArray
if transactions.count >= 1 {
for transaction in transactions {
if (transaction as! SKPaymentTransaction).transactionState == .purchased || (transaction as! SKPaymentTransaction).transactionState == .restored{
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
}
}
}else{
print("沒(méi)有歷史未消耗訂單")
}
}
4)、查詢(xún)的結(jié)果將通過(guò)SKProductsRequestDelegate得到查詢(xún)的結(jié)果
獲取商品的查詢(xún)結(jié)果,這里可以拿到訂單的相信信息,代碼比較相信,就不詳細(xì)的講解
/// 內(nèi)購(gòu)商品回調(diào)代理
///
/// - Parameters:
/// - request: SKProductsRequest
/// - response: SKProductsResponse
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print(response.products)
print(response.invalidProductIdentifiers)
let products = response.products
if products.count == 0{
print("沒(méi)有產(chǎn)品信息")
if notProductsBlock != nil{
notProductsBlock()
}
removeSKPaymentQueue()
return
}
///發(fā)送購(gòu)買(mǎi)請(qǐng)求
for product in products{
if product.productIdentifier == self.productId{
print("SKProduct 描述信息\(product.description)")
print("產(chǎn)品標(biāo)題\(product.localizedTitle)")
print("產(chǎn)品描述信息\(product.localizedDescription)")
print("價(jià)格\(product.price)")
print("Product id\(product.productIdentifier)")
let skPayment = SKPayment(product: product)
SKPaymentQueue.default().add(skPayment)
break
}
}
}
5)、支付結(jié)果,里面有5中狀態(tài),個(gè)人客官自己看代碼就能知道了
/// 內(nèi)夠代理回調(diào)
///
/// - Parameters:
/// - queue: SKPaymentQueue
/// - transactions: [SKPaymentTransaction]
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions{
switch transaction.transactionState {
case .purchasing://事務(wù)正在添加到服務(wù)器隊(duì)列中。
print("事務(wù)正在添加到服務(wù)器隊(duì)列中。")
break
case .purchased://完成支付
print("支付成功")
getAndSaveReceipt(transaction)
queue.finishTransaction(transaction)
removeSKPaymentQueue()
break
case .failed://支付失敗
print("支付失敗")
payFailed(transaction:transaction)
break
case .restored://已經(jīng)購(gòu)買(mǎi)過(guò)該商品
print("事務(wù)從用戶(hù)的購(gòu)買(mǎi)歷史中恢復(fù)。客戶(hù)應(yīng)完成交易。")
queue.finishTransaction(transaction)
break
case .deferred://最終狀態(tài)未確定
print("最終狀態(tài)未確定")
removeSKPaymentQueue()
break
default:
break
}
}
}
說(shuō)道這里我們來(lái)解決第二個(gè)坑,天坑,解決了1天,我在支付回調(diào)的時(shí)候始終拿到的都是支付失敗,打印出來(lái)的錯(cuò)誤就是無(wú)法連接到 iTunes Store,網(wǎng)上也查詢(xún)很多資料,給我的結(jié)果就是更改Build

我不知道是不是我更錯(cuò)了還是怎么,但是就是不行
然后還有博主說(shuō)的是重置手機(jī),我也重置了,還是不行,后面拿到一個(gè)手機(jī)上面可以翻墻的手機(jī)成功了,然后我的解決方案就是開(kāi)vpn果然解決了(如果有客官有更好的方法歡迎留言)
6)、支付完成,這個(gè)沒(méi)有什么好說(shuō)的,不管支付成功與否都會(huì)調(diào)用這個(gè)方法
func requestDidFinish(_ request: SKRequest) {
print("支付流程完成")
}
7)、支付失敗,也沒(méi)有什么好說(shuō)的
func request(_ request: SKRequest, didFailWithError error: Error) {
print("支付失敗")
if requestErrorBlock != nil{
requestErrorBlock()
}
}
4、測(cè)試
第三個(gè)坑,我在寫(xiě)完這些之后就能正常的支付了,但是支付的回調(diào)成功的時(shí)候輸入AppID之后總是提示我該賬號(hào)沒(méi)有權(quán)限,后面百度才知道有沙盒賬號(hào)的測(cè)試,關(guān)鍵是不需要支付錢(qián)哦,想怎么買(mǎi)就怎么買(mǎi)
創(chuàng)建沙盒賬號(hào)的流程
App Store Connect->用戶(hù)和職能->沙盒技術(shù)測(cè)試員
最后一個(gè)坑:測(cè)試的時(shí)候需要退出自己的賬號(hào)用沙盒賬號(hào)
設(shè)置->iTunes Strore與App Store
App Store->個(gè)人信息
如果覺(jué)得對(duì)各人客官有用就希望點(diǎn)贊一下,下一篇文章支付寶H5支付無(wú)法返回APP坑和解決方案
