in the create event of the very first object in my game which is persistent...
ini_open( "savedata.ini" );
global.NoAds = ini_read_real( "save1", "no_ads", false );
global.test1 = ini_read_real( "save1", "test1", false);
global.test2 = false;
ini_close();
In a game start event of that game object...
global.IAP_Enabled = false;
global.IAP_PurchaseID[0] = "5000_coins";
global.IAP_PurchaseID[1] = "10000_coins";
global.IAP_PurchaseID[2] = "no_ads";
global.IAP_PurchaseID[3] = "12000_coins";
global.IAP_PurchaseID[4] = "iap_001";
global.IAP_PurchaseID[5] = "iap_002";
global.CurrentTokens = ds_list_create();
global.CurrentProducts = ds_list_create();
// Attempt to connect to the store
var _init = GPBilling_ConnectToStore();
if _init == gpb_error_unknown
{
show_debug_message("ERROR - Billing API Has Not Connected!");
alarm[0] = room_speed * 10;
}
In the async iap event of that same object...
/// @description Insert description here
// You can write your code in this editor
var _eventId = async_load[? "id"];
switch (_eventId)
{
case gpb_store_connect:
// Store has connected so here you would generally add the products
global.IAP_Enabled = false;
GPBilling_AddProduct(global.IAP_PurchaseID[0]);
GPBilling_AddProduct(global.IAP_PurchaseID[1]);
GPBilling_AddProduct(global.IAP_PurchaseID[2]);//non-consumable remove ads
GPBilling_AddProduct(global.IAP_PurchaseID[3]);
GPBilling_AddProduct(global.IAP_PurchaseID[4]);//test iap non-consumable
GPBilling_AddProduct(global.IAP_PurchaseID[5]);//test iap non-consumable
// Etc… for all products
GPBilling_QueryProducts();
// Here you would also add any subscription products
// using the function GooglePlayBilling_AddSubscription().
// However, you would NOT call the function GPBilling_QuerySubscriptions()
// here if you have already queried products, but instead query
// the subscription in the appropriate Async Event (see the "Querying
// Products" section, below)
break;
case gpb_store_connect_failed:
// Store has failed to connect, so try again periodically
alarm[0] = room_speed * 10;
break;
case gpb_product_data_response:
// Retrieve the JSON object response string
var _json = async_load[? "response_json"];
var _map = json_decode(_json);
// Check if the query was successful
if _map[? "success"] == true
{
// Get the DS list of products and loop through them
var _plist = _map[? "skuDetails"];
for (var i = 0; i < ds_list_size(_plist); ++i;
{
// The skuDetails key contains a DS list where
// each list entry corresponds to a single
// product in DS map form. This DS map can be parsed
// to extract details like title, description and
// price, as shown in the example, below:
var _pmap = _plist[| i];
var _num = 0;
while(_pmap[? "productId"] != global.IAP_PurchaseID[_num])
{
++_num;
}
global.IAP_ProductData[_num, 0] = _pmap[? "productId"];
global.IAP_ProductData[_num, 1] = _pmap[? "price"];
global.IAP_ProductData[_num, 2] = _pmap[? "title"];
global.IAP_ProductData[_num, 3] = _pmap[? "decription"];
}
// Call the query function for subscriptions here, if required:
// GPBilling_QuerySubscriptions();
// If not required then query purchase data (this would be done
// in the subscription product query if those have been queried.
// Basically, all queries must be made sequentially with the
// purchase queries being done last.
var purchase_json = GPBilling_QueryPurchases(gpb_purchase_skutype_inapp);
global.IAP_Enabled = true;
var _plist = _map[? "skuDetails"];
for (var i = 0; i < ds_list_size(_plist); ++i;
{
// Any code required to store query information goes here
}
var _purchase_json = GPBilling_QueryPurchases(gpb_purchase_skutype_inapp);
var _purchase_map = json_decode(_purchase_json);
if _purchase_map[? "success"] == true
{
var _list = _purchase_map[? "purchases"];
var _sz = ds_list_size(_list);
for (var i = 0; i < _sz; ++i;
{
var _map = _list[| i];
if _map[? "purchaseState"] == 0
{
// Purchase has been made, so now get the product ID
// and unique "token" string to identify the purchase
var _pid = _map[? "productId"];
var _token = _map[? "purchaseToken"];
var _add = false;
// Check against existing purchase IDs
if _pid == global.IAP_PurchaseID[0]
{
// It's a consumable purchase that hasn't been used yet
// so call the consume function on it:
GPBilling_ConsumeProduct(_token);
_add = true;
}
if _pid == global.IAP_PurchaseID[1]
{
// It's a consumable purchase that hasn't been used yet
// so call the consume function on it:
GPBilling_ConsumeProduct(_token);
_add = true;
}
if _pid == global.IAP_PurchaseID[3]
{
// It's a consumable purchase that hasn't been used yet
// so call the consume function on it:
GPBilling_ConsumeProduct(_token);
_add = true;
}
if _pid == global.IAP_PurchaseID[2]//non-consumable remove ads
{
// It's a non-consumable purchase so check and see
// if it's been acknowledged yet:
if _map[? "acknowledged"] == 0
{
// It hasn't been acknowledged, so do that now:
GPBilling_AcknowledgePurchase(_token);
_add = true;
}
else
{
// Purchase has been acknowledged so here you
// you would check it and set any variables,
// for example "global.NoAds".
global.NoAds = true;
}
}
if _pid == global.IAP_PurchaseID[4]//TEST non-consumable remove ads
{
// It's a non-consumable purchase so check and see
// if it's been acknowledged yet:
if _map[? "acknowledged"] == 0
{
// It hasn't been acknowledged, so do that now:
GPBilling_AcknowledgePurchase(_token);
_add = true;
}
else
{
// Purchase has been acknowledged so here you
// you would check it and set any variables,
// for example "global.NoAds".
global.test1 = true;
}
}
if _pid == global.IAP_PurchaseID[5]//TEST non-consumable remove ads
{
// It's a non-consumable purchase so check and see
// if it's been acknowledged yet:
if _map[? "acknowledged"] == 0
{
// It hasn't been acknowledged, so do that now:
GPBilling_AcknowledgePurchase(_token);
_add = true;
}
else
{
// Purchase has been acknowledged so here you
// you would check it and set any variables,
// for example "global.NoAds".
global.test2 = true;
}
}
if _add
{
// add all purchase IDs and tokens into the relevant
// DS lists so they can be confirmed later
ds_list_add(global.CurrentTokens, _token);
ds_list_add(global.CurrentProducts, _pid);
}
}
}
}
ds_map_destroy(_purchase_map);
}
ds_map_destroy(_map);
break;
case gpb_iap_receipt:
// Get the JSON object response string
var _json = async_load[? "response_json"];
var _map = json_decode(_json);
// Check the response to see if it succeeded
if _map[? "success"] == true
{
// Check the purchases key for any outstanding product purchases
if ds_map_exists(_map, "purchases")
{
// Loop through the purchases list and parse each
// entry to get the purchase data DS map
var _plist = ds_map_find_value(_map, "purchases");
for (var i = 0; i < ds_list_size(_plist); ++i;
{
var _pmap = _plist[| i];
var _ptoken = _pmap[? "purchaseToken"];
var _sig = GPBilling_Purchase_GetSignature(_ptoken);
var _pjson = GPBilling_Purchase_GetOriginalJson(_ptoken);
var _pid = _map[? "productId"];
// Verify the purchase before consuming or acknowledging it
if GPBilling_Purchase_VerifySignature(_pjson, _sig)
{
if (_pid != global.IAP_PurchaseID[2] && _pid != global.IAP_PurchaseID[4] && _pid != global.IAP_PurchaseID[5])
{
GPBilling_ConsumeProduct(_ptoken);
}
if _pid == global.IAP_PurchaseID[2] then GPBilling_AcknowledgePurchase(_ptoken);
if _pid == global.IAP_PurchaseID[4] then GPBilling_AcknowledgePurchase(_ptoken);
if _pid == global.IAP_PurchaseID[5] then GPBilling_AcknowledgePurchase(); //i tried not putting _ptoken in this one to see if it made a difference
// If it is a durable product then you'd call
// GPBilling_AcknowledgePurchase();
ds_list_add(global.CurrentTokens, _ptoken);
ds_list_add(global.CurrentProducts, _pmap[? "productId"]);
}
}
}
}
ds_map_destroy(_map);
break;
case gpb_product_consume_response:
// Get the JSON object response string
var _json = async_load[? "response_json"];
var _map = json_decode(_json);
var _num = -1;
// Get the purchase token for the product that has been purchased
if ds_map_exists(_map, "purchaseToken")
{
// compare the response purchase token against the list
// of purchase token requests
for (var i = 0; i < ds_list_size(global.CurrentTokens); ++i;
{
// the response matches a token in the purchase check list
if _map[? "purchaseToken"] == global.CurrentTokens[| i]
{
// Find out what product the token refers to
if global.CurrentProducts[| i] == global.IAP_PurchaseID[0]
{
// Assign a reward according to the product being purchased
global.coins += 5000;
_num = i;
break;
}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[1]
{
// Assign a reward according to the product being purchased
global.coins += 10000;
_num = i;
break;
}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[3]
{
// Assign a reward according to the product being purchased
global.coins += 12000;
_num = i;
break;
}
// Check any other products here…
}
}
// Remove the purchased product and its purchase token
// from the appropriate check lists
if _num > -1
{
ds_list_delete(global.CurrentProducts, _num);
ds_list_delete(global.CurrentTokens, _num);
}
}
else
{
// Parse the error response codes here
// and react appropriately
}
ds_map_destroy(_map);
break;
case gpb_acknowledge_purchase_response:
var _map = json_decode(async_load[? "response_json"]);
var _num = -1;
// Check the response code to see if it has been successfully acknowledged
if _map[? "responseCode"] == 0
{
var _sz = ds_list_size(global.CurrentProducts);
// Loop through the products on the consumed/purchase list
// to find which one triggered this event
for (var i = 0; i < _sz; ++i;
{
if global.CurrentProducts[| i] == global.IAP_PurchaseID[2]
{
// The product has been found so enable/disable
// the feature it corresponds to
global.NoAds = true;
ini_open( "savedata.ini" );
ini_write_real( "save1", "no_ads", global.NoAds);
ini_close();
_num = i;
break;
}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[4]
{
// The product has been found so enable/disable
// the feature it corresponds to
global.test1 = true;
ini_open( "savedata.ini" );
ini_write_real( "save1", "test1", global.test1);
ini_close();
_num = i;
break;
}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[5]
{
// The product has been found so enable/disable
// the feature it corresponds to
global.test2 = true;
ini_open( "savedata.ini" );
ini_write_real( "save1", "test2", global.test2);
ini_close();
_num = i;
break;
}
// Add further checks for other products here if required…
}
// Remove the purchased product and its purchase token
// from the appropriate check lists
if _num > -1
{
ds_list_delete(global.CurrentProducts, _num);
ds_list_delete(global.CurrentTokens, _num);
}
}
else
{
// Parse the other response codes here
// and react appropriately
}
ds_map_destroy(_map);
break;
}
This is in the mouse_click event for the actual button to remove ads...
audio_play_sound (snd_clickbutton, 10, false);
if GPBilling_IsStoreConnected() && global.IAP_Enabled
{
var _chk = GPBilling_PurchaseProduct(global.IAP_PurchaseID[2]);
// alternatively, for subscriptions:
// var _chk = GPBilling_PurchaseSubscription(global.IAP_PurchaseID[0]);
if _chk != gpb_no_error
{
// Purchase unavailable, add failsafe code if required
}
}
if GPBilling_IsStoreConnected() && global.IAP_Enabled
{
var _chk = GPBilling_PurchaseProduct(global.IAP_PurchaseID[4]);
// alternatively, for subscriptions:
// var _chk = GPBilling_PurchaseSubscription(global.IAP_PurchaseID[0]);
if _chk != gpb_no_error
{
// Purchase unavailable, add failsafe code if required
}
}
if GPBilling_IsStoreConnected() && global.IAP_Enabled
{
var _chk = GPBilling_PurchaseProduct(global.IAP_PurchaseID[5]);
// alternatively, for subscriptions:
// var _chk = GPBilling_PurchaseSubscription(global.IAP_PurchaseID[0]);
if _chk != gpb_no_error
{
// Purchase unavailable, add failsafe code if required
}
}