iaptest.monkey2 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #rem
  2. IMPORTANT!
  3. 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.
  4. #end
  5. Namespace myapp
  6. #Import "<iap>"
  7. #Import "<std>"
  8. #Import "<mojo>"
  9. #Import "<mojox>"
  10. Using iap..
  11. Using std..
  12. Using mojo..
  13. Using mojox..
  14. Class MyWindow Extends Window
  15. Field _purchases:JsonObject
  16. Field _products:Product[]
  17. Field _info:String
  18. Field _listView:ListView
  19. Field _iap:IAPStore
  20. Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )
  21. Super.New( title,width,height,flags )
  22. Layout="stretch"
  23. 'Create our IAP products.
  24. '
  25. _products=New Product[](
  26. New Product( "speed_boost",ProductType.Consumable ),
  27. New Product( "bullet_boost",ProductType.Consumable ),
  28. New Product( "ship_upgrade",ProductType.NonConsumable ) )
  29. 'Load purchases we've alreday bought.
  30. '
  31. LoadPurchases()
  32. 'Create a ListView to fill in with products later...
  33. '
  34. _listView=New ListView
  35. _listView.Layout="float"
  36. _listView.Gravity=New Vec2f( .5,.5 )
  37. _listView.ItemClicked=Lambda( item:ListView.Item )
  38. If _iap.Busy Return
  39. Local index:= _listView.IndexOfItem( item )
  40. If index=_products.Length
  41. _iap.GetOwnedProducts()
  42. Return
  43. Endif
  44. Local product:=_products[ index ]
  45. 'it's actually harmless to let someone purchase a non consumable again, they'll
  46. 'only be charged for it once, but still...
  47. If product.Type=ProductType.NonConsumable And _purchases.GetNumber( product.Identifier )>0 Return
  48. _iap.BuyProduct( product )
  49. _info="Buying product "+product.Identifier
  50. End
  51. ContentView=_listView
  52. 'Create IAPStore and various handlers.
  53. '
  54. _iap=New IAPStore
  55. 'This isc alled when OpenStore completes.
  56. '
  57. _iap.OpenStoreComplete=Lambda( result:Int,interrupted:Product[],owned:Product[] )
  58. Select result
  59. Case 0
  60. 'Handle interrupted purchases - these are purchases that the user was charged for but your app never
  61. 'got notified about coz it or the OS crashed or something...
  62. '
  63. 'This array is always empty on ios which apparently handles this edge case better?
  64. '
  65. For Local product:=Eachin interrupted
  66. MakePurchase( product )
  67. Next
  68. 'Handle owned products - these are non-consumables that have been bought by the user. Android tracks these for
  69. '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
  70. 'uniformity we will on android too.
  71. '
  72. 'On Android, you never really need to use GetOwnProducts() because you are given this array of owned products when the store
  73. 'opens. So in a sense, android automatically 'restores purchases' whenever you open the store.
  74. '
  75. 'This array is always empty on ios. To restore non-consumables on ios you must call GetOwnedProducts in response to the push
  76. 'of a 'Restore Purchases' button or similar. Apps with IAP but no 'restore purchases' mechanism will be rejected from the
  77. 'app store. GetOwnedProducts may cause dialogs to appear etc as the user may need to log into itunes, which is why it's not
  78. 'just done by default when the store opens the way it is on android.
  79. '
  80. For Local product:=Eachin owned
  81. MakePurchase( product )
  82. Next
  83. SavePurchases()
  84. UpdateListView()
  85. _info="OpenStore successful"
  86. Default
  87. _info="OpenStore error:"+result
  88. End
  89. End
  90. 'This is called when BuyProduct completes.
  91. '
  92. _iap.BuyProductComplete=Lambda( result:Int,product:Product )
  93. Select result
  94. Case 0 'success!
  95. MakePurchase( product )
  96. SavePurchases()
  97. UpdateListView()
  98. _info="BuyProduct successful:"+product.Identifier
  99. Case 1 'cancelled!
  100. _info="BuyProduct cancelled:"+product.Identifier
  101. Default
  102. _info="BuyProduct error:"+result
  103. End
  104. End
  105. 'This is called when GetOwnProducts completes.
  106. '
  107. _iap.GetOwnedProductsComplete=Lambda( result:Int,owned:Product[] )
  108. Select result
  109. Case 0 'success!
  110. 'Make sure we really own all owned products.
  111. '
  112. For Local product:=Eachin owned
  113. MakePurchase( product )
  114. Next
  115. SavePurchases()
  116. UpdateListView()
  117. _info="GetOwnProducts successful"
  118. Default
  119. _info="GetOwnedProducts error:"+result
  120. End
  121. End
  122. _iap.OpenStore( _products )
  123. _info="Opening store..."
  124. End
  125. Method MakePurchase( product:Product )
  126. Select product.Type
  127. Case ProductType.Consumable
  128. _purchases.SetNumber( product.Identifier,_purchases.GetNumber( product.Identifier )+1 )
  129. Case ProductType.NonConsumable
  130. _purchases.SetNumber( product.Identifier,1 )
  131. End
  132. End
  133. Method LoadPurchases()
  134. 'load purchases file from internal app storage.
  135. '
  136. _purchases=JsonObject.Load( "internal::purchases.json" )
  137. 'if not found, create new purchases file.
  138. '
  139. If Not _purchases
  140. _purchases=New JsonObject
  141. For Local product:=Eachin _products
  142. _purchases.SetNumber( product.Identifier,0 )
  143. Next
  144. SavePurchases()
  145. Endif
  146. End
  147. Method SavePurchases()
  148. _purchases.Save( "internal::purchases.json" )
  149. end
  150. 'populate listview with products
  151. '
  152. Method UpdateListView()
  153. _listView.RemoveAllItems()
  154. If _iap.Open
  155. For Local product:=Eachin _products
  156. 'products become valid when store is opened.
  157. '
  158. 'If Not product.Valid Continue
  159. _listView.AddItem( product.Title+" - "+product.Description+" for the low price of "+product.Price+" ("+_purchases.GetNumber( product.Identifier )+")" )
  160. Next
  161. Endif
  162. _listView.AddItem( "[RESTORE PURCHASES]" )
  163. End
  164. Method OnRender( canvas:Canvas ) Override
  165. App.RequestRender()
  166. canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
  167. canvas.DrawText( "IAP info:"+_info,0,0 )
  168. End
  169. Method OnMeasure:Vec2i() Override
  170. Return New Vec2i( 640,360 )
  171. End
  172. End
  173. Function Main()
  174. New AppInstance
  175. New MyWindow
  176. App.Run()
  177. End