• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!
  • Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Android Problems with the updated In App Purchase

S

Schekhovtsov

Guest
Hello. The Google Play Services extension has recently been updated, and with it, the in-app purchase has changed a lot. There is an official code change guide, but there are errors in it, and apparently the code does not work. Has anyone been able to configure to a working state? Maybe there is a more understandable guide?
 
B

booksmaster

Guest
I tried to make the ios version work. And it almost works but with a major bug. Still waiting for stuff to reply.
 

Appsurd

Member
I tried both Android and iOS. The help center article contained lots of textual errors, which I have reported en have been fixed already. At the end, I got Android working for 100% but wasn't able to test iOS properly, which I will do somewhere next week
 
L

leenio

Guest
Please, can you help me? @Appsurd

I don't know what to do to make it work, I tried everything I could, but the code it's doing nothing. Except, I proved drawing the variable that at least the store connected, but nothing else. Here is my code:

Async

var _eventId = async_load[? "id"];
switch (_eventId)
{
case gpb_store_connect:
global.IAP_Enabled = true;
GPBilling_AddProduct(global.quilmcha_compra[0]);
GPBilling_QueryProducts();
break;

case gpb_store_connect_failed:
alarm[0]= 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.quilmcha_compra[_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);
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.quilmcha_compra[0]
{
// 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;
}
}
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);
// Verify the purchase before consuming or acknowledging it
if GPBilling_Purchase_VerifySignature(_pjson, _sig)
{
//GPBilling_ConsumeProduct(_ptoken);
// If it is a durable product then you'd call
GPBilling_AcknowledgePurchase(_ptoken);
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.quilmcha_compra[0]
{
// Assign a reward according to the product being purchased
quilmcha_book = 93102837473398474023;
_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.quilmcha_compra[0]
{
// The product has been found so enable/disable
// the feature it corresponds to
quilmcha_book = 93102837473398474023;
_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;


}

I know it's long, I tried to replicate the guide as much as I could. Thank you so much!
 

Appsurd

Member
When things don't work, but you won't exactly know why, use debug messages! For example, call
show_debug_message(_eventId) at line 2 to find out which case of the switch event is triggering.
Secondly, everywhere you have a json, try show_debug_message(_json) to see what response you are getting.
Thirdly, when posting code on the forums, use [ code] and end with [/ code][/code]. This prevents strange ;)-characters in your code :)

Now you should be able to find out what the problem is. If not, please post the result of the debug messages here
 
Top