Google In-App Billing 實現(內含Unity 實現經驗)


實現內購計費

傻逼目錄

 
    Adding the AIDL file
  1. Updating Your Manifest
  2. Creating a ServiceConnection
  3. Making In-app Billing Requests
      Querying Items Available for Purchase
    1. Purchasing an Item
    2. Querying Purchased Items
    3. Consuming a Purchase
    4. Implementing Subscriptions
  4. Securing Your App

二逼參考

    In-app Billing Reference (V3)

根本無法執行的例子

    Sample Application (V3)

也看

    Selling In-app Products

 Google Play 的 In-app Billing 提供了一種直(hui)觀(se)簡(nan)單(dong)的接口, 提供向GooglePlay發送內購請求和管理GooglePlay內購交易的功能。這都基於V3版本的API

測試你的程序的教程,參見  Selling In-app Products 訓練課程. 教程提供了完整的內購示例。

包含方便的類庫,用於從google play設置你的連接,發送賬單,購買響應,以及管理后台線程讓你可以在主線程調用內購。

在此之前,確保你閱讀了 In-app Billing Overview 以了解內購的基本概念,讓你更容易實現內購。

實現內購,你需要

  1. IInAppBillingService庫文件植入你的項目
  2. AndroidManifest.xml 文件
  3. ServiceConnection 並綁定到 IInAppBillingService.
  4. 添加 AIDL 文件到你的工程

是一個 Android Interface Definition Language (AIDL) 文件他定義了V3版內購服務的接口,你可以使用這些接口,通過IPC方法的方式調用函式,創建賬單請求

獲取ADIL:

  1. Android SDK Manager.
  2. Extras 段
  3. 選擇Google Play Billing Library.
  4. 點擊Install packages 完成下載

 sdk/extras/google/play_billing/.

具體來說:

  1. 首先,下載 Google Play Billing Library到你的安卓工程
      Tools > Android > SDK Manager.(2.0版AS-File->Settings)
    1. SDK Tools 子頁下載下一步,拷貝  文件到你的工
        原文都是垃圾,直接創建src/com/android/vending/billing/
      1. 把文件考進去,拉倒。
      2. 原文說需要Gradle編譯,沒有也一樣,直接打個APK試試,對應文件就會自己生成!
    2. 編譯你的工程.編譯出IInAppBillingService.java
    3. 需要用gradle編譯一下,但是已經編好的也可以直接拿過來用(別聽他的!)。(重要的事情說3遍,Unity用戶請不要用AS,用Eclipse)X3。

更新你的 App的 Manifest

不翻譯了,廢話那么多,直接加上這句拉倒

<uses-permissionandroid:name="com.android.vending.BILLING"/>

創建一個 ServiceConnection

你的APP必須有一個 ServiceConnection 來協助你的APP和GooglePlay之間的消息傳遞,至少你應該:

  • IInAppBillingService.
  • 向 IInAppBillingService 發送賬單
為了和GooglePlay上的內購服務建立連接,你需要實現一個 ServiceConnection 並把你的Activity綁定到IInAppBillingService

 

重寫onServiceDisconnected 和 onServiceConnected 方法,在建立連接后獲得IInAppBillingService實例的引用

IInAppBillingService mService;
ServiceConnection mServiceConn =newServiceConnection(){
@Override
publicvoid onServiceDisconnected(ComponentName name){
=null;
}
@Override
publicvoid onServiceConnected(ComponentName name,
IBinder service){
=IInAppBillingService.Stub.asInterface(service);
}
};

onCreate 方法中,調用 bindService 方法綁定. 把 Intent 傳給方法,他代表內購服務。再傳入一個你剛剛創建的 ServiceConnection 的實例,並且顯式的設定你的Intent的包名為  使用如下所示的setPackage() 方法時刻確保顯示的設置intent的目標包名為@Override
publicvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
(R.layout.activity_main);
Intent serviceIntent =
newIntent("com.android.vending.billing.InAppBillingService.BIND");
.setPackage("com.android.vending");
(serviceIntent, mServiceConn,Context.BIND_AUTO_CREATE);
}

