Skip to content

Instantly share code, notes, and snippets.

Created June 17, 2013 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/82ce8dc6f8345e87ae9c to your computer and use it in GitHub Desktop.
Save anonymous/82ce8dc6f8345e87ae9c to your computer and use it in GitHub Desktop.
Verification of purchase of via IAP.
/*
* FreemiumPaymentManager.cpp
*
* Created on: 22.1.2013
* Author: tom
*/
#include "FreemiumPaymentManager.h"
#include <bb/cascades/Application>
#include <bb/cascades/Window>
#include <QSettings>
#include <bb/platform/CancelSubscriptionReply>
#include <bb/platform/ExistingPurchasesReply>
#include <bb/platform/PriceReply>
#include <bb/platform/PurchaseReceipt>
#include <bb/platform/PurchaseReply>
#include <bb/platform/SubscriptionStatusReply>
#include <bb/platform/SubscriptionTermsReply>
using namespace bb::platform;
//#define __DEBUG
FreemiumPaymentManager::FreemiumPaymentManager(QString virtualGoodsId, QObject* parent = 0) :
QObject(parent),
mPaymentManager(new PaymentManager(this)),
mCurrentStatus(tr("Payment System Init"))
{
const QString windowGroupId = bb::cascades::Application::instance()->mainWindow()->groupId();
mVirtualGoodsId = virtualGoodsId;
mPaymentManager->setWindowGroupId(windowGroupId);
#ifdef __DEBUG
mPaymentManager->setConnectionMode(PaymentConnectionMode::Test);
#endif
}
bool FreemiumPaymentManager::localStatus() {
QSettings settings;
return settings.value(SETTINGS_KEY_STATUS_CHECKED, QVariant(false)).toBool();
}
void FreemiumPaymentManager::checkStatus() {
QSettings settings;
mCurrentStatus = tr("Checking settings");
// if there was successful check before
if (localStatus()) {
// emit status stored in QSettings
reportPremiumStatus(settings.value(SETTINGS_KEY_PREMIUM_STATUS, QVariant(false)).toBool());
mCurrentStatus = tr("Approved according settings");
} else {
// start checking in App World
emit showPleaseWaitMessage();
mCurrentStatus = tr("Requesting status from cache");
const ExistingPurchasesReply *reply = mPaymentManager->requestExistingPurchases(false);
connect(reply, SIGNAL(finished()), SLOT(localPurchasesCheckFinished()));
}
}
void FreemiumPaymentManager::askBBWorldServer() {
emit showPleaseWaitMessage();
const ExistingPurchasesReply *reply = mPaymentManager->requestExistingPurchases(true);
connect(reply, SIGNAL(finished()), SLOT(remotePurchasesCheckFinished()));
}
void FreemiumPaymentManager::localPurchasesCheckFinished() {
bb::platform::ExistingPurchasesReply *reply = qobject_cast<bb::platform::ExistingPurchasesReply*>(sender());
Q_ASSERT(reply);
mCurrentStatus = tr("Got cached response from server");
//emits error signal upon errors.
if (reply->isError()) {
qDebug() << "Existing purchases response error (local). Code(" << reply->errorCode() << ") Text(" << reply->errorText() << ")";
mCurrentStatus = tr("Local errors, asking BB World online.");
askBBWorldServer();
//emits success signal upon success
} else {
mCurrentStatus = tr("Got cached response.");
qDebug() << "Existing purchases response success (local).";
const QList<PurchaseReceipt> receipts = reply->purchases();
if (receipts.isEmpty()) {
mCurrentStatus = tr("Denied according cached response. Asking BB World online.");
qDebug() << "Existing purchases response success (local). (No purchases)";
askBBWorldServer();
} else {
mCurrentStatus = tr("Approved online.");
rememberPremiumStatus(true);
}
}
reply->deleteLater();
hidePleaseWaitMessage();
}
void FreemiumPaymentManager::remotePurchasesCheckFinished() {
qDebug() << "Remote purchase check finished...";
bb::platform::ExistingPurchasesReply *reply = qobject_cast<bb::platform::ExistingPurchasesReply*>(sender());
Q_ASSERT(reply);
//emits error signal upon errors.
if (reply->isError()) {
#ifdef __DEBUG
// this solves situation when local testing fails while remote request comes. Should never be in production code!
rememberPremiumStatus(false);
#else
qDebug() << "Existing purchases response error (remote). Code(" << reply->errorCode() << ") Text(" << reply->errorText() << ")";
mCurrentStatus = tr("Error asking online.");
emit errorOccured(reply->errorCode(), reply->errorText());
#endif
//emits success signal upon success
} else {
qDebug() << "Existing purchases response success (remote).";
const QList<PurchaseReceipt> receipts = reply->purchases();
if (receipts.isEmpty()) {
qDebug() << "Existing purchases response success (remote). (No purchases)";
mCurrentStatus = tr("Denied according online response.");
rememberPremiumStatus(false);
} else {
mCurrentStatus = tr("Approved according online response.");
rememberPremiumStatus(true);
}
}
reply->deleteLater();
hidePleaseWaitMessage();
}
void FreemiumPaymentManager::reportPremiumStatus(bool isPremium) {
emit freemiumStatusUpdated(isPremium);
}
void FreemiumPaymentManager::rememberPremiumStatus(bool isPremium) {
QSettings settings;
// remember everything
settings.setValue(SETTINGS_KEY_STATUS_CHECKED, QVariant(true));
settings.setValue(SETTINGS_KEY_PREMIUM_STATUS, isPremium);
// send signal
reportPremiumStatus(isPremium);
}
PurchaseInvokationResult FreemiumPaymentManager::purchase() {
QSettings settings;
bool statusKnown = settings.value(SETTINGS_KEY_STATUS_CHECKED, QVariant(false)).toBool();
// if current status is known
if (statusKnown) {
bool alreadyPurchased = settings.value(SETTINGS_KEY_PREMIUM_STATUS, QVariant(false)).toBool();
if (!alreadyPurchased) {
const PurchaseReply *reply = mPaymentManager->requestPurchase(mVirtualGoodsId);
connect(reply, SIGNAL(finished()), SLOT(purchaseResponse()));
return PurchaseInvoked;
} else {
return AlreadyPurchased;
}
} else {
// current status is not known lets fail
return CurrentStatusUnknown;
}
}
void FreemiumPaymentManager::purchaseResponse() {
bb::platform::PurchaseReply *reply = qobject_cast<bb::platform::PurchaseReply*>(sender());
Q_ASSERT(reply);
//emits error signal upon errors.
if (reply->isError()) {
qDebug() << "Purchase response error. Code(" << reply->errorCode() << ") Text(" << reply->errorText() << ")";
emit purchaseErrorOccured(reply->errorCode(), reply->errorText());
//emits success signal upon success
} else {
qDebug() << "Purchase successful!";
rememberPremiumStatus(true);
}
reply->deleteLater();
}
/*
* FreemiumPaymentManager.h
*
* Created on: 22.1.2013
* Author: tom
*/
#ifndef FREEMIUMPAYMENTMANAGER_H_
#define FREEMIUMPAYMENTMANAGER_H_
#define SETTINGS_KEY_STATUS_CHECKED "iapStatusChecked"
#define SETTINGS_KEY_PREMIUM_STATUS "iapPremiumStatus"
#include <QObject>
#include <bb/platform/PaymentManager>
enum PurchaseInvokationResult {
PurchaseInvoked = 0,
AlreadyPurchased = 1 ,
CurrentStatusUnknown = 2
};
class FreemiumPaymentManager : public QObject {
Q_OBJECT
public:
FreemiumPaymentManager(QString virtualGoodsId, QObject *parent);
QString currentStatus() {
return mCurrentStatus;
}
void checkStatus();
PurchaseInvokationResult purchase();
bool localStatus();
signals:
void showPleaseWaitMessage();
void hidePleaseWaitMessage();
void freemiumStatusUpdated(bool proEnabled);
void errorOccured(int errorCode, QString errorMessage);
void purchaseErrorOccured(int errorCode, QString errorMessage);
private slots:
void localPurchasesCheckFinished();
void remotePurchasesCheckFinished();
void purchaseResponse();
private:
void askBBWorldServer();
void reportPremiumStatus(bool isPremium);
void rememberPremiumStatus(bool isPremium);
bb::platform::PaymentManager *mPaymentManager;
QString mVirtualGoodsId;
QString mCurrentStatus;
};
#endif /* FREEMIUMPAYMENTMANAGER_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment