Difference between revisions of "Iab"

From GiderosMobile
m (Text replacement - "</source>" to "</syntaxhighlight>")
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
'''Interface usage is quite simple:'''
+
__NOTOC__
 +
<!-- GIDEROSOBJ:iab -->
 +
'''Supported platforms:''' [[File:Platform android.png]][[File:Platform ios.png]][[File:Platform winrt.png]]<br/>
 +
'''Available since:''' Gideros 2016.12<br/>
 +
'''Inherits from:''' [[EventDispatcher]]<br/>
 +
 
 +
=== Description ===
 +
The idea is to provide common In App Billing interface for most of available iap frameworks, so users could use in app purchases across platforms and iap frameworks with completely same or similar interface.
 +
 
 +
 
 +
'''What IAB Interface provides''':
 +
*Same API through all supported In-app billing frameworks on all platforms
 +
*Completely same workflow for all In-app Billing frameworks
 +
*Can dynamically detect which stores are installed on device and return the list to you in prioritized order, so you can have one single binary for all stores
 +
**Provides internal product ID usage through all In-app Billing frameworks, which might use different product IDs
 +
**Provides unique Receipt ID even if In-app Billing does not support it
 +
**Manages all the confirmation and consumption internally
 +
 
 +
 
 +
'''Interface usage is quite simple''':
 
* IAB.new(iabframework) ''-- initialize specified IAB framework''
 
* IAB.new(iabframework) ''-- initialize specified IAB framework''
  
Line 5: Line 24:
  
 
* IAB:setUp(value1, value2, ..., valueN) ''-- provide all the keys/devids/appids/etc needed for the framework, which you will get in same order on Native part in Map object''
 
* IAB:setUp(value1, value2, ..., valueN) ''-- provide all the keys/devids/appids/etc needed for the framework, which you will get in same order on Native part in Map object''
 +
 
* IAB:setProducts({internalId1 = "storeId1", internalId2 = "storeId2", ..., internalIdn = "storeIdn"}) ''-- provide list of products you will be using (key is your internal products id, value is store specific product id)''
 
* IAB:setProducts({internalId1 = "storeId1", internalId2 = "storeId2", ..., internalIdn = "storeIdn"}) ''-- provide list of products you will be using (key is your internal products id, value is store specific product id)''
 +
 
* IAB:setConsumables({"internalId1", "internalId2", ..., "internalIdn"}) ''-- which of your products are consumables, that people can buy many times (provide internal product ids)''
 
* IAB:setConsumables({"internalId1", "internalId2", ..., "internalIdn"}) ''-- which of your products are consumables, that people can buy many times (provide internal product ids)''
 +
 
* IAB:isAvailable() ''--check if IAB is available, raises event:''
 
* IAB:isAvailable() ''--check if IAB is available, raises event:''
 
** Event.AVAILABLE ''--iab is available''
 
** Event.AVAILABLE ''--iab is available''
 +
** Event.NOT_AVAILABLE ''--iab is NOT available''
 +
 
* IAB:requestProducts() ''--request information for products provided in setProducts method''
 
* IAB:requestProducts() ''--request information for products provided in setProducts method''
** Event.PRODUCT_COMPLETE
+
** Event.PRODUCTS_COMPLETE
 
*** event.productId
 
*** event.productId
 
*** event.title
 
*** event.title
 
*** event.description
 
*** event.description
 
*** event.price
 
*** event.price
** Event.PRODUCT_ERROR
+
** Event.PRODUCTS_ERROR
 
*** event.error
 
*** event.error
 +
 
* IAB:purchase(prodId) ''--purchase product by providing your internal product id, raises two events:''
 
* IAB:purchase(prodId) ''--purchase product by providing your internal product id, raises two events:''
 
** Event.PURCHASE_COMPLETE
 
** Event.PURCHASE_COMPLETE
Line 25: Line 50:
 
* iab:restore() ''--raise purchase events for each previously purchases entitled (not consumed) items, raises two events:''
 
* iab:restore() ''--raise purchase events for each previously purchases entitled (not consumed) items, raises two events:''
 
