02-01-2012 09:29 AM
I am currently trying to implement in-app purchases into our app in order to provide the option to buy an additional feature.
We have uploaded a draft version into the App World and created a sandbox user. We have successfully bought the draft version on a test device with the sandbox user.
I was also able to successfully perform the in-app purchase with the sandbox user.
Our app usese the following code to check if the user has already purchased the additional feature:
public boolean isLocalPurchase() {
try {
ExistingPurchasesResult result = paymentEngine.getExistingPurchases(false);
Purchase[] resultPurchases = result.getPurchases();
if (resultPurchases != null) {
for (int i = 0; i < resultPurchases.length; i++) {
if (´_DG_SKU.equals(resultPurchases[i].getDigitalGood Sku())) {
return true;
}
}
}
} catch (PaymentException e) {
...
}
return false;
}
After the purchase this successfully returns true, even after a battery pull of the device. But if I turn off Mobile Network and WiFi on the device, the purchase is not found and I get the following error message:
"You do not have sufficient wireless coverage or your connection to the wireless network is turned off."
Isn't paymentEngine.getExistingPurchases(false) meant to perform a local check without connecting to the App World server? Why does it need any wireless coverage then?
But this is not the only problem. If I turn back on Mobile Network and WiFi afterwards, the local check now fails with a PaymentException and the message "Couldn't get get response from AppWorld". This also happens if I use paymentEngine.getExistingPurchases(true) instead. The boolean parameter doesn't seem to make a difference.
I then tried to simply buy the feature again. However this resulted in two NullPointerExceptions that are thrown by the Payment API. This is our code for the in-app purchase:
public boolean purchase() throws PaymentException {
PurchaseArgumentsBuilder arguments = new PurchaseArgumentsBuilder()
.withDigitalGoodSku(OUR_FEATURE_DG_SKU)
.withDigitalGoodName(OUR_FEATURE_DG_NAME)
.withPurchasingAppName(PURCHASING_APP_NAME);
try {
PurchaseResult purchaseResult = paymentEngine.purchase(arguments.build());
serviceRegistry.getLoggerService().debug("Status message: " + purchaseResult.getStatusMessage());
return purchaseResult.isSuccessful();
} catch (IllegalArgumentException e) {
serviceRegistry.getLoggerService().error("Purchase failed", e);
} catch (PaymentException e) {
serviceRegistry.getLoggerService().error("Purchase failed", e);
throw e;
}
return false;
}
And this is from the system log:
Name: NullPointerException GUID: 9c3cd62e3320b498 Time: Feb 01, 2012 14:51:20 No detail message net_rim_cldc(4D38A7C0) Hashtable put 0x5F0B OurApp-14(4F1EDAB4) a c 0x341 OurApp-14(4F1EDAB4) a <init> 0x42A OurApp-27(4F1EDAB4) h run 0xD5F OurApp-27(4F1EDAB4) a run 0x270 net_rim_cldc-2(4D38A7C0) Thread run 0xAAC9
Name: NullPointerException GUID: 9c3cd62e3320b498 Time: Feb 01, 2012 14:51:20 No detail message OurApp-15(4F1EDAB4) PaymentEngine <private> 0x2C8 OurApp-15(4F1EDAB4) PaymentEngine purchase 0x113 OurApp-2(4F1EDAB4) PurchaseServiceImpl purchase 0xA5E1 OurApp-5(4F1EDAB4) InAppPurchaseScreen fieldChanged 0x2EA8 net_rim_cldc-13(4D38A7C0) Field fieldChangeNotify 0xB2D net_rim_cldc-16(4D38A7C0) ButtonField <private> 0x85E1 net_rim_cldc-16(4D38A7C0) ButtonField trackwheelUnclick 0x84E4 net_rim_cldc-14(4D38A7C0) Manager trackwheelUnclick 0x265B net_rim_cldc-14(4D38A7C0) Manager trackwheelUnclick 0x265B net_rim_cldc-14(4D38A7C0) Screen trackwheelUnclick 0x91E7 net_rim_cldc-14(4D38A7C0) Screen dispatchNavigationEvent 0x6B8D net_rim_cldc-15(4D38A7C0) UiEngineImpl processMessage 0x6C3C net_rim_cldc-9(4D38A7C0) Application <private> 0x2D18 net_rim_cldc-9(4D38A7C0) Application processNextMessage 0x1C3E net_rim_cldc-9(4D38A7C0) Application enterEventDispatcher 0x1B63 OurApp-1(4F1EDAB4) OurApp main 0x69AD
Any ideas?
After a battery pull, paymentEngine.getExistingPurchases(false) correctly returns the purchase again, but the behavior described above is reproducable.
02-01-2012 03:52 PM
Hi there,
I will be looking into this issue in detail, seems like a few bugs may need to eb filed. In the meantime could you send me the following information:
1) Payment SDK being used
2) App World version being used
3) Device model and software version (I don't anticipate this being needed, so just if you happent to know)
Cheers,
02-02-2012 03:29 AM
1) 1.5
2) 3.1.0.60
3) Torch 9800, OS 6.0 [Platform: 6.4.0.211, App Version: 6.0.0.450 (1908)]
Is there any workaround for my problems? Should I do something different in the code?
Or is it a known problem that checking for in-app-purchases leads to errors when all connectivity is turned off on the device?
02-06-2012 02:05 PM
Sorry for the delayed response, I'm continuing to investigate but the devs I am working with are out of the office today.
02-08-2012 02:34 PM
Network connectivity is required to poll past purchases, even if doing so from cache. I'm investigating the full reason for this and will update once I have more info.
The second issue of restoring Mobile and WiFi and then queries failing does appear to be a bug. Please log in Issue Tracker and post back with the URL so I can begin investigating.
Regards,
02-10-2012 10:36 AM
Hi, I have created a new issue for it on the issue tracker:
https://www.blackberry.com/jira/browse/JAVAAPI-223
I think for the time being a workaround will be to always perform a check for network connectivity before calling any method from the Payment API. I will try this next week.
02-20-2012 08:08 AM - last edited on 02-20-2012 08:10 AM
I have now implemented a workaround for the errors. Before performing a purchase or restoring a purchase I check if coverage is available in order to prevent the bug from occurring.
When a purchase or a restore is successful I save this state in the PersistentStore so that I can perform a local check by checking the PersistentStore. No coverage is needed for this check and it should also be secure, because according to this article it should only be possible to log in with one BlackBerry ID per device. Changing the ID would require a security wipe of the device.
@gbeukeboom: Do you have any new information why network connectivity is required to poll past purchases or regarding the bug? So far there hasn't been any progress on the Issue Tracker.
02-21-2012 08:55 AM
Hi Hendrik,
Just got a response to this myself
. The network connectivity is required even when polling from cache as App World needs to make a call to the server to verify the identity of the application.
I will try to get to the Issue Tracker item this week.
Regardsm
02-22-2012 04:17 PM
> But this is not the only problem. If I turn back on Mobile Network and WiFi afterwards,
> the local check now fails with a PaymentException and the message
> "Couldn't get get response from AppWorld".
Just for the record - we did observe similar problem in the past, though I am not sure if we submitted a formal bug report.
If I remember correctly, problem is caused by
1. the client-server architecture (Payment SDK performs invocation API call in order to execute the actual code inside app world module) and
2. security imposed on some RuntimeStorage objects used internally during this communication (caller sets the object - allowing only specific modules to access it, server does not deletes the object when there is no network coverage, client cannot set it again on consequent API calls - gets Security Exception, but converts it to different error)
3. Once the problem is introduced, you need to do a battery pull in order to fix it (to clear RuntimeStorage)
Since we get very few in-app purchases, we decided to just log the problem and ignore it ...
Anyway there are probably 3-5 other serious problems that we have found in the Payment SDK - our feeling is that this SDK was assigned to a team of trainees and RIM does not actually care about it's quality (there is no formal QA etc.)
I plan to send a summary of all the problems to Alex, but I am not sure when I will manage to find the time.
02-22-2012 04:26 PM
Hi KraKra,
The Payment SDK group is experienced but there are always issues that will make it through to production. If you encounter any issues please log them to Issue Tracker which is the official bug reporting location for all BlackBerry development issues:
Without issues being reported it can be quite difficult to know what issues the community may be facing, I'm sure you would agree.
Regards,