Merge lp:~alecu/pay-ui/euro-and-more into lp:pay-ui
- euro-and-more
- Merge into first-branch
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 | ||||
Related bugs: |
|
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
Description of the change
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
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 : | # |
PASSED: Continuous integration, rev:72
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
review:
Approve
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'app/payui.qml' |
2 | --- app/payui.qml 2014-09-29 22:27:29 +0000 |
3 | +++ app/payui.qml 2014-10-02 18:57:25 +0000 |
4 | @@ -56,6 +56,7 @@ |
5 | property bool purchasing: false |
6 | property bool recentLogin: false |
7 | property bool cancellable: true |
8 | + property string suggestedCurrency: "USD" |
9 | |
10 | backgroundColor: "transparent" |
11 | |
12 | @@ -88,20 +89,17 @@ |
13 | id: purchase |
14 | |
15 | onItemDetailsObtained: { |
16 | - var loc_c = Qt.locale("C"); |
17 | - // This string comes from a json double, and must be parsed with C locale |
18 | - var pnum = Number.fromLocaleString(loc_c, price); |
19 | - |
20 | - var loc = Qt.locale(); |
21 | + suggestedCurrency = currency; |
22 | checkout.itemTitle = title; |
23 | checkout.itemSubtitle = publisher; |
24 | - checkout.price = pnum.toLocaleCurrencyString(loc, "US$"); |
25 | + checkout.price = formatted_price; |
26 | payment.itemTitle = title; |
27 | payment.itemSubtitle = publisher; |
28 | - payment.price = pnum.toLocaleCurrencyString(loc, "US$"); |
29 | + payment.price = formatted_price; |
30 | direct.itemTitle = title; |
31 | direct.itemSubtitle = publisher; |
32 | - direct.price = pnum.toLocaleCurrencyString(loc, "US$"); |
33 | + direct.price = formatted_price; |
34 | + checkCredentials(); |
35 | } |
36 | |
37 | onPaymentTypesObtained: { |
38 | @@ -190,10 +188,14 @@ |
39 | if (mainView.state == "online-accounts") { |
40 | purchase.checkItemPurchased(); |
41 | } else if (mainView.state != "checkout" && !mainView.purchasing && mainView.state != "buy-interaction") { |
42 | - purchase.getPaymentTypes(); |
43 | + purchase.getPaymentTypes(suggestedCurrency); |
44 | } |
45 | } |
46 | |
47 | + onItemNotPurchased: { |
48 | + purchase.getPaymentTypes(suggestedCurrency); |
49 | + } |
50 | + |
51 | onCredentialsNotFound: { |
52 | mainView.recentLogin = false; |
53 | if (mainView.state == "online-accounts") { |
54 | @@ -286,7 +288,7 @@ |
55 | |
56 | onRetry: { |
57 | mainView.showLoading(); |
58 | - purchase.checkCredentials(); |
59 | + purchase.getItemDetails(); |
60 | } |
61 | |
62 | onClose: { |
63 | @@ -301,7 +303,7 @@ |
64 | |
65 | onRetry: { |
66 | mainView.showLoading(); |
67 | - purchase.checkCredentials(); |
68 | + purchase.getItemDetails(); |
69 | } |
70 | |
71 | onClose: { |
72 | @@ -316,7 +318,7 @@ |
73 | |
74 | onRetry: { |
75 | mainView.showLoading(); |
76 | - purchase.checkCredentials(); |
77 | + purchase.getItemDetails(); |
78 | } |
79 | |
80 | onClose: { |
81 | @@ -360,7 +362,7 @@ |
82 | Component.onCompleted: { |
83 | showLoading(); |
84 | mainView.createDB(); |
85 | - purchase.checkCredentials(); |
86 | + purchase.getItemDetails(); |
87 | } |
88 | |
89 | onCurrentPageChanged: { |
90 | @@ -400,17 +402,17 @@ |
91 | mainView.purchasing = true; |
92 | mainView.cancellable = false; |
93 | showLoading(); |
94 | - purchase.buyItem(email, password, otp, direct.paymentId, direct.backendId, mainView.recentLogin); |
95 | + purchase.buyItem(email, password, otp, suggestedCurrency, direct.paymentId, direct.backendId, mainView.recentLogin); |
96 | } else if (direct.hasPayments && direct.hasPreferredPayment) { |
97 | mainView.purchasing = true; |
98 | mainView.cancellable = false; |
99 | showLoading(); |
100 | - purchase.buyItemWithPreferredPayment(email, password, otp, mainView.recentLogin); |
101 | + purchase.buyItemWithPreferredPayment(email, password, otp, suggestedCurrency, mainView.recentLogin); |
102 | } else if (direct.hasStoredPayment) { |
103 | var values = mainView.getLastPayment(); |
104 | var backendid = values[0]; |
105 | var paymentid = values[1]; |
106 | - purchase.buyItem(email, password, otp, paymentid, backendid, mainView.recentLogin); |
107 | + purchase.buyItem(email, password, otp, suggestedCurrency, paymentid, backendid, mainView.recentLogin); |
108 | } else { |
109 | mainView.state = "checkout"; |
110 | pageStack.push(checkout); |
111 | @@ -439,7 +441,7 @@ |
112 | } |
113 | |
114 | if (mainView.recentLogin) { |
115 | - purchase.buyItem(email, "", "", paymentId, backendId, mainView.recentLogin); |
116 | + purchase.buyItem(email, "", "", suggestedCurrency, paymentId, backendId, mainView.recentLogin); |
117 | } else { |
118 | mainView.cancellable = true; |
119 | mainView.purchasing = false; |
120 | @@ -458,7 +460,7 @@ |
121 | |
122 | onAddCreditCard: { |
123 | webkit.title = i18n.tr("Add Payment"); |
124 | - webkit.url = purchase.getAddPaymentUrl(); |
125 | + webkit.url = purchase.getAddPaymentUrl(suggestedCurrency); |
126 | mainView.state = "add-payment"; |
127 | pageStack.push(webkit); |
128 | } |
129 | @@ -494,7 +496,7 @@ |
130 | onPurchaseSucceeded: { |
131 | if (mainView.state == "add-payment") { |
132 | showLoading(); |
133 | - purchase.getPaymentTypes(); |
134 | + purchase.getPaymentTypes(suggestedCurrency); |
135 | } else { |
136 | purchase.quitSuccess(); |
137 | } |
138 | |
139 | === modified file 'backend/modules/payui/network.cpp' |
140 | --- backend/modules/payui/network.cpp 2014-09-25 20:46:48 +0000 |
141 | +++ backend/modules/payui/network.cpp 2014-10-02 18:57:25 +0000 |
142 | @@ -36,6 +36,7 @@ |
143 | #define PAY_PURCHASES_PATH "/purchases" |
144 | #define PAY_PAYMENTMETHODS_PATH "/paymentmethods" |
145 | #define PAY_PAYMENTMETHODS_ADD_PATH PAY_PAYMENTMETHODS_PATH + "/add" |
146 | +#define SUGGESTED_CURRENCY_HEADER_NAME "X-Suggested-Currency" |
147 | |
148 | #define PREFERED_PAYMENT_TYPE "0" |
149 | #define PAYMENT_TYPES "1" |
150 | @@ -90,6 +91,42 @@ |
151 | m_service.setCredentials(token); |
152 | } |
153 | |
154 | +QMap<QString, QString> buildCurrencyMap() |
155 | +{ |
156 | + /* NOTE: The list of currencies we need to handle mapping symbols of. |
157 | + * Please keep this list in A-Z order. |
158 | + */ |
159 | + QMap<QString, QString> currencies_map { |
160 | + { "CNY", "RMB"}, |
161 | + { "EUR", "€"}, |
162 | + { "GBP", "₤"}, |
163 | + { "HKD", "HK$"}, |
164 | + { "TWD", "TW$"}, |
165 | + { "USD", "US$"}, |
166 | + }; |
167 | + return currencies_map; |
168 | +} |
169 | + |
170 | +const QString DEFAULT_CURRENCY {"USD"}; |
171 | + |
172 | +QString Network::getSymbolForCurrency(const QString ¤cy_code) |
173 | +{ |
174 | + static QMap<QString, QString> currency_map = buildCurrencyMap(); |
175 | + |
176 | + if (currency_map.contains(currency_code)) { |
177 | + return currency_map[currency_code]; |
178 | + } else{ |
179 | + return currency_code; |
180 | + } |
181 | +} |
182 | + |
183 | +bool Network::isSupportedCurrency(const QString& currency_code) |
184 | +{ |
185 | + static QMap<QString, QString> currency_map = buildCurrencyMap(); |
186 | + |
187 | + return currency_map.contains(currency_code); |
188 | +} |
189 | + |
190 | void Network::onReply(QNetworkReply *reply) |
191 | { |
192 | QVariant statusAttr = reply->attribute( |
193 | @@ -167,10 +204,26 @@ |
194 | QJsonObject object = document.object(); |
195 | QString title = object.value("title").toString(); |
196 | QString publisher = object.value("publisher").toString(); |
197 | - QString price = QString::number(object.value("price").toDouble()); |
198 | QString icon = object.value("icon_url").toString(); |
199 | |
200 | - Q_EMIT itemDetailsObtained(title, publisher, price, icon); |
201 | + QJsonObject prices = object.value("prices").toObject(); |
202 | + QString suggested_currency = DEFAULT_CURRENCY; |
203 | + QString currency = DEFAULT_CURRENCY; |
204 | + if (reply->hasRawHeader(SUGGESTED_CURRENCY_HEADER_NAME)) { |
205 | + suggested_currency = reply->rawHeader(SUGGESTED_CURRENCY_HEADER_NAME); |
206 | + } |
207 | + const char* env_value = std::getenv(CURRENCY_ENVVAR); |
208 | + if (env_value != NULL) { |
209 | + suggested_currency = env_value; |
210 | + } |
211 | + |
212 | + if (isSupportedCurrency(suggested_currency) && prices.contains(suggested_currency)) { |
213 | + currency = suggested_currency; |
214 | + } |
215 | + double price = prices[currency].toDouble(); |
216 | + QLocale locale; |
217 | + QString formatted_price = locale.toCurrencyString(price, getSymbolForCurrency(currency)); |
218 | + Q_EMIT itemDetailsObtained(title, publisher, currency, formatted_price, icon); |
219 | } else if (state->operation.contains(CHECK_PURCHASED)) { |
220 | Q_EMIT buyItemSucceeded(); |
221 | } else { |
222 | @@ -182,22 +235,25 @@ |
223 | } else if (httpStatus == 401 || httpStatus == 403) { |
224 | Q_EMIT authenticationError(); |
225 | } else if (httpStatus == 404 && state->operation.contains(CHECK_PURCHASED)) { |
226 | - requestPaymentTypes(); |
227 | + Q_EMIT itemNotPurchased(); |
228 | } else { |
229 | Q_EMIT error(QString::number(httpStatus)); |
230 | } |
231 | reply->deleteLater(); |
232 | } |
233 | |
234 | -void Network::requestPaymentTypes() |
235 | +void Network::requestPaymentTypes(const QString& currency) |
236 | { |
237 | QNetworkRequest request; |
238 | request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); |
239 | - QString url = getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_PATH + "/"; |
240 | - qDebug() << "Request Payment Types:" << url; |
241 | - signRequestUrl(request, url); |
242 | + QUrl url(getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_PATH + "/"); |
243 | + QUrlQuery query; |
244 | + query.addQueryItem("currency", currency); |
245 | + url.setQuery(query); |
246 | + qDebug() << "Request Payment Types:" << url.toString(); |
247 | + signRequestUrl(request, url.toString()); |
248 | request.setRawHeader("Accept", "application/json"); |
249 | - request.setUrl(QUrl(url)); |
250 | + request.setUrl(url); |
251 | RequestObject* reqObject = new RequestObject(QString(PAYMENT_TYPES)); |
252 | request.setOriginatingObject(reqObject); |
253 | m_nam.get(request); |
254 | @@ -210,12 +266,14 @@ |
255 | } |
256 | |
257 | void Network::buyItemWithPreferredPaymentType(const QString& email, const QString& password, const QString& otp, |
258 | - const QString& appid, const QString& itemid, bool recentLogin) |
259 | + const QString& appid, const QString& itemid, const QString& currency, |
260 | + bool recentLogin) |
261 | { |
262 | m_selectedPaymentId = m_preferred->paymentId(); |
263 | m_selectedBackendId = m_preferred->backendId(); |
264 | m_selectedAppId = appid; |
265 | m_selectedItemId = itemid; |
266 | + m_currency = currency; |
267 | if (recentLogin) { |
268 | purchaseProcess(); |
269 | } else { |
270 | @@ -226,13 +284,14 @@ |
271 | |
272 | void Network::buyItem(const QString& email, const QString& password, |
273 | const QString& otp, |
274 | - const QString& appid, const QString& itemid, |
275 | + const QString& appid, const QString& itemid, const QString& currency, |
276 | const QString& paymentId, const QString& backendId, bool recentLogin) |
277 | { |
278 | m_selectedPaymentId = paymentId; |
279 | m_selectedBackendId = backendId; |
280 | m_selectedAppId = appid; |
281 | m_selectedItemId = itemid; |
282 | + m_currency = currency; |
283 | if (recentLogin) { |
284 | purchaseProcess(); |
285 | } else { |
286 | @@ -252,6 +311,7 @@ |
287 | serializer.insert("name", m_selectedAppId); |
288 | serializer.insert("backend_id", m_selectedBackendId); |
289 | serializer.insert("method_id", m_selectedPaymentId); |
290 | + serializer.insert("currency", m_currency); |
291 | QJsonDocument doc(serializer); |
292 | |
293 | QByteArray content = doc.toJson(); |
294 | @@ -304,14 +364,16 @@ |
295 | request.setRawHeader("Authorization", sign.toUtf8()); |
296 | } |
297 | |
298 | -QString Network::getAddPaymentUrl() |
299 | +QString Network::getAddPaymentUrl(const QString& currency) |
300 | { |
301 | - QString baseUrl = getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_ADD_PATH + "/"; |
302 | + QUrl baseUrl(getAPIUrl(PAY_BASE_URL_ENVVAR, QString(PAY_BASE_URL)) + PAY_API_ROOT + PAY_PAYMENTMETHODS_ADD_PATH + "/"); |
303 | + QUrlQuery query; |
304 | + query.addQueryItem("currency", currency); |
305 | + baseUrl.setQuery(query); |
306 | qDebug() << "Get Add Payment URL:" << baseUrl; |
307 | - QString sign = m_token.signUrl(baseUrl, QStringLiteral("GET"), true); |
308 | + QString sign = m_token.signUrl(baseUrl.toString(), QStringLiteral("GET"), true); |
309 | QUrl signedUrl(baseUrl); |
310 | signedUrl.setQuery(sign); |
311 | - |
312 | return signedUrl.toString(); |
313 | } |
314 | |
315 | |
316 | === modified file 'backend/modules/payui/network.h' |
317 | --- backend/modules/payui/network.h 2014-09-11 03:10:25 +0000 |
318 | +++ backend/modules/payui/network.h 2014-10-02 18:57:25 +0000 |
319 | @@ -38,6 +38,7 @@ |
320 | constexpr static const char* PAY_BASE_URL_ENVVAR{"PAY_BASE_URL"}; |
321 | constexpr static const char* PAY_BASE_URL{"https://software-center.ubuntu.com"}; |
322 | constexpr static const char* PAY_API_ROOT{"/api/2.0/click"}; |
323 | +constexpr static const char* CURRENCY_ENVVAR {"U1_SEARCH_CURRENCY"}; |
324 | |
325 | class RequestObject : public QObject |
326 | { |
327 | @@ -58,26 +59,28 @@ |
328 | public: |
329 | explicit Network(QObject *parent = 0); |
330 | |
331 | - void requestPaymentTypes(); |
332 | + void requestPaymentTypes(const QString& currency); |
333 | void buyItem(const QString& email, const QString& password, |
334 | const QString& otp, const QString& appid, |
335 | - const QString& itemid, const QString& paymentId, |
336 | + const QString& itemid, const QString& currency, const QString& paymentId, |
337 | const QString& backendId, bool recentLogin); |
338 | void buyItemWithPreferredPaymentType(const QString& email, const QString& password, |
339 | const QString& otp, |
340 | - const QString& appid, const QString& itemid, |
341 | + const QString& appid, const QString& itemid, const QString& currency, |
342 | bool recentLogin); |
343 | void getItemInfo(const QString &packagename); |
344 | void checkPassword(const QString& email, const QString& password, |
345 | const QString& otp); |
346 | void getCredentials(); |
347 | void setCredentials(Token token); |
348 | - QString getAddPaymentUrl(); |
349 | + QString getAddPaymentUrl(const QString& currency); |
350 | QDateTime getTokenUpdated(); |
351 | void checkItemPurchased(const QString& appid); |
352 | + static QString getSymbolForCurrency(const QString& currency_code); |
353 | + static bool isSupportedCurrency(const QString& currency_code); |
354 | |
355 | Q_SIGNALS: |
356 | - void itemDetailsObtained(QString title, QString publisher, QString price, QString icon); |
357 | + void itemDetailsObtained(QString title, QString publisher, QString currency, QString formatted_price, QString icon); |
358 | void paymentTypesObtained(QVariantList payments); |
359 | void buyItemSucceeded(); |
360 | void buyItemFailed(); |
361 | @@ -90,6 +93,7 @@ |
362 | void noPreferredPaymentMethod(); |
363 | void loginError(const QString& message); |
364 | void twoFactorAuthRequired(); |
365 | + void itemNotPurchased(); |
366 | |
367 | private Q_SLOTS: |
368 | void onReply(QNetworkReply*); |
369 | @@ -107,6 +111,7 @@ |
370 | QString m_selectedBackendId; |
371 | QString m_selectedAppId; |
372 | QString m_selectedItemId; |
373 | + QString m_currency; |
374 | bool m_startPurchase = false; |
375 | |
376 | QString getAPIUrl(QString urlKey, QString defaultValue); |
377 | |
378 | === modified file 'backend/modules/payui/purchase.cpp' |
379 | --- backend/modules/payui/purchase.cpp 2014-09-11 03:10:25 +0000 |
380 | +++ backend/modules/payui/purchase.cpp 2014-10-02 18:57:25 +0000 |
381 | @@ -38,6 +38,8 @@ |
382 | this, &Purchase::loginError); |
383 | connect(&m_network, &Network::twoFactorAuthRequired, |
384 | this, &Purchase::twoFactorAuthRequired); |
385 | + connect(&m_network, &Network::itemNotPurchased, |
386 | + this, &Purchase::itemNotPurchased); |
387 | |
388 | QCoreApplication* instance = QCoreApplication::instance(); |
389 | Logger::setupLogging(); |
390 | @@ -74,30 +76,27 @@ |
391 | |
392 | void Purchase::checkCredentials() |
393 | { |
394 | + m_network.getCredentials(); |
395 | +} |
396 | + |
397 | +QString Purchase::getAddPaymentUrl(QString currency) |
398 | +{ |
399 | + return m_network.getAddPaymentUrl(currency); |
400 | +} |
401 | + |
402 | +void Purchase::getItemDetails() |
403 | +{ |
404 | if (m_appid.isEmpty() && m_itemid.isEmpty()) { |
405 | qDebug() << "AppId or ItemId not provided"; |
406 | quitCancel(); |
407 | - } else { |
408 | - qDebug() << "Getting Item Details"; |
409 | - getItemDetails(m_appid, m_itemid); |
410 | } |
411 | - m_network.getCredentials(); |
412 | -} |
413 | - |
414 | -QString Purchase::getAddPaymentUrl() |
415 | -{ |
416 | - return m_network.getAddPaymentUrl(); |
417 | -} |
418 | - |
419 | -void Purchase::getItemDetails(QString packagename, QString itemid) |
420 | -{ |
421 | - Q_UNUSED(itemid); |
422 | - m_network.getItemInfo(packagename); |
423 | -} |
424 | - |
425 | -void Purchase::getPaymentTypes() |
426 | -{ |
427 | - m_network.requestPaymentTypes(); |
428 | + qDebug() << "Getting Item Details"; |
429 | + m_network.getItemInfo(m_appid); |
430 | +} |
431 | + |
432 | +void Purchase::getPaymentTypes(const QString& currency) |
433 | +{ |
434 | + m_network.requestPaymentTypes(currency); |
435 | } |
436 | |
437 | void Purchase::checkWallet(QString email, QString password, QString otp) |
438 | @@ -105,14 +104,14 @@ |
439 | m_network.checkPassword(email, password, otp); |
440 | } |
441 | |
442 | -void Purchase::buyItemWithPreferredPayment(QString email, QString password, QString otp, bool recentLogin) |
443 | +void Purchase::buyItemWithPreferredPayment(QString email, QString password, QString otp, QString currency, bool recentLogin) |
444 | { |
445 | - m_network.buyItemWithPreferredPaymentType(email, password, otp, m_appid, m_itemid, recentLogin); |
446 | + m_network.buyItemWithPreferredPaymentType(email, password, otp, m_appid, m_itemid, currency, recentLogin); |
447 | } |
448 | |
449 | -void Purchase::buyItem(QString email, QString password, QString otp, QString paymentId, QString backendId, bool recentLogin) |
450 | +void Purchase::buyItem(QString email, QString password, QString otp, QString currency, QString paymentId, QString backendId, bool recentLogin) |
451 | { |
452 | - m_network.buyItem(email, password, otp, m_appid, m_itemid, paymentId, backendId, recentLogin); |
453 | + m_network.buyItem(email, password, otp, m_appid, m_itemid, currency, paymentId, backendId, recentLogin); |
454 | } |
455 | |
456 | QDateTime Purchase::getTokenUpdated() |
457 | |
458 | === modified file 'backend/modules/payui/purchase.h' |
459 | --- backend/modules/payui/purchase.h 2014-09-11 03:10:25 +0000 |
460 | +++ backend/modules/payui/purchase.h 2014-10-02 18:57:25 +0000 |
461 | @@ -17,12 +17,12 @@ |
462 | explicit Purchase(QObject *parent = 0); |
463 | ~Purchase(); |
464 | |
465 | - Q_INVOKABLE void getItemDetails(QString packagename, QString itemid); |
466 | - Q_INVOKABLE void getPaymentTypes(); |
467 | - Q_INVOKABLE void buyItemWithPreferredPayment(QString email, QString password, QString otp, bool recentLogin); |
468 | - Q_INVOKABLE void buyItem(QString email, QString password, QString otp, QString paymentId, QString backendId, bool recentLogin); |
469 | + Q_INVOKABLE void getItemDetails(); |
470 | + Q_INVOKABLE void getPaymentTypes(const QString ¤cy); |
471 | + Q_INVOKABLE void buyItemWithPreferredPayment(QString email, QString password, QString otp, QString currency, bool recentLogin); |
472 | + Q_INVOKABLE void buyItem(QString email, QString password, QString otp, QString currency, QString paymentId, QString backendId, bool recentLogin); |
473 | Q_INVOKABLE void checkCredentials(); |
474 | - Q_INVOKABLE QString getAddPaymentUrl(); |
475 | + Q_INVOKABLE QString getAddPaymentUrl(QString currency); |
476 | Q_INVOKABLE void checkWallet(QString email, QString password, QString otp); |
477 | |
478 | Q_INVOKABLE void quitSuccess(); |
479 | @@ -31,7 +31,7 @@ |
480 | Q_INVOKABLE void checkItemPurchased(); |
481 | |
482 | Q_SIGNALS: |
483 | - void itemDetailsObtained(QString title, QString publisher, QString price, QString icon); |
484 | + void itemDetailsObtained(QString title, QString publisher, QString currency, QString formatted_price, QString icon); |
485 | void paymentTypesObtained(QVariantList payments); |
486 | void buyItemSucceeded(); |
487 | void buyItemFailed(); |
488 | @@ -44,6 +44,7 @@ |
489 | void noPreferredPaymentMethod(); |
490 | void loginError(const QString& message); |
491 | void twoFactorAuthRequired(); |
492 | + void itemNotPurchased(); |
493 | |
494 | private: |
495 | Network m_network; |
496 | |
497 | === modified file 'backend/tests/mock_click_server.py' |
498 | --- backend/tests/mock_click_server.py 2014-09-12 19:21:55 +0000 |
499 | +++ backend/tests/mock_click_server.py 2014-10-02 18:57:25 +0000 |
500 | @@ -1,8 +1,5 @@ |
501 | -import sys |
502 | -import os |
503 | import json |
504 | import threading |
505 | -import subprocess |
506 | from http.server import BaseHTTPRequestHandler, HTTPServer |
507 | |
508 | |
509 | @@ -89,11 +86,17 @@ |
510 | self.end_headers() |
511 | self.wfile.write(bytes(json.dumps(response), 'UTF-8')) |
512 | |
513 | - def response_item_info(self, fail=False): |
514 | + def response_item_info(self, fail, eurozone, dotar): |
515 | response = { |
516 | "title": "title", |
517 | "publisher": "publisher", |
518 | "price": 9.99, |
519 | + "prices": { |
520 | + "USD": 1.99, |
521 | + "EUR": 1.69, |
522 | + "GBP": 1.29, |
523 | + "ARS": 18.05, |
524 | + }, |
525 | "icon_url": "icon_url", |
526 | } |
527 | if fail: |
528 | @@ -101,6 +104,10 @@ |
529 | else: |
530 | self.send_response(200) |
531 | self.send_header("Content-type", "application/json") |
532 | + if eurozone: |
533 | + self.send_header("X-Suggested-Currency", "EUR") |
534 | + if dotar: |
535 | + self.send_header("X-Suggested-Currency", "ARS") |
536 | self.end_headers() |
537 | self.wfile.write(bytes(json.dumps(response), 'UTF-8')) |
538 | |
539 | @@ -132,7 +139,9 @@ |
540 | self.response_buy_item(fail=fail, interaction=interaction) |
541 | elif self.path.find("iteminfo/") != -1: |
542 | fail = self.path.find("/fail/") != -1 |
543 | - self.response_item_info(fail) |
544 | + eurozone = self.path.find("/eurozone/") != -1 |
545 | + dotar = self.path.find("/dotar/") != -1 |
546 | + self.response_item_info(fail, eurozone, dotar) |
547 | |
548 | |
549 | def run_click_server(): |
550 | |
551 | === modified file 'backend/tests/test_network.cpp' |
552 | --- backend/tests/test_network.cpp 2014-09-12 19:21:55 +0000 |
553 | +++ backend/tests/test_network.cpp 2014-10-02 18:57:25 +0000 |
554 | @@ -53,6 +53,10 @@ |
555 | void testNetworkButItemWithPaymentTypeFail(); |
556 | void testNetworkButItemWithPaymentTypeInProgress(); |
557 | void testNetworkGetItemInfo(); |
558 | + void testNetworkGetItemInfoEurozone(); |
559 | + void testNetworkGetItemInfoOtherCoins(); |
560 | + void testNetworkGetItemInfoOverride(); |
561 | + void testNetworkGetItemInfoOverrideOther(); |
562 | void testNetworkGetItemInfoFail(); |
563 | void testUseExistingCredentials(); |
564 | void testCheckAlreadyPurchased(); |
565 | @@ -89,7 +93,7 @@ |
566 | { |
567 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/authError/", 1); |
568 | QSignalSpy spy(&network, SIGNAL(authenticationError())); |
569 | - network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false); |
570 | + network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false); |
571 | QTRY_COMPARE(spy.count(), 1); |
572 | } |
573 | |
574 | @@ -97,7 +101,7 @@ |
575 | { |
576 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
577 | QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList))); |
578 | - network.requestPaymentTypes(); |
579 | + network.requestPaymentTypes("USD"); |
580 | QTRY_COMPARE(spy.count(), 1); |
581 | QList<QVariant> arguments = spy.takeFirst(); |
582 | QVERIFY(arguments.at(0).toList().count() == 3); |
583 | @@ -117,7 +121,7 @@ |
584 | { |
585 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1); |
586 | QSignalSpy spy(&network, SIGNAL(error(QString))); |
587 | - network.requestPaymentTypes(); |
588 | + network.requestPaymentTypes("USD"); |
589 | QTRY_COMPARE(spy.count(), 1); |
590 | QList<QVariant> arguments = spy.takeFirst(); |
591 | QVERIFY(arguments.at(0).toString() == "404"); |
592 | @@ -127,7 +131,7 @@ |
593 | { |
594 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
595 | QSignalSpy spy(&network, SIGNAL(buyItemSucceeded())); |
596 | - network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false); |
597 | + network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false); |
598 | QTRY_COMPARE(spy.count(), 1); |
599 | } |
600 | |
601 | @@ -135,7 +139,7 @@ |
602 | { |
603 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1); |
604 | QSignalSpy spy(&network, SIGNAL(buyInteractionRequired(QString))); |
605 | - network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false); |
606 | + network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false); |
607 | QTRY_COMPARE(spy.count(), 1); |
608 | QList<QVariant> arguments = spy.takeFirst(); |
609 | QString url(arguments.at(0).toString()); |
610 | @@ -147,7 +151,7 @@ |
611 | { |
612 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1); |
613 | QSignalSpy spy(&network, SIGNAL(buyItemFailed())); |
614 | - network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", false); |
615 | + network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", false); |
616 | QTRY_COMPARE(spy.count(), 1); |
617 | } |
618 | |
619 | @@ -155,10 +159,10 @@ |
620 | { |
621 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
622 | QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList))); |
623 | - network.requestPaymentTypes(); |
624 | + network.requestPaymentTypes("USD"); |
625 | QTRY_COMPARE(spy.count(), 1); |
626 | QSignalSpy spy2(&network, SIGNAL(buyItemSucceeded())); |
627 | - network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false); |
628 | + network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false); |
629 | QTRY_COMPARE(spy2.count(), 1); |
630 | } |
631 | |
632 | @@ -166,11 +170,11 @@ |
633 | { |
634 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
635 | QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList))); |
636 | - network.requestPaymentTypes(); |
637 | + network.requestPaymentTypes("USD"); |
638 | QTRY_COMPARE(spy.count(), 1); |
639 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/fail/", 1); |
640 | QSignalSpy spy2(&network, SIGNAL(buyItemFailed())); |
641 | - network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false); |
642 | + network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false); |
643 | QTRY_COMPARE(spy2.count(), 1); |
644 | } |
645 | |
646 | @@ -178,25 +182,80 @@ |
647 | { |
648 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
649 | QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList))); |
650 | - network.requestPaymentTypes(); |
651 | + network.requestPaymentTypes("USD""USD"); |
652 | QTRY_COMPARE(spy.count(), 1); |
653 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/interaction/", 1); |
654 | QSignalSpy spy2(&network, SIGNAL(buyInteractionRequired(QString))); |
655 | - network.buyItemWithPreferredPaymentType("email", "password", "otp", "appid", "itemid", false); |
656 | + network.buyItemWithPreferredPaymentType("email", "password", "otp", "USD", "appid", "itemid", false); |
657 | QTRY_COMPARE(spy2.count(), 1); |
658 | } |
659 | |
660 | void TestNetwork::testNetworkGetItemInfo() |
661 | { |
662 | setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/", 1); |
663 | - QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString))); |
664 | - network.getItemInfo("packagename"); |
665 | - QTRY_COMPARE(spy.count(), 1); |
666 | + unsetenv(CURRENCY_ENVVAR); |
667 | + QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString))); |
668 | + network.getItemInfo("packagename"); |
669 | + QTRY_COMPARE(spy.count(), 1); |
670 | + QList<QVariant> arguments = spy.takeFirst(); |
671 | + QCOMPARE(arguments.at(2).toString(), QStringLiteral("USD")); |
672 | + QCOMPARE(arguments.at(3).toString(), QStringLiteral("US$1.99")); |
673 | +} |
674 | + |
675 | +void TestNetwork::testNetworkGetItemInfoEurozone() |
676 | +{ |
677 | + setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/eurozone/", 1); |
678 | + unsetenv(CURRENCY_ENVVAR); |
679 | + QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString))); |
680 | + network.getItemInfo("packagename"); |
681 | + QTRY_COMPARE(spy.count(), 1); |
682 | + QList<QVariant> arguments = spy.takeFirst(); |
683 | + QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR")); |
684 | + QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69")); |
685 | +} |
686 | + |
687 | +void TestNetwork::testNetworkGetItemInfoOtherCoins() |
688 | +{ |
689 | + setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/dotar/", 1); |
690 | + unsetenv(CURRENCY_ENVVAR); |
691 | + QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString))); |
692 | + network.getItemInfo("packagename"); |
693 | + QTRY_COMPARE(spy.count(), 1); |
694 | + QList<QVariant> arguments = spy.takeFirst(); |
695 | + QCOMPARE(arguments.at(2).toString(), QStringLiteral("USD")); |
696 | + QCOMPARE(arguments.at(3).toString(), QStringLiteral("US$1.99")); |
697 | +} |
698 | + |
699 | +void TestNetwork::testNetworkGetItemInfoOverride() |
700 | +{ |
701 | + setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/", 1); |
702 | + setenv(CURRENCY_ENVVAR, "EUR", true); |
703 | + QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString))); |
704 | + network.getItemInfo("packagename"); |
705 | + QTRY_COMPARE(spy.count(), 1); |
706 | + QList<QVariant> arguments = spy.takeFirst(); |
707 | + QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR")); |
708 | + QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69")); |
709 | + unsetenv(CURRENCY_ENVVAR); |
710 | +} |
711 | + |
712 | +void TestNetwork::testNetworkGetItemInfoOverrideOther() |
713 | +{ |
714 | + setenv("URL_PACKAGE_INFO", "http://localhost:8000/iteminfo/dotar/", 1); |
715 | + setenv(CURRENCY_ENVVAR, "EUR", true); |
716 | + QSignalSpy spy(&network, SIGNAL(itemDetailsObtained(QString,QString,QString,QString,QString))); |
717 | + network.getItemInfo("packagename"); |
718 | + QTRY_COMPARE(spy.count(), 1); |
719 | + QList<QVariant> arguments = spy.takeFirst(); |
720 | + QCOMPARE(arguments.at(2).toString(), QStringLiteral("EUR")); |
721 | + QCOMPARE(arguments.at(3).toString(), QStringLiteral("€1.69")); |
722 | + unsetenv(CURRENCY_ENVVAR); |
723 | } |
724 | |
725 | void TestNetwork::testNetworkGetItemInfoFail() |
726 | { |
727 | setenv("URL_PACKAGE_INFO", "http://localhost:8000/fail/iteminfo/", 1); |
728 | + unsetenv(CURRENCY_ENVVAR); |
729 | QSignalSpy spy(&network, SIGNAL(error(QString))); |
730 | network.getItemInfo("packagename"); |
731 | QTRY_COMPARE(spy.count(), 1); |
732 | @@ -206,7 +265,7 @@ |
733 | { |
734 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/", 1); |
735 | QSignalSpy spy(&network, SIGNAL(buyItemSucceeded())); |
736 | - network.buyItem("email", "password", "otp", "appid", "itemid", "paymentid", "backendid", true); |
737 | + network.buyItem("email", "password", "otp", "USD", "appid", "itemid", "paymentid", "backendid", true); |
738 | QTRY_COMPARE(spy.count(), 1); |
739 | } |
740 | |
741 | @@ -221,7 +280,7 @@ |
742 | void TestNetwork::testCheckAlreadyPurchasedFail() |
743 | { |
744 | setenv(PAY_BASE_URL_ENVVAR, "http://localhost:8000/notpurchased/", 1); |
745 | - QSignalSpy spy(&network, SIGNAL(paymentTypesObtained(QVariantList))); |
746 | + QSignalSpy spy(&network, SIGNAL(itemNotPurchased())); |
747 | network.checkItemPurchased("com.example.fakeapp"); |
748 | QTRY_COMPARE(spy.count(), 1); |
749 | } |
750 | |
751 | === modified file 'manifest.json' |
752 | --- manifest.json 2014-09-30 16:45:24 +0000 |
753 | +++ manifest.json 2014-10-02 18:57:25 +0000 |
754 | @@ -11,6 +11,6 @@ |
755 | "pay-ui": "payui_payui.desktop" |
756 | } |
757 | }, |
758 | - "version": "0.3.26", |
759 | - "maintainer": "Diego Sarmentero <diego.sarmentero@canonical.com>" |
760 | + "version": "0.4.0", |
761 | + "maintainer": "Ubuntu Appstore Developers <ubuntu-appstore-developers@lists.launchpad.net>" |
762 | } |
763 | \ No newline at end of file |
PASSED: Continuous integration, rev:70 jenkins. qa.ubuntu. com/job/ pay-ui- ci/94/ jenkins. qa.ubuntu. com/job/ generic- click-builder- utopic- armhf/742 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- amd64-ci/ 91 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- armhf-ci/ 91 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- armhf-ci/ 91/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ pay-ui- utopic- i386-ci/ 91
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/pay- ui-ci/94/ rebuild
http://