mirror of
https://github.com/defold/extension-iap
synced 2025-06-27 10:27:46 +02:00
Formatting and cleanup
This commit is contained in:
parent
83876a508b
commit
8cf185056f
@ -37,10 +37,8 @@ import com.android.billingclient.api.SkuDetailsResponseListener;
|
|||||||
public class IapGooglePlay implements PurchasesUpdatedListener {
|
public class IapGooglePlay implements PurchasesUpdatedListener {
|
||||||
public static final String TAG = "IapGooglePlay";
|
public static final String TAG = "IapGooglePlay";
|
||||||
|
|
||||||
|
private Map<String, SkuDetails> products = new HashMap<String, SkuDetails>();
|
||||||
private BillingClient billingClient;
|
private BillingClient billingClient;
|
||||||
|
|
||||||
private Map<String, SkuDetails> products;
|
|
||||||
|
|
||||||
private IPurchaseListener purchaseListener;
|
private IPurchaseListener purchaseListener;
|
||||||
private boolean autoFinishTransactions;
|
private boolean autoFinishTransactions;
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
@ -48,7 +46,6 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
public IapGooglePlay(Activity activity, boolean autoFinishTransactions) {
|
public IapGooglePlay(Activity activity, boolean autoFinishTransactions) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.autoFinishTransactions = autoFinishTransactions;
|
this.autoFinishTransactions = autoFinishTransactions;
|
||||||
products = new HashMap<String, SkuDetails>();
|
|
||||||
|
|
||||||
billingClient = BillingClient.newBuilder(activity).setListener(this).enablePendingPurchases().build();
|
billingClient = BillingClient.newBuilder(activity).setListener(this).enablePendingPurchases().build();
|
||||||
billingClient.startConnection(new BillingClientStateListener() {
|
billingClient.startConnection(new BillingClientStateListener() {
|
||||||
@ -56,7 +53,8 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
public void onBillingSetupFinished(BillingResult billingResult) {
|
public void onBillingSetupFinished(BillingResult billingResult) {
|
||||||
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
||||||
Log.v(TAG, "Setup finished");
|
Log.v(TAG, "Setup finished");
|
||||||
// TODO BillingClient.queryPurchases()
|
// NOTE: we will not query purchases here. This is done
|
||||||
|
// when the extension listener is set
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.wtf(TAG, "Setup error: " + billingResult.getDebugMessage());
|
Log.wtf(TAG, "Setup error: " + billingResult.getDebugMessage());
|
||||||
@ -69,6 +67,12 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
Log.d(TAG, "stop()");
|
||||||
|
billingClient.endConnection();
|
||||||
|
}
|
||||||
|
|
||||||
public String toISO8601(final Date date) {
|
public String toISO8601(final Date date) {
|
||||||
String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(date);
|
String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(date);
|
||||||
return formatted.substring(0, 22) + ":" + formatted.substring(22);
|
return formatted.substring(0, 22) + ":" + formatted.substring(22);
|
||||||
@ -133,8 +137,7 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
return defoldState;
|
return defoldState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int billingResponseCodeToDefoldResponse(int responseCode)
|
private int billingResponseCodeToDefoldResponse(int responseCode) {
|
||||||
{
|
|
||||||
int defoldResponse;
|
int defoldResponse;
|
||||||
switch(responseCode) {
|
switch(responseCode) {
|
||||||
case BillingResponseCode.BILLING_UNAVAILABLE:
|
case BillingResponseCode.BILLING_UNAVAILABLE:
|
||||||
@ -176,8 +179,9 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
return billingResponseCodeToDefoldResponse(result.getResponseCode());
|
return billingResponseCodeToDefoldResponse(result.getResponseCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
/**
|
||||||
|
* Query Google Play for purchases done within the app.
|
||||||
|
*/
|
||||||
private List<Purchase> queryPurchases(final String type) {
|
private List<Purchase> queryPurchases(final String type) {
|
||||||
PurchasesResult result = billingClient.queryPurchases(type);
|
PurchasesResult result = billingClient.queryPurchases(type);
|
||||||
if (result.getBillingResult().getResponseCode() != BillingResponseCode.OK) {
|
if (result.getBillingResult().getResponseCode() != BillingResponseCode.OK) {
|
||||||
@ -187,8 +191,13 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
return result.getPurchasesList();
|
return result.getPurchasesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processPendingConsumables(final IPurchaseListener purchaseListener)
|
/**
|
||||||
{
|
* This method is called either explicitly from Lua or from extension code
|
||||||
|
* when "set_listener()" is called from Lua.
|
||||||
|
* The method will query purchases and try to handle them one by one (either
|
||||||
|
* trying to consume/finish them or simply notify the provided listener).
|
||||||
|
*/
|
||||||
|
public void processPendingConsumables(final IPurchaseListener purchaseListener) {
|
||||||
Log.d(TAG, "processPendingConsumables()");
|
Log.d(TAG, "processPendingConsumables()");
|
||||||
List<Purchase> purchasesList = new ArrayList<Purchase>();
|
List<Purchase> purchasesList = new ArrayList<Purchase>();
|
||||||
purchasesList.addAll(queryPurchases(SkuType.INAPP));
|
purchasesList.addAll(queryPurchases(SkuType.INAPP));
|
||||||
@ -198,67 +207,78 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
/**
|
||||||
|
* Consume a purchase. This will acknowledge the purchase and make it
|
||||||
private void consumePurchase(final Purchase purchase, final IPurchaseListener purchaseListener)
|
* available to buy again.
|
||||||
{
|
*/
|
||||||
Log.d(TAG, "consumePurchase()");
|
private void consumePurchase(final String purchaseToken, final ConsumeResponseListener consumeListener) {
|
||||||
|
Log.d(TAG, "consumePurchase() " + purchaseToken);
|
||||||
ConsumeParams consumeParams = ConsumeParams.newBuilder()
|
ConsumeParams consumeParams = ConsumeParams.newBuilder()
|
||||||
.setPurchaseToken(purchase.getPurchaseToken())
|
.setPurchaseToken(purchaseToken)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
|
billingClient.consumeAsync(consumeParams, consumeListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from Lua. This method will try to consume a purchase.
|
||||||
|
*/
|
||||||
|
public void finishTransaction(final String purchaseToken, final IPurchaseListener purchaseListener) {
|
||||||
|
Log.d(TAG, "finishTransaction() " + purchaseToken);
|
||||||
|
consumePurchase(purchaseToken, new ConsumeResponseListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
|
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
|
||||||
Log.d(TAG, "consumePurchase() onConsumeResponse " + billingResult.getResponseCode() + " purchaseToken: " + purchaseToken);
|
Log.d(TAG, "finishTransaction() response code " + billingResult.getResponseCode() + " purchaseToken: " + purchaseToken);
|
||||||
|
// note: we only call the purchase listener if an error happens
|
||||||
if (billingResult.getResponseCode() != BillingResponseCode.OK) {
|
if (billingResult.getResponseCode() != BillingResponseCode.OK) {
|
||||||
Log.e(TAG, "Unable to consume purchase: " + billingResult.getDebugMessage());
|
Log.e(TAG, "Unable to consume purchase: " + billingResult.getDebugMessage());
|
||||||
purchaseListener.onPurchaseResult(billingResultToDefoldResponse(billingResult), "");
|
purchaseListener.onPurchaseResult(billingResultToDefoldResponse(billingResult), "");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishTransaction(final String purchaseToken, final IPurchaseListener purchaseListener) {
|
/**
|
||||||
Log.d(TAG, "finishTransaction() " + purchaseToken);
|
* Handle a purchase. If the extension is configured to automatically
|
||||||
List<Purchase> purchasesList = new ArrayList<Purchase>();
|
* finish transactions the purchase will be immediately consumed. Otherwise
|
||||||
purchasesList.addAll(queryPurchases(SkuType.INAPP));
|
* the product will be returned via the listener without being consumed.
|
||||||
purchasesList.addAll(queryPurchases(SkuType.SUBS));
|
* NOTE: Billing 3.0 requires purchases to be acknowledged within 3 days of
|
||||||
|
* purchase unless they are consumed.
|
||||||
for(Purchase p : purchasesList) {
|
*/
|
||||||
Log.d(TAG, "finishTransaction() purchase: " + p.getOriginalJson());
|
|
||||||
if (p.getPurchaseToken().equals(purchaseToken)) {
|
|
||||||
consumePurchase(p, purchaseListener);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.e(TAG, "Unable to find purchase for token: " + purchaseToken);
|
|
||||||
purchaseListener.onPurchaseResult(IapJNI.BILLING_RESPONSE_RESULT_ERROR, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------
|
|
||||||
|
|
||||||
private void handlePurchase(final Purchase purchase, final IPurchaseListener purchaseListener) {
|
private void handlePurchase(final Purchase purchase, final IPurchaseListener purchaseListener) {
|
||||||
if (this.autoFinishTransactions) {
|
if (this.autoFinishTransactions) {
|
||||||
consumePurchase(purchase, purchaseListener);
|
consumePurchase(purchase.getPurchaseToken(), new ConsumeResponseListener() {
|
||||||
|
@Override
|
||||||
|
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
|
||||||
|
Log.d(TAG, "handlePurchase() response code " + billingResult.getResponseCode() + " purchaseToken: " + purchaseToken);
|
||||||
|
purchaseListener.onPurchaseResult(billingResultToDefoldResponse(billingResult), convertPurchase(purchase));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
purchaseListener.onPurchaseResult(billingResponseCodeToDefoldResponse(BillingResponseCode.OK), convertPurchase(purchase));
|
purchaseListener.onPurchaseResult(billingResponseCodeToDefoldResponse(BillingResponseCode.OK), convertPurchase(purchase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BillingClient listener set in the constructor.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
|
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
|
||||||
if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) {
|
if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) {
|
||||||
for (Purchase purchase : purchases) {
|
for (Purchase purchase : purchases) {
|
||||||
handlePurchase(purchase, this.purchaseListener);
|
handlePurchase(purchase, this.purchaseListener);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.purchaseListener.onPurchaseResult(billingResultToDefoldResponse(billingResult), "");
|
this.purchaseListener.onPurchaseResult(billingResultToDefoldResponse(billingResult), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buy a product. This method stores the listener and uses it in the
|
||||||
|
* onPurchasesUpdated() callback.
|
||||||
|
*/
|
||||||
private void buyProduct(SkuDetails sku, final IPurchaseListener purchaseListener) {
|
private void buyProduct(SkuDetails sku, final IPurchaseListener purchaseListener) {
|
||||||
this.purchaseListener = purchaseListener;
|
this.purchaseListener = purchaseListener;
|
||||||
|
|
||||||
@ -273,6 +293,9 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from Lua.
|
||||||
|
*/
|
||||||
public void buy(final String product, final IPurchaseListener purchaseListener) {
|
public void buy(final String product, final IPurchaseListener purchaseListener) {
|
||||||
Log.d(TAG, "buy()");
|
Log.d(TAG, "buy()");
|
||||||
|
|
||||||
@ -298,10 +321,11 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
/**
|
||||||
|
* Get details for a list of products. The products can be a mix of
|
||||||
private void querySkuDetailsAsync(final List<String> skuList, final SkuDetailsResponseListener listener)
|
* in-app products and subscriptions.
|
||||||
{
|
*/
|
||||||
|
private void querySkuDetailsAsync(final List<String> skuList, final SkuDetailsResponseListener listener) {
|
||||||
SkuDetailsResponseListener detailsListener = new SkuDetailsResponseListener() {
|
SkuDetailsResponseListener detailsListener = new SkuDetailsResponseListener() {
|
||||||
private List<SkuDetails> allSkuDetails = new ArrayList<SkuDetails>();
|
private List<SkuDetails> allSkuDetails = new ArrayList<SkuDetails>();
|
||||||
private int queries = 2;
|
private int queries = 2;
|
||||||
@ -309,15 +333,14 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetails) {
|
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetails) {
|
||||||
// cache skus (cache will be used to speed up buying)
|
// cache skus (cache will be used to speed up buying)
|
||||||
for (SkuDetails sd : skuDetails)
|
for (SkuDetails sd : skuDetails) {
|
||||||
{
|
|
||||||
IapGooglePlay.this.products.put(sd.getSku(), sd);
|
IapGooglePlay.this.products.put(sd.getSku(), sd);
|
||||||
}
|
}
|
||||||
//
|
// add to list of all sku details
|
||||||
allSkuDetails.addAll(skuDetails);
|
allSkuDetails.addAll(skuDetails);
|
||||||
|
// we're finished when we have queried for both in-app and subs
|
||||||
queries--;
|
queries--;
|
||||||
if (queries == 0)
|
if (queries == 0) {
|
||||||
{
|
|
||||||
listener.onSkuDetailsResponse(billingResult, allSkuDetails);
|
listener.onSkuDetailsResponse(billingResult, allSkuDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,8 +349,10 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
billingClient.querySkuDetailsAsync(SkuDetailsParams.newBuilder().setSkusList(skuList).setType(SkuType.SUBS).build(), detailsListener);
|
billingClient.querySkuDetailsAsync(SkuDetailsParams.newBuilder().setSkusList(skuList).setType(SkuType.SUBS).build(), detailsListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listItems(final String products, final IListProductsListener productsListener, final long commandPtr)
|
/**
|
||||||
{
|
* Called from Lua.
|
||||||
|
*/
|
||||||
|
public void listItems(final String products, final IListProductsListener productsListener, final long commandPtr) {
|
||||||
Log.d(TAG, "listItems()");
|
Log.d(TAG, "listItems()");
|
||||||
|
|
||||||
// create list of skus from comma separated string
|
// create list of skus from comma separated string
|
||||||
@ -343,8 +368,7 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetails) {
|
public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetails) {
|
||||||
JSONArray a = new JSONArray();
|
JSONArray a = new JSONArray();
|
||||||
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
||||||
for (SkuDetails sd : skuDetails)
|
for (SkuDetails sd : skuDetails) {
|
||||||
{
|
|
||||||
a.put(convertSkuDetails(sd));
|
a.put(convertSkuDetails(sd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,15 +380,7 @@ public class IapGooglePlay implements PurchasesUpdatedListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
public void restore(final IPurchaseListener listener) {
|
||||||
|
|
||||||
public void stop()
|
|
||||||
{
|
|
||||||
Log.d(TAG, "stop()");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void restore(final IPurchaseListener listener)
|
|
||||||
{
|
|
||||||
Log.d(TAG, "restore()");
|
Log.d(TAG, "restore()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,8 @@ local function buy_listener(self, transaction, error)
|
|||||||
gui.set_color(gui.get_node("reset/larrylabel"), vmath.vector4(1,1,1,1))
|
gui.set_color(gui.get_node("reset/larrylabel"), vmath.vector4(1,1,1,1))
|
||||||
product_items["reset"] = transaction
|
product_items["reset"] = transaction
|
||||||
else
|
else
|
||||||
log("iap.buy() ok")
|
log("iap.buy() ok %s", transaction.ident)
|
||||||
log("iap.finish()")
|
log("iap.finish() %s", transaction.ident)
|
||||||
iap.finish(transaction)
|
iap.finish(transaction)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user