Browse Source

IAP tweaks.

Mark Sibly 7 years ago
parent
commit
d2acfd573e

+ 55 - 26
modules/iap/bananas/iaptest.monkey2

@@ -6,6 +6,7 @@ IMPORTANT!
 This wont work 'as is'! You'll need to set up a bunch of stuff on GooglePlay/iTunes Connect developer portal such as app/products etc.
 This wont work 'as is'! You'll need to set up a bunch of stuff on GooglePlay/iTunes Connect developer portal such as app/products etc.
 
 
 #end
 #end
+
 Namespace myapp
 Namespace myapp
 
 
 #Import "<iap>"
 #Import "<iap>"
@@ -28,12 +29,16 @@ Class MyWindow Extends Window
 
 
 	Field _listView:ListView
 	Field _listView:ListView
 
 
+	Field _openStoreItem:ListView.Item
+	
+	Field _restorePurchasesItem:ListView.Item
+	
 	Field _iap:IAPStore
 	Field _iap:IAPStore
 	
 	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )
 
 
 		Super.New( title,width,height,flags )
 		Super.New( title,width,height,flags )
-
+		
 		Layout="stretch"
 		Layout="stretch"
 		
 		
 		'Create our IAP products.
 		'Create our IAP products.
@@ -43,7 +48,7 @@ Class MyWindow Extends Window
 			New Product( "bullet_boost",ProductType.Consumable ),
 			New Product( "bullet_boost",ProductType.Consumable ),
 			New Product( "ship_upgrade",ProductType.NonConsumable ) )
 			New Product( "ship_upgrade",ProductType.NonConsumable ) )
 		
 		
-		'Load purchases we've alreday bought.
+		'Load purchases we've already bought.
 		'
 		'
 		LoadPurchases()
 		LoadPurchases()
 
 
@@ -55,17 +60,23 @@ Class MyWindow Extends Window
 		
 		
 		_listView.ItemClicked=Lambda( item:ListView.Item )
 		_listView.ItemClicked=Lambda( item:ListView.Item )
 		
 		
-			If _iap.Busy Return
+			If Not _iap Or _iap.Busy Return
 			
 			
-			Local index:= _listView.IndexOfItem( item )
+			If item=_restorePurchasesItem
+
+				_iap.GetOwnedProducts()
+
+				Return
+			Endif
 			
 			
-			If index=_products.Length
+			If item=_openStoreItem
 				
 				
-				_iap.GetOwnedProducts()
+				OpenStore()
 				
 				
 				Return
 				Return
-			
 			Endif
 			Endif
+
+			Local index:= _listView.IndexOfItem( item )
 			
 			
 			Local product:=_products[ index ]
 			Local product:=_products[ index ]
 			
 			
@@ -80,14 +91,37 @@ Class MyWindow Extends Window
 		
 		
 		ContentView=_listView
 		ContentView=_listView
 		
 		
+		OpenStore()
+	End
+	
+	Method MakePurchase( product:Product )
+		
+		Select product.Type
+		Case ProductType.Consumable
+			_purchases.SetNumber( product.Identifier,_purchases.GetNumber( product.Identifier )+1 )
+		Case ProductType.NonConsumable
+			_purchases.SetNumber( product.Identifier,1 )
+		End
+	End
+	
+	Method OpenStore()
+
+		_iap?.CloseStore()
+		_iap=Null
+		
 		'Create IAPStore and various handlers.
 		'Create IAPStore and various handlers.
 		'
 		'
 		_iap=New IAPStore
 		_iap=New IAPStore
-		
-		'This isc alled when OpenStore completes.
+
+		GCCollect()
+		GCCollect()
+
+		'This is called when OpenStore completes.
 		'
 		'
 		_iap.OpenStoreComplete=Lambda( result:Int,interrupted:Product[],owned:Product[] )
 		_iap.OpenStoreComplete=Lambda( result:Int,interrupted:Product[],owned:Product[] )
 		
 		
