Difference between revisions of "Iab"

From GiderosMobile
m (Text replacement - "</source>" to "</syntaxhighlight>")
 
(14 intermediate revisions by 4 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/>
  
<source lang="lua">
+
=== Description ===
IAB.new(iabframework) -- initialize specified IAB framework
+
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.
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
 
IAB:requestProducts() --request information for products provided in setProducts method
 
Event.PRODUCT_COMPLETE
 
event.productId
 
event.title
 
event.description
 
event.price
 
Event.PRODUCT_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_COMPLETE
 
event.error
 
</source>
 
  
===== Code example: =====
+
 
<source lang="lua">
+
'''What IAB Interface provides''':
local test
+
*Same API through all supported In-app billing frameworks on all platforms
if application:getDeviceInfo() == "Android" then
+
*Completely same workflow for all In-app Billing frameworks
    test = IAB.new("google")
+
*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
    test:setUp("keys")
+
**Provides internal product ID usage through all In-app Billing frameworks, which might use different product IDs
elseif application:getDeviceInfo() == "iOS" then
+
**Provides unique Receipt ID even if In-app Billing does not support it
    test = IAB.new("storekit")
+
**Manages all the confirmation and consumption internally
    test:setUp("keys")
+
 
 +
 
 +
'''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 ===
 +
<syntaxhighlight lang="lua">
 +
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
 
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