private PendingIntent fetchPendingIntentFromGetBuyIntentResponse(Bundle responseData) { int code = responseData.getInt(RESPONSE_CODE); ResponseCode responseCode = ResponseCode.findByCode(code); if (responseCode != ResponseCode.BILLING_RESPONSE_RESULT_OK) { // TODO: unit test this. throw new GdxPayException("Unexpected getBuyIntent() responseCode: " + responseCode + " with response data: " + responseData); } PendingIntent pendingIntent = responseData.getParcelable(BUY_INTENT); if (pendingIntent == null) { throw new GdxPayException("Missing value for key: " + BUY_INTENT + "in getBuyIntent() response: " + responseData); } return pendingIntent; }
@Override public void disconnected(GdxPayException exception) { observer.handleInstallError(new GdxPayException("Failed to bind to service", exception)); } });
private void assertInstalled() { if (!installed()) { throw new GdxPayException("Payment system must be installed to perform this action."); } }
@Override public void onServiceDisconnected(ComponentName name) { unbindBillingServiceConnection(); iInAppBillingService = null; connectionListener.disconnected(new GdxPayException(ERROR_ON_SERVICE_DISCONNECTED_RECEIVED)); } }
private IInAppBillingService billingService() { if (!isConnected()) { throw new GdxPayException(ERROR_NOT_CONNECTED_TO_GOOGLE_IAB); } return iInAppBillingService; }
@Override public void run() { // it might happen that this was already disposed until the service connection was established if (PurchaseManagerGoogleBilling.this.observer == null) return; if (!serviceConnected) PurchaseManagerGoogleBilling.this.observer.handleInstallError( new GdxPayException("Connection to Play Billing not possible")); else if (autoFetchInformation) { fetchOfferDetails(); } else setInstalledAndNotifyObserver(); } });
@Override public void purchaseRestore() { mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, new PurchaseHistoryResponseListener() { @Override public void onPurchaseHistoryResponse(int responseCode, List<Purchase> purchases) { if (responseCode == BillingClient.BillingResponse.OK && purchases != null) { handlePurchase(purchases, true); } else { Gdx.app.error(TAG, "onPurchaseHistoryResponse failed with responseCode " + responseCode); observer.handleRestoreError(new GdxPayException("onPurchaseHistoryResponse failed with " + "responseCode " + responseCode)); } } }); }
@Override public void onPurchaseHistoryResponse(int responseCode, List<Purchase> purchases) { if (responseCode == BillingClient.BillingResponse.OK && purchases != null) { handlePurchase(purchases, true); } else { Gdx.app.error(TAG, "onPurchaseHistoryResponse failed with responseCode " + responseCode); observer.handleRestoreError(new GdxPayException("onPurchaseHistoryResponse failed with " + "responseCode " + responseCode)); } } });
protected void bindBillingServiceConnectionToActivity() { try { if (!applicationProxy.bindService(createBindBillingServiceIntent(), billingServiceConnection, Context.BIND_AUTO_CREATE)) { this.connectionListener.disconnected(new GdxPayException("bindService() returns false.")); } } catch (GdxPayException e) { throw e; } catch (RuntimeException e) { this.connectionListener.disconnected(new GdxPayException("requestConnect() failed.", e)); } }
protected void handleResultOk(Intent data) { final Transaction transaction; try { transaction = convertPurchaseResponseDataToTransaction(data); } catch (GdxPayException e) { listener.purchaseError(new GdxPayException("Error converting purchase success response: " + data, e)); return; } listener.purchaseSuccess(transaction); } });
private Bundle executeGetSkuDetails(Bundle skusRequest, String type) { try { return billingService().getSkuDetails(BILLING_API_VERSION, installerPackageName, type, skusRequest); } catch (RemoteException e) { // TODO: unit test this. throw new GdxPayException("getProductsDetails failed for bundle:" + skusRequest, e); } }
@Override public Map<String, Information> getProductsDetails(List<String> productIds, String productType) { long startTimeInMs = System.currentTimeMillis(); try { Map<String, Information> result = new HashMap<String, Information>(); // max 20 Items List<List<String>> splitProductList = splitList(productIds, 20); for (List<String> splitProductIds : splitProductList) { result.putAll(fetchSkuDetails(splitProductIds, productType)); } return result; } catch (RuntimeException e) { throw new GdxPayException("getProductsDetails(" + productIds + " failed) after " + deltaInSeconds(startTimeInMs) + " seconds", e); } }
public Transaction convertToTransaction(Intent responseData) { String purchaseDataString = responseData.getStringExtra(GoogleBillingConstants.INAPP_PURCHASE_DATA); try { Transaction transaction = convertJSONPurchaseToTransaction(purchaseDataString); transaction.setTransactionDataSignature(responseData.getStringExtra(GoogleBillingConstants.INAPP_DATA_SIGNATURE)); String productId = transaction.getIdentifier(); setInformationFields(transaction, productId); return transaction; } catch (JSONException e) { throw new GdxPayException("JSON Exception while parsing: " + purchaseDataString, e); } }
@Override public List<Transaction> getPurchases() { try { Bundle inAppPurchases = billingService().getPurchases(BILLING_API_VERSION, installerPackageName, PURCHASE_TYPE_IN_APP, null); Bundle subscriptions = billingService().getPurchases(BILLING_API_VERSION, installerPackageName, PURCHASE_TYPE_SUBSCRIPTION, null); List<Transaction> transactions = new ArrayList<>(); transactions.addAll(convertPurchasesResponseToTransactions(inAppPurchases)); transactions.addAll(convertPurchasesResponseToTransactions(subscriptions)); return transactions; } catch (RemoteException | RuntimeException e) { // TODO: unit test RuntimeException scenario, e.g. : java.lang.IllegalArgumentException: Unexpected response code: ResponseCode{code=3, message='Billing API version is not supported for the type requested'}, response: Bundle[{RESPONSE_CODE=3}] throw new GdxPayException("Unexpected exception in getPurchases()", e); } }
@Override public void onEvent(int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { handleResultOk(data); return; } if (resultCode == Activity.RESULT_CANCELED) { listener.purchaseCanceled(); return; } listener.purchaseError(new GdxPayException("Unexpected resultCode:" + resultCode + "with data:" + data)); }
@Test public void shouldCallObserverInstallErrorOnConnectFailure() throws Exception { requestPurchaseMangerInstallWithFullEditionOffer(); verify(googleInAppBillingService).requestConnect(connectResultListenerArgumentCaptor.capture()); connectResultListenerArgumentCaptor.getValue() .disconnected(new GdxPayException("Disconnected", new SecurityException("Test"))); verify(purchaseObserver).handleInstallError(isA(GdxPayException.class)); }
private void internalStartPurchaseRequest(String productId, String type, PurchaseRequestCallback listener, boolean retryOnError) { PendingIntent pendingIntent; try { pendingIntent = getBuyIntent(productId, type); } catch (RemoteException | RuntimeException e) { if (retryOnError) { reconnectToHandleDeadObjectExceptions(); schedulePurchaseRetry(productId, listener); return; } listener.purchaseError(new GdxPayException("startPurchaseRequest failed at getBuyIntent() for product: " + productId, e)); return; } startPurchaseIntentSenderForResult(productId, pendingIntent, listener); }
@Test public void restoreErrorShouldDelegateResultToObserver() throws Exception { connectBindAndForFullEditionEntitlement(); GdxPayException exception = new GdxPayException("Network error"); when(this.googleInAppBillingService.getPurchases()).thenThrow(exception); purchaseManager.purchaseRestore(); verify(googleInAppBillingService).getPurchases(); verify(purchaseObserver).handleRestoreError(exception); }
@Test public void purchaseErrorShouldDelegateResultErrorToObserver() throws Exception { PurchaseRequestCallback callback = connectBindAndPurchaseRequestForFullEditionEntitlement(); GdxPayException exception = new GdxPayException("Network error"); callback.purchaseError(exception); verify(purchaseObserver).handlePurchaseError(exception); }
@Test public void shouldCallPurchaseErrorIfConvertingIntentDataToTransactionFails() throws Exception { bindConnectAndStartPurchaseRequest(offerFullEditionEntitlement()); when(purchaseResponseActivityResultConverter.convertToTransaction(isA(Intent.class))) .thenThrow(new GdxPayException("Exception parsing Json")); androidEventListener.onActivityResult(ACTIVITY_REQUEST_CODE, Activity.RESULT_OK, activityResultPurchaseFullEditionSuccess()); verify(purchaseRequestCallback).purchaseError(isA(GdxPayException.class)); }