improve android payments
GodotPaymentV3 currently consumes purchased item right after purchasing. But, some in-app item should not consume like "remove ads permanently" So, I added "setAutoConsume(boolean)", "requestPurchased()", "consume(sku_string)". AutoConsume is true by default as before. usage: func _ready(): var payment = Globals.get_singleton("GodotPayments") payment.setPurchaseCallbackId(get_instance_ID()) payment.setAutoConsume(false) # default : true payment.requestPurchased() # callback : has_purchased payment.purchase("item_name") # callback : purchase_success, purchase_fail, purchase_cancel, purchase_owned payment.consume("item_name") # callback : consume_success func purchase_success(receipt, signature, sku): print("purchase_success : ", sku) func purchase_fail(): print("purchase_fail") func purchase_cancel(): print("purchase_cancel") func purchase_owned(sku): print("purchase_owned : ", sku) func consume_success(receipt, signature, sku): print("consume_success : ", sku) func has_purchased(receipt, signature, sku): if sku == "": print("has_purchased : nothing") else: print("has_purchased : ", sku)
This commit is contained in:
parent
bd736e5af2
commit
3fbaa479e3
|
@ -27,7 +27,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
activity.getPaymentsManager().requestPurchase(sku, transactionId);
|
activity.getPaymentsManager().requestPurchase(sku, transactionId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/* public string requestPurchasedTicket(){
|
/* public string requestPurchasedTicket(){
|
||||||
activity.getPaymentsManager()
|
activity.getPaymentsManager()
|
||||||
|
@ -42,7 +42,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
|
|
||||||
public GodotPaymentV3(Activity p_activity) {
|
public GodotPaymentV3(Activity p_activity) {
|
||||||
|
|
||||||
registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases"});
|
registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume"});
|
||||||
activity=(Godot) p_activity;
|
activity=(Godot) p_activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
activity.getPaymentsManager().consumeUnconsumedPurchases();
|
activity.getPaymentsManager().consumeUnconsumedPurchases();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String signature;
|
private String signature;
|
||||||
|
@ -63,25 +62,26 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void callbackSuccess(String ticket, String signature){
|
public void callbackSuccess(String ticket, String signature, String sku){
|
||||||
// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
|
// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
|
||||||
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
|
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
|
||||||
// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
|
// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
|
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
|
||||||
// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
|
// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
|
||||||
GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
|
Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku);
|
||||||
// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
|
GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
|
||||||
|
// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callbackSuccessNoUnconsumedPurchases(){
|
public void callbackSuccessNoUnconsumedPurchases(){
|
||||||
GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
|
GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callbackFail(){
|
public void callbackFail(){
|
||||||
GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
|
GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
|
||||||
// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
|
// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callbackCancel(){
|
public void callbackCancel(){
|
||||||
|
@ -89,6 +89,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
|
// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void callbackAlreadyOwned(String sku){
|
||||||
|
GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
|
||||||
|
}
|
||||||
|
|
||||||
public int getPurchaseCallbackId() {
|
public int getPurchaseCallbackId() {
|
||||||
return purchaseCallbackId;
|
return purchaseCallbackId;
|
||||||
}
|
}
|
||||||
|
@ -97,8 +101,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
this.purchaseCallbackId = purchaseCallbackId;
|
this.purchaseCallbackId = purchaseCallbackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getPurchaseValidationUrlPrefix(){
|
public String getPurchaseValidationUrlPrefix(){
|
||||||
return this.purchaseValidationUrlPrefix ;
|
return this.purchaseValidationUrlPrefix ;
|
||||||
}
|
}
|
||||||
|
@ -107,12 +109,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
this.purchaseValidationUrlPrefix = url;
|
this.purchaseValidationUrlPrefix = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getAccessToken() {
|
public String getAccessToken() {
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setAccessToken(String accessToken) {
|
public void setAccessToken(String accessToken) {
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
}
|
}
|
||||||
|
@ -125,4 +125,30 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||||
return this.transactionId;
|
return this.transactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// request purchased items are not consumed
|
||||||
|
public void requestPurchased(){
|
||||||
|
activity.getPaymentsManager().setBaseSingleton(this);
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
activity.getPaymentsManager().requestPurchased();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback for requestPurchased()
|
||||||
|
public void callbackPurchased(String receipt, String signature, String sku){
|
||||||
|
GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku});
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume item automatically after purchase. default is true.
|
||||||
|
public void setAutoConsume(boolean autoConsume){
|
||||||
|
activity.getPaymentsManager().setAutoConsume(autoConsume);
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume a specific item
|
||||||
|
public void consume(String sku){
|
||||||
|
activity.getPaymentsManager().consume(sku);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,8 @@ import com.android.vending.billing.IInAppBillingService;
|
||||||
public class PaymentsManager {
|
public class PaymentsManager {
|
||||||
|
|
||||||
public static final int BILLING_RESPONSE_RESULT_OK = 0;
|
public static final int BILLING_RESPONSE_RESULT_OK = 0;
|
||||||
|
|
||||||
|
|
||||||
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
|
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
|
||||||
|
private static boolean auto_consume = true;
|
||||||
|
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
IInAppBillingService mService;
|
IInAppBillingService mService;
|
||||||
|
@ -69,13 +67,12 @@ public class PaymentsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected(ComponentName name,
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
IBinder service) {
|
mService = IInAppBillingService.Stub.asInterface(service);
|
||||||
mService = IInAppBillingService.Stub.asInterface(service);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void requestPurchase(String sku, String transactionId){
|
public void requestPurchase(final String sku, String transactionId){
|
||||||
new PurchaseTask(mService, Godot.getInstance()) {
|
new PurchaseTask(mService, Godot.getInstance()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,6 +85,12 @@ public class PaymentsManager {
|
||||||
protected void canceled() {
|
protected void canceled() {
|
||||||
godotPaymentV3.callbackCancel();
|
godotPaymentV3.callbackCancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void alreadyOwned() {
|
||||||
|
godotPaymentV3.callbackAlreadyOwned(sku);
|
||||||
|
}
|
||||||
|
|
||||||
}.purchase(sku, transactionId);
|
}.purchase(sku, transactionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,26 +117,82 @@ public class PaymentsManager {
|
||||||
}.consumeItAll();
|
}.consumeItAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void requestPurchased(){
|
||||||
|
try{
|
||||||
|
PaymentsCache pc = new PaymentsCache(Godot.getInstance());
|
||||||
|
|
||||||
|
// Log.d("godot", "requestPurchased for " + activity.getPackageName());
|
||||||
|
Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp",null);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (String key : bundle.keySet()) {
|
||||||
|
Object value = bundle.get(key);
|
||||||
|
Log.d("godot", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
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!");
|
||||||
|
godotPaymentV3.callbackPurchased("", "", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.d("godot", "# products are purchased:" + 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", "purchased item:" + token + "\n" + receipt);
|
||||||
|
|
||||||
|
pc.setConsumableValue("ticket_signautre", sku, signature);
|
||||||
|
pc.setConsumableValue("ticket", sku, receipt);
|
||||||
|
pc.setConsumableFlag("block", sku, true);
|
||||||
|
pc.setConsumableValue("token", sku, token);
|
||||||
|
|
||||||
|
godotPaymentV3.callbackPurchased(receipt, signature, sku);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void processPurchaseResponse(int resultCode, Intent data) {
|
public void processPurchaseResponse(int resultCode, Intent data) {
|
||||||
new HandlePurchaseTask(activity){
|
new HandlePurchaseTask(activity){
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void success(final String sku, final String signature, final String ticket) {
|
protected void success(final String sku, final String signature, final String ticket) {
|
||||||
godotPaymentV3.callbackSuccess(ticket, signature);
|
godotPaymentV3.callbackSuccess(ticket, signature, sku);
|
||||||
new ConsumeTask(mService, activity) {
|
|
||||||
|
|
||||||
@Override
|
if (auto_consume){
|
||||||
protected void success(String ticket) {
|
new ConsumeTask(mService, activity) {
|
||||||
// godotPaymentV3.callbackSuccess("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(String message) {
|
protected void success(String ticket) {
|
||||||
godotPaymentV3.callbackFail();
|
// godotPaymentV3.callbackSuccess("");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
}.consume(sku);
|
protected void error(String message) {
|
||||||
|
godotPaymentV3.callbackFail();
|
||||||
|
|
||||||
|
}
|
||||||
|
}.consume(sku);
|
||||||
|
}
|
||||||
|
|
||||||
// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
|
// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
|
||||||
// godotPaymentV3.callbackSuccess(ticket);
|
// godotPaymentV3.callbackSuccess(ticket);
|
||||||
|
@ -151,7 +210,7 @@ public class PaymentsManager {
|
||||||
godotPaymentV3.callbackCancel();
|
godotPaymentV3.callbackCancel();
|
||||||
|
|
||||||
}
|
}
|
||||||
}.handlePurchaseRequest(resultCode, data);
|
}.handlePurchaseRequest(resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validatePurchase(String purchaseToken, final String sku){
|
public void validatePurchase(String purchaseToken, final String sku){
|
||||||
|
@ -165,7 +224,7 @@ public class PaymentsManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void success(String ticket) {
|
protected void success(String ticket) {
|
||||||
godotPaymentV3.callbackSuccess(ticket, null);
|
godotPaymentV3.callbackSuccess(ticket, null, sku);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,11 +251,31 @@ public class PaymentsManager {
|
||||||
}.validatePurchase(sku);
|
}.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) {
|
||||||
|
godotPaymentV3.callbackSuccessProductMassConsumed(ticket, "", sku);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void error(String message) {
|
||||||
|
godotPaymentV3.callbackFail();
|
||||||
|
|
||||||
|
}
|
||||||
|
}.consume(sku);
|
||||||
|
}
|
||||||
|
|
||||||
private GodotPaymentV3 godotPaymentV3;
|
private GodotPaymentV3 godotPaymentV3;
|
||||||
|
|
||||||
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
|
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
|
||||||
this.godotPaymentV3 = godotPaymentV3;
|
this.godotPaymentV3 = godotPaymentV3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,11 @@ abstract public class PurchaseTask {
|
||||||
// Log.d("XXX", "Buy intent response code: " + responseCode);
|
// Log.d("XXX", "Buy intent response code: " + responseCode);
|
||||||
if(responseCode == 1 || responseCode == 3 || responseCode == 4){
|
if(responseCode == 1 || responseCode == 3 || responseCode == 4){
|
||||||
canceled();
|
canceled();
|
||||||
return ;
|
return;
|
||||||
|
}
|
||||||
|
if(responseCode == 7){
|
||||||
|
alreadyOwned();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +96,6 @@ abstract public class PurchaseTask {
|
||||||
|
|
||||||
abstract protected void error(String message);
|
abstract protected void error(String message);
|
||||||
abstract protected void canceled();
|
abstract protected void canceled();
|
||||||
|
abstract protected void alreadyOwned();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue