Browse Source

Merge pull request #2691 from volzhs/android_payment

improve android payments
Juan Linietsky 9 years ago
parent
commit
34a558ee8d

+ 43 - 17
platform/android/java/src/com/android/godot/GodotPaymentV3.java

@@ -27,7 +27,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 				activity.getPaymentsManager().requestPurchase(sku, transactionId);				
 			}
 		});
-	};
+	}
 	
 /*	public string requestPurchasedTicket(){
 	    activity.getPaymentsManager()
@@ -42,7 +42,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 	
 	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;
 	}
 
@@ -54,7 +54,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 				activity.getPaymentsManager().consumeUnconsumedPurchases();				
 			}
 		});
-		
 	}
 
 	private String signature;
@@ -63,25 +62,26 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 	}
 	
 	
-	public void callbackSuccess(String ticket, String signature){
-//        Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
-        GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
-//    	Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
+	public void callbackSuccess(String ticket, String signature, String sku){
+//		Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
+		GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
+//		Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
 }
 
 	public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
-//        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(), "POST-Send callback to consume success");
+//		Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
+		Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku);
+        	GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
+//		Log.d(this.getClass().getName(), "POST-Send callback to consume success");
 	}
 
 	public void callbackSuccessNoUnconsumedPurchases(){
-        GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
+		GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
 	}
 	
 	public void callbackFail(){
-                GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
-//                GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
+		GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
+//		GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
 	}
 	
 	public void callbackCancel(){
@@ -89,6 +89,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 //		GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
 	}
 	
+	public void callbackAlreadyOwned(String sku){
+		GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
+	}
+	
 	public int getPurchaseCallbackId() {
 		return purchaseCallbackId;
 	}
@@ -97,8 +101,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 		this.purchaseCallbackId = purchaseCallbackId;
 	}
 
-
-
 	public String getPurchaseValidationUrlPrefix(){
 		return this.purchaseValidationUrlPrefix ;
 	}
@@ -107,12 +109,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 		this.purchaseValidationUrlPrefix = url;
 	}
 
-
 	public String getAccessToken() {
 		return accessToken;
 	}
 
-
 	public void setAccessToken(String accessToken) {
 		this.accessToken = accessToken;
 	}
@@ -125,4 +125,30 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 		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);
+	}
 }
+

+ 101 - 22
platform/android/java/src/com/android/godot/payments/PaymentsManager.java

@@ -25,10 +25,8 @@ import com.android.vending.billing.IInAppBillingService;
 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;
@@ -69,13 +67,12 @@ public class PaymentsManager {
 	    }
 
 	    @Override
-	    public void onServiceConnected(ComponentName name, 
-	    		IBinder service) {
-		mService = IInAppBillingService.Stub.asInterface(service);
+	    public void onServiceConnected(ComponentName name, IBinder 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()) {
 			
 			@Override
@@ -88,6 +85,12 @@ public class PaymentsManager {
 			protected void canceled() {
 				godotPaymentV3.callbackCancel();
 			}
+			
+			@Override
+			protected void alreadyOwned() {
+				godotPaymentV3.callbackAlreadyOwned(sku);
+			}
+			
 		}.purchase(sku, transactionId);
 
 	}
@@ -114,26 +117,82 @@ public class PaymentsManager {
 		}.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) {
 		new HandlePurchaseTask(activity){
 
 			@Override
 			protected void success(final String sku, final String signature, final String ticket) {
-				godotPaymentV3.callbackSuccess(ticket, signature);
-				new ConsumeTask(mService, activity) {
+				godotPaymentV3.callbackSuccess(ticket, signature, sku);
+
+				if (auto_consume){
+					new ConsumeTask(mService, activity) {
 					
-					@Override
-					protected void success(String ticket) {
-//						godotPaymentV3.callbackSuccess("");
-					}
+						@Override
+						protected void success(String ticket) {
+//							godotPaymentV3.callbackSuccess("");
+						}
 					
-					@Override
-					protected void error(String message) {
-						godotPaymentV3.callbackFail();
+						@Override
+						protected void error(String message) {
+							godotPaymentV3.callbackFail();
 						
-					}
-				}.consume(sku);
-
+						}
+					}.consume(sku);
+				}
 				
 //				godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
 //			    godotPaymentV3.callbackSuccess(ticket);
@@ -151,7 +210,7 @@ public class PaymentsManager {
 				godotPaymentV3.callbackCancel();
 				
 			}
-			}.handlePurchaseRequest(resultCode, data);
+		}.handlePurchaseRequest(resultCode, data);
 	}
 	
 	public void validatePurchase(String purchaseToken, final String sku){
@@ -165,7 +224,7 @@ public class PaymentsManager {
 					
 					@Override
 					protected void success(String ticket) {
-						godotPaymentV3.callbackSuccess(ticket, null);
+						godotPaymentV3.callbackSuccess(ticket, null, sku);
 						
 					}
 					
@@ -192,11 +251,31 @@ public class PaymentsManager {
 		}.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;
 	
 	public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
 		this.godotPaymentV3 = godotPaymentV3;
-		
 	}
 
 }

+ 6 - 2
platform/android/java/src/com/android/godot/payments/PurchaseTask.java

@@ -62,7 +62,11 @@ abstract public class PurchaseTask {
 //		Log.d("XXX", "Buy intent response code: " + responseCode);
 		if(responseCode == 1 || responseCode == 3 || responseCode == 4){
 			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 canceled();
-
+	abstract protected void alreadyOwned();
 	
 }