** Event.RESTORE_COMPLETE
 
** Event.RESTORE_COMPLETE
** Event.RESTORE_COMPLETE
+
** Event.RESTORE_ERROR
 
*** event.error
 
*** event.error
<source lang="lua">
 
</source>
 
  
===== '''Code example:''' =====
+
=== Example ===
<source lang="lua">
+
<syntaxhighlight lang="lua">
local test
+
if not tv then pcall(function() require "iab" end) end
if application:getDeviceInfo() == "Android" then
+
if IAB then
    test = IAB.new("google")
+
if android then
    test:setUp("keys")
+
if kindle then
elseif application:getDeviceInfo() == "iOS" then
+
iab=IAB.new("amazon")
    test = IAB.new("storekit")
+
iab:setProducts({
    test:setUp("keys")
+
credit50="credit_50",
 +
credit100="credit_100",
 +
credit500="credit_500",
 +
credit1000="credit_1000"
 +
})
 +
else
 +
iab=IAB.new("google")
 +
iab:setUp(googleLicence)
 +
iab:setProducts({
 +
credit50="credit50",
 +
credit100="credit100",
 +
credit500="credit500",
 +
credit1000="credit1000"
 +
})
 +
end
 +
elseif ios then
 +
iab=IAB.new("ios")
 +
iab:setProducts({
 +
credit50="credit50",
 +
credit100="credit100",
 +
credit500="credit500",
 +
credit1000="credit1000"
 +
})
 +
end
 +
 +
if iab then
 +
iab:setConsumables({"credit50","credit100","credit500","credit1000"})
 +
iab:addEventListener(Event.AVAILABLE,function(e)
 +
print("iab is available")
 +
iabCheck=false
 +
iab:requestProducts()
 +
end)
 +
 +
--usually here we would set a flag that it is possible to make purchases
 +
--basically you can allow doing all the iap stuff after this event is called
 +
 +
--[[ REQUESTING PRODUCTS ]]--
 +
--if this event is called, we received the list of products and information about them
 +
iab:addEventListener(Event.PRODUCTS_COMPLETE,function(e)
 +
print("Product list completed")
 +
for i = 1, #e.products do
 +
local p=e.products[i]
 +
--id, title, description and price
 +
print(p.productId,p.title,p.description,p.price)
 +
if p.productId=="fullgame" then
 +
iabCheck=true
 +
iabFullGame=false
 +
end
 +
for loop=1,#creditText do
 +
local c=creditText[loop]
 +
if p.productId==c[1] then
 +
c[2]=p.price
 +
c[3]=true
 +
end
 +
end
 +
end
 +
iab:restore()
 +
end)
 +
 +
--else we could not retrieve information about products now
 +
iab:addEventListener(Event.PRODUCTS_ERROR,function(e)
 +
print(e:getType(),e.error)
 +
end)
 +
 +
iab:addEventListener(Event.PURCHASE_COMPLETE,function(e)
 +
--purchases successfully completed
 +
--here you need to check if receiptId was not already saved previously
 +
--as in if purchase was not already made
 +
--then you can unlock the item here
 +
--and store receiptId presistently to know
 +
--that you have already provided this item to user
 +
print("Purchase completed")
 +
if remainingCredits<0 then remainingCredits=0 end
 +
if e.productId=="credit50" then
 +
remainingCredits+=50
 +
saveSettings()
 +
elseif e.productId=="credit100" then
 +
remainingCredits+=100
 +
saveSettings()
 +
elseif e.productId=="credit500" then
 +
remainingCredits+=500
 +
saveSettings()
 +
elseif e.productId=="credit1000" then
 +
remainingCredits+=1000
 +
saveSettings()
 +
elseif e.productId=="fullgame" then
 +
iabCheck=true
 +
iabFullGame=true
 +
end
 +
print(e:getType(),e.productId,e.receiptId)
 +
end)
 +
 +
