Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Payment Service

Reply
BlackBerry Development Advisor (Retired)
gbeukeboom
Posts: 2,559
Registered: ‎10-16-2009
My Device: BlackBerry Z10
My Carrier: Bell

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

Hi Andre,

 

How was the app loaded to the device? In order to test using PaymentManager::setConnectionMode(PaymentConnectionMode::smileytongue:roduction); the app needs to be installed via BlackBerry World.

Garett
@garettBeuk
--
Goodbye everybody!
Please use plain text.
Contributor
ajochems
Posts: 33
Registered: ‎01-12-2011
My Device: Torch

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

When i deploy from Momentics IDE to Dev Alpha device with PaymentConnectionMode:: Test i can do a purchase and then check with requestExistingPurchases(false) without any problem. I can readout the receipt and everything works fine. I then do the following:

- I change to PaymentConnectionMode:: Production

- I upload a new draft version to appworld

- I remove the Momentics installed version of the app

- I go to Settings -> Development Mode in AppWorld on the Dev Alpha

- I enter 20321769 as ID which is my app id

- I download and install the app

If i now try the same i will never receive any finished signals on doing either requestPurchase or requestExistingPurchases calls. I you would like to test i can add you as sandbox user to my application? Just sent me an email to andre'at'jochems.com

Please use plain text.
BlackBerry Development Advisor (Retired)
gbeukeboom
Posts: 2,559
Registered: ‎10-16-2009
My Device: BlackBerry Z10
My Carrier: Bell

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

I've tested but can't see much of how the app is functioning in the back end based on my tests.

 

Could you post up a snippet of the code used for the purchase, verification of purchase and retrieval of past purchased goods?

Garett
@garettBeuk
--
Goodbye everybody!
Please use plain text.
Contributor
ajochems
Posts: 33
Registered: ‎01-12-2011
My Device: Torch

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

In my last version i reverted back to the finished() signals instead of the purchaseFinished and existingPurchasesFinished signals because that change i tried to see if it solved the problem but it did not, so now i am back to the code as in the samples.

 

During application initialisation i execute:

// Instantiate a new PaymentManager instance and connect signals to slots
m_paymentManager = new PaymentManager(this);
// Get the window group ID and pass it to the PaymentService instance.
const QString windowGroupId = bb::cascades::Application::instance()->mainWindow()->groupId();
m_paymentManager->setWindowGroupId(windowGroupId);

 Then for purchase i have:

void LogoMania::purchaseFullVersion()
{
	// Define the Virtual Good ID in the appstore
	QString goodID = "20485923";
	qDebug()<<"#### Buy Good ID: " << goodID;
	SystemToast *toast = new SystemToast(this);
	toast->setBody("Connecting to payment manager for Good ID: " + goodID);
	toast->show();
	// request purchase
	const PurchaseReply *reply = m_paymentManager->requestPurchase(goodID);
	connect(reply, SIGNAL(finished()), SLOT(purchaseResponse()));
}

void LogoMania::purchaseResponse()
{
	bb::platform::PurchaseReply *reply = qobject_cast<bb::platform::PurchaseReply*>(sender());
	Q_ASSERT(reply);
    qDebug() << "### purchaseResponse() isError(): " << reply->isError();
    SystemToast *toast = new SystemToast(this);
	toast->setBody("Payment Service answer received.");
	toast->show();
	//emits error signal upon errors.
	if (reply->isError()) {
			// emit error signal
			qDebug() << "Emit Purchase Error Signal";
			emit infoResponseError(reply->errorCode(), reply->errorText(), "Purchase Error, no receipt");
	} else {
		const QString purchaseDateString = reply->receipt().date().toString();
		qDebug() << "Receipt: " << receiptToString(reply->receipt());
		saveFullVersionAndUnlock(purchaseDateString);
		// emit succes signal
		qDebug() << "Emit Purchase Success Signal";
		emit purchaseResponseSuccess(purchaseDateString);
	}
	reply->deleteLater();
}

 And for existing purchases check i have:

void LogoMania::checkPreviousPurchase()
{
	qDebug() << "### Check for existing purchases";
	// if not full version and not already checked than check for previous purchase
	qDebug() << "### Connect to payment manager";
	SystemToast *toast = new SystemToast(this);
    toast->setBody("Connecting to payment manager.");
	toast->show();
	//Request the existing purchases from the Payment Services server.
	bool refresh = false;
	const ExistingPurchasesReply *reply = m_paymentManager->requestExistingPurchases(refresh);
	connect(reply, SIGNAL(finished()), SLOT(handleExistingPurchases()));
}

