筆記:Google Play應用內購買結算(In-app Billing)的接入
Google Play應用內購買結算(In-app Billing)
最近公司有需求在Google渠道上加入Google支付 ,所以照著Google官方文件,寫了一個Dome,同時也寫這篇部落格記錄一下希望可以幫到有需要的人。
注意:In-app Billing Version 2 API 已於 2015 年 1 月關閉。如果您現有的應用內購買結算實現使用的是 API 版本 2 或更低版本,則必須遷移到應用內購買結算版本 3。應用內購買結算只能用於銷售數字內容,而不能用於銷售實體商品、個人服務或任何需要進行實物交付的商品/服務。 與明碼標價的應用不同,在使用者購買應用內商品後,系統不會提供退款視窗。
應用內購買結算版本 3 提供以下功能:
- 您的應用通過簡化的 API 傳送請求,讓使用者可以輕鬆地向 Google Play 請求商品詳情並訂購應用內商品。 API 可以根據使用者對商品的所有權快速恢復商品。
- API 會在購買完成時將訂單資訊同步傳送至裝置。
- 所有購買都是託管的(也就是說,Google Play 負責跟蹤使用者對應用內商品的所有權)。 使用者無論何時都只能擁有同一應用內商品的一個副本而不能擁有多個副本。
- 您可以消耗所購商品。消耗後,此商品將切換回未被擁有狀態,且可被使用者從 Google Play 中再次購買。
- API 支援訂閱。
我按個人開發的理解,解釋一下:
1、在應用內的購買一切商品,都是通過在Google Play完成,可以理解成,都是呼叫Google Play完成商品的購買和消耗,在Google Play都有著一切訂單資訊的儲存。
2、相同ID的商品只能被購買一次,不能重複購買,除非該ID的商品被消耗後,才能被重新購買。
開始記錄開發流程:
1、環境配置
這裡有一些坑,就是在開發最好使用Google手機進行開發,國產系統手機有些裝不了Google服務構架,有些無法調起Google Play付款介面。如何安裝Google服務構架,可以嘗試使用谷歌安裝器,這樣它會自動幫你轉好整個谷歌全家桶。
需要許可權:<uses-permission android:name="com.android.vending.BILLING" />
Android SDK需要下載:
編譯後會自動生成一個類
完成以上所有步驟後,就完成專案開發環境的配置,同時你要在有翻牆的網路環境下開發,也要確定手機安裝了Google Play開發構架,最好是谷歌親兒子測試,不然會出現很多吐血的坑。
2、谷歌後臺上架商品
在谷歌開發者後臺,要有企業開發者賬號才可以接入支付功能,上架商品,獲得商品ID(該ID很重要,谷歌支付不需要支付key,只需要商品id就可以了),在後臺你還需要新增測試賬號,讓相關的測試人員加入該軟體的封閉測試,這裡有一點不要忘記,將測試賬號加入後,需要將裡面的驗證網址發給他們,讓他們完成驗證,這才是真正加入測試組。如果想讓他們測試裡面的支付功能,要將他們加入許可測試組,如果沒有加入許可測試組的話,他們測試購買商品需要對應的金額,接入方法如下:
如果你已經完成以上所有步驟,恭喜你已經成功一半拉,哈哈,因為在這裡面我遇到了好幾個坑。
3、程式碼實現
- 繫結到 InAppBillingService
先建立一個new ServiceConnection()在onServiceConnected(ComponentName name, IBinder service) 中繫結InAppBillingService。
程式碼如下:
IInAppBillingService.Stub.asInterface(service);
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");//要明確指定地址,防止被攔截
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);//需要記得解綁
在回撥內拉取使用者google play store已經擁有的產品,不過要先判斷是否支援in-app billing v3(in-app billing v2已經被拋棄)
mService.isBillingSupported(3, packageName, "inapp");
如果返回為0,說明支援,其他返回值詳見最後面的附錄。
- 拉取谷歌賬號對應擁有的商品
mService.getPurchases(3, packageName,"inapp", null);
備註:第四個引數為continuationToken:用於在拉取資料,如果一次無法拉取完所有資料,而會在Bundle中"INAPP_CONTINUATION_TOKEN" 返回一串String,在接下來繼續拉取時,需要該引數,第一次拉取時不用,寫入“null”即可。
返回的Bundle,通過get("RESPONSE_CODE")獲得響應程式碼,返回0為請求成功,其他返回值詳見最後面的附錄。
通過不同key,獲得不同型別StringArrayList(官方例子使用“INAPP_PURCHASE_DATA_LIST”)
“INAPP_PURCHASE_ITEM_LIST” - 包含SKU列表的StringArrayList
“INAPP_PURCHASE_DATA_LIST” - 包含購買資訊的StringArrayList
“INAPP_DATA_SIGNATURE_LIST” - 包含簽名的StringArrayList購買資訊
然後通過迴圈判斷使用者擁有的產品有沒有我們app的需要的ID產品。
- 獲取特定商品的資訊,比如價格,資訊。商品id由後臺提供,無商品id就無法獲取該id商品的資訊(該操作需要在新執行緒中,詢問,該方法會訪問網路,防止ANR)
ArrayList<String> skuList = new ArrayList<String>();
skuList.add(商品ID);
Bundle querySkus = new Bundle();
querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
"ITEM_ID_LIST"為固定的key
mService.getSkuDetails(3, packageName, ITEM_TYPE_INAPP, querySkus);//詢問指定ID商品的資訊
查詢結果將儲存在Bundle中帶有鍵 DETAILS_LIST 的字串 ArrayList 中。購買資訊儲存在 JSON 格式的字串中。
對應key-value如下:
- 購買商品
mService.getBuyIntent(3, getPackageName(), sku, "inapp", "developerPayload 字串");
developerPayload 字串:可以由後臺生成,生成唯一訂單號。
請求成功後,返回的Bundle中getParcelable("BUY_INTENT"),獲得PendingIntent,呼叫startIntentSenderForResult調起Google Play進行購買,(購買方式可以通過金額購買也可以通過促銷碼付款),Google Play 會將對您的PendingIntent響應傳送至應用的onActivityResult方法。
返回的訂單型別(JSON 格式的字串):
'{
"orderId":"GPA.1234-5678-9012-34567",//唯一的訂單號
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseToken":"opaque-token-up-to-1000-characters"//用於消耗該商品的令牌
}'
這裡可以對訂單進行RSA驗證(在後臺進行),返回的Intent中的”INAPP_DATA_SIGNATURE”包含著已使用開發者私鑰簽署的購買資料簽名的字串。 資料簽名使用 RSASSA-PKCS1-v1_5 模式。
在這裡為了確保驗證使用者擁有該產品可以通過getPurchases()拉取使用者已經擁有的產品,進行確認。
此處返回的相應程式碼如果為:7 說明使用者已經擁有該產品。
- 消耗商品
mService.consumePurchase(3, getPackageName(),purchaseToken);
到這裡你已經完成了整個購買流程和消耗流程,程式碼邏輯和常規的PMS應用商品管理一樣,沒有什麼難點,主要還是因為被牆還有國產手機系統被閹割,導致的開發難度高。
在講一個應用內促銷
使用促銷程式碼有兩種方式:在應用內購買商品內使用和在google play使用;
1、應用內購買商品內使用
很容易只是在對話方塊選擇用促銷程式碼付款
2、google play商店內兌換使用
應用需要監聽google play的資料庫變化
IntentFilter promoFilter = new IntentFilter("com.android.vending.billing.PURCHASES_UPDATED");
registerReceiver(myPromoReceiver, promoFilter);
onReceive() 中呼叫 getPurchases(),判斷使用者是否使用對應的促銷程式碼onActivityResult,如果就按照購買商品處理。
關於後臺支付校驗,可以參考這篇部落格:
附錄(所有可能的請求的返回程式碼都是一致):
*所有呼叫都將提供具有以下可能值的響應程式碼
* RESULT_OK = 0 - 成功
* RESULT_USER_CANCELED = 1 - 使用者按下或取消了對話方塊
* RESULT_SERVICE_UNAVAILABLE = 2 - 網路連線已關閉
* RESULT_BILLING_UNAVAILABLE = 3 - 請求的型別不支援此結算API版本
* RESULT_ITEM_UNAVAILABLE = 4 - 無法購買請求的SKU
* RESULT_DEVELOPER_ERROR = 5 - 提供給API的引數無效
* RESULT_ERROR = 6 - API操作期間出現致命錯誤
* RESULT_ITEM_ALREADY_OWNED = 7 - 由於物品已經擁有,因此無法購買
* RESULT_ITEM_NOT_OWNED = 8 - 由於專案不屬於,因此無法使用
可能今後Google應用會有更加成熟的發展,到時該篇部落格有些內容可能會被遺棄,該篇部落格希望能成為你很好的開發參考資料,如果其中有錯誤之處,希望大神指出,轉載,請標明出處,謝謝