將應用程式內金流機制整合進您的APP裡。 - 极客分享

文章推薦指數: 80 %
投票人數:10人

[Android in-app billing第2篇]Implementing In-app Billing實作應用程式 ... 並且,您必須擁有Google Checkout Merchant帳戶來新增範例程式商品列表 ... 您的位置:首页 > 移动开发 > Android开发 [Androidin-appbilling第2篇]ImplementingIn-appBilling實作應用程式內部金流機制(中文翻譯)... 2020-02-2920:49 901 查看 藉由一步一步的引導,將應用程式內金流機制整合進您的APP裡。

原文連結︰IMPLEMENTINGIN-APPBILLING翻譯︰小鰻翻譯版本號︰V.1.0如需轉載請註明出處「小鰻的ANDROID學習筆記」讓我參與最直接的討論以及錯誤修正,謝謝! INTHISDOCUMENT此章節含蓋的內容 DownloadingtheSampleApplication AddingtheAIDLfiletoyourproject UpdatingYourApplication'sManifest CreatingaService CreatingaBroadcastReceiver Creatingasecurityprocessingcomponent ModifyingYourApplicationCode DOWNLOADS下載 SampleApplication SEEALSO也可以參考其它同質文章 OverviewofIn-appBilling SecurityandDesign TestingIn-appBilling AdministeringIn-appBilling In-appBillingReference AndroidMarketIn-appBillingprovidesastraightforward,simpleinterfaceforsendingin-appbillingrequestsandmanagingin-appbillingtransactionsusingAndroidMarket.Thisdocumenthelpsyouimplementin-appbillingbysteppingthroughtheprimaryimplementationtasks,usingthein-appbillingsampleapplicationasanexample.Android市集的應用程式內部金流(以下簡稱iap)機制透過Android市集提供了一個直接、簡單的介面,讓程式可以寄送iap請求或管理iap交易。

這份文件將幫助你一步一步地透過主要的實作任務-也就是iap的範例程式來做範例教學。

Beforeyouimplementin-appbillinginyourownapplication,besurethatyouread OverviewofIn-appBilling and SecurityandDesign.Thesedocumentsprovidebackgroundinformationthatwillmakeiteasierforyoutoimplementin-appbilling.在你將你的APP實作iap之前,請確定你已讀過應用程式金流概述(OverviewofIn-appBilling)以及安全和設計(SecurityandDesign)章節,這些文件提供了一些iap的背後原理,它們將會幫助你更輕鬆的實作完成iap機制。

Toimplementin-appbillinginyourapplication,youneedtodothefollowing:如果你的APP要實作iap機制,你必須做好下列事項︰ Downloadthein-appbillingsampleapplication. 下載iap範例程式 AddtheIMarketBillingService.aidlfile toyourproject. 新增IMarketBillingService.aidl檔至你的專案夾 UpdateyourAndroidManifest.xmlfile. 更新你的AndroidManifest.xml檔 CreateaService andbindittothe MarketBillingService soyourapplicationcansendbillingrequestsandreceivebillingresponsesfromtheAndroidMarketapplication. 建立一個Service,並且將它綁定到MarketBillingService,你的APP才能夠透過Android市集軟體發送金流請求和接收金流回應。

CreateaBroadcastReceiver tohandlebroadcastintentsfromtheAndroidMarketapplication. 建立一個廣播監聽去處理從Android市集軟體來的廣播意圖(broadcastintents)。

Createasecurityprocessingcomponent toverifytheintegrityofthetransactionmessagesthataresentbyAndroidMarket. 建立一套安全流程元件去驗証那些藉由Android市集發送的完整的交易訊息。

Modifyyourapplicationcode tosupportin-appbilling. 修改你的程式去對應iap機制。

  DOWNLOADINGTHESAMPLEAPPLICATION下載範例程式 Thein-appbillingsampleapplicationshowsyouhowtoperformseveraltasksthatarecommontoallAndroidMarketin-appbillingimplementations,including:範例程式將會告訴你一些執行Android市集iap機制很常見也很一般的實作概念,包括︰ Sendingin-appbillingrequeststotheAndroidMarketapplication. 發送IAP請求給Android市集 HandlingsynchronousresponsesfromtheAndroidMarketapplication. 處理從Android市集來的同步回應 Handlingbroadcastintents(asynchronousresponses)fromtheAndroidMarketapplication. 處理從Android市集來的廣播意圖(非同步) Usingin-appbillingsecuritymechanismstoverifytheintegrityofbillingresponses.  使用iap安全架構來確認金流回應的完整性 Creatingauserinterfacethatletsusersselectitemsforpurchase. 建立使用介面讓使用者能夠購買商品File Description IMarketBillingService.aidl AndroidInterfaceDefinitionLanguage(AIDL)filethatdefinestheIPCinterfacetoAndroidMarket'sin-appbillingservice(MarketBillingService).Android接口定義語言檔。

定義了到Android市集iap機制的內部進程溝通介面。

Dungeons.java SampleapplicationfilethatprovidesaUIformakingpurchasesanddisplayingpurchasehistory.提供購買的使用介面以及顯示購買記錄的範例程式檔。

PurchaseDatabase.java Alocaldatabaseforstoringpurchaseinformation. 一個用來儲存購買資訊的本地端資料庫。

BillingReceiver.java ABroadcastReceiverthatreceivesasynchronousresponsemessages(broadcastintents)fromAndroidMarket.ForwardsallmessagestotheBillingService.一個用來接收從Android市集來的異步訊息回應的廣播接收器。

它會將所有傳來的訊息轉至BillingService去處理。

BillingService.java AServicethatsendsmessagestoAndroidMarketonbehalfoftheapplicationbyconnecting(binding)totheMarketBillingService.一個有能力發送訊息至Android市集的Service(服務)。

它也是APP能夠連線到市集金流服務的代表。

ResponseHandler.java AHandlerthatcontainsmethodsforupdatingthepurchasesdatabaseandtheUI.一個包含更新購買資料庫和更新畫面等函式的處理機制 PurchaseObserver.java Anabstractclassforobservingchangesrelatedtopurchases. 一個觀察並監聽購買狀態相關資訊遭改變的抽象類別 Security.java Providesvarioussecurity-relatedmethods. 提供各種安全相關的函式 Consts.java DefinesvariousAndroidMarketconstantsandsampleapplicationconstants.AllconstantsthataredefinedbyAndroidMarketmustbedefinedthesamewayinyourapplication.定義了各種Android市集和範例程式會用到的常數。

所有定義的常數,你的APP都應該照彷。

Base64.javaandBase64DecoderException.java ProvidesconversionservicesfrombinarytoBase64encoding.The Security classreliesontheseutilityclasses. 提供從二進位至Base64編碼轉換的服務。

Security這個類別都是依賴這些類別工具在運作的。

Thesampleapplicationincludesanapplicationfile(Dungeons.java),theAIDLfilefortheMarketBillingService (IMarketBillingService.aidl),andseveralclassesthatdemonstratein-appbillingmessaging.Italsoincludesaclassthatdemonstratesbasicsecuritytasks,suchassignatureverification.Table1liststhesourcefilesthatareincludedwiththesampleapplication. 範例程式包含了程式檔(Dungeions.java)、市集金流服務專用的AIDL檔和數個用來說明iap機制傳遞訊息的類別檔。

另外也解釋了基本安全認証的流程,像是數位簽章的驗証。

表1列出範例程式裡所含蓋的資源檔檔名Table1. In-appbillingsampleapplicationsourcefiles.表1.iap機制範例程式的資源檔  Thein-appbillingsampleapplicationisavailableasadownloadablecomponentoftheAndroidSDK.Todownloadthesampleapplicationcomponent,launchtheAndroidSDKandAVDManagerandthenselectthe"GoogleMarketBillingpackage"component(seefigure1),andclick InstallSelect 1a4bb ed tobeginthedownload.Iap範例程式是在AndroidSDK裡,可供下載的內容之一。

如果要下載範例程式這個內容,請執行AndroidSDK和AVDManager,然後選擇"GoogleMarketBillingpackage"這個內容(見圖1),然後點擊InstallSelected來下載。

 Figure1. TheGoogleMarketBillingpackagecontainsthesampleapplicationandtheAIDLfile. 圖1.Google市集金流套件包含了範例程式和一個AIDL(Android定義接口語言)檔 Whenthedownloadiscomplete,theAndroidSDKandAVDManagersavesthecomponentintothefollowingdirectory:當下載完成後,AndroidSDK和AVDManager會將該內容存至下載的資料夾中︰/extras/google/market_billing/Ifyouwanttoseeanend-to-enddemonstrationofin-appbillingbeforeyouintegratein-appbillingintoyourownapplication,youcanbuildandrunthesampleapplication.Buildingandrunningthesampleapplicationinvolvesthreetasks:如果你想要看如何將iap機制與您的APP完全整合的完整說明,你可以建立並執行這個範例程式。

建立和運行範例程式有3個工作要做︰ Configuringandbuildingthesampleapplication. 設定並建立範例程式 UploadingthesampleapplicationtoAndroidMarket. 上傳範例程式至AndroidMarket(譯者註︰Androidpublisher) Settinguptestaccountsandrunningthesampleapplication. 設定測試帳戶,並且同時執行範例程式Note: Buildingandrunningthesampleapplicationisnecessaryonlyifyouwanttoseeademonstrationofin-appbilling.Ifyoudonotwanttorunthesampleapplication,youcanskiptothenextsection, AddingtheAIDLfiletoyourproject.註︰如果你想要看關於iap機制的說明,才需要建立並運行範例程式。

假如你不想要看這個說明,你可以直接跳到 AddingtheAIDLfiletoyourproject這個篇幅。

Configuringandbuildingthesampleapplication設定並建立範例程式 Beforeyoucanrunthesampleapplication,youneedtoconfigureitandbuilditbydoingthefollowing:在你開始執行範例程式以前,你需要先依照下列的說明做一些相關的設定︰AddyourAndroidMarketpublickeytothesampleapplicationcode. ThisenablestheapplicationtoverifythesignatureofthetransactioninformationthatisreturnedfromAndroidMarket.Toaddyourpublickeytothesampleapplicationcode,dothefollowing: 將您Android市集的公鑰放進範例程式原始碼中。

