package org.onepf.oms;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.aptoide.amethyst.Aptoide;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.persistence.DurationInMillis;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import com.aptoide.amethyst.openiab.IABPurchaseActivity;
import com.aptoide.amethyst.openiab.webservices.IabConsumeRequest;
import com.aptoide.amethyst.openiab.webservices.IabPurchasesRequest;
import com.aptoide.amethyst.openiab.webservices.IabSkuDetailsRequest;
import com.aptoide.amethyst.openiab.webservices.json.IabConsumeJson;
import com.aptoide.amethyst.openiab.webservices.json.IabPurchasesJson;
import com.aptoide.amethyst.openiab.webservices.json.IabSkuDetailsJson;
/**
* Created by j-pac on 12-02-2014.
*/
public class BillingBinder extends IOpenInAppBillingService.Stub {
// Response result codes
public static final int RESULT_OK = 0;
public static final int RESULT_USER_CANCELED = 1;
public static final int RESULT_BILLING_UNAVAILABLE = 3;
public static final int RESULT_ITEM_UNAVAILABLE = 4;
public static final int RESULT_DEVELOPER_ERROR = 5;
public static final int RESULT_ERROR = 6;
public static final int RESULT_ITEM_ALREADY_OWNED = 7;
public static final int RESULT_ITEM_NOT_OWNED = 8;
// Keys for the responses
public static final String RESPONSE_CODE = "RESPONSE_CODE";
public static final String DETAILS_LIST = "DETAILS_LIST";
public static final String BUY_INTENT = "BUY_INTENT";
public static final String INAPP_PURCHASE_DATA = "INAPP_PURCHASE_DATA";
public static final String INAPP_DATA_SIGNATURE = "INAPP_DATA_SIGNATURE";
public static final String INAPP_PURCHASE_ITEM_LIST = "INAPP_PURCHASE_ITEM_LIST";
public static final String INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
public static final String INAPP_DATA_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST";
public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN";
// Param keys
public static final String ITEM_ID_LIST = "ITEM_ID_LIST";
public static final String ITEM_TYPE_LIST = "ITEM_TYPE_LIST";
// Item types
public static final String ITEM_TYPE_INAPP = "inapp";
public static final String ITEM_TYPE_SUBS = "subs";
public static final String SERVICES_LIST = "SERVICES_LIST";
private final SpiceManager manager;
private Context context;
public BillingBinder(Context context, SpiceManager manager) {
this.context = context;
this.manager = manager;
}
@Override
public int isBillingSupported(int apiVersion, String packageName, String type) throws RemoteException {
Log.d("AptoideBillingService", "[isBillingSupported]: " + packageName);
if (apiVersion >= 3 &&
(type.equals(BillingBinder.ITEM_TYPE_INAPP) || type.equals(BillingBinder.ITEM_TYPE_SUBS))) {
return RESULT_OK;
} else {
return RESULT_BILLING_UNAVAILABLE;
}
}
private String getMccCode(String networkOperator) {
return networkOperator == null ? "" : networkOperator.substring(0, mncPortionLength(networkOperator));
}
private String getMncCode(String networkOperator) {
return networkOperator == null ? "" : networkOperator.substring(mncPortionLength(networkOperator));
}
private int mncPortionLength(String networkOperator) {
return Math.min(3, networkOperator.length());
}
@Override
public Bundle getSkuDetails(int apiVersion, String packageName, String type, Bundle skusBundle) throws RemoteException {
Log.d("AptoideBillingService", "[getSkuDetails]: " + packageName + " " + type);
final Bundle result = new Bundle();
if (!skusBundle.containsKey(ITEM_ID_LIST) || apiVersion < 3) {
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
return result;
}
ArrayList<String> itemIdList = skusBundle.getStringArrayList(ITEM_ID_LIST);
if ( itemIdList == null || itemIdList.size() <= 0 ) {
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
return result;
}
try {
AccountManager accountManager = AccountManager.get(context);
String token = accountManager.blockingGetAuthToken(accountManager.getAccountsByType(Aptoide.getConfiguration().getAccountType())[0], "Full access", true);
//String token = "27286b943179065fcef3b6adcafe8680d8515e4652010602c45f6";
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(token != null) {
IabSkuDetailsRequest request = new IabSkuDetailsRequest();
request.setApiVersion(Integer.toString(apiVersion));
request.setPackageName(packageName);
request.setToken(token);
if(telephonyManager != null && telephonyManager.getSimState()==TelephonyManager.SIM_STATE_READY){
request.setMcc(getMccCode(telephonyManager.getNetworkOperator()));
request.setMnc(getMncCode(telephonyManager.getNetworkOperator()));
request.setSimcc(telephonyManager.getSimCountryIso());
}
//request.setOemid(((AptoideConfigurationPartners)Aptoide.getConfiguration()).PARTNERID);
for(String itemId : itemIdList) {
request.addToSkuList(itemId);
Log.d("AptoideBillingService", "Sku details request for " + itemId);
}
final CountDownLatch latch = new CountDownLatch(1);
manager.execute(request, packageName + "-getSkuDetails-" + request.getSkuList() + token, DurationInMillis.ONE_SECOND*5, new RequestListener<IabSkuDetailsJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
result.putInt(RESPONSE_CODE, RESULT_ERROR);
latch.countDown();
}
@Override
public void onRequestSuccess(IabSkuDetailsJson response) {
ArrayList<String> detailsList = new ArrayList<String>();
if("OK".equals(response.getStatus())) {
for(IabSkuDetailsJson.PurchaseDataObject details : response.getPublisher_response().getDetailss_list()) {
String s = "";
try {
s = new ObjectMapper().writeValueAsString(details);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
detailsList.add(s);
Log.d("AptoideBillingService", "Sku Details: " + s);
}
if (detailsList.size() == 0) {
result.putInt(RESPONSE_CODE, RESULT_ITEM_UNAVAILABLE);
} else {
result.putInt(RESPONSE_CODE, RESULT_OK);
result.putStringArrayList(DETAILS_LIST, detailsList);
}
} else {
Log.d("AptoideBillingService", "Response not ok ");
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
}
latch.countDown();
}
});
latch.await();
}
} catch (Exception e) {
e.printStackTrace();
result.putInt(RESPONSE_CODE, RESULT_ERROR);
}
return result;
}
@Override
public Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type, String developerPayload) throws RemoteException {
Log.d("AptoideBillingService", "[getBuyIntent]: " + packageName + " " + type);
Bundle result = new Bundle();
PendingIntent pendingIntent;
Intent purchaseIntent = new Intent(context, /*Aptoide.getConfiguration().*/getIABPurchaseActivityClass());
if (apiVersion < 3 || !(type.equals(ITEM_TYPE_INAPP) || type.equals(ITEM_TYPE_SUBS))) {
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
} else {
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Aptoide.getConfiguration().getAccountType());
if(accounts.length == 0) {
Log.d("AptoideBillingService", "BillingUnavailable: user not logged in");
}else{
try {
String token = accountManager.blockingGetAuthToken(accounts[0], "Full access", true);
purchaseIntent.putExtra("token", token);
purchaseIntent.putExtra("user", accounts[0].name);
} catch (OperationCanceledException e) {
result.putInt(RESPONSE_CODE, RESULT_ERROR);
e.printStackTrace();
} catch (IOException e) {
result.putInt(RESPONSE_CODE, RESULT_ERROR);
e.printStackTrace();
} catch (AuthenticatorException e) {
result.putInt(RESPONSE_CODE, RESULT_ERROR);
e.printStackTrace();
}
}
purchaseIntent.putExtra("developerPayload", developerPayload);
purchaseIntent.putExtra("apiVersion", apiVersion);
purchaseIntent.putExtra("type", type);
purchaseIntent.putExtra("packageName", packageName);
purchaseIntent.putExtra("sku", sku);
result.putInt(RESPONSE_CODE, RESULT_OK);
}
pendingIntent = PendingIntent.getActivity(context, 0, purchaseIntent, PendingIntent.FLAG_UPDATE_CURRENT);
result.putParcelable(BUY_INTENT, pendingIntent);
return result;
}
public Class getIABPurchaseActivityClass(){
return IABPurchaseActivity.class;
}
@Override
public Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken) throws RemoteException {
Log.d("AptoideBillingService", "[getPurchases]: " + packageName + " " + type);
final Bundle result = new Bundle();
if (apiVersion < 3 || !(type.equals(ITEM_TYPE_INAPP) || type.equals(ITEM_TYPE_SUBS))) {
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
return result;
}
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Aptoide.getConfiguration().getAccountType());
if(accounts.length == 0) {
Log.d("AptoideBillingService", "BillingUnavailable: user not logged in");
result.putStringArrayList(INAPP_PURCHASE_ITEM_LIST, new ArrayList<String>());
result.putStringArrayList(INAPP_PURCHASE_DATA_LIST, new ArrayList<String>());
result.putStringArrayList(INAPP_DATA_SIGNATURE_LIST, new ArrayList<String>());
result.putInt(RESPONSE_CODE, RESULT_OK);
return result;
}
try {
String token = accountManager.blockingGetAuthToken(accounts[0], "Full access", true);
if(token != null) {
final CountDownLatch latch = new CountDownLatch(1);
IabPurchasesRequest request = new IabPurchasesRequest();
request.setApiVersion(Integer.toString(apiVersion));
request.setPackageName(packageName);
request.setType(type);
request.setToken(token);
manager.execute(request, packageName + "-getPurchases-"+type, DurationInMillis.ONE_SECOND*5, new RequestListener<IabPurchasesJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
result.putInt(RESPONSE_CODE, RESULT_ERROR);
latch.countDown();
}
@Override
public void onRequestSuccess(IabPurchasesJson response) {
if("OK".equals(response.getStatus())) {
ArrayList<String> purchaseItemList = (ArrayList<String>) response.getPublisher_response().getItemList();
ArrayList<String> purchaseSignatureList = (ArrayList<String>) response.getPublisher_response().getSignatureList();
ArrayList<String> purchaseDataList = new ArrayList<String>();
for(IabPurchasesJson.PublisherResponse.PurchaseDataObject purchase : response.getPublisher_response().getPurchaseDataList()) {
Log.d("AptoideBillingService", "Purchase: " + purchase.getJson());
purchaseDataList.add(purchase.getJson());
}
result.putStringArrayList(INAPP_PURCHASE_ITEM_LIST, purchaseItemList);
result.putStringArrayList(INAPP_PURCHASE_DATA_LIST, purchaseDataList);
result.putStringArrayList(INAPP_DATA_SIGNATURE_LIST, purchaseSignatureList);
if(response.getPublisher_response().getInapp_continuation_token() != null) {
result.putString(INAPP_CONTINUATION_TOKEN, response.getPublisher_response().getInapp_continuation_token());
}
result.putInt(RESPONSE_CODE, RESULT_OK);
} else {
result.putInt(RESPONSE_CODE, RESULT_DEVELOPER_ERROR);
}
latch.countDown();
}
});
latch.await();
}
} catch (Exception e) {
e.printStackTrace();
result.putInt(RESPONSE_CODE, RESULT_ERROR);
}
return result;
}
@Override
public int consumePurchase(int apiVersion, String packageName, String purchaseToken) throws RemoteException {
Log.d("AptoideBillingService", "[consumePurchase]: " + packageName + " " + purchaseToken);
if(apiVersion < 3) {
return RESULT_DEVELOPER_ERROR;
}
try {
AccountManager accountManager = AccountManager.get(context);
String token = accountManager.blockingGetAuthToken(accountManager.getAccountsByType(Aptoide.getConfiguration().getAccountType())[0], "Full access", true);
final int[] result = {RESULT_OK};
if(token != null) {
IabConsumeRequest request = new IabConsumeRequest();
request.setApiVersion(Integer.toString(apiVersion));
request.setToken(token);
request.setPackageName(packageName);
request.setPurchaseToken(purchaseToken);
final CountDownLatch latch = new CountDownLatch(1);
manager.execute(request, new RequestListener<IabConsumeJson>() {
@Override
public void onRequestFailure(SpiceException spiceException) {
latch.countDown();
}
@Override
public void onRequestSuccess(IabConsumeJson response) {
if("OK".equals(response.getStatus())) {
result[0] = RESULT_OK;
}else{
result[0] = RESULT_ERROR;
}
latch.countDown();
}
});
latch.await();
return result[0];
}
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (AuthenticatorException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return RESULT_ITEM_NOT_OWNED;
}
}