void LogoMania::handleExistingPurchases()
{
	bb::platform::ExistingPurchasesReply *reply = qobject_cast<bb::platform::ExistingPurchasesReply*>(sender());
	Q_ASSERT(reply);
	qDebug() << "### handleExistingPurchases() isError(): " << reply->isError();
	SystemToast *toast = new SystemToast(this);
	toast->setBody("Payment Service answer received.");
	toast->show();
	QString receiptString = "No Receipt yet";
	if(!reply->purchases().isEmpty()){
		receiptString = receiptToString(reply->purchases().first());
	}
	// Emit an error signal if there were errors.
	if (reply->isError()) {
		QString errorMsg = "### Existing Purchases response error. Code(" + QString(reply->errorCode())  + ") Text(" + reply->errorText() + ")";
		qDebug() << errorMsg;
		SystemToast *toast = new SystemToast(this);
		toast->setBody(errorMsg);
		toast->show();
		// emit error signal
		qDebug() << "### Emit Purchase Error Signal";
		emit infoResponseError(reply->errorCode(), reply->errorText(), receiptString);
	//Emit a success signal if there were no errors.
	} else {
		qDebug() << "### Purchase check OK";
		// update checked parameter
		const QList<PurchaseReceipt> receipts = reply->purchases();
		if (!receipts.isEmpty()) {
			qDebug()<<"### Number of receipts: "<<receipts.size();
			QString displayString = "Number of receipts: " + QString(receipts.size())+ "\n";
			Q_FOREACH(PurchaseReceipt r, receipts) {
				displayString += (receiptToString(r) + "\n");
			}
			qDebug()<<"### Receipts: " << displayString;
			toast->setBody(displayString);
			toast->show();
			const QString purchaseDateString = receipts.first().date().toString();
			if(receipts.first().state() == DigitalGoodState::Owned){
				if(!lstUserdata.value("payedVersion").toBool()){
					qDebug()<<"### Good state Owned,  saveFullVersionAndUnlock";
					saveFullVersionAndUnlock(purchaseDateString);
					// emit success signal
					emit purchaseResponseSuccess(purchaseDateString);
				}
			} else {
				qDebug()<<"### Good state not Owned";
				// emit error signal
				emit infoResponseError(receipts.first().state(), "Game no longer owned", displayString);
			}
		} else {
			qDebug()<<"### Receipts isEmpty";
			toast->setBody("No receipts found.");
			toast->show();
		}
	}
	reply->deleteLater();
}

 Both functions are called from QML, i have the object made available with:

qml->setContextProperty("_logoMania", this);

 And call the functions from QML with:

_logoMania.purchaseFullVersion();
_logoMania.checkPreviousPurchase();

 

Please use plain text.
BlackBerry Development Advisor (Retired)
gbeukeboom
Posts: 2,559
Registered: ‎10-16-2009
My Device: BlackBerry Z10
My Carrier: Bell

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

I don't see any real issues with the code posted below. The only part where I see an error could occur would be with calls like this:
const PurchaseReply *reply = m_paymentManager->requestPurchase(goodID);

 

According to the docs the requestPurchase() call could return 0 if a failure occurs. With this in mind I have never seen this failure occur and I have also just tested this in another app that I have in sandbox mode and verified the purchase retrieval works as expected.

 

I think the next step would be to see if you could provide a small sample app that reproduces this issue? Please also let me know which SDK version was used to create the app.

 

From the sample I can test and verify if somethign strange may be going on.

Garett
@garettBeuk
--
Goodbye everybody!
Please use plain text.
Contributor
ajochems
Posts: 33
Registered: ‎01-12-2011
My Device: Torch

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

Can i just create any sample app and upload it as draft to appworld? I will try that. I am currently on SDK 10.0.10.738. By the way, how can requestPurchase return 0 if it returns a PurchaseReply object? Could you sent me your test application that does work?

 

Kind Regards,

Andre

Please use plain text.
BlackBerry Development Advisor (Retired)
gbeukeboom
Posts: 2,559
Registered: ‎10-16-2009
My Device: BlackBerry Z10
My Carrier: Bell

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

This is the one I used:

https://github.com/blackberry/Cascades-Samples/tree/master/paymentservice

 

You can either add the same goods to your portal or modify the XML file to use your goods.

Garett
@garettBeuk
--
Goodbye everybody!
Please use plain text.
Contributor
ajochems
Posts: 33
Registered: ‎01-12-2011
My Device: Torch

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

Ok i made a test application with the sample code using my own digital good id's and that is working as expected. I now am completely rewriting the Payment Service code to incorporate the PaymentServiceControl object as it is used in the sample. 

 

There is one thing i have not clear yet and that is the exact function of the refresh boolean of the m_paymentManager->requestExistingPurchases(refresh) call.

 

What will happen in production if refresh is true and if refresh is false?

 

Kind Regards,

Andre

Please use plain text.
BlackBerry Development Advisor (Retired)
gbeukeboom
Posts: 2,559
Registered: ‎10-16-2009
My Device: BlackBerry Z10
My Carrier: Bell

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

Hi Andre,

 

Passing in false to requestExistingPurchases() results in the app asking the BlackBerry World Client to check its cache to see if any purchases have been made.

 

Passing in true to requestExistingPurchases() results in the app asking the BlackBerry World Client to check with the BlackBerry World Server records to see if any purchases have been made.

 

The "false" method is much quicker but will miss scenarios where the user switches devices or has just re-installed the app. So if "false" returns nothing you may want to call the same method using "true".

Garett
@garettBeuk
--
Goodbye everybody!
Please use plain text.
Contributor
ajochems
Posts: 33
Registered: ‎01-12-2011
My Device: Torch

Re: Does the App with the Payment Service code need to be in App World to test properly in BB10 Cascades?

Hi,

Well finally some progress, i uploaded the new version as draft and now in sandbox mode i do receive the finished() signal. I had set refresh to true and now i get and error (instead of an empty receipts object which i would expect):

Code: 3 Text: The parent application could not be located within the reconcile cache

What does that mean.

Please use plain text.