You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
Complete the implementation of the GodotPayment plugin.
Move the remaining plugin components within the plugin source code.
This commit is contained in:
@@ -95,7 +95,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.godotengine.godot.input.GodotEditText;
|
||||
import org.godotengine.godot.payments.PaymentsManager;
|
||||
import org.godotengine.godot.plugin.GodotPlugin;
|
||||
import org.godotengine.godot.plugin.GodotPluginRegistry;
|
||||
import org.godotengine.godot.utils.GodotNetUtils;
|
||||
@@ -174,21 +173,17 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
|
||||
}
|
||||
public ResultCallback result_callback;
|
||||
|
||||
private PaymentsManager mPaymentsManager = null;
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE) {
|
||||
mPaymentsManager.processPurchaseResponse(resultCode, data);
|
||||
} else if (result_callback != null) {
|
||||
if (result_callback != null) {
|
||||
result_callback.callback(requestCode, resultCode, data);
|
||||
result_callback = null;
|
||||
};
|
||||
}
|
||||
|
||||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
plugin.onMainActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
@@ -445,8 +440,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
|
||||
|
||||
result_callback = null;
|
||||
|
||||
mPaymentsManager = PaymentsManager.createManager(this).initService();
|
||||
|
||||
godot_initialized = true;
|
||||
}
|
||||
|
||||
@@ -603,7 +596,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
|
||||
if (mPaymentsManager != null) mPaymentsManager.destroy();
|
||||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
plugin.onMainDestroy();
|
||||
}
|
||||
@@ -938,10 +930,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
|
||||
return true;
|
||||
}
|
||||
|
||||
public PaymentsManager getPaymentsManager() {
|
||||
return mPaymentsManager;
|
||||
}
|
||||
|
||||
public boolean requestPermission(String p_name) {
|
||||
return PermissionsUtil.requestPermission(p_name, this);
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* ConsumeTask.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.RemoteException;
|
||||
import com.android.vending.billing.IInAppBillingService;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
abstract public class ConsumeTask {
|
||||
|
||||
private Context context;
|
||||
private IInAppBillingService mService;
|
||||
|
||||
private String mSku;
|
||||
private String mToken;
|
||||
|
||||
private static class ConsumeAsyncTask extends AsyncTask<String, String, String> {
|
||||
|
||||
private WeakReference<ConsumeTask> mTask;
|
||||
|
||||
ConsumeAsyncTask(ConsumeTask consume) {
|
||||
mTask = new WeakReference<>(consume);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... strings) {
|
||||
ConsumeTask consume = mTask.get();
|
||||
if (consume != null) {
|
||||
return consume.doInBackground(strings);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String param) {
|
||||
ConsumeTask consume = mTask.get();
|
||||
if (consume != null) {
|
||||
consume.onPostExecute(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConsumeTask(IInAppBillingService mService, Context context) {
|
||||
this.context = context;
|
||||
this.mService = mService;
|
||||
}
|
||||
|
||||
public void consume(final String sku) {
|
||||
mSku = sku;
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
Boolean isBlocked = pc.getConsumableFlag("block", sku);
|
||||
mToken = pc.getConsumableValue("token", sku);
|
||||
if (!isBlocked && mToken == null) {
|
||||
// Consuming task is processing
|
||||
} else if (!isBlocked) {
|
||||
return;
|
||||
} else if (mToken == null) {
|
||||
this.error("No token for sku:" + sku);
|
||||
return;
|
||||
}
|
||||
new ConsumeAsyncTask(this).execute();
|
||||
}
|
||||
|
||||
private String doInBackground(String... params) {
|
||||
try {
|
||||
int response = mService.consumePurchase(3, context.getPackageName(), mToken);
|
||||
if (response == 0 || response == 8) {
|
||||
return null;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
return "Some error";
|
||||
}
|
||||
|
||||
private void onPostExecute(String param) {
|
||||
if (param == null) {
|
||||
success(new PaymentsCache(context).getConsumableValue("ticket", mSku));
|
||||
} else {
|
||||
error(param);
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void success(String ticket);
|
||||
abstract protected void error(String message);
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* GodotPaymentInterface.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
public interface GodotPaymentInterface {
|
||||
void purchase(String sku, String transactionId);
|
||||
|
||||
void consumeUnconsumedPurchases();
|
||||
|
||||
String getSignature();
|
||||
|
||||
void callbackSuccess(String ticket, String signature, String sku);
|
||||
|
||||
void callbackSuccessProductMassConsumed(String ticket, String signature, String sku);
|
||||
|
||||
void callbackSuccessNoUnconsumedPurchases();
|
||||
|
||||
void callbackFailConsume(String message);
|
||||
|
||||
void callbackFail(String message);
|
||||
|
||||
void callbackCancel();
|
||||
|
||||
void callbackAlreadyOwned(String sku);
|
||||
|
||||
int getPurchaseCallbackId();
|
||||
|
||||
void setPurchaseCallbackId(int purchaseCallbackId);
|
||||
|
||||
String getPurchaseValidationUrlPrefix();
|
||||
|
||||
void setPurchaseValidationUrlPrefix(String url);
|
||||
|
||||
String getAccessToken();
|
||||
|
||||
void setAccessToken(String accessToken);
|
||||
|
||||
void setTransactionId(String transactionId);
|
||||
|
||||
String getTransactionId();
|
||||
|
||||
// request purchased items are not consumed
|
||||
void requestPurchased();
|
||||
|
||||
// callback for requestPurchased()
|
||||
void callbackPurchased(String receipt, String signature, String sku);
|
||||
|
||||
void callbackDisconnected();
|
||||
|
||||
void callbackConnected();
|
||||
|
||||
// true if connected, false otherwise
|
||||
boolean isConnected();
|
||||
|
||||
// consume item automatically after purchase. default is true.
|
||||
void setAutoConsume(boolean autoConsume);
|
||||
|
||||
// consume a specific item
|
||||
void consume(String sku);
|
||||
|
||||
// query in app item detail info
|
||||
void querySkuDetails(String[] list);
|
||||
|
||||
void addSkuDetail(String itemJson);
|
||||
|
||||
void completeSkuDetail();
|
||||
|
||||
void errorSkuDetail(String errorMessage);
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* HandlePurchaseTask.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
abstract public class HandlePurchaseTask {
|
||||
|
||||
private Activity context;
|
||||
|
||||
public HandlePurchaseTask(Activity context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void handlePurchaseRequest(int resultCode, Intent data) {
|
||||
//Log.d("XXX", "Handling purchase response");
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
try {
|
||||
//int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
|
||||
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
|
||||
//Log.d("XXX", "Purchase data:" + purchaseData);
|
||||
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
|
||||
//Log.d("XXX", "Purchase signature:" + dataSignature);
|
||||
//Log.d("SARLANGA", purchaseData);
|
||||
|
||||
JSONObject jo = new JSONObject(purchaseData);
|
||||
//String sku = jo.getString("productId");
|
||||
//alert("You have bought the " + sku + ". Excellent choice, aventurer!");
|
||||
//String orderId = jo.getString("orderId");
|
||||
//String packageName = jo.getString("packageName");
|
||||
String productId = jo.getString("productId");
|
||||
//Long purchaseTime = jo.getLong("purchaseTime");
|
||||
//Integer state = jo.getInt("purchaseState");
|
||||
String developerPayload = jo.getString("developerPayload");
|
||||
String purchaseToken = jo.getString("purchaseToken");
|
||||
|
||||
if (!pc.getConsumableValue("validation_hash", productId).equals(developerPayload)) {
|
||||
error("Untrusted callback");
|
||||
return;
|
||||
}
|
||||
//Log.d("XXX", "Este es el product ID:" + productId);
|
||||
pc.setConsumableValue("ticket_signautre", productId, dataSignature);
|
||||
pc.setConsumableValue("ticket", productId, purchaseData);
|
||||
pc.setConsumableFlag("block", productId, true);
|
||||
pc.setConsumableValue("token", productId, purchaseToken);
|
||||
|
||||
success(productId, dataSignature, purchaseData);
|
||||
return;
|
||||
} catch (JSONException e) {
|
||||
error(e.getMessage());
|
||||
}
|
||||
} else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
canceled();
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void success(String sku, String signature, String ticket);
|
||||
abstract protected void error(String message);
|
||||
abstract protected void canceled();
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* PaymentsCache.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
public class PaymentsCache {
|
||||
|
||||
public Context context;
|
||||
|
||||
public PaymentsCache(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setConsumableFlag(String set, String sku, Boolean flag) {
|
||||
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPref.edit();
|
||||
editor.putBoolean(sku, flag);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public boolean getConsumableFlag(String set, String sku) {
|
||||
SharedPreferences sharedPref = context.getSharedPreferences(
|
||||
"consumables_" + set, Context.MODE_PRIVATE);
|
||||
return sharedPref.getBoolean(sku, false);
|
||||
}
|
||||
|
||||
public void setConsumableValue(String set, String sku, String value) {
|
||||
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPref.edit();
|
||||
editor.putString(sku, value);
|
||||
//Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public String getConsumableValue(String set, String sku) {
|
||||
SharedPreferences sharedPref = context.getSharedPreferences(
|
||||
"consumables_" + set, Context.MODE_PRIVATE);
|
||||
//Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
|
||||
return sharedPref.getString(sku, null);
|
||||
}
|
||||
}
|
||||
@@ -1,418 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* PaymentsManager.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.android.vending.billing.IInAppBillingService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class PaymentsManager {
|
||||
|
||||
public static final int BILLING_RESPONSE_RESULT_OK = 0;
|
||||
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
|
||||
private static boolean auto_consume = true;
|
||||
|
||||
private Activity activity;
|
||||
IInAppBillingService mService;
|
||||
|
||||
public void setActivity(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public static PaymentsManager createManager(Activity activity) {
|
||||
PaymentsManager manager = new PaymentsManager(activity);
|
||||
return manager;
|
||||
}
|
||||
|
||||
private PaymentsManager(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public PaymentsManager initService() {
|
||||
Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
|
||||
intent.setPackage("com.android.vending");
|
||||
activity.bindService(
|
||||
intent,
|
||||
mServiceConn,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mService != null) {
|
||||
activity.unbindService(mServiceConn);
|
||||
}
|
||||
}
|
||||
|
||||
ServiceConnection mServiceConn = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mService = null;
|
||||
|
||||
// At this stage, godotPayment might not have been initialized yet.
|
||||
if (godotPayment != null) {
|
||||
godotPayment.callbackDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mService = IInAppBillingService.Stub.asInterface(service);
|
||||
|
||||
// At this stage, godotPayment might not have been initialized yet.
|
||||
if (godotPayment != null) {
|
||||
godotPayment.callbackConnected();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void requestPurchase(final String sku, String transactionId) {
|
||||
new PurchaseTask(mService, activity) {
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFail(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void canceled() {
|
||||
godotPayment.callbackCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void alreadyOwned() {
|
||||
godotPayment.callbackAlreadyOwned(sku);
|
||||
}
|
||||
}
|
||||
.purchase(sku, transactionId);
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return mService != null;
|
||||
}
|
||||
|
||||
public void consumeUnconsumedPurchases() {
|
||||
new ReleaseAllConsumablesTask(mService, activity) {
|
||||
@Override
|
||||
protected void success(String sku, String receipt, String signature, String token) {
|
||||
godotPayment.callbackSuccessProductMassConsumed(receipt, signature, sku);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
Log.d("godot", "consumeUnconsumedPurchases :" + message);
|
||||
godotPayment.callbackFailConsume(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notRequired() {
|
||||
Log.d("godot", "callbackSuccessNoUnconsumedPurchases :");
|
||||
godotPayment.callbackSuccessNoUnconsumedPurchases();
|
||||
}
|
||||
}
|
||||
.consumeItAll();
|
||||
}
|
||||
|
||||
public void requestPurchased() {
|
||||
try {
|
||||
PaymentsCache pc = new PaymentsCache(activity);
|
||||
|
||||
String continueToken = null;
|
||||
|
||||
do {
|
||||
Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp", continueToken);
|
||||
|
||||
if (bundle.getInt("RESPONSE_CODE") == 0) {
|
||||
|
||||
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
|
||||
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
|
||||
|
||||
if (myPurchases == null || myPurchases.size() == 0) {
|
||||
godotPayment.callbackPurchased("", "", "");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < myPurchases.size(); i++) {
|
||||
|
||||
try {
|
||||
String receipt = myPurchases.get(i);
|
||||
JSONObject inappPurchaseData = new JSONObject(receipt);
|
||||
String sku = inappPurchaseData.getString("productId");
|
||||
String token = inappPurchaseData.getString("purchaseToken");
|
||||
String signature = mySignatures.get(i);
|
||||
|
||||
pc.setConsumableValue("ticket_signautre", sku, signature);
|
||||
pc.setConsumableValue("ticket", sku, receipt);
|
||||
pc.setConsumableFlag("block", sku, true);
|
||||
pc.setConsumableValue("token", sku, token);
|
||||
|
||||
godotPayment.callbackPurchased(receipt, signature, sku);
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
continueToken = bundle.getString("INAPP_CONTINUATION_TOKEN");
|
||||
Log.d("godot", "continue token = " + continueToken);
|
||||
} while (!TextUtils.isEmpty(continueToken));
|
||||
} catch (Exception e) {
|
||||
Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void processPurchaseResponse(int resultCode, Intent data) {
|
||||
new HandlePurchaseTask(activity) {
|
||||
@Override
|
||||
protected void success(final String sku, final String signature, final String ticket) {
|
||||
godotPayment.callbackSuccess(ticket, signature, sku);
|
||||
|
||||
if (auto_consume) {
|
||||
new ConsumeTask(mService, activity) {
|
||||
@Override
|
||||
protected void success(String ticket) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFail(message);
|
||||
}
|
||||
}
|
||||
.consume(sku);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFail(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void canceled() {
|
||||
godotPayment.callbackCancel();
|
||||
}
|
||||
}
|
||||
.handlePurchaseRequest(resultCode, data);
|
||||
}
|
||||
|
||||
public void validatePurchase(String purchaseToken, final String sku) {
|
||||
|
||||
new ValidateTask(activity, godotPayment) {
|
||||
@Override
|
||||
protected void success() {
|
||||
|
||||
new ConsumeTask(mService, activity) {
|
||||
@Override
|
||||
protected void success(String ticket) {
|
||||
godotPayment.callbackSuccess(ticket, null, sku);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFail(message);
|
||||
}
|
||||
}
|
||||
.consume(sku);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFail(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void canceled() {
|
||||
godotPayment.callbackCancel();
|
||||
}
|
||||
}
|
||||
.validatePurchase(sku);
|
||||
}
|
||||
|
||||
public void setAutoConsume(boolean autoConsume) {
|
||||
auto_consume = autoConsume;
|
||||
}
|
||||
|
||||
public void consume(final String sku) {
|
||||
new ConsumeTask(mService, activity) {
|
||||
@Override
|
||||
protected void success(String ticket) {
|
||||
godotPayment.callbackSuccessProductMassConsumed(ticket, "", sku);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
godotPayment.callbackFailConsume(message);
|
||||
}
|
||||
}
|
||||
.consume(sku);
|
||||
}
|
||||
|
||||
// Workaround to bug where sometimes response codes come as Long instead of Integer
|
||||
int getResponseCodeFromBundle(Bundle b) {
|
||||
Object o = b.get("RESPONSE_CODE");
|
||||
if (o == null) {
|
||||
//logDebug("Bundle with null response code, assuming OK (known issue)");
|
||||
return BILLING_RESPONSE_RESULT_OK;
|
||||
} else if (o instanceof Integer)
|
||||
return ((Integer)o).intValue();
|
||||
else if (o instanceof Long)
|
||||
return (int)((Long)o).longValue();
|
||||
else {
|
||||
//logError("Unexpected type for bundle response code.");
|
||||
//logError(o.getClass().getName());
|
||||
throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a human-readable description for the given response code.
|
||||
*
|
||||
* @param code The response code
|
||||
* @return A human-readable string explaining the result code.
|
||||
* It also includes the result code numerically.
|
||||
*/
|
||||
public static String getResponseDesc(int code) {
|
||||
String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/"
|
||||
+
|
||||
"3:Billing Unavailable/4:Item unavailable/"
|
||||
+
|
||||
"5:Developer Error/6:Error/7:Item Already Owned/"
|
||||
+
|
||||
"8:Item not owned")
|
||||
.split("/");
|
||||
String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/"
|
||||
+
|
||||
"-1002:Bad response received/"
|
||||
+
|
||||
"-1003:Purchase signature verification failed/"
|
||||
+
|
||||
"-1004:Send intent failed/"
|
||||
+
|
||||
"-1005:User cancelled/"
|
||||
+
|
||||
"-1006:Unknown purchase response/"
|
||||
+
|
||||
"-1007:Missing token/"
|
||||
+
|
||||
"-1008:Unknown error/"
|
||||
+
|
||||
"-1009:Subscriptions not available/"
|
||||
+
|
||||
"-1010:Invalid consumption attempt")
|
||||
.split("/");
|
||||
|
||||
if (code <= -1000) {
|
||||
int index = -1000 - code;
|
||||
if (index >= 0 && index < iabhelper_msgs.length)
|
||||
return iabhelper_msgs[index];
|
||||
else
|
||||
return String.valueOf(code) + ":Unknown IAB Helper Error";
|
||||
} else if (code < 0 || code >= iab_msgs.length)
|
||||
return String.valueOf(code) + ":Unknown";
|
||||
else
|
||||
return iab_msgs[code];
|
||||
}
|
||||
|
||||
public void querySkuDetails(final String[] list) {
|
||||
(new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ArrayList<String> skuList = new ArrayList<String>(Arrays.asList(list));
|
||||
if (skuList.size() == 0) {
|
||||
return;
|
||||
}
|
||||
// Split the sku list in blocks of no more than 20 elements.
|
||||
ArrayList<ArrayList<String>> packs = new ArrayList<ArrayList<String>>();
|
||||
ArrayList<String> tempList;
|
||||
int n = skuList.size() / 20;
|
||||
int mod = skuList.size() % 20;
|
||||
for (int i = 0; i < n; i++) {
|
||||
tempList = new ArrayList<String>();
|
||||
for (String s : skuList.subList(i * 20, i * 20 + 20)) {
|
||||
tempList.add(s);
|
||||
}
|
||||
packs.add(tempList);
|
||||
}
|
||||
if (mod != 0) {
|
||||
tempList = new ArrayList<String>();
|
||||
for (String s : skuList.subList(n * 20, n * 20 + mod)) {
|
||||
tempList.add(s);
|
||||
}
|
||||
packs.add(tempList);
|
||||
}
|
||||
for (ArrayList<String> skuPartList : packs) {
|
||||
Bundle querySkus = new Bundle();
|
||||
querySkus.putStringArrayList("ITEM_ID_LIST", skuPartList);
|
||||
Bundle skuDetails = null;
|
||||
try {
|
||||
skuDetails = mService.getSkuDetails(3, activity.getPackageName(), "inapp", querySkus);
|
||||
if (!skuDetails.containsKey("DETAILS_LIST")) {
|
||||
int response = getResponseCodeFromBundle(skuDetails);
|
||||
if (response != BILLING_RESPONSE_RESULT_OK) {
|
||||
godotPayment.errorSkuDetail(getResponseDesc(response));
|
||||
} else {
|
||||
godotPayment.errorSkuDetail("No error but no detail list.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
|
||||
|
||||
for (String thisResponse : responseList) {
|
||||
Log.d("godot", "response = " + thisResponse);
|
||||
godotPayment.addSkuDetail(thisResponse);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
godotPayment.errorSkuDetail("RemoteException error!");
|
||||
}
|
||||
}
|
||||
godotPayment.completeSkuDetail();
|
||||
}
|
||||
}))
|
||||
.start();
|
||||
}
|
||||
|
||||
private GodotPaymentInterface godotPayment;
|
||||
|
||||
public void setBaseSingleton(GodotPaymentInterface godotPaymentInterface) {
|
||||
this.godotPayment = godotPaymentInterface;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* PurchaseTask.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import com.android.vending.billing.IInAppBillingService;
|
||||
|
||||
abstract public class PurchaseTask {
|
||||
|
||||
private Activity context;
|
||||
|
||||
private IInAppBillingService mService;
|
||||
public PurchaseTask(IInAppBillingService mService, Activity context) {
|
||||
this.context = context;
|
||||
this.mService = mService;
|
||||
}
|
||||
|
||||
private boolean isLooping = false;
|
||||
|
||||
public void purchase(final String sku, final String transactionId) {
|
||||
Log.d("XXX", "Starting purchase for: " + sku);
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
Boolean isBlocked = pc.getConsumableFlag("block", sku);
|
||||
/*
|
||||
if(isBlocked){
|
||||
Log.d("XXX", "Is awaiting payment confirmation");
|
||||
error("Awaiting payment confirmation");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
final String hash = transactionId;
|
||||
|
||||
Bundle buyIntentBundle;
|
||||
try {
|
||||
buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash);
|
||||
} catch (RemoteException e) {
|
||||
//Log.d("XXX", "Error: " + e.getMessage());
|
||||
error(e.getMessage());
|
||||
return;
|
||||
}
|
||||
Object rc = buyIntentBundle.get("RESPONSE_CODE");
|
||||
int responseCode = 0;
|
||||
if (rc == null) {
|
||||
responseCode = PaymentsManager.BILLING_RESPONSE_RESULT_OK;
|
||||
} else if (rc instanceof Integer) {
|
||||
responseCode = ((Integer)rc).intValue();
|
||||
} else if (rc instanceof Long) {
|
||||
responseCode = (int)((Long)rc).longValue();
|
||||
}
|
||||
//Log.d("XXX", "Buy intent response code: " + responseCode);
|
||||
if (responseCode == 1 || responseCode == 3 || responseCode == 4) {
|
||||
canceled();
|
||||
return;
|
||||
}
|
||||
if (responseCode == 7) {
|
||||
alreadyOwned();
|
||||
return;
|
||||
}
|
||||
|
||||
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
|
||||
pc.setConsumableValue("validation_hash", sku, hash);
|
||||
try {
|
||||
if (context == null) {
|
||||
//Log.d("XXX", "No context!");
|
||||
}
|
||||
if (pendingIntent == null) {
|
||||
//Log.d("XXX", "No pending intent");
|
||||
}
|
||||
//Log.d("XXX", "Starting activity for purchase!");
|
||||
context.startIntentSenderForResult(
|
||||
pendingIntent.getIntentSender(),
|
||||
PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
|
||||
new Intent(),
|
||||
Integer.valueOf(0), Integer.valueOf(0),
|
||||
Integer.valueOf(0));
|
||||
} catch (SendIntentException e) {
|
||||
error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void error(String message);
|
||||
abstract protected void canceled();
|
||||
abstract protected void alreadyOwned();
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* ReleaseAllConsumablesTask.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import com.android.vending.billing.IInAppBillingService;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
abstract public class ReleaseAllConsumablesTask {
|
||||
|
||||
private Context context;
|
||||
private IInAppBillingService mService;
|
||||
|
||||
private static class ReleaseAllConsumablesAsyncTask extends AsyncTask<String, String, String> {
|
||||
|
||||
private WeakReference<ReleaseAllConsumablesTask> mTask;
|
||||
private String mSku;
|
||||
private String mReceipt;
|
||||
private String mSignature;
|
||||
private String mToken;
|
||||
|
||||
ReleaseAllConsumablesAsyncTask(ReleaseAllConsumablesTask task, String sku, String receipt, String signature, String token) {
|
||||
mTask = new WeakReference<ReleaseAllConsumablesTask>(task);
|
||||
|
||||
mSku = sku;
|
||||
mReceipt = receipt;
|
||||
mSignature = signature;
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
ReleaseAllConsumablesTask consume = mTask.get();
|
||||
if (consume != null) {
|
||||
return consume.doInBackground(mToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String param) {
|
||||
ReleaseAllConsumablesTask consume = mTask.get();
|
||||
if (consume != null) {
|
||||
consume.success(mSku, mReceipt, mSignature, mToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ReleaseAllConsumablesTask(IInAppBillingService mService, Context context) {
|
||||
this.context = context;
|
||||
this.mService = mService;
|
||||
}
|
||||
|
||||
public void consumeItAll() {
|
||||
try {
|
||||
//Log.d("godot", "consumeItall for " + context.getPackageName());
|
||||
Bundle bundle = mService.getPurchases(3, context.getPackageName(), "inapp", null);
|
||||
|
||||
if (bundle.getInt("RESPONSE_CODE") == 0) {
|
||||
|
||||
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
|
||||
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
|
||||
|
||||
if (myPurchases == null || myPurchases.size() == 0) {
|
||||
//Log.d("godot", "No purchases!");
|
||||
notRequired();
|
||||
return;
|
||||
}
|
||||
|
||||
//Log.d("godot", "# products to be consumed:" + myPurchases.size());
|
||||
for (int i = 0; i < myPurchases.size(); i++) {
|
||||
|
||||
try {
|
||||
String receipt = myPurchases.get(i);
|
||||
JSONObject inappPurchaseData = new JSONObject(receipt);
|
||||
String sku = inappPurchaseData.getString("productId");
|
||||
String token = inappPurchaseData.getString("purchaseToken");
|
||||
String signature = mySignatures.get(i);
|
||||
//Log.d("godot", "A punto de consumir un item con token:" + token + "\n" + receipt);
|
||||
new ReleaseAllConsumablesAsyncTask(this, sku, receipt, signature, token).execute();
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d("godot", "Error releasing products:" + e.getClass().getName() + ":" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String doInBackground(String token) {
|
||||
try {
|
||||
//Log.d("godot", "Requesting to consume an item with token ." + token);
|
||||
int response = mService.consumePurchase(3, context.getPackageName(), token);
|
||||
//Log.d("godot", "consumePurchase response: " + response);
|
||||
if (response == 0 || response == 8) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.d("godot", "Error " + e.getClass().getName() + ":" + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract protected void success(String sku, String receipt, String signature, String token);
|
||||
abstract protected void error(String message);
|
||||
abstract protected void notRequired();
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* ValidateTask.java */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.payments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.AsyncTask;
|
||||
import java.lang.ref.WeakReference;
|
||||
import org.godotengine.godot.utils.HttpRequester;
|
||||
import org.godotengine.godot.utils.RequestParams;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
abstract public class ValidateTask {
|
||||
|
||||
private Activity context;
|
||||
private GodotPaymentInterface godotPayments;
|
||||
private ProgressDialog dialog;
|
||||
private String mSku;
|
||||
|
||||
private static class ValidateAsyncTask extends AsyncTask<String, String, String> {
|
||||
private WeakReference<ValidateTask> mTask;
|
||||
|
||||
ValidateAsyncTask(ValidateTask task) {
|
||||
mTask = new WeakReference<>(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ValidateTask task = mTask.get();
|
||||
if (task != null) {
|
||||
task.onPreExecute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
ValidateTask task = mTask.get();
|
||||
if (task != null) {
|
||||
return task.doInBackground(params);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String response) {
|
||||
ValidateTask task = mTask.get();
|
||||
if (task != null) {
|
||||
task.onPostExecute(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ValidateTask(Activity context, GodotPaymentInterface godotPayments) {
|
||||
this.context = context;
|
||||
this.godotPayments = godotPayments;
|
||||
}
|
||||
|
||||
public void validatePurchase(final String sku) {
|
||||
mSku = sku;
|
||||
new ValidateAsyncTask(this).execute();
|
||||
}
|
||||
|
||||
private void onPreExecute() {
|
||||
dialog = ProgressDialog.show(context, null, "Please wait...");
|
||||
}
|
||||
|
||||
private String doInBackground(String... params) {
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
String url = godotPayments.getPurchaseValidationUrlPrefix();
|
||||
RequestParams param = new RequestParams();
|
||||
param.setUrl(url);
|
||||
param.put("ticket", pc.getConsumableValue("ticket", mSku));
|
||||
param.put("purchaseToken", pc.getConsumableValue("token", mSku));
|
||||
param.put("sku", mSku);
|
||||
//Log.d("XXX", "Haciendo request a " + url);
|
||||
//Log.d("XXX", "ticket: " + pc.getConsumableValue("ticket", sku));
|
||||
//Log.d("XXX", "purchaseToken: " + pc.getConsumableValue("token", sku));
|
||||
//Log.d("XXX", "sku: " + sku);
|
||||
param.put("package", context.getApplicationContext().getPackageName());
|
||||
HttpRequester requester = new HttpRequester();
|
||||
String jsonResponse = requester.post(param);
|
||||
//Log.d("XXX", "Validation response:\n"+jsonResponse);
|
||||
return jsonResponse;
|
||||
}
|
||||
|
||||
private void onPostExecute(String response) {
|
||||
if (dialog != null) {
|
||||
dialog.dismiss();
|
||||
dialog = null;
|
||||
}
|
||||
JSONObject j;
|
||||
try {
|
||||
j = new JSONObject(response);
|
||||
if (j.getString("status").equals("OK")) {
|
||||
success();
|
||||
return;
|
||||
} else if (j.getString("status") != null) {
|
||||
error(j.getString("message"));
|
||||
} else {
|
||||
error("Connection error");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
error(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void success();
|
||||
abstract protected void error(String message);
|
||||
abstract protected void canceled();
|
||||
}
|
||||
Reference in New Issue
Block a user