Merge lp:~alecu/pay-ui/euro-and-more into lp:pay-ui

Proposed by Alejandro J. Cura
Status: Merged
Approved by: dobey
Approved revision: 72
Merged at revision: 63
Proposed branch: lp:~alecu/pay-ui/euro-and-more
Merge into: lp:pay-ui
Diff against target: 763 lines (+229/-92)
8 files modified
app/payui.qml (+21/-19)
backend/modules/payui/network.cpp (+76/-14)
backend/modules/payui/network.h (+10/-5)
backend/modules/payui/purchase.cpp (+23/-24)
backend/modules/payui/purchase.h (+7/-6)
backend/tests/mock_click_server.py (+14/-5)
backend/tests/test_network.cpp (+76/-17)
manifest.json (+2/-2)
To merge this branch: bzr merge lp:~alecu/pay-ui/euro-and-more
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
dobey (community) Approve
Diego Sarmentero (community) Approve
Review via email: mp+236792@code.launchpad.net

Commit message

Support for currencies other than USD

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
Revision history for this message
dobey (dobey) :
review: Needs Fixing
lp:~alecu/pay-ui/euro-and-more updated
71. By Alejandro J. Cura

Make the pay-ui handle suggested currencies just like the click scope

72. By Alejandro J. Cura

Update maintainer

Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/payui.qml'
--- app/payui.qml 2014-09-29 22:27:29 +0000
+++ app/payui.qml 2014-10-02 18:57:25 +0000
@@ -56,6 +56,7 @@
56 property bool purchasing: false56 property bool purchasing: false
57 property bool recentLogin: false57 property bool recentLogin: false
58 property bool cancellable: true58 property bool cancellable: true
59 property string suggestedCurrency: "USD"
5960
60 backgroundColor: "transparent"61 backgroundColor: "transparent"
6162
@@ -88,20 +89,17 @@
88 id: purchase89 id: purchase
8990
90 onItemDetailsObtained: {91 onItemDetailsObtained: {
91 var loc_c = Qt.locale("C");92 suggestedCurrency = currency;
92 // This string comes from a json double, and must be parsed with C locale
93 var pnum = Number.fromLocaleString(loc_c, price);
94
95 var loc = Qt.locale();
96 checkout.itemTitle = title;93 checkout.itemTitle = title;
97 checkout.itemSubtitle = publisher;94 checkout.itemSubtitle = publisher;
98 checkout.price = pnum.toLocaleCurrencyString(loc, "US$");95 checkout.price = formatted_price;
99 payment.itemTitle = title;96 payment.itemTitle = title;
100 payment.itemSubtitle = publisher;97 payment.itemSubtitle = publisher;
101 payment.price = pnum.toLocaleCurrencyString(loc, "US$");98 payment.price = formatted_price;
102 direct.itemTitle = title;99 direct.itemTitle = title;
103 direct.itemSubtitle = publisher;100 direct.itemSubtitle = publisher;
104 direct.price = pnum.toLocaleCurrencyString(loc, "US$");101 direct.price = formatted_price;
102 checkCredentials();
105 }103 }
106104
107 onPaymentTypesObtained: {105 onPaymentTypesObtained: {
@@ -190,10 +188,14 @@
190 if (mainView.state == "online-accounts") {188 if (mainView.state == "online-accounts") {
191 purchase.checkItemPurchased();189 purchase.checkItemPurchased();
192 } else if (mainView.state != "checkout" && !mainView.purchasing && mainView.state != "buy-interaction") {190 } else if (mainView.state != "checkout" && !mainView.purchasing && mainView.state != "buy-interaction") {
193 purchase.getPaymentTypes();191 purchase.getPaymentTypes(suggestedCurrency);
194 }192 }
195 }193 }
196194
195 onItemNotPurchased: {
196 purchase.getPaymentTypes(suggestedCurrency);
197 }
198
197 onCredentialsNotFound: {199 onCredentialsNotFound: {
198 mainView.recentLogin = false;200 mainView.recentLogin = false;
199 if (mainView.state == "online-accounts") {201 if (mainView.state == "online-accounts") {
@@ -286,7 +288,7 @@
286288
287 onRetry: {289 onRetry: {
288 mainView.showLoading();290 mainView.showLoading();
289 purchase.checkCredentials();291 purchase.getItemDetails();
290 }292 }
291293
292 onClose: {294 onClose: {
@@ -301,7 +303,7 @@
301303
302 onRetry: {304 onRetry: {
303 mainView.showLoading();305 mainView.showLoading();
304 purchase.checkCredentials();306 purchase.getItemDetails();
305 }307 }
306308
307 onClose: {309 onClose: {
@@ -316,7 +318,7 @@
316318
317 onRetry: {319 onRetry: {
318 mainView.showLoading();320 mainView.showLoading();
319 purchase.checkCredentials();321 purchase.getItemDetails();
320 }322 }
321323
322 onClose: {324 onClose: {
@@ -360,7 +362,7 @@
360 Component.onCompleted: {362 Component.onCompleted: {
361 showLoading();363 showLoading();
362 mainView.createDB();364 mainView.createDB();
363 purchase.checkCredentials();365 purchase.getItemDetails();
364 }366 }
365367
366 onCurrentPageChanged: {368 onCurrentPageChanged: {
@@ -400,17 +402,17 @@
400 mainView.purchasing = true;402 mainView.purchasing = true;
401 mainView.cancellable = false;403 mainView.cancellable = false;
402 showLoading();404 showLoading();
403 purchase.buyItem(email, password, otp, direct.paymentId, direct.backendId, mainView.recentLogin);405 purchase.buyItem(email, password, otp, suggestedCurrency, direct.paymentId, direct.backendId, mainView.recentLogin);
404 } else if (direct.hasPayments && direct.hasPreferredPayment) {406 } else if (direct.hasPayments && direct.hasPreferredPayment) {
405 mainView.purchasing = true;407 mainView.purchasing = true;
406 mainView.cancellable = false;408 mainView.cancellable = false;
407 showLoading();409 showLoading();
408 purchase.buyItemWithPreferredPayment(email, password, otp, mainView.recentLogin);410 purchase.buyItemWithPreferredPayment(email, password, otp, suggestedCurrency, mainView.recentLogin);
409 } else if (direct.hasStoredPayment) {411 } else if (direct.hasStoredPayment) {
410 var values = mainView.getLastPayment();412 var values = mainView.getLastPayment();
411 var backendid = values[0];413 var backendid = values[0];
412 var paymentid = values[1];414 var paymentid = values[1];
413 purchase.buyItem(email, password, otp, paymentid, backendid, mainView.recentLogin);415 purchase.buyItem(email, password, otp, suggestedCurrency, paymentid, backendid, mainView.recentLogin);
414 } else {416 } else {
415 mainView.state = "checkout";417 mainView.state = "checkout";
416 pageStack.push(checkout);418 pageStack.push(checkout);
@@ -439,7 +441,7 @@
439 }441 }
440442
441 if (mainView.recentLogin) {443 if (mainView.recentLogin) {
442 purchase.buyItem(email, "", "", paymentId, backendId, mainView.recentLogin);444 purchase.buyItem(email, "", "", suggestedCurrency, paymentId, backendId, mainView.recentLogin);
443 } else {445 } else {
444 mainView.cancellable = true;446 mainView.cancellable = true;
445 mainView.purchasing = false;447 mainView.purchasing = false;
@@ -458,7 +460,7 @@
458460
459 onAddCreditCard: {461 onAddCreditCard: {
460 webkit.title = i18n.tr("Add Payment");462 webkit.title = i18n.tr("Add Payment");
461 webkit.url = purchase.getAddPaymentUrl();463 webkit.url = purchase.getAddPaymentUrl(suggestedCurrency);
462 mainView.state = "add-payment";464 mainView.state = "add-payment";
463 pageStack.push(webkit);465 pageStack.push(webkit);
464 }466 }
@@ -494,7 +496,7 @@
494 onPurchaseSucceeded: {496 onPurchaseSucceeded: {
495 if (mainView.state == "add-payment") {497 if (mainView.state == "add-payment") {
496 showLoading();498 showLoading();
497 purchase.getPaymentTypes();499 purchase.getPaymentTypes(suggestedCurrency);
498 } else {500 } else {
499 purchase.quitSuccess();501 purchase.quitSuccess();
500 }502 }
501503
=== modified file 'backend/modules/payui/network.cpp'
--- backend/modules/payui/network.cpp 2014-09-25 20:46:48 +0000
+++ backend/modules/payui/network.cpp 2014-10-02 18:57:25 +0000
@@ -36,6 +36,7 @@
36#define PAY_PURCHASES_PATH "/purchases"36#define PAY_PURCHASES_PATH "/purchases"
37#define PAY_PAYMENTMETHODS_PATH "/paymentmethods"37#define PAY_PAYMENTMETHODS_PATH "/paymentmethods"
38#define PAY_PAYMENTMETHODS_ADD_PATH PAY_PAYMENTMETHODS_PATH + "/add"38#define PAY_PAYMENTMETHODS_ADD_PATH PAY_PAYMENTMETHODS_PATH + "/add"
39#define SUGGESTED_CURRENCY_HEADER_NAME "X-Suggested-Currency"
3940
40#define PREFERED_PAYMENT_TYPE "0"41#define PREFERED_PAYMENT_TYPE "0"
41#define PAYMENT_TYPES "1"42#define PAYMENT_TYPES "1"
@@ -90,6 +91,42 @@
90 m_service.setCredentials(token);91 m_service.setCredentials(token);
91}92}
9293
94QMap<QString, QString> buildCurrencyMap()
95{
96 /* NOTE: The list of currencies we need to handle mapping symbols of.
97 * Please keep this list in A-Z order.
98 */
99 QMap<QString, QString> currencies_map {
100 { "CNY", "RMB"},
101 { "EUR", "€"},
102 { "GBP", "₤"},
103 { "HKD", "HK$"},
104 { "TWD", "TW$"},
105 { "USD", "US$"},
106 };
107 return currencies_map;
108}
109
110const QString DEFAULT_CURRENCY {"USD"};
111
112QString Network::getSymbolForCurrency(const QString &currency_code)
113{
114 static QMap<QString, QString> currency_map = buildCurrencyMap();
115
116 if (currency_map.contains(currency_code)) {
117 return currency_map[currency_code];
118 } else{
119 return currency_code;
120 }
121}
122
123bool Network::isSupportedCurrency(const QString& currency_code)
124{
125 static QMap<QString, QString> currency_map = buildCurrencyMap();
126
127 return currency_map.contains(currency_code);
128}
129
93void Network::onReply(QNetworkReply *reply)130void Network::onReply(QNetworkReply *reply)
94{131{
95 QVariant statusAttr = reply->attribute(132 QVariant statusAttr = reply->attribute(
@@ -167,10 +204,26 @@
167 QJsonObject object = document.object();204 QJsonObject object = document.object();
168 QString title = object.value("title").toString();205 QString title = object.value("title").toString();
169 QString publisher = object.value("publisher").toString();206 QString publisher = object.value("publisher").toString();
170 QString price = QString::number(object.value("price").toDouble());
171 QString icon = object.value("icon_url").toString();207 QString icon = object.value("icon_url").toString();
172208
173 Q_EMIT itemDetailsObtained(title, publisher, price, icon);209 QJsonObject prices = object.value("prices").toObject();
210 QString suggested_currency = DEFAULT_CURRENCY;
211 QString currency = DEFAULT_CURRENCY;
212 if (reply->hasRawHeader(SUGGESTED_CURRENCY_HEADER_NAME)) {
213 suggested_currency = reply->rawHeader(SUGGESTED_CURRENCY_HEADER_NAME);
214 }
215 const char* env_value = std::getenv(CURRENCY_ENVVAR);
216 if (env_value != NULL) {
217 suggested_currency = env_value;
218 }
219
220 if (isSupportedCurrency(suggested_currency) && prices.contains(suggested_currency)) {
221 currency = suggested_currency;
222 }
223 double price = prices[currency].toDouble();
224 QLocale locale;
225 QString formatted_price = locale.toCurrencyString(price, getSymbolForCurrency(currency));
226 Q_EMIT itemDetailsObtained(title, publisher, currency, formatted_price, icon);
174 } else if (state->operation.contains(CHECK_PURCHASED)) {227 } else if (state->operation.contains(CHECK_PURCHASED)) {
175 Q_EMIT buyItemSucceeded(); 228 Q_EMIT buyItemSucceeded();
176 } else {229 } else {
@@ -182,22 +235,25 @@
182 } else if (httpStatus == 401 || httpStatus == 403) {235 } else if (httpStatus == 401 || httpStatus == 403) {
183 Q_EMIT authenticationError();236 Q_EMIT authenticationError();
184 } else if (httpStatus == 404 && state->operation.contains(CHECK_PURCHASED)) {237 } else if (httpStatus == 404 && state->operation.contains(CHECK_PURCHASED)) {
185 requestPaymentTypes();238 Q_EMIT itemNotPurchased();
186 } else {239 } else {
187 Q_EMIT error(QString::number(httpStatus));240 Q_EMIT error(QString::number(httpStatus));
188 }241 }
189 reply->deleteLater();242 reply->deleteLater();
190}243}
191244
192void Network::requestPaymentTypes()245void Network::requestPaymentTypes(const QString& currency)
193{246{
194 QNetworkRequest request;247 QNetworkRequest request;
195 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");248 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
196 QString url = getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_PATH + "/";249 QUrl url(getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_PATH + "/");
197 qDebug() << "Request Payment Types:" << url;250 QUrlQuery query;
198 signRequestUrl(request, url);251 query.addQueryItem("currency", currency);
252 url.setQuery(query);
253 qDebug() << "Request Payment Types:" << url.toString();
254 signRequestUrl(request, url.toString());
199 request.setRawHeader("Accept", "application/json");255 request.setRawHeader("Accept", "application/json");
200 request.setUrl(QUrl(url));256 request.setUrl(url);
201 RequestObject* reqObject = new RequestObject(QString(PAYMENT_TYPES));257 RequestObject* reqObject = new RequestObject(QString(PAYMENT_TYPES));
202 request.setOriginatingObject(reqObject);258 request.setOriginatingObject(reqObject);
203 m_nam.get(request);259 m_nam.get(request);
@@ -210,12 +266,14 @@
210}266}
211267
212void Network::buyItemWithPreferredPaymentType(const QString& email, const QString& password, const QString& otp,268void Network::buyItemWithPreferredPaymentType(const QString& email, const QString& password, const QString& otp,
213 const QString& appid, const QString& itemid, bool recentLogin)269 const QString& appid, const QString& itemid, const QString& currency,
270 bool recentLogin)
214{271{
215 m_selectedPaymentId = m_preferred->paymentId();272 m_selectedPaymentId = m_preferred->paymentId();
216 m_selectedBackendId = m_preferred->backendId();273 m_selectedBackendId = m_preferred->backendId();
217 m_selectedAppId = appid;274 m_selectedAppId = appid;
218 m_selectedItemId = itemid;275 m_selectedItemId = itemid;
276 m_currency = currency;
219 if (recentLogin) {277 if (recentLogin) {
220 purchaseProcess();278 purchaseProcess();
221 } else {279 } else {
@@ -226,13 +284,14 @@
226284
227void Network::buyItem(const QString& email, const QString& password,285void Network::buyItem(const QString& email, const QString& password,
228 const QString& otp,286 const QString& otp,
229 const QString& appid, const QString& itemid,287 const QString& appid, const QString& itemid, const QString& currency,
230 const QString& paymentId, const QString& backendId, bool recentLogin)288 const QString& paymentId, const QString& backendId, bool recentLogin)
231{289{
232 m_selectedPaymentId = paymentId;290 m_selectedPaymentId = paymentId;
233 m_selectedBackendId = backendId;291 m_selectedBackendId = backendId;
234 m_selectedAppId = appid;292 m_selectedAppId = appid;
235 m_selectedItemId = itemid;293 m_selectedItemId = itemid;
294 m_currency = currency;
236 if (recentLogin) {295 if (recentLogin) {
237 purchaseProcess();296 purchaseProcess();
238 } else {297 } else {
@@ -252,6 +311,7 @@
252 serializer.insert("name", m_selectedAppId);311 serializer.insert("name", m_selectedAppId);
253 serializer.insert("backend_id", m_selectedBackendId);312 serializer.insert("backend_id", m_selectedBackendId);
254 serializer.insert("method_id", m_selectedPaymentId);313 serializer.insert("method_id", m_selectedPaymentId);
314 serializer.insert("currency", m_currency);
255 QJsonDocument doc(serializer);315 QJsonDocument doc(serializer);
256316
257 QByteArray content = doc.toJson();317 QByteArray content = doc.toJson();
@@ -304,14 +364,16 @@
304 request.setRawHeader("Authorization", sign.toUtf8());364 request.setRawHeader("Authorization", sign.toUtf8());
305}365}
306366
307QString Network::getAddPaymentUrl()367QString Network::getAddPaymentUrl(const QString& currency)
308{368{
309 QString baseUrl = getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_ADD_PATH + "/";369 QUrl baseUrl(getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_ADD_PATH + "/");
370 QUrlQuery query;
371 query.addQueryItem("currency", currency);
372 baseUrl.setQuery(query);
310 qDebug() << "Get Add Payment URL:" << baseUrl;373 qDebug() << "Get Add Payment URL:" << baseUrl;
311 QString sign = m_token.signUrl(baseUrl, QStringLiteral("GET"), true);374 QString sign = m_token.signUrl(baseUrl.toString(), QStringLiteral("GET"), true);
312 QUrl signedUrl(baseUrl);375 QUrl signedUrl(baseUrl);
313 signedUrl.setQuery(sign);376 signedUrl.setQuery(sign);
314
315 return signedUrl.toString();377 return signedUrl.toString();
316}378}
317379
318380
=== modified file 'backend/modules/payui/network.h'
--- backend/modules/payui/network.h 2014-09-11 03:10:25 +0000
+++ backend/modules/payui/network.h 2014-10-02 18:57:25 +0000
@@ -38,6 +38,7 @@
38constexpr static const char* PAY_BASE_URL_ENVVAR{"PAY_BASE_URL"};38constexpr static const char* PAY_BASE_URL_ENVVAR{"PAY_BASE_URL"};
39constexpr static const char* PAY_BASE_URL{"https://software-center.ubuntu.com"};39constexpr static const char* PAY_BASE_URL{"https://software-center.ubuntu.com"};
40constexpr static const char* PAY_API_ROOT{"/api/2.0/click"};40constexpr static const char* PAY_API_ROOT{"/api/2.0/click"};
41constexpr static const char* CURRENCY_ENVVAR {"U1_SEARCH_CURRENCY"};
4142
42class RequestObject : public QObject43class RequestObject : public QObject
43{44{
@@ -58,26 +59,28 @@
58public:59public:
59 explicit Network(QObject *parent = 0);60 explicit Network(QObject *parent = 0);
6061
61 void requestPaymentTypes();62 void requestPaymentTypes(const QString& currency);
62 void buyItem(const QString& email, const QString& password,63 void buyItem(const QString& email, const QString& password,
63 const QString& otp, const QString& appid,64 const QString& otp, const QString& appid,
64 const QString& itemid, const QString& paymentId,65 const QString& itemid, const QString& currency, const QString& paymentId,
65 const QString& backendId, bool recentLogin);66 const QString& backendId, bool recentLogin);
66 void buyItemWithPreferredPaymentType(const QString& email, const QString& password,67 void buyItemWithPreferredPaymentType(const QString& email, const QString& password,
67 const QString& otp,68 const QString& otp,
68 const QString& appid, const QString& itemid,69 const QString& appid, const QString& itemid, const QString& currency,
69 bool recentLogin);70 bool recentLogin);
70 void getItemInfo(const QString &packagename);71 void getItemInfo(const QString &packagename);
71 void checkPassword(const QString& email, const QString& password,72 void checkPassword(const QString& email, const QString& password,
72 const QString& otp);73 const QString& otp);
73 void getCredentials();74 void getCredentials();
74 void setCredentials(Token token);75 void setCredentials(Token token);
75 QString getAddPaymentUrl();76 QString getAddPaymentUrl(const QString& currency);
76 QDateTime getTokenUpdated();77 QDateTime getTokenUpdated();
77 void checkItemPurchased(const QString& appid);78 void checkItemPurchased(const QString& appid);
79 static QString getSymbolForCurrency(const QString& currency_code);
80 static bool isSupportedCurrency(const QString& currency_code);
7881
79Q_SIGNALS:82Q_SIGNALS:
80 void itemDetailsObtained(QString title, QString publisher, QString price, QString icon);83 void itemDetailsObtained(QString title, QString publisher, QString currency, QString formatted_price, QString icon);
81 void paymentTypesObtained(QVariantList payments);84 void paymentTypesObtained(QVariantList payments);
82 void buyItemSucceeded();85 void buyItemSucceeded();
83 void buyItemFailed();86 void buyItemFailed();
@@ -90,6 +93,7 @@
90 void noPreferredPaymentMethod();93 void noPreferredPaymentMethod();
91 void loginError(const QString& message);94 void loginError(const QString& message);
92 void twoFactorAuthRequired();95 void twoFactorAuthRequired();
96 void itemNotPurchased();
9397
94private Q_SLOTS:98private Q_SLOTS:
95 void onReply(QNetworkReply*);99 void onReply(QNetworkReply*);
@@ -107,6 +111,7 @@
107 QString m_selectedBackendId;111 QString m_selectedBackendId;
108 QString m_selectedAppId;112 QString m_selectedAppId;
109 QString m_selectedItemId;113 QString m_selectedItemId;
114 QString m_currency;
110 bool m_startPurchase = false;115 bool m_startPurchase = false;
111116
112 QString getAPIUrl(QString urlKey, QString defaultValue);117 QString getAPIUrl(QString urlKey, QString defaultValue);
113118
=== modified file 'backend/modules/payui/purchase.cpp'
--- backend/modules/payui/purchase.cpp 2014-09-11 03:10:25 +0000
+++ backend/modules/payui/purchase.cpp 2014-10-02 18:57:25 +0000
@@ -38,6 +38,8 @@
38 this, &Purchase::loginError);38 this, &Purchase::loginError);
39 connect(&m_network, &Network::twoFactorAuthRequired,39 connect(&m_network, &Network::twoFactorAuthRequired,
40 this, &Purchase::twoFactorAuthRequired);40 this, &Purchase::twoFactorAuthRequired);
41 connect(&m_network, &Network::itemNotPurchased,
42 this, &Purchase::itemNotPurchased);
4143
42 QCoreApplication* instance = QCoreApplication::instance();44 QCoreApplication* instance = QCoreApplication::instance();
43 Logger::setupLogging();45 Logger::setupLogging();
@@ -74,30 +76,27 @@
7476
75void Purchase::checkCredentials()77void Purchase::checkCredentials()
76{78{
79 m_network.getCredentials();
80}
81
82QString Purchase::getAddPaymentUrl(QString currency)
83{
84 return m_network.getAddPaymentUrl(currency);
85}
86
87void Purchase::getItemDetails()
88{
77 if (m_appid.isEmpty() && m_itemid.isEmpty()) {89 if (m_appid.isEmpty() && m_itemid.isEmpty()) {
78 qDebug() << "AppId or ItemId not provided";90 qDebug() << "AppId or ItemId not provided";
79 quitCancel();91 quitCancel();
80 } else {
81 qDebug() << "Getting Item Details";
82 getItemDetails(m_appid, m_itemid);
83 }92 }
84 m_network.getCredentials();93 qDebug() << "Getting Item Details";
85}94 m_network.getItemInfo(m_appid);
8695}
87QString Purchase::getAddPaymentUrl()96
88{97void Purchase::getPaymentTypes(const QString& currency)
89 return m_network.getAddPaymentUrl();98{
90}99 m_network.requestPaymentTypes(currency);
91
92void Purchase::getItemDetails(QString packagename, QString itemid)
93{
94 Q_UNUSED(itemid);
95 m_network.getItemInfo(packagename);
96}
97
98void Purchase::getPaymentTypes()
99{
100 m_network.requestPaymentTypes();
101}100}
102101
103void Purchase::checkWallet(QString email, QString password, QString otp)102void Purchase::checkWallet(QString email, QString password, QString otp)
@@ -105,14 +104,14 @@
105 m_network.checkPassword(email, password, otp);104 m_network.checkPassword(email, password, otp);
106}105}
107106
108void Purchase::buyItemWithPreferredPayment(QString email, QString password, QString otp, bool recentLogin)107void Purchase::buyItemWithPreferredPayment(QString email, QString password, QString otp, QString currency, bool recentLogin)
109{108{
110 m_network.buyItemWithPreferredPaymentType(email, password, otp, m_appid, m_itemid, recentLogin);109 m_network.buyItemWithPreferredPaymentType(email, password, otp, m_appid, m_itemid, currency, recentLogin);
111}110}
112111
113void Purchase::buyItem(QString email, QString password, QString otp, QString paymentId, QString backendId, bool recentLogin)112void Purchase::buyItem(QString email, QString password, QString otp, QString currency, QString paymentId, QString backendId, bool recentLogin)
114{113{
115 m_network.buyItem(email, password, otp, m_appid, m_itemid, paymentId, backendId, recentLogin);114 m_network.buyItem(email, password, otp, m_appid, m_itemid, currency, paymentId, backendId, recentLogin);
116}115}
117116
118QDateTime Purchase::getTokenUpdated()117QDateTime Purchase::getTokenUpdated()
119118
=== modified file 'backend/modules/payui/purchase.h'
--- backend/modules/payui/purchase.h 2014-09-11 03:10:25 +0000
+++ backend/modules/payui/purchase.h 2014-10-02 18:57:25 +0000
@@ -17,12 +17,12 @@
17 explicit Purchase(QObject *parent = 0);17 explicit Purchase(QObject *parent = 0);
18 ~Purchase();18 ~Purchase();
1919
20 Q_INVOKABLE void getItemDetails(QString packagename, QString itemid);20 Q_INVOKABLE void getItemDetails();
21 Q_INVOKABLE void getPaymentTypes();21 Q_INVOKABLE void getPaymentTypes(const QString &currency);
22 Q_INVOKABLE void buyItemWithPreferredPayment(QString email, QString password, QString otp, bool recentLogin);22 Q_INVOKABLE void buyItemWithPreferredPayment(QString email, QString password, QString otp, QString currency, bool recentLogin);
23 Q_INVOKABLE void buyItem(QString email, QString password, QString otp, QString paymentId, QString backendId, bool recentLogin);23 Q_INVOKABLE void buyItem(QString email, QString password, QString otp, QString currency, QString paymentId, QString backendId, bool recentLogin);
24 Q_INVOKABLE void checkCredentials();24 Q_INVOKABLE void checkCredentials();
25 Q_INVOKABLE QString getAddPaymentUrl();25 Q_INVOKABLE QString getAddPaymentUrl(QString currency);
26 Q_INVOKABLE void checkWallet(QString email, QString password, QString otp);26 Q_INVOKABLE void checkWallet(QString email, QString password, QString otp);
2727
28 Q_INVOKABLE void quitSuccess();28 Q_INVOKABLE void quitSuccess();
@@ -31,7 +31,7 @@
31 Q_INVOKABLE void checkItemPurchased();31 Q_INVOKABLE void checkItemPurchased();
3232
33Q_SIGNALS:33Q_SIGNALS:
34 void itemDetailsObtained(QString title, QString publisher, QString price, QString icon);34 void itemDetailsObtained(QString title, QString publisher, QString currency, QString formatted_price, QString icon);
35 void paymentTypesObtained(QVariantList payments);35 void paymentTypesObtained(QVariantList payments);
36 void buyItemSucceeded();36 void buyItemSucceeded();
37 void buyItemFailed();37 void buyItemFailed();
@@ -44,6 +44,7 @@
44 void noPreferredPaymentMethod();44 void noPreferredPaymentMethod();
45 void loginError(const QString& message);45 void loginError(const QString& message);
46 void twoFactorAuthRequired();46 void twoFactorAuthRequired();
47 void itemNotPurchased();
4748
48private:49private:
49 Network m_network;50 Network m_network;
5051
=== modified file 'backend/tests/mock_click_server.py'
--- backend/tests/mock_click_server.py 2014-09-12 19:21:55 +0000
+++ backend/tests/mock_click_server.py 2014-10-02 18:57:25 +0000
@@ -1,8 +1,5 @@
1import sys
2import os
3import json1import json
4import threading2import threading
5import subprocess
6from http.server import BaseHTTPRequestHandler, HTTPServer3from http.server import BaseHTTPRequestHandler, HTTPServer
74
85
@@ -89,11 +86,17 @@
89 self.end_headers()86 self.end_headers()
90 self.wfile.write(bytes(json.dumps(response), 'UTF-8'))87 self.wfile.write(bytes(json.dumps(response), 'UTF-8'))
9188
92 def response_item_info(self, fail=False):89 def response_item_info(self, fail, eurozone, dotar):
93 response = {90 response = {
94 "title": "title",91 "title": "title",
95 "publisher": "publisher",92 "publisher": "publisher",
96 "price": 9.99,93 "price": 9.99,
94 "prices": {
95 "USD": 1.99,
96 "EUR": 1.69,
97 "GBP": 1.29,
98 "ARS": 18.05,
99 },
97 "icon_url": "icon_url",100 "icon_url": "icon_url",
98 }101 }
99 if fail:102 if fail:
@@ -101,6 +104,10 @@
101 else:104 else:
102 self.send_response(200)105 self.send_response(200)
103 self.send_header("Content-type", "application/json")106 self.send_header("Content-type", "application/json")
107 if eurozone:
108 self.send_header("X-Suggested-Currency", "EUR")
109 if dotar:
110 self.send_header("X-Suggested-Currency", "ARS")
104 self.end_headers()111 self.end_headers()
105 self.wfile.write(bytes(json.dumps(response), 'UTF-8'))112 self.wfile.write(bytes(json.dumps(response), 'UTF-8'))
106113
@@ -132,7 +139,9 @@
132 self.response_buy_item(fail=fail, interaction=interaction)139 self.response_buy_item(fail=fail, interaction=interaction)
133 elif self.path.find("iteminfo/") != -1:140 elif self.path.find("iteminfo/") != -1:
134 fail = self.path.find("/fail/") != -1141 fail = self.path.find("/fail/") != -1
135 self.response_item_info(fail)142 eurozone = self.path.find("/eurozone/") != -1
143 dotar = self.path.find("/dotar/") != -1
144 self.response_item_info(fail, eurozone, dotar)
136145
137146
138def run_click_server():147def run_click_server():
139148
=== modified file 'backend/tests/test_network.cpp'
--- backend/tests/test_network.cpp 2014-09-12 19:21:55 +0000
+++ backend/tests/test_network.cpp 2014-10-02 18:57:25 +0000
@@ -53,6 +53,10 @@
53 void testNetworkButItemWithPaymentTypeFail();53 void testNetworkButItemWithPaymentTypeFail();
54 void testNetworkButItemWithPaymentTypeInProgress();54 void testNetworkButItemWithPaymentTypeInProgress();
55 void testNetworkGetItemInfo();55 void testNetworkGetItemInfo();
56 void testNetworkGetItemInfoEurozone();
57 void testNetworkGetItemInfoOtherCoins();
58 void testNetworkGetItemInfoOverride();
59 void testNetworkGetItemInfoOverrideOther();
56 void testNetworkGetItemInfoFail();60 void testNetworkGetItemInfoFail();
57 void testUseExistingCredentials();61 void testUseExistingCredentials();
58 void testCheckAlreadyPurchased();62 void testCheckAlreadyPurchased();
@@ -89,7 +93,7 @@
89{93{
90 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/authError/", 1);94 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/authError/", 1);
91 QSignalSpy spy(&network, SIGNAL(authenticationError()));95 QSignalSpy spy(&network, SIGNAL(authenticationError()));
92 network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false);96 network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false);
93 QTRY_COMPARE(spy.count(), 1);97 QTRY_COMPARE(spy.count(), 1);
94}98}
9599
@@ -97,7 +101,7 @@
97{101{
98 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); 102 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
99 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));103 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));
100 network.requestPaymentTypes();104 network.requestPaymentTypes("USD");
101 QTRY_COMPARE(spy.count(), 1);105 QTRY_COMPARE(spy.count(), 1);
102 QList<QVariant> arguments = spy.takeFirst();106 QList<QVariant> arguments = spy.takeFirst();
103 QVERIFY(arguments.at(0).toList().count() == 3);107 QVERIFY(arguments.at(0).toList().count() == 3);
@@ -117,7 +121,7 @@
117{121{
118 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);122 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);
119 QSignalSpy spy(&network, SIGNAL(error(QString)));123 QSignalSpy spy(&network, SIGNAL(error(QString)));
120 network.requestPaymentTypes();124 network.requestPaymentTypes("USD");
121 QTRY_COMPARE(spy.count(), 1);125 QTRY_COMPARE(spy.count(), 1);
122 QList<QVariant> arguments = spy.takeFirst();126 QList<QVariant> arguments = spy.takeFirst();
123 QVERIFY(arguments.at(0).toString() == "404");127 QVERIFY(arguments.at(0).toString() == "404");
@@ -127,7 +131,7 @@
127{131{
128 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);132 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
129 QSignalSpy spy(&network, SIGNAL(buyItemSucceeded()));133 QSignalSpy spy(&network, SIGNAL(buyItemSucceeded()));
130 network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false);134 network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false);
131 QTRY_COMPARE(spy.count(), 1);135 QTRY_COMPARE(spy.count(), 1);
132}136}
133137
@@ -135,7 +139,7 @@
135{139{
136 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1);140 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1);
137 QSignalSpy spy(&network, SIGNAL(buyInteractionRequired(QString)));141 QSignalSpy spy(&network, SIGNAL(buyInteractionRequired(QString)));
138 network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false);142 network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false);
139 QTRY_COMPARE(spy.count(), 1);143 QTRY_COMPARE(spy.count(), 1);
140 QList<QVariant> arguments = spy.takeFirst();144 QList<QVariant> arguments = spy.takeFirst();
141 QString url(arguments.at(0).toString());145 QString url(arguments.at(0).toString());
@@ -147,7 +151,7 @@
147{151{
148 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);152 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);
149 QSignalSpy spy(&network, SIGNAL(buyItemFailed()));153 QSignalSpy spy(&network, SIGNAL(buyItemFailed()));
150 network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false);154 network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false);
151 QTRY_COMPARE(spy.count(), 1);155 QTRY_COMPARE(spy.count(), 1);
152}156}
153157
@@ -155,10 +159,10 @@
155{159{
156 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);160 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
157 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));161 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));
158 network.requestPaymentTypes();162 network.requestPaymentTypes("USD");
159 QTRY_COMPARE(spy.count(), 1);163 QTRY_COMPARE(spy.count(), 1);
160 QSignalSpy spy2(&network, SIGNAL(buyItemSucceeded()));164 QSignalSpy spy2(&network, SIGNAL(buyItemSucceeded()));
161 network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false);165 network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false);
162 QTRY_COMPARE(spy2.count(), 1);166 QTRY_COMPARE(spy2.count(), 1);
163}167}
164168
@@ -166,11 +170,11 @@
166{170{
167 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);171 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
168 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));172 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));
169 network.requestPaymentTypes();173 network.requestPaymentTypes("USD");
170 QTRY_COMPARE(spy.count(), 1);174 QTRY_COMPARE(spy.count(), 1);
171 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);175 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1);
172 QSignalSpy spy2(&network, SIGNAL(buyItemFailed()));176 QSignalSpy spy2(&network, SIGNAL(buyItemFailed()));
173 network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false);177 network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false);
174 QTRY_COMPARE(spy2.count(), 1);178 QTRY_COMPARE(spy2.count(), 1);
175}179}
176180
@@ -178,25 +182,80 @@
178{182{
179 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);183 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
180 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));184 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));
181 network.requestPaymentTypes();185 network.requestPaymentTypes("USD""USD");
182 QTRY_COMPARE(spy.count(), 1);186 QTRY_COMPARE(spy.count(), 1);
183 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1);187 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1);
184 QSignalSpy spy2(&network, SIGNAL(buyInteractionRequired(QString)));188 QSignalSpy spy2(&network, SIGNAL(buyInteractionRequired(QString)));
185 network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false);189 network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false);
186 QTRY_COMPARE(spy2.count(), 1);190 QTRY_COMPARE(spy2.count(), 1);
187}191}
188192
189void TestNetwork::testNetworkGetItemInfo()193void TestNetwork::testNetworkGetItemInfo()
190{194{
191 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/", 1);195 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/", 1);
192 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString)));196 unsetenv(CURRENCY_ENVVAR);
193 network.getItemInfo("packagename");197 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString)));
194 QTRY_COMPARE(spy.count(), 1);198 network.getItemInfo("packagename");
199 QTRY_COMPARE(spy.count(), 1);
200 QList<QVariant> arguments = spy.takeFirst();
201 QCOMPARE(arguments.at(2).toString(), QStringLiteral("USD"));
202 QCOMPARE(arguments.at(3).toString(), QStringLiteral("US$1.99"));
203}
204
205void TestNetwork::testNetworkGetItemInfoEurozone()
206{
207 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/eurozone/", 1);
208 unsetenv(CURRENCY_ENVVAR);
209 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString)));
210 network.getItemInfo("packagename");
211 QTRY_COMPARE(spy.count(), 1);
212 QList<QVariant> arguments = spy.takeFirst();
213 QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR"));
214 QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69"));
215}
216
217void TestNetwork::testNetworkGetItemInfoOtherCoins()
218{
219 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/dotar/", 1);
220 unsetenv(CURRENCY_ENVVAR);
221 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString)));
222 network.getItemInfo("packagename");
223 QTRY_COMPARE(spy.count(), 1);
224 QList<QVariant> arguments = spy.takeFirst();
225 QCOMPARE(arguments.at(2).toString(), QStringLiteral("USD"));
226 QCOMPARE(arguments.at(3).toString(), QStringLiteral("US$1.99"));
227}
228
229void TestNetwork::testNetworkGetItemInfoOverride()
230{
231 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/", 1);
232 setenv(CURRENCY_ENVVAR, "EUR", true);
233 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString)));
234 network.getItemInfo("packagename");
235 QTRY_COMPARE(spy.count(), 1);
236 QList<QVariant> arguments = spy.takeFirst();
237 QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR"));
238 QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69"));
239 unsetenv(CURRENCY_ENVVAR);
240}
241
242void TestNetwork::testNetworkGetItemInfoOverrideOther()
243{
244 setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/dotar/", 1);
245 setenv(CURRENCY_ENVVAR, "EUR", true);
246 QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString)));
247 network.getItemInfo("packagename");
248 QTRY_COMPARE(spy.count(), 1);
249 QList<QVariant> arguments = spy.takeFirst();
250 QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR"));
251 QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69"));
252 unsetenv(CURRENCY_ENVVAR);
195}253}
196254
197void TestNetwork::testNetworkGetItemInfoFail()255void TestNetwork::testNetworkGetItemInfoFail()
198{256{
199 setenv("URL_PACKAGE_INFO", "http://localhost:8000/fail/iteminfo/", 1);257 setenv("URL_PACKAGE_INFO", "http://localhost:8000/fail/iteminfo/", 1);
258 unsetenv(CURRENCY_ENVVAR);
200 QSignalSpy spy(&network, SIGNAL(error(QString)));259 QSignalSpy spy(&network, SIGNAL(error(QString)));
201 network.getItemInfo("packagename");260 network.getItemInfo("packagename");
202 QTRY_COMPARE(spy.count(), 1);261 QTRY_COMPARE(spy.count(), 1);
@@ -206,7 +265,7 @@
206{265{
207 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);266 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1);
208 QSignalSpy spy(&network, SIGNAL(buyItemSucceeded()));267 QSignalSpy spy(&network, SIGNAL(buyItemSucceeded()));
209 network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", true);268 network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", true);
210 QTRY_COMPARE(spy.count(), 1);269 QTRY_COMPARE(spy.count(), 1);
211}270}
212271
@@ -221,7 +280,7 @@
221void TestNetwork::testCheckAlreadyPurchasedFail()280void TestNetwork::testCheckAlreadyPurchasedFail()
222{281{
223 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/notpurchased/", 1);282 setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/notpurchased/", 1);
224 QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList)));283 QSignalSpy spy(&network, SIGNAL(itemNotPurchased()));
225 network.checkItemPurchased("com.example.fakeapp");284 network.checkItemPurchased("com.example.fakeapp");
226 QTRY_COMPARE(spy.count(), 1);285 QTRY_COMPARE(spy.count(), 1);
227}286}
228287
=== modified file 'manifest.json'
--- manifest.json 2014-09-30 16:45:24 +0000
+++ manifest.json 2014-10-02 18:57:25 +0000
@@ -11,6 +11,6 @@
11 "pay-ui": "payui_payui.desktop"11 "pay-ui": "payui_payui.desktop"
12 }12 }
13 },13 },
14 "version": "0.3.26",14 "version": "0.4.0",
15 "maintainer": "Diego Sarmentero <diego.sarmentero@canonical.com>"15 "maintainer": "Ubuntu Appstore Developers <ubuntu-appstore-developers@lists.launchpad.net>"
16}16}
17\ No newline at end of file17\ No newline at end of file

Subscribers

People subscribed via source and target branches