iab:addEventListener(Event.PURCHASE_ERROR,function(e)
 +
--it was not possible to complete the purchase,
 +
--inform user
 +
--if e.error=="Unable to buy item (response: 7:Item Already Owned)" then
 +
iab:isAvailable()
 +
--end
 +
-- print(e:getType(),e.error)
 +
end)
 +
 +
iab:addEventListener(Event.RESTORE_COMPLETE,function(e)
 +
--restore successfully completed
 +
--here you need to check if receiptId was not already saved previously
 +
--as in if purchase was not already made
 +
--then you can unlock the item here
 +
--and store receiptId presistently to know
 +
--that you have already provided this item to user
 +
if iabCheck then
 +
fullgame=iabFullGame
 +
saveSettings()
 +
end
 +
print("restore complete")
 +
--iab:purchase("credit500")
 +
end)
 +
 +
iab:addEventListener(Event.RESTORE_ERROR,function(e)
 +
--it was not possible to complete the restore,
 +
--inform user
 +
-- print(e:getType(),e.error)
 +
 +
end)
 +
iab:isAvailable()
 +
-- iab:purchase("credit100")
 +
else
 +
print("iab provider not available")
 +
end
 +
else
 +
print("iab not available")
 
end
 
end
 
--and here comes completely same code for both frameworks to request products/buy stuff etc
 
 
test:addEventListener(Event.AVAILABLE, function(e)
 
--provide setup stuff (framework specific)
 
test:setUp("value1", "value2", "value3")
 
test:purchase("product1") --purchase something
 
end)
 
  
test:addEventListener(Event.PURCHASE_COMPLETE, function(e)
+
--To make a purchase I would:
--unlock your purchase here
+
--if iab then iab:purchase("credit50") end
print(e.productId, e.receiptId)
+
</syntaxhighlight>
test:confirm(e.productId)
 
end)
 
  
test:isAvailable()
+
{{GIDEROS IMPORTANT LINKS}}
test:restore()
 
</source>
 

Latest revision as of 14:28, 13 July 2023

Supported platforms: Platform android.pngPlatform ios.pngPlatform winrt.png
Available since: Gideros 2016.12
Inherits from: EventDispatcher

Description

The idea is to provide common In App Billing interface for most of available iap frameworks, so users could use in app purchases across platforms and iap frameworks with completely same or similar interface.


What IAB Interface provides:

  • Same API through all supported In-app billing frameworks on all platforms
  • Completely same workflow for all In-app Billing frameworks
  • Can dynamically detect which stores are installed on device and return the list to you in prioritized order, so you can have one single binary for all stores
    • Provides internal product ID usage through all In-app Billing frameworks, which might use different product IDs
    • Provides unique Receipt ID even if In-app Billing does not support it
    • Manages all the confirmation and consumption internally


Interface usage is quite simple:

  • IAB.new(iabframework) -- initialize specified IAB framework

Available frameworks: 'amazon', 'google', 'ios'

  • IAB:setUp(value1, value2, ..., valueN) -- provide all the keys/devids/appids/etc needed for the framework, which you will get in same order on Native part in Map object
  • IAB:setProducts({internalId1 = "storeId1", internalId2 = "storeId2", ..., internalIdn = "storeIdn"}) -- provide list of products you will be using (key is your internal products id, value is store specific product id)
  • IAB:setConsumables({"internalId1", "internalId2", ..., "internalIdn"}) -- which of your products are consumables, that people can buy many times (provide internal product ids)
  • IAB:isAvailable() --check if IAB is available, raises event:
    • Event.AVAILABLE --iab is available
    • Event.NOT_AVAILABLE --iab is NOT available
  • IAB:requestProducts() --request information for products provided in setProducts method
    • Event.PRODUCTS_COMPLETE
      • event.productId
      • event.title
      • event.description
      • event.price
    • Event.PRODUCTS_ERROR
      • event.error
  • IAB:purchase(prodId) --purchase product by providing your internal product id, raises two events:
    • Event.PURCHASE_COMPLETE
      • event.productId
      • event.receiptId
    • Event.PURCHASE_ERROR
      • event.error
  • iab:restore() --raise purchase events for each previously purchases entitled (not consumed) items, raises two events:
    • Event.RESTORE_COMPLETE
    • Event.RESTORE_ERROR
      • event.error