+			Print "OpenStoreComplete result="+result
+		
 			Select result
 			Select result
 			Case 0
 			Case 0
 
 
@@ -104,7 +138,7 @@ Class MyWindow Extends Window
 				'you (as long as you're logged in anyway) so you don't strictly need to save them, but you do on ios so for the sake of 
 				'you (as long as you're logged in anyway) so you don't strictly need to save them, but you do on ios so for the sake of 
 				'uniformity we will on android too.
 				'uniformity we will on android too.
 				'
 				'
-				'On Android, you never really need to use GetOwnProducts() because you are given this array of owned products when the store
+				'On Android, you never really need to use GetOwnedProducts() because you are given this array of owned products when the store
 				'opens. So in a sense, android automatically 'restores purchases' whenever you open the store.
 				'opens. So in a sense, android automatically 'restores purchases' whenever you open the store.
 				'
 				'
 				'This array is always empty on ios. To restore non-consumables on ios you must call GetOwnedProducts in response to the push
 				'This array is always empty on ios. To restore non-consumables on ios you must call GetOwnedProducts in response to the push
@@ -117,13 +151,13 @@ Class MyWindow Extends Window
 				Next
 				Next
 				
 				
 				SavePurchases()
 				SavePurchases()
-				UpdateListView()
 				
 				
 				_info="OpenStore successful"
 				_info="OpenStore successful"
 			Default
 			Default
 				_info="OpenStore error:"+result
 				_info="OpenStore error:"+result
 			End
 			End
-		
+
+			UpdateListView()
 		End
 		End
 		
 		
 		'This is called when BuyProduct completes.
 		'This is called when BuyProduct completes.
@@ -165,21 +199,11 @@ Class MyWindow Extends Window
 			End
 			End
 			
 			
 		End
 		End
-		
 
 
 		_iap.OpenStore( _products )
 		_iap.OpenStore( _products )
 		
 		
 		_info="Opening store..."
 		_info="Opening store..."
-	End
-	
-	Method MakePurchase( product:Product )
 		
 		
-		Select product.Type
-		Case ProductType.Consumable
-			_purchases.SetNumber( product.Identifier,_purchases.GetNumber( product.Identifier )+1 )
-		Case ProductType.NonConsumable
-			_purchases.SetNumber( product.Identifier,1 )
-		End
 	End
 	End
 	
 	
 	Method LoadPurchases()
 	Method LoadPurchases()
@@ -216,7 +240,11 @@ Class MyWindow Extends Window
 
 
 		_listView.RemoveAllItems()
 		_listView.RemoveAllItems()
 		
 		
-		If _iap.Open
+		_restorePurchasesItem=Null
+		
+		_openStoreItem=Null
+		
+		If _iap?.Open
 		
 		
 			For Local product:=Eachin _products
 			For Local product:=Eachin _products
 				
 				
@@ -227,15 +255,16 @@ Class MyWindow Extends Window
 				_listView.AddItem( product.Title+" - "+product.Description+" for the low price of "+product.Price+" ("+_purchases.GetNumber( product.Identifier )+")" )
 				_listView.AddItem( product.Title+" - "+product.Description+" for the low price of "+product.Price+" ("+_purchases.GetNumber( product.Identifier )+")" )
 			Next
 			Next
 			
 			
-		Endif
+			_restorePurchasesItem=_listView.AddItem( "[RESTORE PURCHASES]" )
 			
 			
-		_listView.AddItem( "[RESTORE PURCHASES]" )
+		Endif
 		
 		
+		_openStoreItem=_listView.AddItem( "[REOPEN STORE]" )
 	End
 	End
 	
 	
 	Method OnRender( canvas:Canvas ) Override
 	Method OnRender( canvas:Canvas ) Override
 		
 		
-		App.RequestRender()
+		RequestRender()
 		
 		
 		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
 		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
 		
 		

+ 43 - 5
modules/iap/iap.monkey2

@@ -49,7 +49,7 @@ Class IAPStore
 	
 	
 	Method OpenStore( products:Product[] )
 	Method OpenStore( products:Product[] )
 		
 		
-		If _state>0 Return
+		If _state<>0 Return
 		
 		
 		_products=products
 		_products=products
 
 
@@ -57,20 +57,36 @@ Class IAPStore
 		
 		
 		App.Idle+=UpdateState
 		App.Idle+=UpdateState
 
 
-		_iap.OpenStoreAsync( _products )
+		If _iap.OpenStoreAsync( _products ) Return
+		
+		App.Idle-=UpdateState
+		
+		_state=0
+		
+		OpenStoreComplete( -1,Null,Null )
 	End
 	End
 	
 	
 	Method BuyProduct( product:Product )
 	Method BuyProduct( product:Product )
 		
 		
 		If _state<>1 Return
 		If _state<>1 Return
 		
 		
+		Print "_state="+_state
+		
 		_buying=product
 		_buying=product
 		
 		
 		_state=3
 		_state=3
 		
 		
 		App.Idle+=UpdateState
 		App.Idle+=UpdateState
 		
 		
-		_iap.BuyProductAsync( product )
+		If _iap.BuyProductAsync( _buying ) Return
+		
+		App.Idle-=UpdateState
+		
+		_buying=Null
+		
+		_state=1
+		
+		BuyProductComplete( -1,product )
 	End
 	End
 	
 	
 	Method GetOwnedProducts()
 	Method GetOwnedProducts()
@@ -81,7 +97,29 @@ Class IAPStore
 		
 		
 		App.Idle+=UpdateState
 		App.Idle+=UpdateState
 		
 		
-		_iap.GetOwnedProductsAsync()
+		If _iap.GetOwnedProductsAsync() Return
+		
+		App.Idle-=UpdateState
+		
+		_state=1
+		
+		GetOwnedProductsComplete( -1,Null )
+	End
+	
+	Method CloseStore()
+		
+		If _state<>1 Return
+		
+		_iap.CloseStore()
+		
+		_iap=Null
+		
+		_state=-1
+	End
+	
+	Function CanMakePayments:Bool()
+		
+		Return IAPStoreRep.CanMakePayments()
 	End
 	End
 	
 	
 	Private
 	Private
@@ -110,7 +148,7 @@ Class IAPStore
 		Case 2	'openstore
 		Case 2	'openstore
 			
 			
 			If result<0 _state=0
 			If result<0 _state=0
-			
+
 			Local interrupted:=New Stack<Product>
 			Local interrupted:=New Stack<Product>
 			Local owned:=New Stack<Product>
 			Local owned:=New Stack<Product>
 			For Local product:=Eachin _products
 			For Local product:=Eachin _products

+ 8 - 0
modules/iap/iap_android.monkey2

@@ -136,6 +136,9 @@ Class IAPStoreRep
 		Return Env.CallBooleanMethod( _instance,_getownedproductsasync,Null )
 		Return Env.CallBooleanMethod( _instance,_getownedproductsasync,Null )
 	End
 	End
 	
 	
+	Method CloseStore:Void()
+	End
+	
 	Method IsRunning:Bool()
 	Method IsRunning:Bool()
 		
 		
 		Return Env.CallBooleanMethod( _instance,_isrunning,Null )
 		Return Env.CallBooleanMethod( _instance,_isrunning,Null )
@@ -146,6 +149,11 @@ Class IAPStoreRep
 		Return Env.CallIntMethod( _instance,_getresult,Null )
 		Return Env.CallIntMethod( _instance,_getresult,Null )
 	End
 	End
 	
 	
+	Function CanMakePayments:Bool()
+		
+		Return True
+	End
+	
 	Private
 	Private
 	
 	
 	Global _class:jclass
 	Global _class:jclass

+ 3 - 0
modules/iap/iap_ios.monkey2

