Hello guys,
I have problem with IAP, I don´t get how they works. I want to have only 1 DURABLE IAP and nothing else, but I´m testing more than 1.
I used https://help.yoyogames.com/hc/en-us/articles/360031457831-Android-Google-Play-Billing-IAPs- as guide, but nothing is happening.
#1 Problem
If I want to purchase: android.test.purchased - LOG will say ERROR 7 - That should mean Failure to purchase since item is already owned.
If I want to purchase: ID_TEST_FOR_GAME - NOT REAL - LOG will say ERROR 4 - Requested product is not available for purchase.
#2 Problem
Is that http_* really neccesary?
#3 Problem
Should that state be 0 or 1? Is there typo in documentation?
I don´t know how to get that work, where I have an error?
Am I missing something?
Can you guys help me please? I really don´t know how to make it work.
Thank you
I have problem with IAP, I don´t get how they works. I want to have only 1 DURABLE IAP and nothing else, but I´m testing more than 1.
I used https://help.yoyogames.com/hc/en-us/articles/360031457831-Android-Google-Play-Billing-IAPs- as guide, but nothing is happening.
#1 Problem
If I want to purchase: android.test.purchased - LOG will say ERROR 7 - That should mean Failure to purchase since item is already owned.
If I want to purchase: ID_TEST_FOR_GAME - NOT REAL - LOG will say ERROR 4 - Requested product is not available for purchase.
#2 Problem
Is that http_* really neccesary?
#3 Problem
Should that state be 0 or 1? Is there typo in documentation?
Code:
if _map[? "purchaseState"] == 0
I don´t know how to get that work, where I have an error?
Am I missing something?
Can you guys help me please? I really don´t know how to make it work.
Code:
global.IAP_ProductData = 0;
global.CurrentTokens = 0;
global.CurrentProducts = 0;
global.Durable = 0;
global.IAP_PurchaseID[0] = "android.test.purchased";
global.IAP_PurchaseID[1] = "ID_TEST_FOR_GAME - NOT REAL";
etc...
Code:
var _eventId = async_load[? "id"];
switch (_eventId) {
#region gpb_store_connect
//Add products after store is connected
case gpb_store_connect: {
log(string("IAP - CASE - gpb_store_connect "));
//Product #1
GPBilling_AddProduct(global.IAP_PurchaseID[0]);
log(string("IAP - PRODUCT ADD - ")+string(global.IAP_PurchaseID[0]));
//Product #2
GPBilling_AddProduct(global.IAP_PurchaseID[1]);
log(string("IAP - PRODUCT ADD - ")+string(global.IAP_PurchaseID[1]));
//Product #3
GPBilling_AddProduct(global.IAP_PurchaseID[2]);
log(string("IAP - PRODUCT ADD - ")+string(global.IAP_PurchaseID[2]));
//Product #4
GPBilling_AddProduct(global.IAP_PurchaseID[3]);
log(string("IAP - PRODUCT ADD - ")+string(global.IAP_PurchaseID[3]));
//Query
alarm[5] = time_in_seconds(1); // Query products
break;
}
#endregion
#region gpb_store_connect_failed
//Fail to connect to IAP STORE
case gpb_store_connect_failed: {
log(string("IAP - CASE - gpb_store_connect_failed "));
}
#endregion
#region gpb_product_data_response
case gpb_product_data_response: {
//QUERY PRODUCTS
log(string("IAP - CASE - gpb_product_data_response #1"));
// Retrieve the JSON object response string
var _map = json_decode(async_load[? "response_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;){
var _pmap = _plist[| i];
var _num = 0;
while(_pmap[? "productId"] != global.IAP_PurchaseID[_num])
{
++_num;
}
//Informations about products
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[? "description"];
log(string("IAP - QUERY - PRODUCT DATA ADDED "));
}
global.iapStatus = true;
}
ds_map_destroy(_map);
//QUERY PURCHASES
log(string("IAP - CASE - gpb_product_data_response #2 "));
var _map = json_decode(async_load[? "response_json"]);
if _map[? "success"] == 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_map = json_decode(GPBilling_QueryPurchases(gpb_purchase_skutype_inapp));
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;
log("IAP - ALREADY ACKNOWLEDGED - " + string(_pid) +string(" = ") + string(_map[? "acknowledged"]));
// Check against existing purchase IDs
if _pid == global.IAP_PurchaseID[0]{if _map[? "acknowledged"] == 0 {GPBilling_AcknowledgePurchase(_token);_add = true;}};
log(string("IAP - ACKNOWLEDGE - " + string(global.IAP_PurchaseID[0])));
if _pid == global.IAP_PurchaseID[1]{if _map[? "acknowledged"] == 0 {GPBilling_AcknowledgePurchase(_token);_add = true;}};
log(string("IAP - ACKNOWLEDGE - " + string(global.IAP_PurchaseID[1])));
if _pid == global.IAP_PurchaseID[2]{if _map[? "acknowledged"] == 0 {GPBilling_AcknowledgePurchase(_token);_add = true;}};
log(string("IAP - ACKNOWLEDGE - " + string(global.IAP_PurchaseID[2])));
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;
}
#endregion
#region gpb_iap_receipt
case gpb_iap_receipt:
log(string("IAP - CASE - gpb_iap_receipt "));
var _map = json_decode(async_load[? "response_json"]);
if _map[? "success"] == true {
log(string("IAP - CASE - gpb_iap_receipt - MAP SUCCESS "));
// 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);
if GPBilling_Purchase_VerifySignature(_pjson, _sig) {
log(string("IAP - CASE - gpb_iap_receipt - ACKNOWLEDGE PURCHASE" + string(_ptoken)));
GPBilling_AcknowledgePurchase(_ptoken);
ds_list_add(global.CurrentTokens, _ptoken);
ds_list_add(global.CurrentProducts, _pmap[? "productId"]);
}
}
}
} else {
if _map[? "responseCode"] == -3 {log("IAP - RESPONSE CODE (-3) - The request has reached the maximum timeout before Google Play responds");}
if _map[? "responseCode"] == -2 {log("IAP - RESPONSE CODE (-2) - Requested feature is not supported by Play Store on the current device.");}
if _map[? "responseCode"] == -1 {log("IAP - RESPONSE CODE (-1) - The Play Store service is not connected currently");}
if _map[? "responseCode"] == +1 {log("IAP - RESPONSE CODE (+1) - User has cancelled the action");}
if _map[? "responseCode"] == +2 {log("IAP - RESPONSE CODE (+2) - Network connection is down");}
if _map[? "responseCode"] == +4 {log("IAP - RESPONSE CODE (+4) - Requested product is not available for purchase");}
if _map[? "responseCode"] == +6 {log("IAP - RESPONSE CODE (+6) - Fatal error during the API action");}
if _map[? "responseCode"] == +7 {log("IAP - RESPONSE CODE (+7) - Failure to purchase since item is already owned");}
if _map[? "responseCode"] == +8 {log("IAP - RESPONSE CODE (+8) - Failure to consume since item is not owned");}
}
ds_map_destroy(_map);
break;
#endregion
#region gpb_acknowledge_purchase_response
case gpb_acknowledge_purchase_response:
log(string("IAP - 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);
for (var i = 0; i < _sz; ++i;)
{
if global.CurrentProducts[| i] == global.IAP_PurchaseID[0]{global.Durable = true;_num = i;break;}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[1]{global.Durable = true;_num = i;break;}
if global.CurrentProducts[| i] == global.IAP_PurchaseID[2]{global.Durable = true;_num = i;break;}
}
// 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
{
//ERRORS
}
ds_map_destroy(_map);
break;
#endregion
}
}
Thank you