/*
* Copyright 2014 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.checkout;
import com.android.vending.billing.IInAppBillingService;
import org.json.JSONException;
import android.os.Bundle;
import android.os.RemoteException;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.solovyev.android.checkout.ResponseCodes.EXCEPTION;
final class GetPurchasesRequest extends Request<Purchases> {
@Nonnull
private final String mProduct;
@Nullable
private final String mContinuationToken;
@Nonnull
private final PurchaseVerifier mVerifier;
GetPurchasesRequest(@Nonnull String product, @Nullable String continuationToken, @Nonnull PurchaseVerifier verifier) {
super(RequestType.GET_PURCHASES);
mProduct = product;
mContinuationToken = continuationToken;
mVerifier = verifier;
}
GetPurchasesRequest(@Nonnull GetPurchasesRequest request, @Nonnull String continuationToken) {
super(RequestType.GET_PURCHASES, request);
mProduct = request.mProduct;
mContinuationToken = continuationToken;
mVerifier = request.mVerifier;
}
@Nonnull
String getProduct() {
return mProduct;
}
@Nullable
String getContinuationToken() {
return mContinuationToken;
}
@Override
void start(@Nonnull IInAppBillingService service, @Nonnull String packageName) throws RemoteException {
final Bundle bundle = service.getPurchases(mApiVersion, packageName, mProduct, mContinuationToken);
if (handleError(bundle)) {
return;
}
try {
final String continuationToken = Purchases.getContinuationTokenFromBundle(bundle);
final List<Purchase> purchases = Purchases.getListFromBundle(bundle);
if (purchases.isEmpty()) {
onSuccess(new Purchases(mProduct, purchases, continuationToken));
return;
}
final VerificationListener listener = new VerificationListener(this, mProduct, continuationToken);
mVerifier.verify(purchases, listener);
if (!listener.mCalled) {
listener.onError(ResponseCodes.EXCEPTION, new IllegalStateException("Either onSuccess or onError methods must be called by PurchaseVerifier"));
}
} catch (JSONException e) {
onError(e);
}
}
@Nullable
@Override
protected String getCacheKey() {
if (mContinuationToken != null) {
return mProduct + "_" + mContinuationToken;
} else {
return mProduct;
}
}
private static class VerificationListener implements RequestListener<List<Purchase>> {
@Nonnull
private final Request<Purchases> mRequest;
@Nonnull
private final String mProduct;
@Nullable
private final String mContinuationToken;
@Nonnull
private final Thread mOriginalThread;
private boolean mCalled;
public VerificationListener(@Nonnull Request<Purchases> request, @Nonnull String product, @Nullable String continuationToken) {
mRequest = request;
mProduct = product;
mContinuationToken = continuationToken;
mOriginalThread = Thread.currentThread();
}
@Override
public void onSuccess(@Nonnull List<Purchase> verifiedPurchases) {
Check.equals(mOriginalThread, Thread.currentThread(), "Must be called on the same thread");
mCalled = true;
mRequest.onSuccess(new Purchases(mProduct, verifiedPurchases, mContinuationToken));
}
@Override
public void onError(int response, @Nonnull Exception e) {
Check.equals(mOriginalThread, Thread.currentThread(), "Must be called on the same thread");
mCalled = true;
if (response == EXCEPTION) {
mRequest.onError(e);
} else {
mRequest.onError(response);
}
}
}
}