@@ -23,9 +23,12 @@ Class BBIAPStore="BBIAPStore"
 	Method BBOpenStoreAsync:Bool( products:BBProduct[] )="OpenStoreAsync"
 	Method BBOpenStoreAsync:Bool( products:BBProduct[] )="OpenStoreAsync"
 	Method BBBuyProductAsync:Bool( product:BBProduct )="BuyProductAsync"
 	Method BBBuyProductAsync:Bool( product:BBProduct )="BuyProductAsync"
 	Method GetOwnedProductsAsync:Bool()
 	Method GetOwnedProductsAsync:Bool()
+	Method CloseStore()
 	
 	
 	Method IsRunning:Bool()
 	Method IsRunning:Bool()
 	Method GetResult:Int()
 	Method GetResult:Int()
+		
+	Function CanMakePayments:Bool()
 End
 End
 
 
 public
 public

+ 3 - 0
modules/iap/native/iap_ios.h

@@ -63,10 +63,13 @@ struct BBIAPStore : public bbObject{
 	bool OpenStoreAsync( bbArray<bbGCVar<BBProduct>> products );
 	bool OpenStoreAsync( bbArray<bbGCVar<BBProduct>> products );
 	bool BuyProductAsync( BBProduct* product );
 	bool BuyProductAsync( BBProduct* product );
 	bool GetOwnedProductsAsync();
 	bool GetOwnedProductsAsync();
+	void CloseStore();
 	
 	
 	bool IsRunning();
 	bool IsRunning();
 	int GetResult();
 	int GetResult();
 	
 	
+	static bool CanMakePayments();
+	
 	BBProduct *FindProduct( bbString id );
 	BBProduct *FindProduct( bbString id );
 	void OnRequestProductDataResponse( SKProductsRequest *request,SKProductsResponse *response );
 	void OnRequestProductDataResponse( SKProductsRequest *request,SKProductsResponse *response );
 	void OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transactions );
 	void OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transactions );

+ 36 - 10
modules/iap/native/iap_ios.mm

@@ -53,10 +53,6 @@ BBProduct::~BBProduct(){
 
 
 BBIAPStore::BBIAPStore():_running( false ),_products( 0 ),_result( -1 ){
 BBIAPStore::BBIAPStore():_running( false ),_products( 0 ),_result( -1 ){
 
 
-	_delegate=[[BBIAPStoreDelegate alloc] initWithPeer:this];
-	
-	[[SKPaymentQueue defaultQueue] addTransactionObserver:_delegate];
-	
 	_priceFormatter=[[NSNumberFormatter alloc] init];
 	_priceFormatter=[[NSNumberFormatter alloc] init];
 	
 	
 	[_priceFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
 	[_priceFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
@@ -69,6 +65,12 @@ bool BBIAPStore::OpenStoreAsync( bbArray<bbGCVar<BBProduct>> products ){
 
 
 	if( ![SKPaymentQueue canMakePayments] ) return false;
 	if( ![SKPaymentQueue canMakePayments] ) return false;
 	
 	
+	if( !_delegate ){	
+		_delegate=[[BBIAPStoreDelegate alloc] initWithPeer:this];
+	
+		[[SKPaymentQueue defaultQueue] addTransactionObserver:_delegate];
+	}
+	
 	_products=products;
 	_products=products;
 	
 	
 	id __strong *objs=new id[products.length()];
 	id __strong *objs=new id[products.length()];
@@ -124,6 +126,15 @@ bool BBIAPStore::GetOwnedProductsAsync(){
 	return true;
 	return true;
 }
 }
 
 
+void BBIAPStore::CloseStore(){
+
+	if( !_delegate ) return;
+	
+	[[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
+
+	_delegate=0;
+}
+
 bool BBIAPStore::IsRunning(){
 bool BBIAPStore::IsRunning(){
 
 
 	return _running;
 	return _running;
@@ -134,6 +145,11 @@ int BBIAPStore::GetResult(){
 	return _result;
 	return _result;
 }
 }
 
 
+bool BBIAPStore::CanMakePayments(){
+
+	return [SKPaymentQueue canMakePayments];
+}
+
 BBProduct *BBIAPStore::FindProduct( bbString id ){
 BBProduct *BBIAPStore::FindProduct( bbString id ){
 
 
 	for( int i=0;i<_products.length();++i ){
 	for( int i=0;i<_products.length();++i ){
@@ -151,7 +167,7 @@ void BBIAPStore::OnRequestProductDataResponse( SKProductsRequest *request,SKProd
 	//Get product details
 	//Get product details
 	for( SKProduct *p in response.products ){
 	for( SKProduct *p in response.products ){
 	
 	
-		printf( "product=%p\n",p );fflush( stdout );
+//		printf( "product=%p\n",p );fflush( stdout );
 	
 	
 		BBProduct *prod=FindProduct( p.productIdentifier );
 		BBProduct *prod=FindProduct( p.productIdentifier );
 		if( !prod ) continue;
 		if( !prod ) continue;
@@ -175,7 +191,13 @@ void BBIAPStore::OnRequestProductDataResponse( SKProductsRequest *request,SKProd
 		_result=0;
 		_result=0;
 		break;
 		break;
 	}
 	}
-	
+
+	if( _result==-1 ){	
+		[[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
+
+		_delegate=0;
+	}
+
 	_running=false;
 	_running=false;
 }
 }
 
 
@@ -187,7 +209,7 @@ void BBIAPStore::OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transacti
 	
 	
 		if( transaction.transactionState==SKPaymentTransactionStatePurchased ){
 		if( transaction.transactionState==SKPaymentTransactionStatePurchased ){
 		
 		
-			printf( "IAP purchased\n" );fflush( stdout );
+//			printf( "IAP purchased\n" );fflush( stdout );
 			
 			
 			_result=0;
 			_result=0;
 			
 			
@@ -195,7 +217,7 @@ void BBIAPStore::OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transacti
 			
 			
 		}else if( transaction.transactionState==SKPaymentTransactionStateFailed ){
 		}else if( transaction.transactionState==SKPaymentTransactionStateFailed ){
 		
 		
-			printf( "IAP failed %i\n",transaction.error.code );fflush( stdout );
+//			printf( "IAP failed %i\n",transaction.error.code );fflush( stdout );
 			
 			
 			_result=(transaction.error.code==SKErrorPaymentCancelled) ? 1 : -1;
 			_result=(transaction.error.code==SKErrorPaymentCancelled) ? 1 : -1;
 			
 			
@@ -203,13 +225,13 @@ void BBIAPStore::OnUpdatedTransactions( SKPaymentQueue *queue,NSArray *transacti
 			
 			
 		}else if( transaction.transactionState==SKPaymentTransactionStateRestored ){
 		}else if( transaction.transactionState==SKPaymentTransactionStateRestored ){
 		
 		
-			printf( "IAP restored\n" );fflush( stdout );
+//			printf( "IAP restored\n" );fflush( stdout );
 			
 			
 			if( BBProduct *p=FindProduct( transaction.payment.productIdentifier ) ) p->owned=true;
 			if( BBProduct *p=FindProduct( transaction.payment.productIdentifier ) ) p->owned=true;
 		
 		
 		}else{
 		}else{
 		
 		
-			printf( "IAP ?????\n" );fflush( stdout );
+//			printf( "IAP ?????\n" );fflush( stdout );
 
 
 			continue;
 			continue;
 		}
 		}
@@ -227,6 +249,10 @@ void BBIAPStore::OnRestoreTransactionsFinished( SKPaymentQueue *queue,NSError *e
 
 
 void BBIAPStore::OnRequestFailed( SKRequest *request,NSError *error ){
 void BBIAPStore::OnRequestFailed( SKRequest *request,NSError *error ){
 
 
+	[[SKPaymentQueue defaultQueue] removeTransactionObserver:_delegate];
+
+	_delegate=0;
+
 	_running=false;
 	_running=false;
 }
 }