現在有很多應用都使用了In-App Purchase,雖然對於很多使用者來說,可能並不喜歡甚至討厭這個模式,以為一點擊就要從賬戶裡扣錢。但是,在應用程式內購買對於開發人員而言不失為一種好的商業模式,而且人們也將越來越接受這種購買模式。
下面開始介紹一下在應用程式內購買的基本原理和編程方法。
1、基本原理
這裡參考了Apple的開發文檔In-App Purchase Programming Guide
簡要介紹一下整個流程:
Pre 0:在iTunesConnect中對於的App建立相應的產品,並在應用資訊中加入這些產品。具體步驟之後介紹。
Step 1:應用內根據建立的產品的bundle identifier來擷取產品的List。
Step 2:應用請求產品的資訊。產品資訊為SKProduct對象。
Step 3:App Store返回資訊。在實際編程中,Step1,2,3是在一起的。通過建立SKProductsRequest得到SKProductsResponse。SKProducts資訊就在SKProductsResponse的對象中,是其Property。
Step 4:在應用中顯示產品資訊給使用者
Step 5:使用者點擊了一個產品。
Step 6:應用向App Store發出一個購買請求 Payment Request
Step 7:App Store處理請求,完成交易,並返回資訊到應用。
Step 8: 應用擷取資訊然後根據交易情況將購買的內容解鎖給使用者使用。
這是In-App Purchase的一個基本的流程說明。在我們實際的編程過程中。對於這個產品列表,我們可能會選擇直接提供給使用者,而不是通過App Store擷取資訊。只有當使用者點擊了某個產品後,我們才開始去擷取產品資訊並完成購買。另一方面,在購買過程中,我們在應用中應該顯示足夠的提示資訊,因此交易過程中的Notification也很重要。
下面開始StepByStep介紹整個具體的實現過程。這裡只是介紹最基本的實現方法,以non-consumable產品為例。
Step 1:建立產品
首先要說明一下為了實現在應用程式內購買,你的AppID就是com.companyname.appname必須是唯一的,不能帶*。
在iTunesConnect中Manage My Applications中選擇Manage In-App Purchases
有四種產品類型,具體詳見開發文檔。這裡選擇non-consumable,就是一次購買終身受用的產品。consumable就是消費類可以不斷購買的,這種在遊戲中比較常見。
上面是產品的詳細資料填寫。這裡特別注意的是ProductID的填寫,其實就是ProductIdentifier,這個和應用的BundleIdentifier類似,必須獨一無二,一般的做法是填寫成com.companyname.appname.productname,當然從本質上講可以是任一字元串,只要獨一無二就可以了。這個ProductID是之後在程式中擷取產品資訊的依據。其他方面的資訊填寫很簡單,這裡不在費述。
Step 2:在應用版本資訊中加入產品
進入到應用頁面,點擊View Detail,然後在下面可以看到
In-App Purchases,點擊Edit然後加入之前建立的Products。
Step 3:建立測試User
為了在開發階段測試In-App Purchase,Apple為我們提供了Test User功能,通過它,可以在開發時用這個帳號免費實現在應用程式內購買。
具體就是在iTunesConnect首頁,點擊Manage Users
點擊Test User進行建立。
Step 4:開始編程。在Xcode中要加入StoreKit.framework,通過它來實現功能
Step 5:一般我們會單獨建立一個類來實現在應用程式內購買的功能。由於這個是教程,而不是案例,所以不打算把整個類的編寫都搬進來。只是介紹一下重要的東西和流程。
在類中要加入
<SKProductsRequestDelegate,SKPaymentTransactionObserver>
對於SKPaymentTransactionObserver這個東西可以監測交易的整個過程,即使交易時退出應用,交易也可以繼續進行,當然要回到應用內的頁面才能最後完成交易,顯示產品相應內容。類的初始化應加入
[[SKPaymentQueuedefaultQueue]
addTransactionObserver:self];
加入這句代碼來實現TransactionObserver的功能,後面有相應的Methods可以加入
paymentQueue:開頭
Step 6:下面的介紹不局限在一個類的編寫,而是按照購買流程。假設我們已經編寫好了一個在應用程式內購買的類,然後我們要實現購買。首先就是Request Products。
_productRequest = [[SKProductsRequestalloc]
initWithProductIdentifiers:_productIdentifiers];
_productRequest.delegate =self;
[_productRequest
start];
一個完整的請求如上,對於productsIdentifiers,這是一個Set,就是在這裡建立一個set加入各個ProductIdentifer
NSSet *productIdentifiers = [NSSetsetWithObjects:
K_CAMERA_ANGLE_MODE,
K_SLOPE_ANGLE_MODE,
K_DIHEDRAL_ANGLE_MODE,
K_LINE_PLANE_ANGLE_MODE,
nil];
然後就是request delegate的methods
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse
*)response
{
NSArray *skProducts = response.products;
// process....
}
- (void)request:(SKRequest *)request didFailWithError:(NSError
*)error
{
// process....
}
請求成功,就能擷取Products,一個NSArray,裡面就是SKProduct 對象的產品資訊了。產品資訊有名稱,價格,等等,很容易找到。這些東西只是在顯示資訊時有用,購買時不需要,只要用SKProduct就行了
Step 7:購買
SKPayment *payment = [SKPaymentpaymentWithProduct:product];
[[SKPaymentQueuedefaultQueue]
addPayment:payment];
代碼如上。然後就開始串連App Store了。主要看下面
#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray
*)transactions
{
for (SKPaymentTransaction *transactionin transactions) {
switch (transaction.transactionState) {
caseSKPaymentTransactionStatePurchased:
[selfcompleteTransaction:transaction];
break;
caseSKPaymentTransactionStateFailed:
[selffailedTransaction:transaction];
break;
caseSKPaymentTransactionStateRestored:
[selfrestoreTransaction:transaction];
default:
break;
}
}
}
這裡說一下上面的第三種交易狀態Restore,恢複。這個是這樣的。如果有些人在iPhone上用一個帳號購買了一個產品,那麼在iPad上又下載了這個應用,還要再重新購買嗎?不用了,通過Restore在App Store中檢測你這個帳號的購買記錄,如果有購買記錄存在,那就不用再次購買了,直接restoreTransaction。
接下來就是根據購買的狀態分別進行處理
- (void) completeTransaction: (SKPaymentTransaction *)transaction{
// Your application should implement these two methods. [self recordTransaction:transaction]; [self provideContent:transaction.payment.productIdentifier];
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];}
一般我們用NSUserDefaults來進行交易的記錄就行了。
注意程式中finishTransaction這一行代碼,這樣TransactionObserver就不再監測這個交易了。
其他狀態Restore,failed都是差不多的處理,這些代碼在開發文檔中有。
當然,對於restore,還有一個Method要注意
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError
*)error
如果restore失敗,可以顯示相應的資訊提示
Step 8:附加
在整個購買過程中,我們一般要給使用者一下提示資訊,比如等待,比如正在串連,比如交易已完成。要實現這些功能,就應該用notification,在上面的交易環節加入postNotification,然後對notification進行有效處理。本文只講In-App Purchase,關於notification的編程不做介紹。
基本上,通過上面的環節就能完成整個在應用程式內購買了。當然,從安全性上考慮,Apple在交易完成後會發送驗證資訊,通過發送驗證資訊給App Store來判斷這筆交易是否出自App Store,從而確認交易的合法性。
關於這方面,Apple 有一個程式碼封裝提供了validationController來實現很方便的驗證。