現在你可以使用mService的引用去和GooglePlay Service通信了。

重要: 當你的Activity嗝屁的時候記住對你的mService解綁。不然他會讓你的(其實是用戶的,不關你屁事)設備變慢。如何解綁看下面:

@Override
publicvoid onDestroy(){
super.onDestroy();
if(mService !=null){
(mServiceConn);
}
}

(沒讓你看JJ,看上面的代碼塊)

全套實現Selling In-app Products 訓練課程,和附件例子。

創建In-app Billing請求

一旦你的應用程序連接到 Google Play, 你就可以初始化內購商品了。 GooglePlay提供了校驗接口,使用戶可以進入他們的支付方法,所以你的應用程序不必自己處理支付事務。

當一個物品被購買,GooglePlay會識別這個用戶對那個物品的所有權,並且防止他購買相同id的產品,直到這個物件被消費掉。

你可以在你的APP里面控制物品如何被消耗掉(通常買了就應該馬上消耗掉,這樣客戶才能再買),並通知GooglePlay,那個商品可以被再次購買。

你也可以快速的向GooglePlay查詢為用戶建立的物品購買清單。這很有用,例如,當你的用戶啟動APP時,你可能需要為他恢復購買。

為購買查詢可購買商品

在你的APP里,你可以利用V3內購API向GooglePlay查詢商品的細節。你需要把一個請求發給In-app Billing 服務。

 

首先創建一個Bundle 他包含一個記錄商品ID的,鍵值為"ITEM_ID_LIST"的字符串 ArrayList列表 , 每一個ID都是一個可購買商品。

ArrayList<String> skuList =newArrayList<String>();
.add("premiumUpgrade");
.add("gas");
Bundle querySkus =newBundle();
.putStringArrayList(“ITEM_ID_LIST”, skuList);

getSkuDetails 方法,

getPackageName()

Bundle skuDetails = mService.getSkuDetails(3,
(),"inapp", querySkus);

如果請求成功,返回的bundle將會有返回值代碼 BILLING_RESPONSE_RESULT_OK (0).

getSkuDetails 方法. 調用這個方法會觸發一個網絡請求並阻塞主線程。

作為替代,創建一個單獨線程,並在其中調用getSkuDetails。(不會Java,你倒是說說怎么創建線程)

如果你想指定所有的可能的返回代碼的意義,去看 In-app Billing Reference.(我不知道,也不想知道!)

查詢結果被存在一個key為DETAILS_LIST的字符串ArrayList中。購買信息以字符串形式存於JSON格式中。

想要獲取返回的產品細節信息,參照 In-app Billing Reference.

在這個例子中,你從前面代碼塊里創建的skuDetails 這個bundle里面,取得你的內購商品價格。

int response = skuDetails.getInt("RESPONSE_CODE");

if(response ==0){
ArrayList<String> responseList
= skuDetails.getStringArrayList("DETAILS_LIST");
for(String thisResponse : responseList){
JSONObjectobject=newJSONObject(thisResponse);
String sku =object.getString("productId");
String price =object.getString("price");
if(sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;
elseif(sku.equals("gas")) mGasPrice = price;
}
}
PS:估計你得自己搞一張CSV表,或其他什么的,存放你的商品,然后對應返回信息,來更新UI,顯示給玩家。客戶端有而服務器不存在的商品,或被下架的商品,是不應該顯示給玩家的。
購買一個商品

Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
,"inapp","bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");

Bundle 會有返回值代碼 BILLING_RESPONSE_RESULT_OK (0) 和一個 PendingIntent (這又是啥逼玩意啊!)你可以用他們啟動一個購買流程。

BUY_INTENT從返回的Bundle 提取 PendingIntent .

PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");

想要完成購買事務,需要調用 startIntentSenderForResult 方法,並使用之前創建的 PendingIntent 。在這個栗子里面,你使用一個隨意的值1001作為請求碼。

