在這章裡,可以學到iap服務是如何運作的,也可以看到實作iap機制的典型樣式為何 。
原文連結︰In-app Billing Overview
翻譯︰小鰻
翻譯版本號︰v.1.0
如需轉載請註明出處「小鰻的Android學習筆記」
讓我參與最直接的討論以及錯誤修正, 謝謝!
Android Market In-app Billing is an Android Market service that provides checkout processing for in-app purchases. To use the service, your application sends a billing request for a specific in-app product. The service then handles all of the checkout details for the transaction, including requesting and validating the form of payment and processing the financial transaction. When the checkout process is complete, the service sends your application the purchase details, such as the order number, the order date and time, and the price paid. Android市集的應用程式內部金流機制(以下簡稱iap)是Android的市集服務之一,提供了應用程式內部購買功能。如果要使用此項服務,你的應用程式會發送請求 - 請求特定的應用程式內商品下來。接著,iap服務會處理所有的付費交易相關的細節,包含付款的請求和驗証,以及處理金融交易(financial transaction)。當付費流程結束後,iap服務會發送購買詳細訊息至你的APP裡,像是購買編號、購買日期、購買時間以及支付金額。
At no point does your application have to handle any financial transactions; that role is provided by Android Market's in-app billing service.
你的app完全不需處理金融交易,這個角色已由Android市集的iap機制服務提供。
In-app Billing Architecture應用程式內部金流架構
In-app billing uses an asynchronous message loop to convey billing requests and billing responses between your application and the Android Market server. In practice, your application never directly communicates with the Android Market server (see figure 1). Instead, your application sends billing requests to the Android Market application over interprocess communication (IPC) and receives purchase responses from the Android Market application in the form of asynchronous broadcast intents. Your application does not manage any network connections between itself and the Android Market server or use any special APIs from the Android platform.iap機制使用了一套異步訊息循環機制在你的應用和Android市集伺服器之間傳送金流請求和金流回應。在實際上,你的APP絕不會和Android市集伺服器做直接性的溝通(見圖1)。反之,你的APP透過內部進程通訊(interprocess communication, IPC)和從Android市集傳來的異步broadcast intents(譯者註︰broadcast intents,廣播意圖)來傳達iap金流請求以及接收購買回應。你的APP不會管理到任何程式本身以及Android市集伺服器之間的網路連結,或者使用一套從Android平臺來的特殊APIs。
Some in-app billing implementations may also use a private remote server to deliver content or validate transactions, but a remote server is not required to implement in-app billing. A remote server can be useful if you are selling digital content that needs to be delivered to a user's device, such as media files or photos. You might also use a remote server to store users' transaction history or perform various in-app billing security tasks, such as signature verification. Although you can handle all security-related tasks in your application, performing those tasks on a remote server is recommended because it helps make your application less vulnerable to security attacks.
有些應用程式內部金流也許會架構私有遠端伺服器做串接,但在iap服務裡,遠端伺服器的建置並不是一定要有的。其實自行架設的遠端伺服器是很有用的,假設你今天販售著數位化內容 - 這些內容還必須傳送到使用者的裝置中,像是多媒體音檔或者是相片,這時候你也許就會使用遠端伺服器去儲存使用者的交易記錄或者是執行各種的iap安全認証機制,像是數位簽章的驗証(譯者註︰有些商業模式是透過比對發佈出去的APP數位簽章Signature來確認使用者所使用的版本的合法性)。雖然你可以在你的APP裡處理所有關於安全機制的認証工作,在私有架設的遠端伺服器執行這些任務仍然是比較推薦的。主因是因為它幫助你降低了APP被安全性攻擊的風險。
一個典型的iap實作,仰懶底下3個元件︰
- A
Service
(namedBillingService
in the sample application), which processes purchase messages from the application and sends billing requests to Android Market's in-app billing service.
Service(在範例程式裡被命名為BillingService。譯者註︰Service,服務。這是Android的5大元件之一,因此不特別翻譯成中文。),這個Service元件處理APP裡的購買訊息以及發送金流請求至Android市集的iap服務裡。
- A
BroadcastReceiver
(namedBillingReceiver
in the sample application), which receives all asynchronous billing responses from the Android Market application.
BroadcastReceiver(在範例程式裡命名為BillingReceiver。譯者註︰BroadcastReceiver,廣播接收元件。這也是Android的5大元件之一,因此不特別翻譯成中文。),這個BroadcastReceiver元件接收所有從Android市集軟體裡異步金流的傳來的回應。
- A security component (named
Security
in the sample application), which performs security-related tasks, such as signature verification and2nonce generation. For more information about in-app billing security, see Security controls later in this document.
安全元件(在範例程式裡被命名為Security),被拿來執行一些安全性相關的任務,像是簽章認証以及2組隨機生成(譯者註︰2 nonce generation,這裡我尚未理解是何意)。若想了解更多關於iap機制的安全性問題,請參閱這份文件接下來的Security controls單元。
也許你也會想要將另外2個元件整合進iap機制中:
- A response
Handler
(namedResponseHandler
in the sample application), which providesapplication-specific processing of purchase notifications, errors, and other status messages.
一個回應處理的機制(在範例程式裡被命名為ResponseHandler),用來提供購買訊息、錯誤訊息、其它狀態訊息處理的一套特殊軟體處理流程。
- An observer (named
PurchaseObserver
in the sample application), which is responsible forsending callbacks to your application so you can update your user interface with purchase information and status.
一個觀察員(在範例程式裡被命名為PurchaseObserver),它的責任是寄送回呼函式(callbacks)至你的APP裡,因此你得以依照不同的購買狀態更新使用者的介面。(譯者註︰從範例程式我們可以清楚的看到,只要購買狀態改變,都會被這個觀察員監聽到,因此我們可以藉由此元件做出付費與未付費之間的畫面控管)
附帶一提,你的APP必須提供一個儲存這些購買資訊的管道,而且也要設計類似使用者介面的東西,能讓使用者選擇要購買哪些商品,你無需提供付費機制的使用者介面(譯者註︰雖然後面的文章會教到你要如何設定數位商品至Android Market Publisher,但他們不會知道你要販售紅藥水,所以開發者必須自行去設計購買的畫面,像藥水專櫃)。一旦使用者啟動了iap購買機制,Android市集軟體就會將付費介面呈現在你的使用者面前。當使用者完成了付費程序,你的APP的onResume()回呼函式便被呼叫,回復了原本APP應有的畫面。
In-app Billing Messages應用程式內金流的相關訊息s
When the user initiates a purchase, your application sends billing messages to Android Market's in-app billing service (namedMarketBillingService
) using simple IPC method calls. The Android Market application responds to all billing requests synchronously, providing your application with status notifications and other information. The Android Market application also responds to some billing requests asynchronously, providing your application with error messages and detailed transaction information. The following section describes the basic request-response messaging that takes place between your application and the Android Market application.一旦使用者啟動了購買機制,你的應用程式便會透過簡易的內部進程通訊機制(IPC)發送金流相關訊息至Android市集的iap服務(估且稱他為"市集金流服務")。Android市集那支APP同步地回應了所有的金流請求,提供你的APP狀態通知和其它的相關資訊。Android市集那支軟體也做了一些異步金流請求的回應處理,提供你關於APP裡錯誤訊息和詳細的交易資訊。
In-app billing requests應用程式內金流請求
Your application sends in-app billing requests by invoking a single IPC method (sendBillingRequest()
), which is exposed by the MarketBillingService
interface. This interface is defined in an Android Interface Definition Language file (IMarketBillingService.aidl
). You can download this AIDL file with the in-app billing sample application.你的APP透過呼叫單一的內部進程通訊方式(sendBillingRequest())寄送的iap請求,其實是透過一個叫MarketBillingService介面去接觸的。這個介面被定義在AIDL檔裡(Android Interface Definition Language,Android接口定義語言,檔名叫IMarketBillingService.aidl)。你可以在範例式裡看到這個AIDL檔。
The
sendBillingRequest()
method has a single Bundle
parameter. The Bundle that you deliver must include several key-value pairs that specify various parameters for the request, such as the type of billing request you are making, the item that is being purchased, and the application that is making the request. For more information about the Bundle keys that are sent with a request, see In-app Billing Service Interface. sendBillingRequest()這個函式擁有一個單一的Bundle參數,您要發送請求時,都將透過這個Bundle傳遞數組key-value和各個特定參數,像是你程式設計出來的金流請求,然後那個物品進入了購買中的狀態,這就是所謂的發送請求。更多關於Bundle的keys和寄送請求,請見In-app Billing Service Interface這個章節。
One of the most important keys that every request Bundle must have is the
BILLING_REQUEST
key. This key lets you specify the type of billing request you are making. Android Market's in-app billing service supports the following five types of billing requests:在每一次使用Bundle發送中,有一個極重要、也是每次Bundle都需包含的key,叫做BILLING_REQUEST。 這組key讓你能夠明確的指出你正在發送的金流請求是何種類型。Android市集的iap服務支援了底下5種金流請求類型︰
CHECK_BILLING_SUPPORTED
This request verifies that the Android Market application supports in-app billing. You usually send this request when your application first starts up. This request is useful if you want to enable or disable certain UI features that are relevant only to in-app billing.
CHECK_BILLING_SUPPORTED 此請求會去驗証Android市集軟體是否支援iap機制(譯者註︰在某些Android市集的版本是不支援iap機制的,文章底下會提到)。這個請求通常會是在你的APP第1次啟動iap機制時呼叫到。假設你今天想要啟動或取消關於iap機制相關的特定使用介面的功能,此請求會是很有用的。
REQUEST_PURCHASE
This request sends a purchase message to the Android Market application and is the foundation of in-app billing. You send this request when a user indicates that he or she wants to purchase an item in your application. Android Market then handles the financial transaction by displaying the checkout user interface.
REQUEST_PURCHASE 此請求會發送購買訊息給Android市集軟體,這個請求也是整個iap機制的基礎。當使用者指定要購買你APP裡的物品時,你會發送此請求。接著,Android市集會處理金融交易以及呈現使用者付費介面出來。
GET_PURCHASE_INFORMATION
This request retrieves the details of a purchase state change. A purchase changes state when a requested purchase is billed successfully or when a user cancels a transaction during checkout. It can also occur when a previous purchase is refunded. Android Market notifies your application when a purchase changes state, so you only need to send this request when there is transaction information to retrieve.
GET_PURCHASE_INFORMATION 這個請求會接收購買狀態改變(purchase state change)的詳細資訊。像是程式是否已成功付過費或使用者在付費過程中途取消了交易,這些都是購買狀態改變的發生時機。另外,這也可以發生在前一次購買後被退款的狀況下。每當購買狀態改變時,Android市集都會知會您的APP,因此你只需要在Android市集要求你接收交易資料時(譯者註︰Android市集發出IN_APP_NOTIFY時。見圖2),才發送這個請求。
CONFIRM_NOTIFICATIONS
This request acknowledges that your application received the details of a purchase state change. Android Market sends purchase state change notifications to your application until you confirm that you received them.
CONFIRM_NOTIFICATIONS此請求用來跟Android市集確認您的APP已收到購買狀況改變的詳細資訊。Android市集會奪命連環發PURCHASE_STATE_CHANGED給你,直到你的APP發送出CONFIRM_NOTIFICATIONS請求為止。(譯者註︰詳情請見圖2)
RESTORE_TRANSACTIONS
This request retrieves a user's transaction status for managed purchases. You should send this request only when you need to retrieve a user's transaction status,which is usually only when your application is reinstalled or installed for the first time on a device.
RESTORE_TRANSACTIONS 此請求用來接收使用者受管理類型的商品款項的交易狀態(譯者註︰iap產品分成受管理和不受管理2種方式,詳情請見其它篇幅的介紹)。比較佳的使用時機是在當你需要接收使用者的交易狀態時,再發出此請求。通常,通常,只會在你的APP被重新安裝或第1次被安裝在裝置上時,才需要發出這個請求。
In-app Billing Responses應用程式內部金流的相關回應
The Android Market application responds to in-app billing requests with both synchronous and asynchronous responses. The synchronous response is aBundle
with the following three keys:對於iap的請求,Android市集給予了同步與異步2種回應。同步的回應會以Bundle的方式,包含下面三組key值(譯者註︰詳情請參見圖2裡伺服器第1次的回應路線)︰
RESPONSE_CODE
This key provides status information and error information about a request.
RESPONSE_CODE 藉由此key,我們獲知發出請求得到的狀態資訊或錯誤資訊。
PURCHASE_INTENT
This key provides aPendingIntent
, which you use to launch the checkout activity.
PURCHASE_INTENT 此key提供了一個PendingIntent去執行付費頁的Activity。(譯者註︰PendingIntent是Android一個很好用的機制,可以呼叫出已經消失或關閉的Activity。我們通常都拿這個PendingIntent去開啟專門處理In-app billing的Activity,或藉由此機制從桌面小工具開啟原本的程式Activity呈現在使用者面前)
REQUEST_ID
This key provides you with a request identifier, which you can use to match asynchronous responses with requests.
REQUEST_ID 此key提供你一組請求識別,你可以用這個識別去核對異步回應和異步請求。
在這裡要稍微提一下,並非每次的請求,都會使用到這些key。若想了解更多資訊,請參閱底下的文件Messaging sequence。
The asynchronous response messages are sent in the form of individual broadcast intents and include the following:
異步回應訊息會以不同的broadcast intents(廣播意圖s),並且包含下列可能的訊息,對我們的APP做出伺服器回應︰
com.android.vending.billing.RESPONSE_CODE
This response contains an Android Market server response code, and is sent after you make an in-app billing request. A server response codecan indicate that a billing request was successfully sent to Android Market or it can indicate that some error occurred during a billing request. This response is not used to report any purchase state changes (such as refund or purchase information). For more information about the response codes that are sent with this response, see Server Response Codes for In-app Billing.
com.android.vending.billing.RESPONSE_CODE 此回應會在你發出iap請求之後,回應你從Android市集伺服器端來的回應值。伺服器的回應值會指出你的金流請求是否成功寄出至Android市集,或者它也可能指出發生了某些錯誤。這個回應並不等於告知你購買狀態改變(pruchase state changes,像是退費或購買資訊)。更多關於傳送給你的APP的回應值資訊,麻煩請參閱Server Response Codes for In-app Billing這個章節。
com.android.vending.billing.IN_APP_NOTIFY
This response indicates that a purchase has changed state, which means a purchase succeeded, was canceled, or was refunded. This response contains one or more notification IDs. Each notification ID corresponds to a specific server-side message, and each messages contains information about one or more transactions.After your application receives anIN_APP_NOTIFY
broadcast intent, you send aGET_PURCHASE_INFORMATION
request with the notification IDs to retrieve message details.
com.android.vending.billing.IN_APP_NOTIFY 此回應指出購買狀態被改變了,這意謂著可能是購買成功了、或者使用者取消了、甚至是被退款了。這個回應包含了1到多個訊息通知IDs。每個通知的ID都對應一個特別的伺服器端的訊息,而每一個訊息又包含了更多的交易資訊。之後,你的APP會接收到IN_APP_NOTIFY這個廣播意圖(broadcast intent),接著,你要再發送一個含有通知IDs的GET_PURCHASE_INFORMATION請求去接收詳細訊息資訊。
com.android.vending.billing.PURCHASE_STATE_CHANGED
This response contains detailed information about one or more transactions. The transaction information is contained in a JSON string. The JSON string is signed and the signature is sent to your application along with the JSON string (unencrypted). To help ensure the security of your in-app billing messages, your application can verify the signature of this JSON string.
com.android.vending.billing.PURCHASE_STATE_CHANGE 此回應包含了關於更多交易的詳細資訊,這個交易資訊被包在JSON字串裡。JSON字串被簽署並且會將簽章寄送至你的APP(未加密狀態)。為了幫助確保你iap訊息的安全性,你的APP可以對這個JSON字串所包含的簽章做驗証。
PURCHASE_STATE_CHANGED
intent provides your application with the details of one or more billing transactions. An example of this JSON string is shown below:那個藉由PURCHASE_STATE_CHANGE intent返回給你的JSON字串,會提供你很多金流交易的詳細項目。JSON字串範例會像下面這個樣子︰
{ "nonce" : 1836535032137741465,
"orders" :
{ "notificationId" : "android.test.purchased",
"orderId" : "transactionId.android.test.purchased",
"packageName" : "com.example.dungeons",
"productId" : "android.test.purchased",
"developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseTime" : 1290114783411,
"purchaseState" : 0 }
}
For more information about the fields in this JSON string, see In-app Billing Broadcast Intents.更多JSON字串值相關資訊,請參見In-app Billing Broadcast Intents。
Messaging sequence訊息序列
The messaging sequence for a typical purchase request is shown in figure 2. Request types for eachsendBillingRequest()
method are shown in bold, broadcast intents are shown in italic. For clarity, figure 2 does not show the RESPONSE_CODE
broadcast intents that are sent for every request.典型的訊息序列請求列於圖2。每個sendBililngRequest()函式發送出去的請求,會以粗體字做表達,廣播意圖(broadcast intent) 則會顯示成斜體字。為了讓你更清楚的了解,圖2不包含每次請求所傳回的RESPONSE_CODE廣播意圖(broadcast intent)。
The basic message sequence for an in-app purchase request is as follows:
每一次iap請求的基本的訊息序列會像下面的方式︰
- Your application sends a purchase request (
REQUEST_PURCHASE
type), specifying a product ID and other parameters.
你的APP發送購買請求(REQUEST_PURCHASE類型),指明了一組產品ID以及其它的參數。
- The Android Market application sends your application a Bundle with the following keys:
RESPONSE_CODE
,PURCHASE_INTENT
, andREQUEST_ID
. ThePURCHASE_INTENT
key provides aPendingIntent
, which your application uses to start the checkout UI for the given product ID.
Android市集APP寄送一個含有RESPONSE_CODE,PURCHASE_INTENT,REQUEST_ID的Bundle給你的APP。其中PURCHASE_INTENT key包含了一個PendingIntent,這個PendingIntent會被拿來開啟含產品ID的付費UI。(譯者註︰此時應用程式內部購買畫面就會被呈現出來了)
- Your application launches the pending intent, which launches the checkout UI.Note: You must launch the pending intent from an activity context and not an application context.
你的APP會啟動這組傳來的pending intent,然後啟動付費UI。
註︰你必須使用activity context來啟動這個pending intent,而不能使用application context的方式來啟動(譯者註︰因為application context綁定原來的context,若Activity被關掉,這個application context也會被回收,可能造成exception) - When the checkout flow finishes (that is, the user successfully purchases the item or cancels the purchase), Android Market sends your application a notification message (an
IN_APP_NOTIFY
broadcast intent). The notification message includes a notification ID, which references the transaction.
當付費流程式束時(也就是説,使用者成功的購買商品或取消購買),Android市集會寄送一組通知訊息(一組IN_APP_NOTIFY broadcast intent)給你的APP,通知訊息包含了通知的ID - 這個ID也代表著這次的交易。
- Your application requests the transaction information by sending a
GET_PURCHASE_STATE_CHANGED
request, specifying the notification ID for the transaction.
你的APP接著藉由發送一組GET_PURCHASE_STATE_CHANGED請求(譯者︰咦咦咦???應該是GET_PURCHASE_INFORMATION吧?),得到一個夾帶著此筆交易通知ID的交易資訊。
- The Android Market application sends a Bundle with a
RESPONSE_CODE
key and aREQUEST_ID
key.
Android市集APP發送一個含RESPONSE_CODE key和REQUEST_ID key的Bundle給你的APP。
- Android Market sends the transaction information to your application in a
PURCHASE_STATE_CHANGED
broadcast intent.
Android市集再發送一組含交易資訊的PURCHASE_STATE_CHANGED的廣播意圖給你的APP。
- Your application confirms that you received the transaction information for the given notification ID by sending a confirmation message (
CONFIRM_NOTIFICATIONS
type), specifying the notification ID for which you received transaction information.
你的APP藉由寄送一個確信息(CONFIRM_NOTIFICATIONS類型),告知Android市集APP你已經收到交易資訊和交易通知ID。
- The Android Market application sends your application a Bundle with a
RESPONSE_CODE
key and aREQUEST_ID
key.
Android市集APP寄一組Bundle和RESPONSE_CODE key、REQUEST_ID key給你。
IN_APP_NOTIFY
messages for the transactions you have not confirmed. As a best practice, you should not send aCONFIRM_NOTIFICATIONS
request for a purchased item until you have delivered the item to the user. This way, if your application crashes or something else prevents your application from delivering the product, your application will still receive an IN_APP_NOTIFY
broadcast intent from Android Market indicating that you need to deliver the product. Also, as a best practice, your application must be able to handle IN_APP_NOTIFY
messagesthat contain multiple orders.The messaging sequence for a restore transaction request is shown in figure 3. Request types for each
sendBillingRequest()
method are shown in bold, broadcast intents are shown in italic. For clarity, figure 3 does not show the RESPONSE_CODE
broadcast intents that are sent for every request.記住,當你一接收到交易資訊,一定要發送確認給Android市集(見圖2的步驟8)。如果你沒有寄送確認訊息讓Android市集知道,Android市集會持續的發送IN_APP_NOTIFY給你。最好的建議是︰在你將商品傳達給使用者前,你都不應該寄送CONFIRM_NOTIFICATIONS請求給Android市集。這樣的話,假如你的APP強制關閉了,或者一些其它因素阻擋了你傳遞APP商品購買訊息給Android市集,你的APP都還是能夠去接收從Android市集IN_APP_NOTIFY傳來的廣播意圖來指出你需要傳遞商品過去。而且,你的APP也最好能夠處理包含多筆訂單的IN_APP_NOTIFY訊息。每一個sendBillingRequest()函式是粗體字呈現的,而廣播意圖是斜體字。為了更清楚地讓你明白,圖3不會顯示每一次發出請求所寄出的RESPONSE_CODE廣播意圖。
Bundle
with a RESPONSE_CODE
key and a REQUEST_ID
key. Next, the Android Market application sends a RESPONSE_CODE
broadcast intent, which provides status information or error information about the request. As always, the RESPONSE_CODE
message references a specific request ID, so you can determine which request a RESPONSE_CODE
message pertains to.The
RESTORE_TRANSACTIONS
request type also triggers a PURCHASE_STATE_CHANGED
broadcast intent, which contains the same type of transaction information that is sent during a purchase request, although you do not need to respond to this intent with a CONFIRM_NOTIFICATIONS
message.這個請求發送了3筆回應(譯者註︰見圖3)。第1個回應是一個含有RESPONSE_CODE、REQUEST_ID key的Bundle。再來,Android市集軟發送了一組RESPONSE_CODE的廣播意圖給你, 這個值代表著剛才所發出請求的交易狀態或錯誤資訊。一般來説,這個RESPONSE_CODE訊息代表一組特定的請求ID,因此你可以斷這個RESPONSE_CODE訊息是涉及到哪一個剛才發出去的請求。
Note: You should use the
備註︰使用RESTORE_TRANSACTIONS(還原交易狀態)這個請求的時機應該是在你的APP被第1次安裝在裝置上,或者你的APP被移除過後,又被安裝回來的時間點上。
The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The request type for the RESTORE_TRANSACTIONS
request type only when your application is installed for the first time on a device or when your application has been removed from a device and reinstalled.備註︰使用RESTORE_TRANSACTIONS(還原交易狀態)這個請求的時機應該是在你的APP被第1次安裝在裝置上,或者你的APP被移除過後,又被安裝回來的時間點上。
sendBillingRequest()
method is shown in bold.檢查iap機制是否被支援在此台裝置上的訊息流程繪製於圖4。sendBillingRequest()函式相關的請求類型都用粗體標註。
CHECK_BILLING_SUPPORTED
request provides a Bundle with a server response code. A RESULT_OK
response code indicates that in-app billing is supported; aRESULT_BILLING_UNAVAILABLE
response code indicates that in-app billing is unavailable because the API version you specified is unrecognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that does not allow in-app billing). A SERVER_ERROR
can also be returned, indicating that there was a problem with the Android Market server.這個CHECK_BILLING_SUPPORTED的同步請求,提供了一組含有伺服器回應值的Bundle。如果回應的是RESULT_OK,代表iap機制是被支援的。如果回應是RESULT_BILLING_UNAVAILABLE,代表iap無法使用,因為你指明的API版本是無法辨識的,或者也可能是使用者沒有使用iap購買的資格(舉例,使用者駐留的國家不允許iap機制)。也許回應的是SERVER_ERROR,代表Android市集伺服器目前可能有問題。
Handling IN_APP_NOTIFY messages
處理IN_APP_NOTIFY訊息
Usually, your application receives anIN_APP_NOTIFY
broadcast intent from Android Market in response to aREQUEST_PURCHASE
message (see figure 2). The IN_APP_NOTIFY
broadcast intent informs your application that the state of a requested purchase has changed. To retrieve the details of that purchase, your application sends a GET_PURCHASE_INFORMATION
request. Android Market responds with a PURCHASE_STATE_CHANGED
broadcast intent, which contains the details of the purchase state change. Your application then sends aCONFIRM_NOTIFICATIONS
message, informing Android Market that you have received the purchase state change information.通常,你的APP接收到從Android市集回應的IN_APP_NOTIFY這個廣播意圖,是因為你發送了REQUEST_PURCHASE訊息出去(見圖2)。IN_APP_NOTIFY廣播意圖通知了你的APP請求購買的狀態遭到變更。如果要去接收那筆購買的詳細資訊,你的APP就要發送GET_PURCHASE_INFORMATION請求出去。Android市集就會回應一組PURCHASE_STATE_CHANGED的廣播意圖給您,這個意圖裡包含了購買狀庇改變的詳細資訊。你的APP接著要做的事就是發送CONFIRM_NOTIFICATIONS訊息給Android市集,通知Android市集你已經收到了購買狀態改變的資訊。
In some special cases, you may receive multiple
IN_APP_NOTIFY
messages even though you have confirmed receipt of the purchase information, or you may receive IN_APP_NOTIFY
messages for a purchase change even though you never initiated the purchase. Your application must handle both of these special cases.在一些特殊案例中,你也許會接收到多筆的IN_APP_NOTIFY訊息,即使您已經確認過過購買資訊,或者即使您從未啟動購買,你也許仍會收到IN_APP_NOTIFY訊息。你的APP必須去處理以上這些特例。
Handling multiple IN_APP_NOTIFY messages
處理多筆的IN_APP_NOTIFY訊息
When Android Market receives aCONFIRM_NOTIFICATIONS
message for a givenPURCHASE_STATE_CHANGED
message, it usually stops sending IN_APP_NOTIFY
intents for thatPURCHASE_STATE_CHANGED
message. Sometimes, however, Android Market may send repeatedIN_APP_NOTIFY
intents for a PURCHASE_STATE_CHANGED
message even though your application has sent aCONFIRM_NOTIFICATIONS
message. This can occur if a device loses network connectivity while you are sending the CONFIRM_NOTIFICATIONS
message. In this case, Android Market might not receive yourCONFIRM_NOTIFICATIONS
message and it could send multiple IN_APP_NOTIFY
messages until it receives acknowledgement that you received the transaction message. Therefore, your application must be able to recognize that the subsequent IN_APP_NOTIFY
messages are for a previously processed transaction. You can do this by checking the orderID
that's contained in the JSON string because every transaction has a uniqueorderId
.當Android市集在丟出PURCHASE_STATE_CHANGED,接收到CONFIRM_NOTIFICATIONS訊息後,就不會再丟出IN_APP_NOTIFY意圖了。然後,有時候,即使您已發送出CONFIRM_NOTIFICATIONS訊息給Android市集,市集仍然會重覆發送PURCHASE_STATE_CHANGE訊息的IN_APP_NOTIFY意圖給您。之所以會發生這種情況,可能是因為在你正要發送CONFIRM_NOTIFICATIONS訊息給Android市集時,裝置突然沒有網路連線的能力。在這個案例中,Android市集也許就無法接收到你傳來的CONFIRM_NOTIFICATIONS訊息,並且,這可能會造成Android市集會發出多筆的IN_APP_NOTIFY訊息給你,直到Android市集收到了你確認過此筆交易訊息以後。因此,你的APP必須要有辨識目前這筆IN_APP_NOTIFY是否為上次那筆交易中,次IN_APP_NOTIFY訊息的能力。你可以透過含蓋在JSON字串裡的訂單Id(orderId)去檢查,因為每次的交易,都含蓋一組唯一的orderId。
Handling refunds and other unsolicited IN_APP_NOTIFY messages
處理退款和其它不請自來的IN_APP_NOTIFY訊息
There are two cases where your application may receiveIN_APP_NOTIFY
broadcast intents even though your application has not sent a REQUEST_PURCHASE
message. Figure 5 shows the messaging sequence for both of these cases. Request types for each sendBillingRequest()
method are shown in bold, broadcast intents are shown in italic. For clarity, figure 5 does not show the RESPONSE_CODE
broadcast intents that are sent for every request.這裡有2個即使你的APP沒有發送REQUEST_PURCHASE訊息給Android市集,但市集卻傳來IN_APP_NOTIFY廣播意圖的特例(譯者註︰天啊!)圖5表達的就是這些特例的訊息序列。每次使用sendBillingRequest()型態的功能,會以粗體表示。而廣播意圖,會以斜體表示。為了讓你更清楚,圖5不會顯示每次請求所回應你APP的RESPONSE_CODE這個廣播意圖。
IN_APP_NOTIFY
broadcast intent when a user has your application installed on two (or more) devices and the user makes an in-app purchase from one of the devices. In this case, Android Market sends an IN_APP_NOTIFY
message to the second device, informing the application that there is a purchase state change. Your application can handle this message the same way it handles the response from an application-initiated REQUEST_PURCHASE
message, so that ultimately your application receives a PURCHASE_STATE_CHANGED
broadcast intent message that includes information about the item that has been purchased. This applies only to items that have their purchase type set to "managed per user account."在第1個特例中,當使用者在2台或多臺裝置上安裝了您的APP,然後,使用者在一臺裝置上使用iap機制,你的應用程式也許會收到一筆IN_APP_NOTIFY廣播意圖。在這個案例中,Android市集卻發送了IN_APP_NOTIFY訊息給第2臺裝置,並通知第2臺裝置上的APP說「購買狀態遭到改變」了!你的APP能運用處理REQUEST_PURCHASE訊息的相同方式來處理這個不請自來的IN_APP_NOTIFY。因此,第2臺裝置終將能收到PURCHASE_STATE_CHANGED廣播意圖訊息以及包含商品已被購買的詳細資訊。剛才提到的這個做法,只在應用程式內商品的型態被設定成「受管理(依使用帳號)」,才被接受。
In the second case, your application can receive an
IN_APP_NOTIFY
broadcast intent when Android Market receives a refund notification from Google Checkout. In this case, Android Market sends an IN_APP_NOTIFY
message to your application. Your application can handle this message the same way it handles responses from an application-initiated REQUEST_PURCHASE
message so that ultimately your application receives aPURCHASE_STATE_CHANGED
message that includes information about the item that has been refunded. The refund information is included in the JSON string that accompanies the PURCHASE_STATE_CHANGED
broadcast intent. Also, the purchaseState
field in the JSON string is set to 2.在第2個特例中,可能您的APP會收到來至於Google Checkout傳給Android市集的退費通知的IN_APP_NOTIFY廣播意圖。在這個案例中,因為Android市集會發送IN_APP_NOTIFY給你的APP,你的APP也是依照處理REQUEST_PURCHASE訊息的預設方式去處理它。因此, 你的APP能夠收到一個PURCHASE_STATE_CHANGED訊息,它包含了被退費商品的資訊。這個退費商品資訊被包在傳給你APP的PURCHASE_STATE_CHANGED廣播意圖的JSON字串裡。所以,在JSON字串的購買狀態值會被設為2(譯者註︰2代表已退費)。
Important: You cannot use the Google Checkout API to issue refunds or cancel in-app billing transactions. You must do this manually through your Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order information.
重要︰你無法使用Google Checkout的API去處理退款或取消iap交易。你必須以手動的方式,透過Google Checkout merchant帳戶,去處理退款或取消iap交易。然而,你仍能用Google Checkout API去接收訂單資訊。
重要︰你無法使用Google Checkout的API去處理退款或取消iap交易。你必須以手動的方式,透過Google Checkout merchant帳戶,去處理退款或取消iap交易。然而,你仍能用Google Checkout API去接收訂單資訊。
Security Controls安全控管
To help ensure the integrity of the transaction information that is sent to your application, Android Market signs the JSON string that is contained in thePURCHASE_STATE_CHANGED
broadcast intent. Android Market uses the private key that is associated with your publisher account to create this signature. The publisher site generates an RSA key pair for each publisher account. You can find the public key portion of this key pair on your account's profile page. It is the same public key that is used with Android Market licensing.為了確保交易資訊完整的寄送至你的APP裡,Android市集將JSON字串包在PURCHASE_STATE_CHANGED這個廣播意圖裡。Android市集使用一組連結至您的publisher帳戶的私鑰,去建立一組數位簽章。publisher網站產生了一對RSA金鑰給每一個publisher帳戶。你可以在帳戶簡介的頁面中,找到這組私鑰的部份,呈現出來的公鑰。這組公鑰也是被拿來做Android市集認証用的。
When Android Market signs a billing response, it includes the signed JSON string (unencrypted) and the signature. When your application receives this signed response you can use the public key portion of your RSA key pair to verify the signature. By performing signature verification you can help detect responses that have been tampered with or that have been spoofed. You can perform this signature verification step in your application; however, if your application connects to a secure remote server then we recommend that you perform the signature verification on that server.
一旦Android市集簽署了金流回應,它就包含了被簽署的JSON字串(未加密)和數位簽章,當你的APP接收到了這份被簽署的回應,你就可以使用那對部份RSA金鑰出來的公鑰去驗証數位簽章。藉由執行數位簽章驗証,就可以幫助你去針測那些已被篡改或被試圖欺騙機制的回應。你可以在你的APP裡執行數位簽章認識的手續;然而,如果你的APP有連線至安全的遠端伺服器,那麼我們會比較建議您在那臺伺服器上去執行數位簽章的認証。
In-app billing also uses nonces (a random number used once) to help verify the integrity of the purchase information that's returned from Android Market. Your application must generate a nonce and send it with a
GET_PURCHASE_INFORMATION
request and a RESTORE_TRANSACTIONS
request. When Android Market receives the request, it adds the nonce to the JSON string that contains the transaction information. The JSON string is then signed and returned to your application. When your application receives the JSON string, you need to verify the nonce as well as the signature of the JSON string.For more information about best practices for security and design, see Security and Design.
iap機制也用了隨機數(nonces,一筆隨機單次使用的數據)去幫助驗証那些從Android市集傳來的購買資訊的完整性。你的APP必須產生一筆隨機數(nonces),然後發送一筆GET_PURCHASE_INFORMATION和一筆RESTORE_TRANSACATIONS請求。當Android市集接收到請求,就會增加隨機數至包含交易資訊的JSON字串當中。接著,JSON字串就被簽署而且也返回至你的APP中。當你的APP接收到了JSON字串,你需要去驗証這個隨機數(nonce)以及JSON字串的數位簽章。更多更好的關於安全設計的實例,請參見Security and Design。
In-app Billing Requirements and Limitations
應用程式內部金流的需求與限制
Before you get started with in-app billing, be sure to review the following requirements and limitations.在您開始使用iap機制以前,請確定您已看過底下列出的需求與限制。
- In-app billing can be implemented only in applications that you publish through Android Market. iap機制只能透過Android市集軟體來實作(譯者註︰意思就是如果你的裝置裡沒有Android市集,將無法使用iap機制)。
- You must have a Google Checkout Merchant account to use Android Market In-app Billing. 你必須有一組Google付款商(Google Checkout Merchant)帳號來使用Android市集的iap機制。
- If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of the MyApps application. If your device is running any other version of Android, in-app billing requires version 2.3.4 (or higher) of the Android Market application. 如果你的裝置運行Android3.0,內建的MyApps軟體版本號需要在5.0.12(含)以上。如果您的裝置是運行Android的其它版本號,內建的Andorid市集軟體版本號需要在2.3.4或更高,方能使用iap機制。
- An application can use in-app billing only if the device is running Android 1.6 (API level 4) or higher. 您的Android裝置必須在Android1.6(API level 4)或更高,方能使用iap機制。
- You can use in-app billing to sell only digital content. You cannot use in-app billing to sell physical goods, personal services, or anything that requires physical delivery. 您只能使用iap機制販售數位化商品。販售實體產品、個人化服務或任何需要被實際傳遞的物品,皆是不被允許的。
- Android Market does not provide any form of content delivery. You are responsible for delivering the digital content that you sell in your applications. Android市集不會提供任何表單來傳遞商品。因此在您的APP裡,傳遞數位化商品內容來做銷售,是您的責任。
- You cannot implement in-app billing on a device that never connects to the network. To complete in-app purchase requests, a device must be able to access the Android Market server over the network. 您無法在從未連結網路的裝置上完成iap機制。為了完整的完成iap購買請求,裝置必須有連線至Android市集伺服器的能力。
更多iap需求的資訊,請參閱In-App Billing Availability and Policies。