From 2c89ff7f662fe364ec2572c72386fa043ca51fdf Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 13 May 2016 11:48:48 -0300 Subject: [PATCH] First integration. BitPay invoice generation is ready. Fake responses from amazon --- Gruntfile.js | 2 +- public/img/amazon-card.png | Bin 0 -> 9650 bytes public/img/amazon-gift-card.png | Bin 0 -> 6648 bytes public/img/amazon-item.png | Bin 0 -> 2127 bytes public/views/amazon.html | 75 ++++++ public/views/buyAmazon.html | 119 +++++++++ public/views/includes/sidebar.html | 7 + public/views/modals/amazon-card-details.html | 45 ++++ src/js/controllers/amazon.js | 53 ++++ src/js/controllers/buyAmazon.js | 239 +++++++++++++++++++ src/js/controllers/index.js | 5 + src/js/routes.js | 20 ++ src/js/services/amazonService.js | 123 ++++++++++ src/js/services/configService.js | 12 + src/js/services/storageService.js | 12 + src/sass/amazon.scss | 22 ++ src/sass/main.scss | 2 +- 17 files changed, 734 insertions(+), 2 deletions(-) create mode 100644 public/img/amazon-card.png create mode 100644 public/img/amazon-gift-card.png create mode 100644 public/img/amazon-item.png create mode 100644 public/views/amazon.html create mode 100644 public/views/buyAmazon.html create mode 100644 public/views/modals/amazon-card-details.html create mode 100644 src/js/controllers/amazon.js create mode 100644 src/js/controllers/buyAmazon.js create mode 100644 src/js/services/amazonService.js create mode 100644 src/sass/amazon.scss diff --git a/Gruntfile.js b/Gruntfile.js index 188cb81b8..3fd51b784 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,7 +52,7 @@ module.exports = function(grunt) { }, }, css: { - files: ['src/css/*.css'], + files: ['src/sass/*.css', 'src/css/*.css'], tasks: ['concat:css'] }, sass: { diff --git a/public/img/amazon-card.png b/public/img/amazon-card.png new file mode 100644 index 0000000000000000000000000000000000000000..6c65982eddc51470a7164d19c9af2d45d6f78c25 GIT binary patch literal 9650 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 literal 0 HcmV?d00001 diff --git a/public/views/amazon.html b/public/views/amazon.html new file mode 100644 index 000000000..d8ba2f0d9 --- /dev/null +++ b/public/views/amazon.html @@ -0,0 +1,75 @@ + +

+ +
+ +
+ +
+
+
+
+
+
+
+
+
+ {{amazon.loading}} +
+
+ +
+ +
+ Amazon Gift Card +
+ +
+ No gift card in your wallet. Buy one now! +
+ +
+

Cards

+
+
+ {{id}} +
+
+ {{item.cardInfo.value.amount | currency : item.cardInfo.value.currencyCode + ' ' : 2}} +
+
+ Error + {{item.date * 1000 | amCalendar}} +
+
+ +
+
+
+ +
+ +
+
diff --git a/public/views/buyAmazon.html b/public/views/buyAmazon.html new file mode 100644 index 000000000..57dfd0323 --- /dev/null +++ b/public/views/buyAmazon.html @@ -0,0 +1,119 @@ +
+
+ + +
+ +
+
+
+
+
+
+
+
+
+ {{buy.loading}} +
+
+ +
+
+ +
+ + {{buy.error}} + +
+ +
+ Amazon Gift Card +
Redeem online
+
+
+ +
+ - + ${{fiat}} + + +
+ +
+ +
+ + + + +
+
+ +
+ Use your Amazon.com Gift Card to shop from a huge selection of books, electronics, music, movies, software, apparel, toys, and more. +
+ +
+ +
+
+
+
+ +
+
+

Gift card ready to redeem!

+ +
+ + {{buy.giftCard.cardInfo.value.amount | currency : buy.giftCard.cardInfo.value.currencyCode + ' ' : 2 }} + +
+ +
+
Claim code
+
{{buy.giftCard.gcClaimCode}}
+
+ +
+ +
+ +
+ To redeem your gift card, follow these steps: +
    +
  1. Visit www.amazon.com/gc.
  2. +
  3. Click Apply to Account and enter the claim code when prompted.
  4. +
  5. Gift card funds will be applied automatically to eligible orders during the checkout process.
  6. +
  7. You must pay for any remaining balance on your order with another payment method.
  8. +
+
+ +
+
BitPay invoice
+
{{buy.giftCard.bitpayInvoiceId}}
+ +
+
+
+ +
+
diff --git a/public/views/includes/sidebar.html b/public/views/includes/sidebar.html index 4b67781da..98e5db930 100644 --- a/public/views/includes/sidebar.html +++ b/public/views/includes/sidebar.html @@ -30,6 +30,13 @@ Buy and Sell +
  • + + +
    + Gift Card +
    +
  • diff --git a/public/views/modals/amazon-card-details.html b/public/views/modals/amazon-card-details.html new file mode 100644 index 000000000..4bb94b945 --- /dev/null +++ b/public/views/modals/amazon-card-details.html @@ -0,0 +1,45 @@ + + + diff --git a/src/js/controllers/amazon.js b/src/js/controllers/amazon.js new file mode 100644 index 000000000..0149c11aa --- /dev/null +++ b/src/js/controllers/amazon.js @@ -0,0 +1,53 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('amazonController', + function($rootScope, $scope, $timeout, $modal, profileService, configService, storageService, amazonService, isChromeApp, animationService, lodash, nodeWebkit) { + + window.ignoreMobilePause = true; + + this.init = function() { + var self = this; + var network = configService.getSync().amazon.testnet ? 'testnet' : 'livenet'; + amazonService.setCredentials(network); + amazonService.getGiftCards(function(err, gcds) { + if (err) { + self.error = err; + return; + } + self.giftCards = gcds; + + }); + }; + + this.openCardModal = function(card) { + $rootScope.modalOpened = true; + var self = this; + var fc = profileService.focusedClient; + var ModalInstanceCtrl = function($scope, $modalInstance) { + $scope.card = card; + + $scope.cancel = lodash.debounce(function() { + $modalInstance.dismiss('cancel'); + }, 0, 1000); + + }; + + var modalInstance = $modal.open({ + templateUrl: 'views/modals/amazon-card-details.html', + windowClass: animationService.modalAnimated.slideRight, + controller: ModalInstanceCtrl, + }); + + var disableCloseModal = $rootScope.$on('closeModal', function() { + modalInstance.dismiss('cancel'); + }); + + modalInstance.result.finally(function() { + $rootScope.modalOpened = false; + disableCloseModal(); + var m = angular.element(document.getElementsByClassName('reveal-modal')); + m.addClass(animationService.modalAnimated.slideOutRight); + }); + }; + + }); diff --git a/src/js/controllers/buyAmazon.js b/src/js/controllers/buyAmazon.js new file mode 100644 index 000000000..6d49eb5d1 --- /dev/null +++ b/src/js/controllers/buyAmazon.js @@ -0,0 +1,239 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('buyAmazonController', + function($rootScope, $scope, $modal, $log, $timeout, lodash, profileService, animationService, bwsError, configService, walletService, fingerprintService, amazonService) { + + window.ignoreMobilePause = true; + var self = this; + var fc; + var minimumAmount = 1; + var stepAmount = 1; + var multiplierAmount = 2; + var maximumAmount = 10; + + var otherWallets = function(network) { + return lodash.filter(profileService.getWallets(network), function(w) { + return w.network == network && w.m == 1; + }); + }; + + var handleEncryptedWallet = function(client, cb) { + if (!walletService.isEncrypted(client)) return cb(); + $rootScope.$emit('Local/NeedsPassword', false, function(err, password) { + if (err) return cb(err); + return cb(walletService.unlock(client, password)); + }); + }; + + this.init = function() { + $scope.fiat = minimumAmount * multiplierAmount; + var network = configService.getSync().amazon.testnet ? 'testnet' : 'livenet'; + amazonService.setCredentials(network); + self.otherWallets = otherWallets(network); + // Choose focused wallet + try { + var currentWalletId = profileService.focusedClient.credentials.walletId; + lodash.find(self.otherWallets, function(w) { + if (w.id == currentWalletId) { + $timeout(function() { + self.selectedWalletId = w.id; + self.selectedWalletName = w.name; + fc = profileService.getClient(w.id); + $scope.$apply(); + }, 100); + } + }); + } catch (e) { + $log.debug(e); + }; + }; + + $scope.openWalletsModal = function(wallets) { + self.error = null; + var ModalInstanceCtrl = function($scope, $modalInstance) { + $scope.type = 'SELL'; + $scope.wallets = wallets; + $scope.noColor = true; + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + + $scope.selectWallet = function(walletId, walletName) { + if (!profileService.getClient(walletId).isComplete()) { + self.error = bwsError.msg('WALLET_NOT_COMPLETE'); + $modalInstance.dismiss('cancel'); + return; + } + $modalInstance.close({ + 'walletId': walletId, + 'walletName': walletName, + }); + }; + }; + + var modalInstance = $modal.open({ + templateUrl: 'views/modals/wallets.html', + windowClass: animationService.modalAnimated.slideUp, + controller: ModalInstanceCtrl, + }); + + modalInstance.result.finally(function() { + var m = angular.element(document.getElementsByClassName('reveal-modal')); + m.addClass(animationService.modalAnimated.slideOutDown); + }); + + modalInstance.result.then(function(obj) { + $timeout(function() { + self.selectedWalletId = obj.walletId; + self.selectedWalletName = obj.walletName; + fc = profileService.getClient(obj.walletId); + $scope.$apply(); + }, 100); + }); + }; + + this.setAmount = function(plus) { + if (plus && $scope.fiat < maximumAmount ) { + stepAmount = stepAmount + 1; + $scope.fiat = stepAmount * multiplierAmount; + } else if (!plus && $scope.fiat > minimumAmount * multiplierAmount) { + stepAmount = stepAmount - 1; + $scope.fiat = stepAmount * multiplierAmount; + } + }; + + this.createTx = function() { + self.error = null; + + var dataSrc = { + price: $scope.fiat, + currency: 'USD' + }; + var outputs = []; + var config = configService.getSync(); + var configWallet = config.wallet; + var walletSettings = configWallet.settings; + + + self.loading = 'Creating invoice...'; + $timeout(function() { + + amazonService.createBitPayInvoice(dataSrc, function(err, data) { + if (err) { + self.loading = null; + self.error = err; + return; + } + + var address, comment, amount; + + address = data.data.bitcoinAddress; + amount = parseInt((data.data.btcPrice * 100000000).toFixed(0)); + comment = 'Buy Amazon Gift Card'; + + outputs.push({ + 'toAddress': address, + 'amount': amount, + 'message': comment + }); + + var txp = { + toAddress: address, + amount: amount, + outputs: outputs, + message: comment, + payProUrl: null, + excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true, + feeLevel: walletSettings.feeLevel || 'normal' + }; + + self.loading = 'Creating transaction...'; + walletService.createTx(fc, txp, function(err, createdTxp) { + self.loading = null; + if (err) { + self.loading = null; + $log.debug(err); + self.error = bwsError.msg(err); + $scope.$apply(); + return; + } + $scope.$emit('Local/NeedsConfirmation', createdTxp, function(accept) { + if (accept) { + self.loading = 'Sending bitcoin...'; + self.confirmTx(createdTxp, function(err, tx) { + if (err) { + self.loading = null; + self.error = err; + return; + } + var gift = { + amount: dataSrc.price, + currencyCode: dataSrc.currency, + bitpayInvoiceId: data.data.id + }; + self.loading = 'Buying gift card...'; + amazonService.buyGiftCard(gift, function(err, giftCard) { + self.loading = null; + if (err) { + self.error = err; + return; + } + self.giftCard = giftCard; + }); + }); + } + }); + }); + }); + }, 100); + }; + + this.confirmTx = function(txp, cb) { + + fingerprintService.check(fc, function(err) { + if (err) { + $log.debug(err); + return cb(err); + } + + handleEncryptedWallet(fc, function(err) { + if (err) { + $log.debug(err); + return bwsError.cb(err, null, cb); + } + + walletService.publishTx(fc, txp, function(err, publishedTxp) { + if (err) { + $log.debug(err); + return bwsError.cb(err, null, cb); + } + + walletService.signTx(fc, publishedTxp, function(err, signedTxp) { + walletService.lock(fc); + if (err) { + $log.debug(err); + walletService.removeTx(fc, signedTxp, function(err) { + if (err) $log.debug(err); + }); + return bwsError.cb(err, null, cb); + } + + walletService.broadcastTx(fc, signedTxp, function(err, broadcastedTxp) { + if (err) { + $log.debug(err); + walletService.removeTx(fc, broadcastedTxp, function(err) { + if (err) $log.debug(err); + }); + return bwsError.cb(err, null, cb); + } + $timeout(function() { + return cb(null, broadcastedTxp); + }, 5000); + }); + }); + }); + }); + }); + }; + + }); diff --git a/src/js/controllers/index.js b/src/js/controllers/index.js index 72de95860..a8bf7b0b1 100644 --- a/src/js/controllers/index.js +++ b/src/js/controllers/index.js @@ -160,6 +160,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r self.initGlidera(); self.initCoinbase(); + self.initAmazon(); self.hideBalance(); @@ -1040,6 +1041,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r }); }; + self.initAmazon = function() { + self.amazonEnabled = configService.getSync().amazon.enabled; + }; + self.initGlidera = function(accessToken) { self.glideraEnabled = configService.getSync().glidera.enabled; self.glideraTestnet = configService.getSync().glidera.testnet; diff --git a/src/js/routes.js b/src/js/routes.js index c2e97747f..61db44513 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -315,6 +315,26 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }, } }) + .state('amazon', { + url: '/amazon', + walletShouldBeComplete: true, + needProfile: true, + views: { + 'main': { + templateUrl: 'views/amazon.html' + }, + } + }) + .state('buyAmazon', { + url: '/buyamazon', + walletShouldBeComplete: true, + needProfile: true, + views: { + 'main': { + templateUrl: 'views/buyAmazon.html' + }, + } + }) .state('preferencesAdvanced', { url: '/preferencesAdvanced', templateUrl: 'views/preferencesAdvanced.html', diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js new file mode 100644 index 000000000..c7dc3ef6f --- /dev/null +++ b/src/js/services/amazonService.js @@ -0,0 +1,123 @@ +'use strict'; + +angular.module('copayApp.services').factory('amazonService', function($http, $log, isCordova, lodash, storageService, configService) { + var root = {}; + var credentials = {}; + + var fakeData = { + "cardInfo": { + "cardNumber":null, + "cardStatus":"RefundedToPurchaser", + "expirationDate":null, + "value":{ + "amount":1.0, + "currencyCode":"USD" + } + }, + "creationRequestId":"AwssbTSpecTest001", + "gcClaimCode":"Z7NV-LBBG39-75MU", + "gcExpirationDate":null, + "gcId":"A2GCN9BRX5QS76", + "status":"SUCCESS", + "bitpayInvoiceId":"NJtevvEponHbQVmYoL7FYp" + }; + + root.setCredentials = function(network) { + + if (network == 'testnet') { + credentials.BITPAY_API = 'https://test.bitpay.com'; + credentials.BITPAY_API_TOKEN = 'GDtYwBqbMZvjz5JrYZ1d2ba96StV92U4Yg4AGhT3C4He'; + credentials.AMAZON_HOST = 'https://agcod-v2-gamma.amazon.com'; + } + else { + credentials.BITPAY_API = 'https://bitpay.com'; + credentials.BITPAY_API_TOKEN = window.bitpay_token; + credentials.AMAZON_HOST = 'https://agcod-v2.amazon.com'; + }; + }; + + var _getBitPay = function(endpoint, token) { + return { + method: 'GET', + url: credentials.BITPAY_API + endpoint, + headers: { + 'content-type': 'application/json' + } + }; + }; + + var _postBitPay = function(endpoint, data) { + data.token = credentials.BITPAY_API_TOKEN; + return { + method: 'POST', + url: credentials.BITPAY_API + endpoint, + headers: { + 'content-type': 'application/json' + }, + data: data + }; + }; + + root.createBitPayInvoice = function(data, cb) { + var data = { + price: data.price, + currency: data.currency + }; + $http(_postBitPay('/invoices', data)).then(function(data) { + $log.info('BitPay Create Invoice: SUCCESS'); + return cb(null, data.data); + }, function(data) { + $log.error('BitPay Create Invoice: ERROR ' + data.statusText); + return cb(data); + }); + }; + + root.saveGiftCard = function(gc, opts, cb) { + var network = configService.getSync().amazon.testnet ? 'testnet' : 'livenet'; + storageService.getAmazonGiftCards(network, function(err, oldGiftCards) { + if (lodash.isString(oldGiftCards)) { + oldGiftCards = JSON.parse(oldGiftCards); + } + if (lodash.isString(gc)) { + gc = JSON.parse(gc); + } + var inv = oldGiftCards || {}; + inv[gc.gcId] = gc; + if (opts && (opts.error || opts.status)) { + inv[gc.gcId] = lodash.assign(inv[gc.gcId], opts); + } + if (opts && opts.remove) { + delete(inv[gc.gcId]); + } + inv = JSON.stringify(inv); + + storageService.setAmazonGiftCards(network, inv, function(err) { + return cb(err); + }); + }); + }; + + root.getGiftCards = function(cb) { + var network = configService.getSync().amazon.testnet ? 'testnet' : 'livenet'; + storageService.getAmazonGiftCards(network, function(err, giftCards) { + var _gcds = giftCards ? JSON.parse(giftCards) : null; + return cb(err, _gcds); + }); + }; + + root.buyGiftCard = function(gift, cb) { + var newId = Math.floor(Date.now() / 1000); + var saveData = fakeData; + saveData.gcId = saveData.gcId + '' + newId; + saveData.cardInfo.value.amount = gift.amount; + saveData.cardInfo.value.currencyCode = gift.currencyCode; + saveData['bitpayInvoiceId'] = gift.bitpayInvoiceId; + saveData['date'] = newId; + root.saveGiftCard(saveData, null, function(err) { + return cb(null, fakeData); + }); + }; + + return root; + +}); diff --git a/src/js/services/configService.js b/src/js/services/configService.js index a552b58fe..c956d2945 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -43,6 +43,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer testnet: false }, + amazon: { + enabled: true, + testnet: false + }, + rates: { url: 'https://insight.bitpay.com:443/api/rates', }, @@ -101,6 +106,9 @@ angular.module('copayApp.services').factory('configService', function(storageSer if (!configCache.coinbase) { configCache.coinbase = defaultConfig.coinbase; } + if (!configCache.amazon) { + configCache.amazon = defaultConfig.amazon; + } if (!configCache.pushNotifications) { configCache.pushNotifications = defaultConfig.pushNotifications; } @@ -117,6 +125,10 @@ angular.module('copayApp.services').factory('configService', function(storageSer // Disabled for testnet configCache.coinbase.testnet = false; + // Amazon + // Disabled for testnet + configCache.amazon.testnet = true; + $log.debug('Preferences read:', configCache) return cb(err, configCache); }); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 33eaa819c..2f67fd282 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -317,6 +317,18 @@ angular.module('copayApp.services') }); }); }; + + root.setAmazonGiftCards = function(network, gcs, cb) { + storage.set('amazonGiftCards-' + network, gcs, cb); + }; + + root.getAmazonGiftCards = function(network, cb) { + storage.get('amazonGiftCards-' + network, cb); + }; + + root.removeAmazonGiftCards = function(network, cb) { + storage.remove('amazonGiftCards-' + network, cb); + }; return root; }); diff --git a/src/sass/amazon.scss b/src/sass/amazon.scss new file mode 100644 index 000000000..bcbae297c --- /dev/null +++ b/src/sass/amazon.scss @@ -0,0 +1,22 @@ + +.amazon-select-amount { + display: inline-block; + padding: 3px 15px; + background-color: #4B6178; + color: #ffffff; + border-radius: 5px; + margin: 0 5px; + &:hover { + color: #ffffff; + } +} + +.amazon-amount { + display: inline-block; + background-color: #E4E8EC; + padding: 3px 10px; + width: 60px; + text-align: center; + border: 1px solid #ccc; + border-radius: 5px; +} diff --git a/src/sass/main.scss b/src/sass/main.scss index 985a219c3..02bcdbd34 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -99,7 +99,7 @@ h4.title a { } } -.modal-content h4, .glidera h4, .coinbase h4 { +.modal-content h4, .glidera h4, .coinbase h4, .amazon h4 { background: #F6F7F9; padding: 25px 0px 5px 10px; text-transform: uppercase;