這麼做是為了要啟動從Android市集傳來交易資訊的簽章認証機制,請依下列方式新增您的公鑰至範例程式中︰LogintoyourAndroidMarket publisheraccount. 登入您的Android市集發佈帳戶 Ontheupperleftpartofthepage,underyourname,click EditProfile. 在頁面上方的左側,你的名字底下,點擊EditProfile OntheEditProfilepage,scrolldowntothe Licensing&In-appBilling panel. 在EditProfile頁面下,往下滑到Licensing&In-appBilling這個區塊中 Copyyourpublickey. 複製區塊中的公鑰 Open src/com/example/dungeons/Security.java intheeditorofyourchoice.Youcanfindthisfileinthesampleapplication'sprojectfolder. 打開您使用的軟體開發工具,並打開範例程式專案並找到我們要設定的地方src/com/example/dungeons/Security.javaAddyourpublickeytothefollowinglineofcode:    將您的公鑰加入至下列的原始碼中   Stringbase64EncodedPublicKey="yourpublickeyhere";Savethefile. 存檔 Changethepackagenameofthesampleapplication. Thecurrentpackagenameiscom.example.dungeons.AndroidMarketdoesnotletyouuploadapplicationswithpackagenamesthatcontain com.example,soyoumustchangethepackagenametosomethingelse. 更改範例程式的套件名稱(packagename)。

現在的套件名稱是com.example.dungeons。

Android市集無法讓您上傳com.example開頭的套件名稱,因此你必須更改套件名稱。

Buildthesampleapplicationinreleasemodeandsignit. Tolearnhowtobuildandsignapplications,see BuildingandRunning. 建立範例程式並將它釋出,然後做簽署。

如果想學習如何建立和替程式加入簽章,請參考BuildingandRunning章節。

  Uploadingthesampleapplication上傳範例程式 Afteryoubuildareleaseversionofthesampleapplicationandsignit,youneedtouploaditasadrafttotheAndroidMarketpublishersite.Youalsoneedtocreateaproductlistforthein-appitemsthatareavailableforpurchaseinthesampleapplication.Thefollowinginstructionsshowyouhowtodothis.在您建立了範例程式的釋出版本,而且也簽署後,您必須將這個範例程式草稿apk上傳至Android市集發佈網站。

您也需要在範例程式中建立一些內部消費的產品列表,下方的說明教告知您如何辦到︰UploadthereleaseversionofthesampleapplicationtoAndroidMarket. Donotpublishthesampleapplication;leaveitasanunpublisheddraftapplication.ThesampleapplicationisfordemonstrationpurposesonlyandshouldnotbemadepubliclyavailableonAndroidMarket.TolearnhowtouploadanapplicationtoAndroidMarket,see Uploadingapplications. 上傳範例程式的釋出版本至Android市集。

請勿發佈此範例程式,請上傳並儲存就好。

由於範例程式只是教學用,因此不需要真的發佈至Android市集。

如果想學習如何上傳APP至Android市集,請參閱Uploadingapplications這篇。

Createaproductlistforthesampleapplication. Thesampleapplicationletsyoupurchasetwoitems:atwo-handedsword(sword_001)andapotion(potion_001).Werecommendthatyousetupyourproductlistsothat sword_001 hasapurchasetypeof"Managedperuseraccount"and potion_001 hasapurchasetypeof"Unmanaged"soyoucanseehowthesetwopurchasetypesbehave.Tolearnhowtosetupaproductlist,see CreatingaProductList. 建立範例程式的產品列表。

在範例程式中,我們提供您可以購買2種商品︰雙手劍(sword_001)和藥水(potion_001)。

我們建議你將sword_001設定成「受管理(依使用帳戶)」,而potion_001則設成「不受管理」,設定完後,您就可以看到這2種商品類別的呈現方式了。

如果想要學如何設定商品列表,請參見CreatingaProductList。

  Note: Youmustpublishtheitemsinyourproductlist(sword_001 and potion_001)eventhoughyouarenotpublishingthesampleapplication.Also,youmusthaveaGoogleCheckoutMerchantaccounttoadditemstothesampleapplication'sproductlist.註︰即使您沒有真的將範例程式發佈出去,內部商品都需要真正發佈出去(sword_001和potion_001)。

並且,您必須擁有GoogleCheckoutMerchant帳戶來新增範例程式商品列表的項目。

(譯者註︰程式不發佈是因為不需要真的發佈,否則Android市集會大亂。

即使之後你真的有APP要測試iap機制的可行性,都不需要將APP真正發佈,但是內部商品則需要發佈。

Google會去檢查您Profile裡設定的測試帳戶,讓那些帳戶可以找到這些未被真實發佈、而又有內部商品的APP供您測試) Runningthesampleapplication執行範例程式 You cannotrun thesampleapplicationintheemulator.Youmustinstallthesampleapplicationontoadevicetorunit.Torunthesampleapplication,dothefollowing:您無法在模擬器中執行範例程式。

您必須在裝置上運行它。

請參照下列方式來運行︰MakesureyouhaveatleastonetestaccountregisteredunderyourAndroidMarketpublisheraccount. Youcannotpurchaseitemsfromyourself(GoogleCheckoutprohibitsthis),soyouneedtocreateatleastonetestaccountthatyoucanusetopurchaseitemsinthesampleapplication.Tolearnhowtosetupatestaccount,seeSettingupTestAccounts. 請確定至少有一組測試帳號被註冊至您的Androidpublisher帳戶中。

您無購買您自己的商品(會被Google付費禁止)。

因此您必須至少加入一組可用的測試帳戶來購買範例程式中的商品。

如果想要了解更多測試帳戶如何設定的資訊,請參見SettingupTestAccounts。

VerifythatyourdeviceisrunningasupportedversionoftheAndroidMarketapplicationortheMyAppsapplication. IfyourdeviceisrunningAndroid3.0,in-appbillingrequiresversion5.0.12(orhigher)oftheMyAppsapplication.IfyourdeviceisrunninganyotherversionofAndroid,in-appbillingrequiresversion2.3.4(orhigher)oftheAndroidMarketapplication.TolearnhowtochecktheversionoftheAndroidMarketapplication,see UpdatingAndroidMarket. 請確認您裝置裡的Android市集軟體或MyApps軟體是能夠支援iap機制的。

如果您的裝置在Android3.0運行,需要MyApps軟體在版號5.0.12(或更高)。

假如您的裝置運行其它的Android版本,那麼Android市集的版號需求為2.3.4(或更高)。

如果想要知道如何檢查Android市集軟體的版號,請參見UpdatingAndroidMarket這篇文章的描述。

Installtheapplicationontoyourdevice. EventhoughyouuploadedtheapplicationtoAndroidMarket,theapplicationisnotpublished,soyoucannotdownloaditfromAndroidMarkettoadevice.Instead,youmustinstalltheapplicationontoyourdevice.Tolearnhowtoinstallanapplicationontoadevice,see Runningonadevice. 將範例程式安裝至裝置上。

即使您上傳了這個範例程式至Android市集,由於此APP未被發佈(譯者註︰請見上面的說明),所以您無法從Android市集下載此APP至裝置上。

但是您仍然需要安裝這個APP!如果想知道要如何安裝,請參見Runningonadevice這篇文章。

Makeoneofyourtestaccountstheprimaryaccountonyourdevice. Theprimaryaccountonyourdevicemustbeoneofthe testaccounts thatyouregisteredontheAndroidMarketsite.Iftheprimaryaccountonyourdeviceisnotatestaccount,youmustdoafactoryresetofthedeviceandthensigninwithoneofyourtestaccounts.Toperformafactoryreset,dothefollowing: 將測試帳戶設定至您裝置上成為主要帳戶。

你裝置上的主要帳戶必須是一組您註冊至Android市集的測試帳戶。

如果您裝置上的主要帳戶不是測試帳戶,您必須做原廠設定,然後用您的測試帳戶來登入。

如果想知道如何做原廠設定,請照以下的方法執行︰OpenSettingsonyourdevice. 開啟裝置上的設定Touch Privacy. 點擊隱私設定Touch Factorydatareset. 點擊重設為原廠設定Touch Resetphone  點擊重設手機按鈕 Afterthephoneresets,besuretosigninwithoneofyourtestaccountsduringthedevicesetupprocess. 手機重置之後,請確認您已登入了一組測試帳戶。

Runtheapplicationandpurchasetheswordorthepotion. Whenyouuseatestaccounttopurchaseitems,thetestaccountisbilledthroughGoogleCheckoutandyourGoogleCheckoutMerchantaccountreceivesapayoutforthepurchase.Therefore,youmaywanttorefundpurchasesthataremadewithtestaccounts,otherwisethepurchaseswillshowupasactualpayoutstoyourmerchantaccount. 執行範例程式,然後購買隻手劍和藥水。

當你使用了測試帳戶來購買商品後,測試帳戶會透過GoogleCheckout的金流流程來執行購買動作。

你的GoogleCheckoutMerchant帳戶會接收到購買的花費記錄。

因此,您也許會想要退費,因為您正在使用測試帳號來做測試。

此外,實際花費的購買項目會顯示在您merchant帳戶裡。

Note:Debuglogmessagesareturnedoffbydefaultinthesampleapplication.Youcanturnthemonbysettingthevariable DEBUG to true inthe Consts.java file.註︰範例程式中,除錯用的log訊息預設是關閉的。

你可以在Consts.java檔中,將DEBUG變數打開。

ADDINGTHEAIDLFILETOYOURPROJECT將AIDL檔加進您的專案夾中 ThesampleapplicationcontainsanAndroidInterfaceDefinitionLanguage(AIDL)file,whichdefinestheinterfacetoAndroidMarket'sin-appbillingservice(MarketBillingService).Whenyouaddthisfiletoyourproject,theAndroidbuildenvironmentcreatesaninterfacefile(IMarketBillingService.java).YoucanthenusethisinterfacetomakebillingrequestsbyinvokingIPCmethodcalls.範例程式裡已將Android接口定義語言加入進去了。

這個檔定義了將請求發送至Android市集iap服務的接口。

當您將此檔案加入至專案夾後,Android建構環境會建立一個接口檔(IMarketBillingService.java)。

您可以使用這個接口,透過呼叫IPC函式的呼叫,來發送金流請求。

IfyouareusingtheADTplug-inwithEclipse,youcanjustaddthisfiletoyour /src directory.Eclipsewillautomaticallygeneratetheinterfacefilewhenyoubuildyourproject(whichshouldhappenimmediately).IfyouarenotusingtheADTplug-in,youcanputtheAIDLfileintoyourprojectandusetheAnttooltobuildyourprojectsothatthe IMarketBillingService.java filegetsgenerated.如果您正在Eclipse裡使用ADT插件工具,您可以單純將此檔放進/src目錄下就好。

Eclipse會在你建立專案時(應該會立即建立)自動產生接口檔。

如果您不是使用ADT插件工具,您仍可以將AIDL檔放至您的專案夾裡,並使用Ant工具來建立您的專案,這樣子IMarketBillingService.java檔仍會產生。

Toaddthe IMarketBillingService.aidl filetoyourproject,dothefollowing:如果您要將IMarketBillingService.aidl檔加進您的專案夾裡,請照著以下的說明︰Createthefollowingdirectoryinyourapplication's /src directory:  將下列的目錄加進您/src資料夾底下com/android/vending/billing/ Copythe IMarketBillingService.aidl fileintothesample/src/com/android/vending/billing/ directory. 將IMarketBillingService.aidl檔放進sample/src/com/android/vending/billing/資料夾下 Buildyourapplication. 建立您的程式Youshouldnowfindageneratedinterfacefilenamed IMarketBillingService.java inthe genfolderofyourproject.現在您應該能在您專案裡gen資料夾下找到產生出來的這個IMarketBillingService.java接口檔。

 UPDATINGYOURAPPLICATION'SMANIFEST更新您APP裡MANIFEST裡的內容 In-appbillingreliesontheAndroidMarketapplication,whichhandlesallcommunicationbetweenyourapplicationandtheAndroidMarketserver.TousetheAndroidMarketapplication,yourapplicationmustrequesttheproperpermission.Youcandothisbyaddingthecom.android.vending.BILLING permissiontoyourAndroidManifest.xmlfile.Ifyourapplicationdoesnotdeclarethein-appbillingpermission,butattemptstosendbillingrequests,AndroidMarket willrefusetherequestsandrespondwitha RESULT_DEVELOPER_ERROR responsecode.Iap機制仰賴在Android市集軟體裡,因為能夠處理所有您的APP和Android市集伺服器之間的通。

為了要使用Android市集軟體,您的APP必須做出合適的權限請求。

您可以將com.android.vending.BILLING權限加進AndroidManifest.xml檔裡。

如果您的APP沒有宣告此iap權限,並且嚐試發送金流請求,Androdi市集將會拒請您的請求,並且發出RESULT_DEVELOPER_ERROR這個回應值給您。

 Inadditiontothebillingpermission,you needtodeclarethe BroadcastReceiver thatyouwillusetoreceiveasynchronousresponsemessages(broadcastintents)fromAndroidMarket,andyouneedto declarethe Service thatyouwillusetobindwiththe IMarketBillingService andsendmessagestoAndroidMarket.Youmustalso declare intentfilters forthe BroadcastReceiver sothattheAndroidsystemknowshowtohandlethebroadcastintentsthataresentfromtheAndroidMarketapplication.關於金流權限的宣告,這裡要附帶一提的是,您必須再宣告一個BroadcastReceiver來讓你能夠接收從Android市集傳來的異步回應訊息(廣播意圖),然後您需要宣告一個Service讓你能夠將IMarketBillingService綁定至您的程式,因而能夠發送訊息至Android市集。

您也需要在BroadcastReceiver裡宣告intentfilters讓Android系統了解如何處理來自Android市集軟體傳來的廣播意圖。

Forexample,hereishowthein-appbillingsampleapplicationdeclaresthebillingpermission,the BroadcastReceiver,the Service,andtheintentfilters.Inthesampleapplication,BillingReceiver isthe BroadcastReceiver thathandlesbroadcastintentsfromtheAndroidMarketapplicationand BillingService isthe Service thatsendsrequeststotheAndroidMarketapplication.底下這些是範例程式裡宣告金流權限的範例,BroadcastReceiver(廣播接收機制)、Service(背景的服務)和intentfilters。

在範例程式裡,BillingReceiver就是這裡提的廣播接收機制,它幫助您處理從Android市集傳來的廣播意圖。

而BillingService就是這個背景服務,負責發送請求至Android市集軟體。

                                                                CREATINGALOCALSERVICE建立一個本地端SERVICE服務 Yourapplicationmusthavealocal Service tofacilitatemessagingbetweenyourapplicationandAndroidMarket.Ataminimum,thisservicemustdothefollowing:您的APP必須有一個本地端的Service來有效率的處理您跟Android市集之間的訊息。

最起碼,這個Service必須有一些下列列出來的功能︰Bindtothe MarketBillingService.  首先,這個Service要和MarketBillingService做綁定的動作 Sendbillingrequests(asIPCmethodcalls)totheAndroidMarketapplication.Thefivetypesofbillingrequestsinclude:  能夠發送金流請求(由IPCmethod來呼叫)到Android市集應用程式中。

這5種請求包含︰ CHECK_BILLING_SUPPORTED requests檢查金流是否支援的請求 REQUEST_PURCHASE requests購買的請求 GET_PURCHASE_INFORMATION requests取得購買資訊的請求 CONFIRM_NOTIFICATIONS requests確認Android傳來的通知的請求 RESTORE_TRANSACTIONS requests還原交易狀態的請求 Handlethesynchronousresponsemessagesthatarereturnedwitheachbillingrequest. 能夠處理每次我們發出金流請求後,Android市集同步回傳回來的同步反應訊息。

 BindingtotheMarketBillingService綁定到市集的金流服務 Bindingtothe MarketBillingService isrelativelyeasyifyou'vealreadyaddedtheIMarketBillingService.aidl filetoyourproject.Thefollowingcodesampleshowshowtousethe bindService() methodtobindaservicetothe MarketBillingService.Youcouldputthiscodeinyourservice's onCreate() method.如果您已經將IMarketBillingService.aidl檔加進您的專案夾裡,綁定到市集的金流服務應該就蠻簡單的了。

跟著下面的範例程式碼,將會告訴您如何使用bindService()函式來綁定一個Service到市集金流服務中。

您可以試著將這些程式碼放入您Service的onCreate()這個回呼函式中。

try{  booleanbindResult=mContext.bindService(   newIntent("com.android.vending.billing.MarketBillingService.BIND"),this,   Context.BIND_AUTO_CREATE);  if(bindResult){   Log.i(TAG,"Servicebindsuccessful.");  }else{   Log.e(TAG,"CouldnotbindtotheMarketBillingService.");  }}catch(SecurityExceptione){  Log.e(TAG,"Securityexception:"+e);} Afteryoubindtotheservice,youneedtocreateareferencetothe IMarketBillingServiceinterfacesoyoucanmakebillingrequestsviaIPCmethodcalls.Thefollowingcodeshowsyouhowtodothisusingthe onServiceConnected() callbackmethod.在您綁定到Service後,您需要建立一個參照到IMarketBillingService介面的接口。

這樣您才可以透過IPC函式的呼叫來達到金流請求的能力。

底下的程式碼告知您如何使用onServiceConnected()回呼函式來做到這件事。

/**  *TheAndroidsystemcallsthiswhenweareconnectedtotheMarketBillingService.  */  publicvoidonServiceConnected(ComponentNamename,IBinderservice){   Log.i(TAG,"MarketBillingServiceconnected.");   mService=IMarketBillingService.Stub.asInterface(service);  } Youcannowusethe mService referencetoinvokethe sendBillingRequest() method.Foracompleteimplementationofaservicethatbindstothe MarketBillingService,seetheBillingService classinthesampleapplication.現在您可以使用參照到的這個mService來呼叫sendBillingRequest()函式了。

想要了解完全實作綁定到市集金流服務的Service要怎麼做的話,可以參照範例程式裡BillingService這個類別檔案。

SendingbillingrequeststotheMarketBillingService發送金流請求至市集金流服務 Nowthatyour Service hasareferencetothe IMarketBillingService interface,youcanusethatreferencetosendbillingrequests(viaIPCmethodcalls)tothe MarketBillingService.TheMarketBillingService IPCinterfaceexposesasinglepublicmethod(sendBillingRequest()),whichtakesasingle Bundle parameter.TheBundlethatyoudeliverwiththismethodspecifiesthetypeofrequestyouwanttoperform,usingvariouskey-valuepairs.Forinstance,onekeyindicatesthetypeofrequestyouaremaking,anotherindicatestheitembeingpurchased,andanotheridentifiesyourapplication.The sendBillingRequest() methodimmediatelyreturnsaBundlecontaininganinitialresponsecode.However,thisisnotthecompletepurchaseresponse;thecompleteresponseisdeliveredwithanasynchronousbroadcastintent.FormoreinformationaboutthevariousBundlekeysthataresupportedbytheMarketBillingService,see In-appBillingServiceInterface.現在您的Service已經有一個IMarketBillingService的接口了。

您可以使用它來發送金流請求(透過IPC函式的呼叫)到市集金流服務中。

市集金流服務這個IPC接口有一個public函式,可以拿它來裝一個Bundle參數。

Bundle讓您傳送您指定的金流請求-使用key-value的方式。

舉例來說,現在有一個key值,您拿來發出一個請求類型(如︰CHECK_BILLING_SUPPORTED)。

而另一個key值傳送您想購買的商品為何,最後一個key值傳送辨識您APP的方式。

此時,sendBillingRequest()函式會立刻返回一個含有初始回應值的Bundle給您。

然而,這並非是完整購買的回應,完整的回應應該是會以一個異步的廣播意圖來傳達給您的。

如果想知道市集金流服務裡,有被支援的各種Bundle的key的用法,請參見 In-appBillingServiceInterface這個章節。

Youcanusethe sendBillingRequest() methodtosendfivetypesofbillingrequests.Thefiverequesttypesarespecifiedusingthe BILLING_REQUEST Bundlekey.ThisBundlekeycanhavethefollowingfivevalues:您可以使用sendBillingRequest()函式去發送五種類型的金流請求。

這五種金流請求皆被指定使用BILLING_REQUESTBundlekey。

這些key如下︰ CHECK_BILLING_SUPPORTED—verifiesthattheAndroidMarketapplicationsupportsin-appbilling. CHECKBILLING_SUPPORTED(檢查是否支援金流服務)-驗証裝置上的Android市集軟體是否支援iap機制。

REQUEST_PURCHASE—sendsapurchaserequestforanin-appitem. REQUEST_PURCHASE(請求購買商品)-發送購買商品的請求。

GET_PURCHASE_INFORMATION—retrievestransactioninformationforapurchaseorrefund. GET_PURCHASE_INFORMATION(取得購買資訊)-接收商品購買或退費的交易資訊。

CONFIRM_NOTIFICATIONS—acknowledgesthatyoureceivedthetransactioninformationforapurchaseorrefund. CONFIRM_NOTIFICATIONS(確認Andorid市集傳來的通知訊息)-向市集做出交易資訊購買或退費而傳來的通知確認。

RESTORE_TRANSACTIONS—retrievesauser'stransactionhistoryfor managedpurchases. RESTORE_TRANSACTIONS(還原交易狀態)-接收使用者受管理類型的購買商品歷史交易資訊。

Tomakeanyofthesebillingrequests,youfirstneedtobuildaninitial Bundle thatcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.ThefollowingcodesampleshowsyouhowtocreateahelpermethodnamedmakeRequestBundle() thatdoesthis.如果要發送以上任一金流請求,首先你需要先建立一個初始化的Bundle用來夾帶3個key值。

這3個key分別為︰BILLING_REQUEST,API_VERSION,PACKAGE_NAME。

下列的程式教你如何建立一個助手函式(helpermethod)-makeRequestBundle()來達成這個任務︰protectedBundlemakeRequestBundle(Stringmethod){  Bundlerequest=newBundle();  request.putString(BILLING_REQUEST,method);  request.putInt(API_VERSION,1);  request.putString(PACKAGE_NAME,getPackageName());  returnrequest;   Tousethishelpermethod,youpassina String thatcorrespondstooneofthefivetypesofbillingrequests.ThemethodreturnsaBundlethathasthethreerequiredkeysdefined.Thefollowingsectionsshowyouhowtousethishelpermethodwhenyousendabillingrequest.要使用這個助手函式,你需要先傳入一組String值,這個String值是上面列出的五種的其中一種。

這個助手函式會返回一個Bundle,該Bundle含蓋了3個被定義的需求key(譯者註︰就是上面提到的BILLING_REQUEST,API_VERSION和PACKAGE_NAME)。

下一個段落將會教你如何在需要發送金流請求時,使用這個助手函式來完成。

Important:Youmustmakeallin-appbillingrequestsfromyourapplication'smainthread.重要︰你必須在你的應用程式主執行緒來發送iap金流請求,不可使用次執行緒來發送。

Verifyingthatin-appbillingissupported(CHECK_BILLING_SUPPPORTED)驗証您裝置上的Android市集APP是否支援iap機制(使用CHECK_BILLING_SUPPORTED) ThefollowingcodesampleshowshowtoverifywhethertheAndroidMarketapplicationsupportsin-appbilling.Inthesample, mService isaninstanceofthe MarketBillingServiceinterface.下面的程式碼列出了如何驗証手上裝置的Android市集軟體是否有支援iap機制。

在這範例中,mService是MarketBillingService介面的物件實體。

/** *RequesttypeisCHECK_BILLING_SUPPORTED */  Bundlerequest=makeRequestBundle("CHECK_BILLING_SUPPORTED");  Bundleresponse=mService.sendBillingRequest(request);  //Dosomethingwiththisresponse.}   The makeRequestBundle() methodconstructsaninitialBundle,whichcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.Therequestreturnsasynchronous Bundle response,whichcontainsonlyasinglekey: RESPONSE_CODE.TheRESPONSE_CODE keycanhavethefollowingvalues:makeRequesstBundle()函式會建構一個初始化的Bundle,這個Bundle會包含3個key值,也就是請求需要的BILLING_REQUEST,API_VERSION和PACKAGE_NAME。

請求會回傳一個同步性質的Bundle回應,這個回應只會包含一個key值︰RESPONSE_CODE。

RESPONSE_CODE可能會傳來︰RESULT_OK—in-appbillingissupported. REQUEST_OK-回覆您手機Android市集的軟體版號有支援iap機制 RESULT_BILLING_UNAVAILABLE—in-appbillingisnotavailablebecausetheAPIversionyouspecifiedisnotrecognizedortheuserisnoteligibletomakein-apppurchases(forexample,theuserresidesinacountrythatprohibitsin-apppurchases). RESULT_BILLING_UNAVAILABLE-由於您指定的API版本無法辨識或者使用者經由非法管道提出iap的請求(例如,使用者居住地禁止使用iap機制),因此無法支援iap服務。

RESULT_ERROR—therewasanerrorconnectingwiththeAndroidMarketapplication. RESULT_ERROR-在連接Android市集軟體時,出了些問題。

RESULT_DEVELOPER_ERROR—theapplicationistryingtomakeanin-appbillingrequestbuttheapplicationhasnotdeclaredthe com.android.vending.BILLING permissioninitsmanifest.Canalsoindicatethatanapplicationisnotproperlysigned,orthatyousentamalformedrequest. RESULT_DEVELOPER_ERROR-您的APP試圖發出iap請求,但是由於AndroidManifest.xml裡未宣告權限︰com.android.vending.BILLING,或者您的APP未做適當的簽署,也或者您的APP發出了一個未制定的請求,因此您收到了這個RESPONSE_CODE。

The CHECK_BILLING_SUPPORTED requestdoesnottriggeranyasynchronousresponses(broadcastintents).CHECK_BILLING_SUPPORTED請求不會發出任何異步回應(指的是廣播意圖)。

Werecommendthatyouinvokethe CHECK_BILLING_SUPPORTED requestwithina RemoteExceptionblock.Whenyourcodethrowsa RemoteException itindicatesthattheremotemethodcallfailed,whichmeansthattheAndroidMarketapplicationisoutofdateandneedstobeupdated.Inthiscase,youcanprovideuserswithanerrormessagethatcontainsalinktothe UpdatingAndroidMarket Helptopic.我們建議您在RemoteException區塊中呼叫CHECK_BILLING_SUPPORTED請求。

當您的程式碼抛出了RemoteException這個例外,表示遠端呼叫函式出錯了,這意謂著Android市集軟體過期了、或者需要更新了。

在這個狀況下,你可以提供一組連結至更新Android市集幫助文檔的連結,告知使用者哪裡出錯了。

 Thesampleapplicationdemonstrateshowyoucanhandlethiserrorcondition(seeDIALOG_CANNOT_CONNECT_ID in Dungeons.java).範例程式也說明了您能如何的處理此錯誤訊息(請看Dungeons.java裡DIALOG_CANNOT_CONNECT_ID)。

Makingapurchaserequest(REQUEST_PURCHASE)發出購買請求(REQUEST_PURCHASE) Tomakeapurchaserequestyoumustdothefollowing:如果要發出購買請求,您必須遵照以下步驟︰Sendthe REQUEST_PURCHASE request. 發送REQUEST_PURCHASE請求 Launchthe PendingIntent thatisreturnedfromtheAndroidMarketapplication. 執行PendingIntent,這是由Android市集軟體回傳回來的值。

HandlethebroadcastintentsthataresentbytheAndroidMarketapplication. 處理由Android市集軟體發送過來的廣播意圖。

Makingtherequest發出請求 Youmustspecifyfourkeysintherequest Bundle.Thefollowingcodesampleshowshowtosetthesekeysandmakeapurchaserequestforasinglein-appitem.Inthesample, mProductId istheAndroidMarketproductIDofanin-appitem(whichislistedintheapplication's productlist),and mService isaninstanceofthe MarketBillingService interface.您必須在請求的Bundle中置入4組key。

底下的程式碼範例將教您如何在一筆iap商品中,設定這4組key的購買請求。

請範例裡,mProductId是Android市集的應用程式內商品的產品ID(被列表於軟體的產品項目中),而mService是MarketBillingService介面的實體。

/** *RequesttypeisREQUEST_PURCHASE */  Bundlerequest=makeRequestBundle("REQUEST_PURCHASE");  request.putString(ITEM_ID,mProductId);  //Notethatthedeveloperpayloadisoptional.  if(mDeveloperPayload!=null){   request.putString(DEVELOPER_PAYLOAD,mDeveloperPayload);  }  Bundleresponse=mService.sendBillingRequest(request);  //Dosomethingwiththisresponse.   The makeRequestBundle() methodconstructsaninitialBundle,whichcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.The ITEM_IDkeyisthenaddedtotheBundlepriortoinvokingthe sendBillingRequest() method.Therequestreturnsasynchronous Bundle response,whichcontainsthreekeys:RESPONSE_CODE, PURCHASE_INTENT,and REQUEST_ID.The RESPONSE_CODE keyprovidesyouwiththestatusoftherequestandthe REQUEST_ID keyprovidesyouwithauniquerequestidentifierfortherequest.The PURCHASE_INTENT keyprovidesyouwitha PendingIntent,whichyoucanusetolaunchthecheckoutUI.makeRequesstBundle()函式建構了一個初始化的Bundle,這個Bundle包含了3組key值,分別為︰BILLING_REQUEST,API_VERSION和PACKAGE_NAME,這些key值都是在使用這個函式時需要的。

keyITEM_ID接著會加進Bundle中,拿來呼叫sendBillingRequest()函式。

此請求會回傳一個同步的Bundle回應,包含了3個key值︰RESPONSE_CODE,PURCHASE_INTENT和REQUEST_ID3組值。

RESPONSE_CODE值提供了請求的狀態,REQUEST_ID值提供您單一的請求識別碼,PURCHASE_INTENT值提供您一組PendingIntent,可以拿它啟動付費使用介面。

Usingthependingintent使用pendingintent(即將發生的意圖) HowyouusethependingintentdependsonwhichversionofAndroidadeviceisrunning.OnAndroid1.6,youmustusethependingintenttolaunchthecheckoutUIinitsownseparatetaskinsteadofyourapplication'sactivitystack.OnAndroid2.0andhigher,youcanusethependingintenttolaunchthecheckoutUIonyourapplication'sactivitystack.Thefollowingcodeshowsyouhowtodothis.Youcanfindthiscodeinthe PurchaseObserver.java fileinthesampleapplication.如何使用pendingintent(即將發生的意圖)完全仰賴於裝置運行的Android版本。

如果是Androdi1.6,您必須在另外的執行緒中運行付費使用介面,而非應用程式主執行緒來完成工作。

在Android2.0或更高的版本,您可以在您應用軟體的activitystack中使用pendingintent。

底下的式碼將教導您如何使用pendingintent。

您可以在範例檔中,PruchaseObserver.java檔裡找到這段式碼。

voidstartBuyPageActivity(PendingIntentpendingIntent,Intentintent){  if(mStartIntentSender!=null){   //ThisisonAndroid2.0andbeyond. Thein-appcheckoutpageactivity   //willbeontheactivitystackoftheapplication.   try{    //Thisimplementsthemethodcall:    //mActivity.startIntentSender(pendingIntent.getIntentSender(),    //  intent,0,0,0);    mStartIntentSenderArgs[0]=pendingIntent.getIntentSender();    mStartIntentSenderArgs[1]=intent;    mStartIntentSenderArgs[2]=Integer.valueOf(0);    mStartIntentSenderArgs[3]=Integer.valueOf(0);    mStartIntentSenderArgs[4]=Integer.valueOf(0);    mStartIntentSender.invoke(mActivity,mStartIntentSenderArgs);   }catch(Exceptione){    Log.e(TAG,"errorstartingactivity",e);    }  }else{   //ThisisonAndroid1.6.Thein-appcheckoutpageactivitywillbeonits   //ownseparateactivitystackinsteadofontheactivitystackof   //theapplication.   try{    pendingIntent.send(mActivity,0/*code*/,intent);   }catch(CanceledExceptione){    Log.e(TAG,"errorstartingactivity",e);    }  }}   Important: Youmustlaunchthependingintentfromanactivitycontextandnotanapplicationcontext.Also,youcannotusethe singleTop launchmode tolaunchthependingintent.Ifyoudoeitherofthese,theAndroidsystemwillnotattachthependingintenttoyourapplicationprocess.Instead,itwillbringAndroidMarkettotheforeground,disruptingyourapplication. 重要︰您必須在Activity的context下運行pendingintent而非使用application的context。

您不能使用singleTop這個launchmode(執行模式)來執行pendingintent。

如果您都這樣做的話,Android系統將無法將pendingintent附著於您的應用程式進程中。

反之,它還會將Android市集帶至前景,擾亂了您的應用程式運行。

  Handlingbroadcastintents處理Android市集傳來的廣播意圖 A REQUEST_PURCHASE requestalsotriggerstwoasynchronousresponses(broadcastintents).First,theAndroidMarketapplicationsendsa RESPONSE_CODE broadcastintent,whichprovideserrorinformationabouttherequest.Iftherequestdoesnotgenerateanerror,the RESPONSE_CODEbroadcastintentreturns RESULT_OK,whichindicatesthattherequestwassuccessfullysent.(Tobeclear,a RESULT_OK responsedoesnotindicatethattherequestedpurchasewassuccessful;itindicatesthattherequestwassentsuccessfullytoAndroidMarket.)當我們發送出REQUEST_PURCHASE請求時,Android市集會以異步的方式傳來2個回應(皆為廣播意圖)。

第1個是RESPONSE_CODE,該廣播意圖可能會傳來關關於請求的錯誤資訊。

倘若請求未發生任何錯誤,REPONSE_CODE原則上應該是會回傳RESULT_OK,這個回應指出你的請求已經成功被發送。

(這裡要釐清一點︰RESULT_OK這個回應並不代表請求購買成功,而是指我們發送請求購買至Android市集這個動作是成功的。

)Next,whentherequestedtransactionchangesstate(forexample,thepurchaseissuccessfullychargedtoacreditcardortheusercancelsthepurchase),theAndroidMarketapplicationsendsan IN_APP_NOTIFY broadcastintent.ThismessagecontainsanotificationID,whichyoucanusetoretrievethetransactiondetailsforthe REQUEST_PURCHASE request.接著,當請求過的交易資訊遭改變(舉例︰購買行為真的使用了信用卡消費或者使用者取消購買),Android市集軟體會發送IN_APP_NOTIFY這個廣播意圖給您。

這個訊息會夾雜訊息通知ID(notificationID),可以用這個ID來接收我們發送出REQUEST_PURCHASE請求的交易詳細資訊。

Note: TheAndroidMarketapplicationalsosendsan IN_APP_NOTIFY forrefunds.Formoreinformation,see HandlingIN_APP_NOTIFYmessages.註︰Android市集軟體也會發送使用者退費的IN_APP_NOTIFY廣播意圖。

更多資訊,請參閱HandlingIN_APP_NOTIFYmessages這個篇幅。

Becausethepurchaseprocessisnotinstantaneousandcantakeseveralseconds(ormore),youmustassumethatapurchaserequestispendingfromthetimeyoureceivea RESULT_OKmessageuntilyoureceivean IN_APP_NOTIFY messageforthetransaction.Whilethetransactionispending,theAndroidMarketcheckoutUIdisplaysan"Authorizingpurchase..."notification;however,thisnotificationisdismissedafter60secondsandyoushouldnotrelyonthisnotificationasyourprimarymeansofconveyingtransactionstatustousers.Instead,werecommendthatyoudothefollowing:由於購買流程不會馬上完成,這可能會花上數分鐘的時間(甚至更多時間),您必須假設會有一段要等待接收該交易RESULT_OK訊息至接收IN_APP_NOTIFY的過程時間。

當交易機制在背後運作時,Android市集提供的付費使用畫面會顯示"購買驗証中..."訊息;然而,當背景在傳送購買的這段過間,付費使用畫面上的訊息可能會在60秒後被關掉,因此您不應該等待這個訊息的完成。

反之,在這段時間,我們會建議您做下列幾件事︰Addan Activity toyourapplicationthatshowsusersthestatusofpendingandcompletedin-apppurchases.新增一個Activity到您的APP中,告知使用者正在等待完成購買應用程式內商品。

Usea statusbarnotification tokeepusersinformedabouttheprogressofapurchase. 用訊息列通知(statusbarnorification)來通知使用者現在的交易狀況。

TousethesetwoUIelements,youcouldinvokeastatusbarnotificationwithaticker-textmessagethatsays"Purchasepending"whenyourapplicationreceivesa RESULT_OK message.Then,whenyourapplicationreceivesan IN_APP_NOTIFY message,youcouldupdatethenotificationwithanewmessagethatsays"Purchasesucceeded"or"Purchasefailed."Whenausertouchestheexpandedstatusbarnotification,youcouldlaunchtheactivitythatshowsthestatusofpendingandcompletedin-apppurchases.若要用到上述的這2個使用介面元件,您應該在您APP接收到RESULT_OK訊息時,呼叫訊息通知欄,並顯示一段文字︰"購買等待中"。

然後,當您的APP接收到了IN_APP_NOTIFY訊息後,您應該更新訊息通知的文字內容,改成"購買成功"或"購買失敗了"。

當使用者點擊了該訊息通知欄位,您應該要啟動一個Activity,顯示出"正在等待購買流程"或"已完成iap購買"的狀態。

IfyouusesomeotherUItechniquetoinformusersaboutthestateofapendingtransaction,besurethatyourpendingstatusUIdoesnotblockyourapplication.Forexample,youshouldavoidusingahoveringprogresswheeltoconveythestatusofapendingtransactionbecauseapendingtransactioncouldlastalongtime,particularlyifadevicelosesnetworkconnectivityandcannotreceivetransactionupdatesfromAndroidMarket.若您要使用一些其它的使用介面技巧來通知您的user「交易正在處理中,請稍待」時,請確定您的通知使用介面不會將您原本的APP鎖死。

舉例來説,您應該避免使用旋轉等待輪之類的東西,告知使用者您正在等待交易的進行。

因為等待交易可能會花上一段很長的時間,特別是裝置在無連線能力或者無法接收從Android市集傳來的交易狀態更新時。

Important: Ifauserpurchasesamanageditem,youmustpreventtheuserfrompurchasingtheitemagainwhiletheoriginaltransactionispending.Ifauserattemptstopurchaseamanageditemtwice,andthefirsttransactionisstillpending,AndroidMarketwilldisplayanerrortotheuser;however,AndroidMarketwillnotsendanerrortoyourapplicationnotifyingyouthatthesecondpurchaserequestwascanceled.Thismightcauseyourapplicationtogetstuckinapendingstatewhileitwaitsforan IN_APP_NOTIFY messageforthesecondpurchaserequest.重要︰如果使用者購買的是受管理性質的商品,您必須預防使用者在既有交易等待狀態下再次購買商品。

假如使用者試圖購買第2次受管理性質的商品,而同時第1筆交易又仍在等待中,Andorid市集會顯示錯誤給使用者;然而,Andorid市集不會發送錯誤給您的APP知道,您的APP也因此不會知道第2次請求購買的動作被取消了。

這可能會造成您的APP在等待第2次購買請求要傳來的IN_APP_NOTIFY訊息時,整個程式卡住了。

  Retrievingtransactioninformationforapurchaseorrefund(GET_PURCHASE_INFORMATION)接收購買成功或退費的交易訊息(GET_PURCHASE_INFORMATION) Youretrievetransactioninformationinresponsetoan IN_APP_NOTIFY broadcastintent.TheIN_APP_NOTIFY messagecontainsanotificationID,whichyoucanusetoretrievetransactioninformation.您會在Androkd市集傳來的IN_APP_NOTIFY廣播意圖裡收到交易資訊。

這個訊息包含了訊息通知ID(notificationID),您可以拿它來接收交易資訊。

Toretrievetransactioninformationforapurchaseorrefundyoumustspecifyfivekeysintherequest Bundle.Thefollowingcodesampleshowshowtosetthesekeysandmaketherequest.Inthesample, mService isaninstanceofthe MarketBillingService interface.如果想要知道購買成功或者被退費,您必須在請求Bundle裡指定5個key值。

底下的程式範例將會教您如何設定這5個key值並且發出詢問的請求。

在這個範例中,mService是MarketBillingService介面的實體元件。

/** *RequesttypeisGET_PURCHASE_INFORMATION */  Bundlerequest=makeRequestBundle("GET_PURCHASE_INFORMATION");  request.putLong(REQUEST_NONCE,mNonce);  request.putStringArray(NOTIFY_IDS,mNotifyIds);  Bundleresponse=mService.sendBillingRequest(request);  //Dosomethingwiththisresponse.}   The makeRequestBundle() methodconstructsaninitialBundle,whichcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.Theadditionalkeysarethenaddedtothebundlepriortoinvokingthe sendBillingRequest()method.The REQUEST_NONCE keycontainsacryptographicallysecurenonce(numberusedonce)thatyoumustgenerate.TheAndroidMarketapplicationreturnsthisnoncewiththePURCHASE_STATE_CHANGED broadcastintentsoyoucanverifytheintegrityofthetransactioninformation.The NOTIFY_IDS keycontainsanarrayofnotificationIDs,whichyoureceivedintheIN_APP_NOTIFY broadcastintent.makeRequestBundle()這個函式建立了一個初始化的Bundle,包含了3個key值,提供發出請求之需,這3個key值分別為︰BILLING_REQUEST,API_VERSION和PACKAGE_NAME,加入後用來呼叫sendBillingRequest()函式。

而REQUEST_NONCE這個key值則包含一組您必須產生的密碼安全隨機數(僅用一次)。

Android市集軟體就會回傳夾雜這個隨機數的PURCHASE_STATE_CHANGED廣播意圖給您,因此您完全可以做好交易資訊的驗証工作。

NOTIFY_IDS這個key值包含了一組訊息通知IDs的陣列,可以在IN_APP_NOTIFY這個廣播意圖中接收到。

Therequestreturnsasynchronous Bundle response,whichcontainstwokeys: RESPONSE_CODEand REQUEST_ID.The RESPONSE_CODE keyprovidesyouwiththestatusoftherequestandtheREQUEST_ID keyprovidesyouwithauniquerequestidentifierfortherequest.A GET_PURCHASE_INFORMATION requestalsotriggerstwoasynchronousresponses(broadcastintents).First,theAndroidMarketapplicationsendsa RESPONSE_CODE broadcastintent,whichprovidesstatusanderrorinformationabouttherequest.Next,iftherequestwassuccessful,theAndroidMarketapplicationsendsa PURCHASE_STATE_CHANGED broadcastintent.Thismessagecontainsdetailedtransactioninformation.ThetransactioninformationiscontainedinasignedJSONstring(unencrypted).Themessageincludesthesignaturesoyoucanverifytheintegrityofthesignedstring.該請求會回傳一組同步的Bundle回應,並且包含了2個key值︰RESPONSE_CODE和REQUEST_ID。

RESPONSE_CODE此key提供給您請求的狀態,REQUEST_ID則提供您一組用來請求的單一請求識別。

GET_PURCHASE_INFORMATION這個請求也會發送出2組異步的回應(廣播意圖)。

首先,Android市集軟體會發送RESPONSE_CODE這個廣播意圖,提供您關於請求的狀態或錯誤資訊。

接著,如果請求是成功的,Android市集軟體會發送PURCHASE_STATE_CHANGE這個廣播意圖過來。

這個訊息包含了交易資訊的詳細內容,而交易訊又是被簽署在JSON字串裡(以未加密的方式)。

該訊息包含了數位簽章,因此您可以對簽章的字串做出高完整度的驗証。

 Acknowledgingtransactioninformation(CONFIRM_NOTIFICATIONS)承認該筆交易資訊(CONFIRM_NOTIFICATIONS) Toacknowledgethatyoureceivedtransactioninformationyousenda CONFIRM_NOTIFICATIONSrequest.Youmustspecifyfourkeysintherequest Bundle.Thefollowingcodesampleshowshowtosetthesekeysandmaketherequest.Inthesample, mService isaninstanceoftheMarketBillingService interface.如果要承認您已收到交易資訊,那就請您發送一組CONFIRM_NOTIFICATIONS請求。

在這個請求的Bundle裡,您必須指定4組key值。

底下的範例程式將會教導您如何設定這些key值,並且發送出請求。

在範例中,mService是MarketBillingService介面的實體元件。

/** *RequesttypeisCONFIRM_NOTIFICATIONS */  Bundlerequest=makeRequestBundle("CONFIRM_NOTIFICATIONS");  request.putStringArray(NOTIFY_IDS,mNotifyIds);  Bundleresponse=mService.sendBillingRequest(request);  //Dosomethingwiththisresponse.}   The makeRequestBundle() methodconstructsaninitialBundle,whichcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.Theadditional NOTIFY_IDS keyisthenaddedtothebundlepriortoinvokingthesendBillingRequest() method.The NOTIFY_IDS keycontainsanarrayofnotificationIDs,whichyoureceivedinan IN_APP_NOTIFY broadcastintentandalsousedinaGET_PURCHASE_INFORMATION request.makeRequestBundle()函式建構了一個初始化的Bundle值,該Bundle值包含了3組key值,用來提供給Android市集,這3組key值分別為BILLING_REQUEST,API_VERSION,PACKAGE_NAME。

接著要將NOTIFY_IDS加進這個Bundle中去呼叫sendBillingRequesst()函式。

NOTIFY_IDS這個key值包含了一組訊息通知ID的陣列,您可以拿來接收IN_APP_NOTIFY廣播意圖,也可以拿來發出GET_PURCHASE_INFORMATION的請求。

Therequestreturnsasynchronous Bundle response,whichcontainstwokeys: RESPONSE_CODEand REQUEST_ID.The RESPONSE_CODE keyprovidesyouwiththestatusoftherequestandtheREQUEST_ID keyprovidesyouwithauniquerequestidentifierfortherequest.該請求會回傳一個同步的Bundle回應,並包含2個key︰RESPONSE_CODE和REQUEST_ID。

RESPONSE_CODEkey提供了請求的狀態以及單一請求識別碼的REQUEST_IDkey。

A CONFIRM_NOTIFICATIONS requesttriggersasingleasynchronousresponse—a RESPONSE_CODEbroadcastintent.Thisbroadcastintentprovidesstatusanderrorinformationabouttherequest.CONFIRM_NOTIFICATIONS請求會回傳一個異步的回應-一個RESPONSE_CODE廣播意圖。

這個廣播意圖提供了請求的狀態與錯誤的相關資訊。

 YoumustsendaconfirmationwhenyoureceivetransactioninformationfromAndroidMarket.Ifyoudon'tsendaconfirmationmessage,AndroidMarketwillcontinuesending IN_APP_NOTIFYmessagesforthetransactionsyouhavenotconfirmed.Also,yourapplicationmustbeabletohandle IN_APP_NOTIFY messagesthatcontainmultipleorders.Inaddition,asabestpractice,youshouldnotsenda CONFIRM_NOTIFICATIONS requestforapurchaseditemuntilyouhavedeliveredtheitemtotheuser.Thisway,ifyourapplicationcrashesorsomethingelsepreventsyourapplicationfromdeliveringtheproduct,yourapplicationwillstillreceivean IN_APP_NOTIFY broadcastintentfromAndroidMarketindicatingthatyouneedtodelivertheproduct.當您在接收到來至於Android市集傳來的交易資訊之後,您必發出確認動作。

假如您未發送確認訊息出去,Android市集將會不斷地發送IN_APP_NOTIFY訊息給您,直至您確認了這筆交易。

而且,您的APP必須能夠處理包含多筆訂單的IN_APP_NOTIFY訊息。

附帶一提,在最佳的狀況下,在您尚未傳遞商品給user以前,都不應該發出該商品的CONFIRM_NOTIFICATIONS請求。

假如您的應用程式當了,或者其它的原因造成您的APP無法傳遞商品,您都還可以繼續接收到來至Androkd市集傳來的IN_APP_NOTIFY廣播意圖來傳遞您需要傳遞的商品。

Restoringtransactioninformation(RESTORE_TRANSACTIONS)還原交易資訊(RESTORE_TRANSACTIONS) Torestoreauser'stransactioninformation,yousenda RESTORE_TRANSACTIONS request.Youmustspecifyfourkeysintherequest Bundle.Thefollowingcodesampleshowshowtosetthesekeysandmaketherequest.Inthesample, mService isaninstanceoftheMarketBillingService interface.如果要還原使用者的交易資訊,您必須發送RESTORE_TRANSACTIONS請求至Androkd市集。

您必須使用4組指定請求的Bundlekey。

底下這段程式範例將會教導您如何設定這些key並發出請求。

在範例程式中,mService是MarketBillingService介面的物件實體。

/** *RequesttypeisRESTORE_TRANSACTIONS */  Bundlerequest=makeRequestBundle("RESTORE_TRANSACTIONS");  request.putLong(REQUEST_NONCE,mNonce);  Bundleresponse=mService.sendBillingRequest(request);  //Dosomethingwiththisresponse.}   The makeRequestBundle() methodconstructsaninitialBundle,whichcontainsthethreekeysthatarerequiredforallrequests: BILLING_REQUEST, API_VERSION,and PACKAGE_NAME.Theadditional REQUEST_NONCE keyisthenaddedtothebundlepriortoinvokingthesendBillingRequest() method.The REQUEST_NONCE keycontainsacryptographicallysecurenonce(numberusedonce)thatyoumustgenerate.TheAndroidMarketapplicationreturnsthisnoncewiththetransactionsinformationcontainedinthe PURCHASE_STATE_CHANGED broadcastintentsoyoucanverifytheintegrityofthetransactioninformation.makeRequestBundle()函式建構了一個初始化的Bundle,用來夾帶這3組請求需要的key︰BILLING_REQUEST,API_VERSION和PACKAGE_NAME。

附帶的REQUEST_NONCEkey加入Bundle裡主要是用來呼叫sendBillingRequest()函式用的。

REQUEST_NONCEkey包含了您產生的一組加密安全隨機數(僅用一次)。

Android市集軟體會透過PURCHASE_STATE_CHANGED這個廣播意圖來返回這串隨機數和交易資訊,因此您可以用來做完整交易資訊的驗証工作。

 Therequestreturnsasynchronous Bundle response,whichcontainstwokeys: RESPONSE_CODEand REQUEST_ID.The RESPONSE_CODE keyprovidesyouwiththestatusoftherequestandtheREQUEST_ID keyprovidesyouwithauniquerequestidentifierfortherequest.該請求回傳了一組同步的Bundle回應,該Bundle包含了2個key︰RESPONSE_CODE和REQUEST_ID。

RESPONSE_CODEkey提供您請求的狀態,REQUEST_IDkey提供您該請求的單一請求識別碼。

A RESTORE_TRANSACTIONS requestalsotriggerstwoasynchronousresponses(broadcastintents).First,theAndroidMarketapplicationsendsa RESPONSE_CODE broadcastintent,whichprovidesstatusanderrorinformationabouttherequest.Next,iftherequestwassuccessful,theAndroidMarketapplicationsendsa PURCHASE_STATE_CHANGED broadcastintent.Thismessagecontainsthedetailedtransactioninformation.ThetransactioninformationiscontainedinasignedJSONstring(unencrypted).Themessageincludesthesignaturesoyoucanverifytheintegrityofthesignedstring.RESTORE_TRANSACTIONS請求也會傳來2組異步的回應(廣播意圖)。

首先,Android市集軟體會發送一組RESPONSE_CODE廣播意圖,用來提供請求的狀態以及錯誤資訊。

接著,如果請求是成功的,Android市集軟體會發送PURCHASE_STATE_CHANGED廣播意圖過來。

這個訊息包含了交易資訊的詳細內容。

此交易資訊被包含在一個被簽署的JSON字串裡(非加密狀態)。

這個JSON訊息包含了數位簽章,因此您可以用這個簽章來做完整的簽章字串驗證。

Note: Youshouldusethe RESTORE_TRANSACTIONS requesttypeonlywhenyourapplicationisinstalledforthefirsttimeonadeviceorwhenyourapplicationhasbeenremovedfromadeviceandreinstalled.註︰使用RESTORE_TRANSACTIONS請求的時機應該只會發生在當您的APP首次安裝在裝置上,或者是被移除後又安裝回來的狀況底下。

  Otherservicetasks Service的其它工作 Youmayalsowantyour Service toreceiveintentmessagesfromyour BroadcastReceiver.YoucanusetheseintentmessagestoconveytheinformationthatwassentasynchronouslyfromtheAndroidMarketapplicationtoyour BroadcastReceiver.Toseeanexampleofhowyoucansendandreceivetheseintentmessages,seethe BillingReceiver.java andBillingService.java filesinthesampleapplication.Youcanusethesesamplesasabasisforyourownimplementation.However,ifyouuseanyofthecodefromthesampleapplication,besureyoufollowtheguidelinesin SecurityandDesign. 您也許也想要使用您的Service來接收從您BroadcastReceiver傳來的意圖訊息。

您可以將那些從Android市集軟體以異步方式傳至您BroadcastReceiver裡的意圖訊息來傳遞資訊。

若想看範例説明該如何發送和接收這些意圖訊息,請參見歸檔在範例程式中的BillingReceiver.java和BillingService.java檔。

您可以像基本實作自己類別的方式來使用它們。

然而,如果您真的採用了範例程式裡的任何原始碼來編寫您的iap機制,我們希望您已經確定讀過SecurityandDesign這篇文章。

CREATINGABROADCASTRECEIVER建立一個廣播接收機制 TheAndroidMarketapplicationusesbroadcastintentstosendasynchronousbillingresponsestoyourapplication.Toreceivetheseintentmessages,youneedtocreateaBroadcastReceiver thatcanhandlethefollowingintents: Androkd市集使用了一個廣播意圖來傳送異步的金流回應到您的APP裡。

如果要接收這些意圖訊,您必須建立一個BroadReceiver來處理底下的這些意圖︰com.android.vending.billing.RESPONSE_CODEThisbroadcastintentcontainsanAndroidMarketresponsecode,andissentafteryoumakeanin-appbillingrequest.Formoreinformationabouttheresponsecodesthataresentwiththisresponse,see AndroidMarketResponseCodesforIn-appBilling. com.android.vending.billing.RESPONSE_CODE這個廣播意圖包含了一個Android市集回應碼,會在您接著要執行iap機制再被發送出去。

如果想知道更多關於這個回應將被發送出去的回應碼的相關訊息,請見 AndroidMarketResponseCodesforIn-appBilling這個篇幅。

com.android.vending.billing.IN_APP_NOTIFYThisresponseindicatesthatapurchasehaschangedstate,whichmeansapurchasesucceeded,wascanceled,orwasrefunded.Formoreinformationaboutnotificationmessages,see In-appBillingBroadcastIntents com.android.vending.billing.IN_APP_NOTIFY這個回應指出了購買狀態遭到變更了。

這意謂著購買成功了、取消了、甚至是退費了。

更多關於訊息通知的相關資訊,請參見In-appBillingBroadcastIntents篇幅。

com.android.vending.billing.PURCHASE_STATE_CHANGEDThisbroadcastintentcontainsdetailedinformationaboutoneormoretransactions.Formoreinformationaboutpurchasestatemessages,see In-appBillingBroadcastIntents com.android.vending.billing.PURCHASE_STATE_CHANGED這個廣播意圖包含了一次或多次交易的詳細資訊。

更多關於購買狀態訊息的更多資訊,請參閱In-appBillingBroadcastIntents這個篇幅。

Eachofthesebroadcastintentsprovideintentextras,whichyour BroadcastReceiver musthandle.  Theintentextrasarelistedinthefollowingtable(seetable1). 每個廣播意圖都提供了intentextras,因此您的BroadcastReceiver必須能夠處理這個東西。

Table1. Descriptionofbroadcastintentextrasthataresentinresponsetobillingrequests.表1.描述出當我們在做金流請求而傳來回應時,我們會用到的相關廣播intentextras。

IntentExtraDescriptioncom.android.vending.billing.RESPONSE_CODE request_id A long representingarequestID.ArequestIDidentifiesaspecificbillingrequestandisreturnedbyAndroidMarketatthetimearequestismade.以Long型態來表示requestID。

一個requestID即為一個向Android市集提出金流請求時間所返回的識別值。

com.android.vending.billing.RESPONSE_CODE response_code An int representingtheactualAndroidMarketserverresponsecode.以int型態來表示Android市集伺服器的回應碼。

com.android.vending.billing.IN_APP_NOTIFY notification_id A String representingthenotificationIDforagivenpurchasestatechange.AndroidMarketnotifiesyouwhenthereisapurchasestatechangeandthenotificationincludesauniquenotificationID.Togetthedetailsofthepurchasestatechange,yousendthenotificationIDwiththeGET_PURCHASE_INFORMATION request.以String型態來表示當購買狀態遭改變時的訊息通知ID。

當購買狀態遭改變,Android市集會通知您,回傳的通知會包含一組特定訊息通知ID。

如果要取得更多詳細的購買狀態改變資料,請您使用GET_PURCHASE_INFORMATION這個請求,並夾帶這裡提到的訊息通知ID過來。

com.android.vending.billing.PURCHASE_STATE_CHANGED inapp_signed_data A String representingthesignedJSONstring.TheJSONstringcontainsinformationaboutthebillingtransaction,suchasordernumber,amount,andtheitemthatwaspurchasedorrefunded.一組String代表著已簽署的JSON字串。

JSON字串包含了有關金流交易的資訊,像是訂單編號、訂單數量以及購買的商品是否購買成功或遭退費。

com.android.vending.billing.PURCHASE_STATE_CHANGED inapp_signature A String representingthesignatureoftheJSONstring.一組String代表JSON字串型態的數位簽章。

Thefollowingcodesampleshowshowtohandlethesebroadcastintentsandintentextraswithina BroadcastReceiver.TheBroadcastReceiverinthiscaseisnamed BillingReceiver,justasitisinthesampleapplication.底下的程式碼教您如何在BroadcastReceiver底下處理這些廣播意圖和intentextras。

BroadcastReceiver在範例裡命名為BillingReceiver。

publicclassBillingReceiverextendsBroadcastReceiver{  privatestaticfinalStringTAG="BillingReceiver";  //IntentactionsthatwereceiveintheBillingReceiverfromAndroidMarket.  //ThesearedefinedbyAndroidMarketandcannotbechanged.  //ThesampleapplicationdefinestheseintheConsts.javafile.  publicstaticfinalStringACTION_NOTIFY="com.android.vending.billing.IN_APP_NOTIFY";  publicstaticfinalStringACTION_RESPONSE_CODE="com.android.vending.billing.RESPONSE_CODE";  publicstaticfinalStringACTION_PURCHASE_STATE_CHANGED=   "com.android.vending.billing.PURCHASE_STATE_CHANGED";  //TheintentextrasthatarepassedinanintentfromAndroidMarket.  //ThesearedefinedbyAndroidMarketandcannotbechanged.  //ThesampleapplicationdefinestheseintheConsts.javafile.  publicstaticfinalStringNOTIFICATION_ID="notification_id";  publicstaticfinalStringINAPP_SIGNED_DATA="inapp_signed_data";  publicstaticfinalStringINAPP_SIGNATURE="inapp_signature";  publicstaticfinalStringINAPP_REQUEST_ID="request_id";  publicstaticfinalStringINAPP_RESPONSE_CODE="response_code";  @Override  publicvoidonReceive(Contextcontext,Intentintent){   Stringaction=intent.getAction();   if(ACTION_PURCHASE_STATE_CHANGED.equals(action)){    StringsignedData=intent.getStringExtra(INAPP_SIGNED_DATA);    Stringsignature=intent.getStringExtra(INAPP_SIGNATURE);    //DosomethingwiththesignedDataandthesignature.   }elseif(ACTION_NOTIFY.equals(action)){    StringnotifyId=intent.getStringExtra(NOTIFICATION_ID);    //DosomethingwiththenotifyId.   }elseif(ACTION_RESPONSE_CODE.equals(action)){    longrequestId=intent.getLongExtra(INAPP_REQUEST_ID,-1);    intresponseCodeIndex=intent.getIntExtra(INAPP_RESPONSE_CODE,     ResponseCode.RESULT_ERROR.ordinal());    //DosomethingwiththerequestIdandtheresponseCodeIndex.   }else{    Log.w(TAG,"unexpectedaction:"+action);   }  }  //Performotherprocessinghere,suchasforwardingintentmessagestoyourlocalservice.}   InadditiontoreceivingbroadcastintentsfromtheAndroidMarketapplication,yourBroadcastReceiver musthandletheinformationitreceivedinthebroadcastintents.Usually,your BroadcastReceiver doesthisbysendingtheinformationtoalocalservice(discussedinthenextsection).The BillingReceiver.java fileinthesampleapplicationshowsyouhowtodothis.Youcanusethissampleasabasisforyourown BroadcastReceiver.However,ifyouuseanyofthecodefromthesampleapplication,besureyoufollowtheguidelinesthatarediscussedin SecurityandDesign .關於從Android市集軟體傳來的廣播意圖,這裡還要稍做說明,您的BroadcastReceiver必須處理在廣播意圖裡收到的資訊。

通常,您的BroadcastReceiver會以發送資訊至本地端的Service來完成這個工作(會在下一個段落做討論)。

在範例程式裡的BillingReceiver.java檔將會教您如何做到。

您可以使用這個範例當成是您的基本BroadcastReceiver。

然而,假如您使用了任何從範例程式出來的原始碼,請確定您遵照SecurityandDesign這個導引章節。

 VERIFYINGSIGNATURESANDNONCES驗証數位簽章和隨機數 AndroidMarket'sin-appbillingserviceusestwomechanismstohelpverifytheintegrityofthetransactioninformationyoureceivefromAndroidMarket:noncesandsignatures.Anonce(numberusedonce)isacryptographicallysecurenumberthatyourapplicationgeneratesandsendswithevery GET_PURCHASE_INFORMATION and RESTORE_TRANSACTIONS request.Thenonceisreturnedwiththe PURCHASE_STATE_CHANGED broadcastintent,enablingyoutoverifythatanygivenPURCHASE_STATE_CHANGED responsecorrespondstoanactualrequestthatyoumade.EveryPURCHASE_STATE_CHANGED broadcastintentalsoincludesasignedJSONstringandasignature,whichyoucanusetoverifytheintegrityoftheresponse. Androidy市集的iap服務使用了2種架構來幫助您完整的驗証從Android市集來的交易資訊,這2個架構分別為︰隨機數(nonces)和數位簽章(signatures)。

一個隨機數(僅用一次的值值)是一個加密地安全數值,它是由您的APP產生的,並且每次使用GET_PURCHASE_INFORMATION和RESTORE_TRANSACTOINS請求時,都會將此值發送出去。

隨機數接著會尾隨PURCHASE_STATE_CHANGED這個廣播意圖被回傳回來,讓您可以去驗証PURCHASE_STATE_CHANGED傳來的值和您用來發請求所產生的值是否相符。

每次的PURCHASE_STATE_CHANGED廣播意圖也會包含一組被簽署過的JSON字串和數位簽章,您可以拿來做完整的回應的驗証動作。

Yourapplicationmustprovideawaytogenerate,manage,andverifynonces.Thefollowingsamplecodeshowssomesimplemethodsyoucanusetodothis 您的APP必須提供一個能產生、管理和驗証隨機數的管道。

底下的範例程式將教您一些簡單的方式來完成這個需求︰ . privatestaticfinalSecureRandomRANDOM=newSecureRandom();  privatestaticHashSetsKnownNonces=newHashSet();  publicstaticlonggenerateNonce(){   longnonce=RANDOM.nextLong();   sKnownNonces.add(nonce);   returnnonce;  }  publicstaticvoidremoveNonce(longnonce){   sKnownNonces.remove(nonce);  }  publicstaticbooleanisNonceKnown(longnonce){   returnsKnownNonces.contains(nonce);  }   YourapplicationmustalsoprovideawaytoverifythesignaturesthataccompanyeveryPURCHASE_STATE_CHANGED broadcastintent.The Security.java fileinthesampleapplicationshowsyouhowtodothis.Ifyouusethisfileasabasisforyourownsecurityimplementation,besuretofollowtheguidelinesin SecurityandDesign andobfuscateyourcode.YouwillneedtouseyourAndroidMarketpublickeytoperformthesignatureverification.ThefollowingprocedureshowsyouhowtoretrieveBase64-encodedpublickeyfromtheAndroidMarketpublishersite. 您的APP必須提供一個方式來替每次傳來的PURCHASE_STATE_CHANGED廣播意圖伴隨的數位簽章做出驗証,範例程式裡的Security.java檔有教您如何做到。

如果您使用了這個檔當成是您實作安全性考量的基礎,請確認已遵照 SecurityandDesign這份導引,並且您也模糊過您的程式碼。

您將會需要使用Android市集的公鑰來執行數位簽章驗証。

底下流程將會教您如何接收從Android市集發佈網站傳來的Base64編碼公鑰。

Logintoyour publisheraccount. 首先請登入您的發佈者帳戶 Ontheupperleftpartofthepage,underyourname,click Editprofile. 請在上方左半部,您的名字底下,點擊Editprofile OntheEditProfilepage,scrolldowntotheLicensing&In-appBillingpanel(seefigure2). 在EditProfile頁面下,下滑到Licensing&In-appBilling區塊(見圖2) Copyyourpublickey. 拷貝您的公鑰Important:Tokeepyourpublickeysafefrommalicioususersandhackers,donotembedyourpublickeyasanentireliteralstring.Instead,constructthestringatruntimefrompiecesorusebitmanipulation(forexample,XORwithsomeotherstring)tohidetheactualkey.Thekeyitselfisnotsecretinformation,butyoudonotwanttomakeiteasyforahackerormalicioususertoreplacethepublickeywithanotherkey.重要︰為了您公鑰的安全,並防止惡意使用者或黑客的攻擊,請物將完整的String全數嵌入您的程式碼中,相反的,在執行期間建構出String或者使用bitmanipulation(舉例,XOR和其它一些字串)來隱藏真實的key都是比較好的做法。

雖然說鑰匙本身並非是一個秘密資訊,但是您並不會想讓黑客或惡意使用者那麼輕易的就將您的公鑰被換成另外一組吧? Figure2. TheLicensingandIn-appBillingpanelofyouraccount'sEditProfilepageletsyouseeyourpublickey. 圖2.  在您帳戶的編輯資料裡「許可與應用程式內部金流機制」的區塊。

您可以看見您的公鑰就擺放於此。

MODIFYINGYOURAPPLICATIONCODE修改您的應用程式原始碼 Afteryoufinishaddingin-appbillingcomponentstoyourproject,youarereadytomodifyyourapplication'scode.Foratypicalimplementation,liketheonethatisdemonstratedinthesampleapplication,thismeansyouneedtowritecodetodothefollowing:  在您專案完成了iap元件的添加以後,您應該準備開始修改您的程式碼了。

在典型的實作行為底下,就如同範例程式說明的一樣,這意謂著您需要照著以下的方式開始攢寫程式碼︰Createastoragemechanismforstoringusers'purchaseinformation. 替儲存使用者的購買資訊建立一個儲存的架構 Createauserinterfacethatletsusersselectitemsforpurchase. 建立一個能夠讓使用者購買商品的使用介面Thesamplecodein Dungeons.java showsyouhowtodobothofthesetasks. 範例程式的Dungeons.java教導您如何做到這2件事。

 Creatingastoragemechanismforstoringpurchaseinformation 建立一個儲存購買資訊的儲存架構 Youmustsetupadatabaseorsomeothermechanismforstoringusers'purchaseinformation.Thesampleapplicationprovidesanexampledatabase(PurchaseDatabase.java);however,theexampledatabasehasbeensimplifiedforclarityanddoesnotexhibitthesecuritybestpracticesthatwerecommend.Ifyouhavearemoteserver,werecommendthatyoustorepurchaseinformationonyourserverinsteadofinalocaldatabaseonadevice.Formoreinformationaboutsecuritybestpractices,see SecurityandDesign. 您必須設定一組資料庫和其它的架構來儲存使用者的購買資訊。

範例程式提供了一個簡單的資料庫(PurchaseDatabase.java)來做儲存。

然而,範例資料庫為了表達地更清楚,因此寫的非常簡單,因而也並無法展示出我們所建議您的的安全性的架構應該為何。

如果您有遠端伺服器,那麼我們會建議您將購買資訊儲存至您的伺服器,而非裝置裡的本地端資料庫。

更多關於最佳安全性實例,請見SecurityandDesign這篇。

Note:Ifyoustoreanypurchaseinformationonadevice,besuretoencryptthedataanduseadevice-specificencryptionkey.Also,ifthepurchasetypeforanyofyouritemsis"unmanaged,"werecommendthatyoubackupthepurchaseinformationfortheseitemstoaremoteserveroruseAndroid's databackup frameworktobackupthepurchaseinformation.Backinguppurchaseinformationforunmanageditemsisimportantbecauseunmanageditemscannotberestoredbyusingthe RESTORE_TRANSACTIONS requesttype.註︰如果您在裝置上儲存了任何的購買資訊,請確定您已將資料加密,並且使用裝置特殊的加密金鑰。

並且,假如您「不受管理」性質的商品被銷售出去,我們建議您將這些商品的購買資訊也備份至我們提供給您的Android資料備份架構的這個遠端伺服器裡。

備份這些不受管理的購買商品是非常重要的,因為不受管理的商品無法被儲存,因此也無法使用RESTORE_TRANSACTIONS請求類型來還原商品的購買數量或狀態。

Creatingauserinterfaceforselectingitems 建立一個能讓使用者選擇商品的使用介面 Youmustprovideuserswithameansforselectingitemsthattheywanttopurchase.AndroidMarketprovidesthecheckoutuserinterface(whichiswheretheuserprovidesaformofpaymentandapprovesthepurchase),butyourapplicationmustprovideacontrol(widget)thatinvokesthe sendBillingRequest() methodwhenauserselectsanitemforpurchase.Youcanrenderthecontrolandtriggerthe sendBillingRequest() methodanywayyouwant.Thesampleapplicationusesaspinnerwidgetandabuttontopresentitemstoauserandtriggerabillingrequest(see Dungeons.java).Theuserinterfacealsoshowsalistofrecentlypurchaseditems. 您必須提供使用者一個選擇購買商品的環境。

Android市集雖然提供您付費使用介面(這個介面是當使用者點選了付款後,Android吐出來的一個標準付費畫面),但是您的APP還是必須去控制(元件)當使用者選擇了商品後呼叫sendBillingRequest()函式的方式。

您可以用任何方式使用控制元件,並發發送sendBillingRequest()函式。

範例程式使用了下拉式的元件(spinnerwidget)和按鈕來呈現使用者發送金流請求的畫面(參見Dungeons.java)。

使用介面也會顯示出最近最購買過的商品列表。

相關文章︰ 1.[Androidin-appbilling前言]In-appBilling應用程式內部付費機制(中文翻譯)2.[Androidin-appbilling第1篇]In-appBillingOverview應用程式內部付費機制概述(中文翻譯)3.[Androidin-appbilling第2篇]ImplementingIn-appBilling實作應用程式內部金流機制(中文翻譯)4.[Androidin-appbilling第3篇]SecurityandDesign安全與設計(中文翻譯)5.[Androidin-appbilling第4篇]TestingIn-appBilling測試應用程式內金流機制(中文翻譯)6.[Androidin-appbilling第5篇]AdministeringIn-appBilling應用程式內金流機制的管理(中文翻譯)7.[Androidin-appbilling第6篇(末)]In-appBillingReference應用程式金流的相關API(中文翻譯) 转载于:https://www.cnblogs.com/androidabc/archive/2012/03/23/2413920.html 点赞 收藏 分享 文章举报 dianye8115 发布了0篇原创文章·获赞0·访问量62 私信 关注 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 标签:  相关文章推荐 [Androidin-appbilling第5篇]AdministeringIn-appBilling應用程式內金流機制的管理(中文翻譯)... [Androidin-appbilling第6篇(末)]In-appBillingReference應用程式金流的相關API(中文翻譯)... androidHTML中实现列表效果以及html支持的标签 Android、iOS和WindowsPhone平台的15个设计要点 AutomateyourAndroidapptesting androidMarket搜索APP Android开发环境配置 Unabletoaddwindow--tokenandroid.os.BinderProxy@164db98fisnotvalid;isyouractivityrunning [android开发]Android_社交软件1_去标题栏 [android开发]android_社交软件3_登录 Android中ListView使用总结 android内核kernel编译脚本Kconfig与Mafile使用 Buildx264&FFmpegforAndroid Android调用系统关机与重启功能 android选中radiobutton后改变TextColor Android软键盘弹出将底部栏顶上去并不会挤压界面 android滚条简单说明 2018/3/7下午第一节Android上机课 给AndroidStudio自带BottomNavigationActivity模板添加一个导航栏 AndroidStudio自带BottomNavigationActivity模板顶栏空白解决方案 新的分享 Android单元测试(九):查漏补缺篇 Android8.0适配指北 Android开发高手课课后练习(1~5) Android开发高手课课后练习(6~8,12,17,19) Android开发高手课课后练习(22,27,ASM) Android开发高手课温故知新篇 Android9.0适配指南 Android单元测试(十):内容更新篇 Android10适配攻略 AppBarLayout中android:fitsSystemWindows="true"无效的解决办法 android:scaleType=“centerCrop” Android使用自定义AlertDialog(退出提示框) 章节导航 添加评论 分享网址 分享文章 返回顶部



請為這篇文章評分?