startIntentSenderForResult(pendingIntent.getIntentSender(),
1001,newIntent(),Integer.valueOf(0),Integer.valueOf(0),
Integer.valueOf(0));

PendingIntent 到你的APP的 onActivityResult 方法中。 onActivityResult 方法會得到一個返回值為Activity.RESULT_OK (1) 或Intent中全部返回訂單 的信息,訪問 In-app Billing Reference.

INAPP_PURCHASE_DATA 鍵值,在返回 Intent,舉個栗子:

'{
"opaque-token-up-to-1000-characters"
 }'

此令牌是一個不可讀的字符序列,最長1000個字符. 將這個令牌整個傳入其他方法,比如當你想消耗購買時,正如 Consume a Purchase. 中提到的。不要省略或者改變令牌的大小寫,你需要保存整個令牌。

Intent的簽名。

@Override
protectedvoid onActivityResult(int requestCode,int resultCode,Intent data){
if(requestCode ==1001){
int responseCode = data.getIntExtra("RESPONSE_CODE",0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if(resultCode == RESULT_OK){
try{
JSONObject jo =newJSONObject(purchaseData);
String sku = jo.getString("productId");
("You have bought the "+ sku +". Excellent choice,
);
}
catch(JSONException e){
("Failed to parse purchase data.");
.printStackTrace();
}
}
}
}

developerPayload中,你可以隨機的生成一個字符串令牌。

當你從GooglePlay獲取購買響應,確保驗證返回數據的前面,orderId和developerPayload 字符串。

附加的安全性:你應該在你自己的安全服務器上,檢測這些東西。

確保你的orderId是一個你之前沒用過的唯一值。並且developerPayload字符串和你之前隨購買請求發送的令牌相互匹配。 

查詢已購商品

要從應用程序檢索用戶的購買的信息,調用V3 API的  getPurchases 方法。參數傳入版號3,包名和“inapp”類別(訂閱為“subs”)
Bundle ownedItems = mService.getPurchases(3, getPackageName(),"inapp",null);

Bundle 返回代碼0. 

Bundle 同時也包含一個產品IDs列表,標記每一個產品的細節和簽名。

getPurchase 調用順序為基准。

Bundle 會返回INAPP_CONTINUATION_TOKEN 暗示還有更多的商品可以獲得。你可以用這個token作為參數,進行后續的getPurchases 請求。

int response = ownedItems.getInt("RESPONSE_CODE");
if(response ==0){
ArrayList<String> ownedSkus =
.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String>  purchaseDataList =
.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String>  signatureList =
.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
String continuationToken =
.getString("INAPP_CONTINUATION_TOKEN");
for(int i =0; i < purchaseDataList.size();++i){
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i);
String sku = ownedSkus.get(i);


}


}

消耗一個購買

consumePurchase 方法到 In-app Billing service 並且將標記將要被移除的購買的 purchaseToken 作為參數傳入。

 

INAPP_PURCHASE_DATA 返回的字符串包含了這次要用的purchaseToken ,他在token變量里面,這就是為什么上面的說明要求你自己記錄token。

int response = mService.consumePurchase(3, getPackageName(), token);

警告: 別在主線程調用這個方法,建立獨立的子線程干這個事。否則他會阻塞你的主線程。

實現訂閱

Bundle bundle = mService.getBuyIntent(3,"com.example.myapp",

 

   MY_SKU,"subs", developerPayload);
PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if(bundle.getInt(RESPONSE_CODE)== BILLING_RESPONSE_RESULT_OK){


(pendingIntent, RC_BUY,newIntent(),
Integer.valueOf(0),Integer.valueOf(0),Integer.valueOf(0));
}

Bundle activeSubs = mService.getPurchases(3,"com.example.myapp",
"subs", continueToken);

保護你的APP

在 Developer Console,打開你的application's details,然后點擊Your License Key for This Application.

由狗狗Play生成的 Base64-encoded RSA 公鑰使用二進制編碼, X.509 subjectPublicKeyInfo DER SEQUENCE 格式. 他與狗狗Play的許可是同一級別的。

 Security and Design.



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM