splash5

Google In App Billing Wrapper

Jan 8th, 2014
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.56 KB | None | 0 0
  1. package com.splash5.spa.iab.v3;
  2.  
  3. import java.util.ArrayList;
  4.  
  5. import org.json.JSONException;
  6. import org.json.JSONObject;
  7.  
  8. import com.android.vending.billing.IInAppBillingService;
  9.  
  10. import android.app.PendingIntent;
  11. import android.content.ComponentName;
  12. import android.content.Context;
  13. import android.content.Intent;
  14. import android.content.ServiceConnection;
  15. import android.os.Bundle;
  16. import android.os.IBinder;
  17. import android.os.Message;
  18. import android.os.RemoteException;
  19. import android.util.Log;
  20.  
  21. @SuppressWarnings("unused")
  22. public class SpaBilling implements ServiceConnection
  23. {
  24.     private static final boolean DEBUG_ENABLED = true;
  25.     private static final String TAG = “SpaBilling";
  26.    
  27.     private static final String BILLING_SERVICE_BIND_INTENT = "com.android.vending.billing.InAppBillingService.BIND";
  28.    
  29.     public static final String BILLING_RESPONSE_CODE = "RESPONSE_CODE";
  30.     public static final String BILLING_RESPONSE_PURCHASE_DATA = "INAPP_PURCHASE_DATA";
  31.     public static final String BILLING_RESPONSE_SIGNATURE = "INAPP_DATA_SIGNATURE";
  32.  
  33.     private static final String BILLING_RESPONSE_DETAILS_LIST = "DETAILS_LIST";
  34.     private static final String BILLING_RESPONSE_BUY_INTENT = "BUY_INTENT";
  35.     private static final String BILLING_RESPONSE_ITEM_LIST = "INAPP_PURCHASE_ITEM_LIST";
  36.     private static final String BILLING_RESPONSE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
  37.     private static final String BILLING_RESPONSE_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST";
  38.     private static final String BILLING_RESPONSE_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN";
  39.    
  40.     private static final String BILLING_ITEM_ID_LIST = "ITEM_ID_LIST";
  41.     private static final String BILLING_ITEM_TYPE_LIST = "ITEM_TYPE_LIST";
  42.    
  43.     public static final String BILLING_ITEM_TYPE_INAPP = "inapp";
  44.     public static final String BILLING_ITEM_TYPE_SUBS = "subs";
  45.  
  46.     public static final int BILLING_RESPONSE_RESULT_OK = 0;
  47.     public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
  48.     public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
  49.     public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4;
  50.     public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;
  51.     public static final int BILLING_RESPONSE_RESULT_ERROR = 6;
  52.     public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
  53.     public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
  54.     public static final int BILLING_RESPONSE_RESULT_UNKNOWN = -1;
  55.    
  56.     private final String mPackageName;
  57.     private IInAppBillingService mService;
  58.  
  59.     public SpaBilling(Context context)
  60.     {
  61.         mPackageName = context.getPackageName();
  62.  
  63.         context.bindService(new Intent(BILLING_SERVICE_BIND_INTENT), this, Context.BIND_AUTO_CREATE);
  64.        
  65.         Log(Log.DEBUG, "start binding billing service, packagename = " + mPackageName);
  66.     }
  67.    
  68.     public void RequestItemDetail(ArrayList<String> items, String type, Message message)
  69.     {
  70.         new Thread(new GetItemDetailRunnable(items, type, message)).start();
  71.     }
  72.    
  73.     public void RequestOwnedItems(String type, Message message)
  74.     {
  75.         new Thread(new GetOwnedItemRunnable(type, message)).start();
  76.     }
  77.    
  78.     public void RequestPurchaseIntent(String item, String type, String payload, Message message)
  79.     {
  80.         new Thread(new PurchaseItemRunnable(item, type, payload, message)).start();
  81.     }
  82.    
  83.     public void RequestConsumeItem(String token, Message message)
  84.     {
  85.         new Thread(new ConsumeItemRunnable(token, message)).start();
  86.     }
  87.    
  88.     /**
  89.      * Check is if billing is supported, don't run this on main thread!
  90.      */
  91.     public int isBillingSupported(String type)
  92.     {
  93.         int ret = BILLING_RESPONSE_RESULT_UNKNOWN;
  94.        
  95.         try
  96.         {
  97.             ret = (mService.isBillingSupported(3, mPackageName, type));
  98.         }
  99.         catch (RemoteException e)
  100.         {
  101.             Log(Log.ERROR, e.toString());
  102.         }
  103.        
  104.         return ret;
  105.     }
  106.  
  107.     private class GetItemDetailRunnable implements Runnable
  108.     {
  109.         private ArrayList<String> mItems;
  110.         private Message mMessage;
  111.         private String mType;
  112.        
  113.         public GetItemDetailRunnable(ArrayList<String> items, String type, Message message)
  114.         {
  115.             mItems = items;
  116.             mMessage = message;
  117.             mType = type;
  118.         }
  119.        
  120.         @Override
  121.         public void run()
  122.         {
  123.             int response_code = BILLING_RESPONSE_RESULT_UNKNOWN;
  124.             DetailResult result = new DetailResult();
  125.             result.items = new ArrayList<SkuDetail>();
  126.            
  127.             try
  128.             {
  129.                 final Bundle bundle = new Bundle();
  130.                 bundle.putStringArrayList(BILLING_ITEM_ID_LIST, mItems);
  131.  
  132.                 // start getting sku detail from google
  133.                 final Bundle items = mService.getSkuDetails(3, mPackageName, mType, bundle);
  134.  
  135.                 if ((response_code = items.getInt(BILLING_RESPONSE_CODE, BILLING_RESPONSE_RESULT_UNKNOWN)) == BILLING_RESPONSE_RESULT_OK)
  136.                 {
  137.                     final ArrayList<String> list = items.getStringArrayList(BILLING_RESPONSE_DETAILS_LIST);
  138.                    
  139.                     for (String sku : list)
  140.                     {
  141.                         try { result.items.add(new SkuDetail(sku)); }
  142.                         catch (JSONException e) {}
  143.                     }
  144.                 }
  145.             }
  146.             catch (Exception e)
  147.             {
  148.                 Log(Log.ERROR, e.toString());
  149.             }
  150.            
  151.             Log(Log.DEBUG, "response = " + response_code + " got " + result.items.size() + " items detail.");
  152.            
  153.             if (mMessage != null)
  154.             {
  155.                 // keep user's object into our object
  156.                 result.obj = mMessage.obj;
  157.                
  158.                 mMessage.arg1 = response_code;
  159.                 mMessage.obj = result;
  160.                 mMessage.sendToTarget();
  161.             }
  162.         }
  163.     }
  164.    
  165.     private class GetOwnedItemRunnable implements Runnable
  166.     {
  167.         private String mType;
  168.         private Message mMessage;
  169.        
  170.         public GetOwnedItemRunnable(String type, Message message)
  171.         {
  172.             mType = type;
  173.             mMessage = message;
  174.         }
  175.        
  176.         @Override
  177.         public void run()
  178.         {
  179.             int response_code = BILLING_RESPONSE_RESULT_UNKNOWN;
  180.             final OwnedItemResult result = new OwnedItemResult();
  181.             result.items = new ArrayList<OwnedItem>();
  182.  
  183.             try
  184.             {
  185.                 ArrayList<String> item_list = null;
  186.                 ArrayList<String> data_list = null;
  187.                 ArrayList<String> sign_list = null;
  188.                 String continuation_token = null;
  189.  
  190.                 do
  191.                 {
  192.                     final Bundle owned = mService.getPurchases(3, mPackageName, mType, continuation_token);
  193.                    
  194.                     if ((response_code = owned.getInt(BILLING_RESPONSE_CODE)) == BILLING_RESPONSE_RESULT_OK)
  195.                     {
  196.                         item_list = owned.getStringArrayList(BILLING_RESPONSE_ITEM_LIST);
  197.                         data_list = owned.getStringArrayList(BILLING_RESPONSE_DATA_LIST);
  198.                         sign_list = owned.getStringArrayList(BILLING_RESPONSE_SIGNATURE_LIST);
  199.                         continuation_token = owned.getString(BILLING_RESPONSE_CONTINUATION_TOKEN);
  200.                        
  201.                         for (int i = 0; i < data_list.size(); i++)
  202.                         {
  203.                             try { result.items.add(new OwnedItem(data_list.get(i), sign_list.get(i), item_list.get(i))); }
  204.                             catch (JSONException e) {}
  205.                         }
  206.                     }
  207.                    
  208.                 } while (continuation_token != null);   // check if user has more items
  209.             }
  210.             catch (Exception e)
  211.             {
  212.                 Log(Log.ERROR, e.toString());
  213.             }
  214.            
  215.             Log(Log.DEBUG, "response = " + response_code + " got " + result.items.size() + " owned items.");
  216.            
  217.             if (mMessage != null)
  218.             {
  219.                 // keep user's object into our object
  220.                 result.obj = mMessage.obj;
  221.                
  222.                 mMessage.arg1 = response_code;
  223.                 mMessage.obj = result;
  224.                 mMessage.sendToTarget();
  225.             }
  226.         }
  227.     }
  228.    
  229.     private class PurchaseItemRunnable implements Runnable
  230.     {
  231.         private String mItem;
  232.         private String mType;
  233.         private String mPayload;
  234.         private Message mMessage;
  235.        
  236.         public PurchaseItemRunnable(String item, String type, String payload, Message message)
  237.         {
  238.             mItem = item;
  239.             mType = type;
  240.             mPayload = payload;
  241.             mMessage = message;
  242.         }
  243.        
  244.         @Override
  245.         public void run()
  246.         {
  247.             int response_code = BILLING_RESPONSE_RESULT_UNKNOWN;
  248.             PurchaseRequest request = new PurchaseRequest();
  249.            
  250.             try
  251.             {
  252.                 final Bundle bundle = mService.getBuyIntent(3, mPackageName, mItem, mType, mPayload);
  253.                
  254.                 if ((response_code = bundle.getInt(BILLING_RESPONSE_CODE)) == BILLING_RESPONSE_RESULT_OK)
  255.                     request.intent = bundle.getParcelable(BILLING_RESPONSE_BUY_INTENT);
  256.             }
  257.             catch (Exception e)
  258.             {
  259.                 Log(Log.ERROR, e.toString());
  260.             }
  261.            
  262.             Log(Log.DEBUG, "response = " + response_code + ", productID = " + mItem + ", type = " + mType + ", payload = " + mPayload);
  263.            
  264.             if (mMessage != null)
  265.             {
  266.                 // keep user's object into our object
  267.                 request.obj = mMessage.obj;
  268.  
  269.                 mMessage.arg1 = response_code;
  270.                 mMessage.obj = request;
  271.                 mMessage.sendToTarget();
  272.             }
  273.         }
  274.     }
  275.    
  276.     private class ConsumeItemRunnable implements Runnable
  277.     {
  278.         private String mToken;
  279.         private Message mMessage;
  280.         private int mDelay;
  281.        
  282.         public ConsumeItemRunnable(String token, Message message)
  283.         {
  284.             mToken = token;
  285.             mMessage = message;
  286.             mDelay = 1000;
  287.         }
  288.        
  289.         @Override
  290.         public void run()
  291.         {
  292.             int response_code = BILLING_RESPONSE_RESULT_UNKNOWN;
  293.            
  294.             try
  295.             {
  296.                 response_code = mService.consumePurchase(3, mPackageName, mToken);
  297.             }
  298.             catch (Exception e)
  299.             {
  300.                 Log(Log.ERROR, e.toString());
  301.             }
  302.            
  303.             Log(Log.DEBUG, "response = " + response_code + " consumed token = " + mToken);
  304.            
  305.             if (mMessage != null)
  306.             {
  307.                 // keep user's object into our object
  308.                 ConsumeResult result = new ConsumeResult();
  309.                 result.token = mToken;
  310.                 result.obj = mMessage.obj;
  311.  
  312.                 mMessage.arg1 = response_code;
  313.                 mMessage.obj = result;
  314.                
  315.                 if (mDelay > 0)
  316.                     mMessage.getTarget().sendMessageDelayed(mMessage, mDelay);
  317.                 else
  318.                     mMessage.sendToTarget();
  319.             }
  320.         }
  321.     }
  322.  
  323.     @Override
  324.     public void onServiceConnected(ComponentName name, IBinder service)
  325.     {
  326.         mService = IInAppBillingService.Stub.asInterface(service);
  327.        
  328.         Log(Log.DEBUG, "in app billing service connected");
  329.     }
  330.  
  331.     @Override
  332.     public void onServiceDisconnected(ComponentName name)
  333.     {
  334.         mService = null;
  335.        
  336.         Log(Log.DEBUG, "in app billing service disconnected");
  337.     }
  338.    
  339.     public static class OwnedItem
  340.     {
  341.         public String data;
  342.         public String signature;
  343.         public String item;
  344.        
  345.         private JSONObject mObj;
  346.        
  347.         public OwnedItem(String data, String signature, String item) throws JSONException
  348.         {
  349.             mObj = new JSONObject(data);
  350.            
  351.             this.data = data;
  352.             this.signature = signature;
  353.             this.item = item;
  354.         }
  355.        
  356.         public String orderId() { return mObj.optString("orderId"); }
  357.         public String packageName() { return mObj.optString("packageName"); }
  358.         public String productId() { return mObj.optString("productId"); }
  359.         public long purchaseTime() { return mObj.optLong("purchaseTime"); }
  360.         public int purchaseState() { return mObj.optInt("purchaseState"); }
  361.         public String developerPayload() { return mObj.optString("developerPayload"); }
  362.         public String purchaseToken() { return mObj.optString("purchaseToken"); }
  363.     }
  364.    
  365.     public static class SkuDetail
  366.     {
  367.         public String sku;
  368.        
  369.         private JSONObject mObj;
  370.        
  371.         public SkuDetail(String sku) throws JSONException
  372.         {
  373.             mObj = new JSONObject(sku);
  374.             this.sku = sku;
  375.         }
  376.        
  377.         public String productId() { return mObj.optString("productId"); }
  378.         public String type() { return mObj.optString("type"); }
  379.         public String price() { return mObj.optString("price"); }
  380.         public String title() { return mObj.optString("title"); }
  381.         public String description() { return mObj.optString("description"); }
  382.     }
  383.    
  384.     public static class OwnedItemResult
  385.     {
  386.         public ArrayList<OwnedItem> items;
  387.         public Object obj;
  388.     }
  389.    
  390.     public static class PurchaseRequest
  391.     {
  392.         public PendingIntent intent;
  393.         public Object obj;
  394.     }
  395.    
  396.     public static class DetailResult
  397.     {
  398.         public ArrayList<SkuDetail> items;
  399.         public Object obj;
  400.     }
  401.    
  402.     public static class ConsumeResult
  403.     {
  404.         public String token;
  405.         public Object obj;
  406.     }
  407.    
  408.     private static void Log(int priority, String msg)
  409.     {
  410.         if (DEBUG_ENABLED)
  411.             Log.println(priority, TAG, msg);
  412.     }
  413. }
Add Comment
Please, Sign In to add comment