Example

if not tv then pcall(function() require "iab" end) end
if IAB then
	if android then
		if kindle then
			iab=IAB.new("amazon")
			iab:setProducts({
				credit50="credit_50",
				credit100="credit_100",
				credit500="credit_500",
				credit1000="credit_1000"
			})
		else
			iab=IAB.new("google")
			iab:setUp(googleLicence)
			iab:setProducts({
				credit50="credit50",
				credit100="credit100",
				credit500="credit500",
				credit1000="credit1000"
			})
		end
	elseif ios then
		iab=IAB.new("ios")
		iab:setProducts({
			credit50="credit50",
			credit100="credit100",
			credit500="credit500",
			credit1000="credit1000"
		})
	end
 
	if iab then
		iab:setConsumables({"credit50","credit100","credit500","credit1000"})
		iab:addEventListener(Event.AVAILABLE,function(e)
			print("iab is available")
			iabCheck=false
			iab:requestProducts()
		end)
 
		--usually here we would set a flag that it is possible to make purchases
		--basically you can allow doing all the iap stuff after this event is called
 
		--[[ REQUESTING PRODUCTS ]]--
		--if this event is called, we received the list of products and information about them
		iab:addEventListener(Event.PRODUCTS_COMPLETE,function(e)
			print("Product list completed")
			for i = 1, #e.products do
				local p=e.products[i]
				--id, title, description and price
				print(p.productId,p.title,p.description,p.price)
				if p.productId=="fullgame" then
					iabCheck=true
					iabFullGame=false
				end
				for loop=1,#creditText do
					local c=creditText[loop]
					if p.productId==c[1] then
						c[2]=p.price
						c[3]=true
					end
				end
			end
			iab:restore()
		end)
 
		--else we could not retrieve information about products now
		iab:addEventListener(Event.PRODUCTS_ERROR,function(e)
			print(e:getType(),e.error)
		end)
 
		iab:addEventListener(Event.PURCHASE_COMPLETE,function(e)
			--purchases successfully completed 
			--here you need to check if receiptId was not already saved previously
			--as in if purchase was not already made
			--then you can unlock the item here
			--and store receiptId presistently to know 
			--that you have already provided this item to user
			print("Purchase completed")
			if remainingCredits<0 then remainingCredits=0 end
			if e.productId=="credit50" then
				remainingCredits+=50
				saveSettings()
			elseif e.productId=="credit100" then
				remainingCredits+=100
				saveSettings()
			elseif e.productId=="credit500" then
				remainingCredits+=500
				saveSettings()
			elseif e.productId=="credit1000" then
				remainingCredits+=1000
				saveSettings()
			elseif e.productId=="fullgame" then
				iabCheck=true
				iabFullGame=true
			end
			print(e:getType(),e.productId,e.receiptId)
		end)
 
		iab:addEventListener(Event.PURCHASE_ERROR,function(e)
			--it was not possible to complete the purchase, 
			--inform user
			--if e.error=="Unable to buy item (response: 7:Item Already Owned)" then
				iab:isAvailable()
			--end
	--		print(e:getType(),e.error)
		end)
 
		iab:addEventListener(Event.RESTORE_COMPLETE,function(e)
			--restore successfully completed 
			--here you need to check if receiptId was not already saved previously
			--as in if purchase was not already made
			--then you can unlock the item here
			--and store receiptId presistently to know 
			--that you have already provided this item to user
			if iabCheck then
				fullgame=iabFullGame
				saveSettings()
			end
			print("restore complete")
			--iab:purchase("credit500")
		end)
 
		iab:addEventListener(Event.RESTORE_ERROR,function(e)
			--it was not possible to complete the restore, 
			--inform user
		--	print(e:getType(),e.error)
 
		end)
		iab:isAvailable() 
	--		iab:purchase("credit100")
	else	
		print("iab provider not available")
	end
else
	print("iab not available")
end

--To make a purchase I would:
--if iab then	iab:purchase("credit50") end