Gift card ready to redeem!
diff --git a/public/views/modals/amazon-card-details.html b/public/views/modals/amazon-card-details.html
index ddf25724f..b8ae6ae90 100644
--- a/public/views/modals/amazon-card-details.html
+++ b/public/views/modals/amazon-card-details.html
@@ -17,28 +17,55 @@
ng-swipe-right="cancel()">
+
+
+ {{error}}
+
+
+
+
+
+
+ There was a temporary/recoverable system failure that can be resolved by retrying the request
+
+
+ Try again
+
+
+
+ There was a failure to the create gift card that could not be recoverable. Please, contact BitPay to refund your bitcoin
+
+
+
-
+
Claim code
{{card.gcClaimCode}}
- Created at
- {{card.date * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}
+ Card status
+ Fulfilled
+ Refunded to purchaser
+ Expired
- Status
- Completed
- Pending
- Error
+ Created at
+ {{card.date * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}
+
+
+ Creation status
+ Success
+ Resend is required
+ Error
+ Refunded
@@ -47,5 +74,33 @@
+
+
+
+ This action will remove the gift card
+
+
+
+ Remove
+
+
+
+
+
+
+
+ This action will cancel the gift card
+
+
+
+ Cancel
+
+
+
+
diff --git a/src/js/controllers/amazon.js b/src/js/controllers/amazon.js
index 0149c11aa..df90a6373 100644
--- a/src/js/controllers/amazon.js
+++ b/src/js/controllers/amazon.js
@@ -15,7 +15,6 @@ angular.module('copayApp.controllers').controller('amazonController',
return;
}
self.giftCards = gcds;
-
});
};
@@ -26,8 +25,55 @@ angular.module('copayApp.controllers').controller('amazonController',
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.card = card;
+ $scope.cancelGiftCard = function() {
+ $scope.refresh = true;
+ var dataSrc = {
+ creationRequestId: $scope.card.creationRequestId,
+ gcId: $scope.card.gcId,
+ bitpayInvoiceId: $scope.card.bitpayInvoiceId,
+ bitpayInvoiceUrl: $scope.card.bitpayInvoiceUrl,
+ date: $scope.card.date
+ };
+ $scope.loading = true;
+ amazonService.cancelGiftCard(dataSrc, function(err, data) {
+ $scope.loading = null;
+ if (err || data.status != 'SUCCESS') {
+ $scope.error = err || data.status;
+ return;
+ }
+ $scope.refreshGiftCard();
+ });
+ };
+
+ $scope.remove = function() {
+ amazonService.saveGiftCard($scope.card, {remove: true}, function(err) {
+ $modalInstance.close(true);
+ });
+ };
+
+ $scope.refreshGiftCard = function() {
+ $scope.refresh = true;
+ var dataSrc = {
+ creationRequestId: $scope.card.creationRequestId,
+ amount: $scope.card.cardInfo.value.amount,
+ currencyCode: $scope.card.cardInfo.value.currencyCode,
+ bitpayInvoiceId: $scope.card.bitpayInvoiceId,
+ bitpayInvoiceUrl: $scope.card.bitpayInvoiceUrl,
+ date: $scope.card.date
+ };
+ $scope.loading = true;
+ amazonService.createGiftCard(dataSrc, function(err, data) {
+ $scope.loading = null;
+ if (err) {
+ $scope.error = err;
+ return;
+ }
+ $scope.card = data;
+ });
+ };
+
$scope.cancel = lodash.debounce(function() {
- $modalInstance.dismiss('cancel');
+ $modalInstance.close($scope.refresh);
}, 0, 1000);
};
@@ -39,7 +85,7 @@ angular.module('copayApp.controllers').controller('amazonController',
});
var disableCloseModal = $rootScope.$on('closeModal', function() {
- modalInstance.dismiss('cancel');
+ modalInstance.close($scope.refresh);
});
modalInstance.result.finally(function() {
@@ -48,6 +94,10 @@ angular.module('copayApp.controllers').controller('amazonController',
var m = angular.element(document.getElementsByClassName('reveal-modal'));
m.addClass(animationService.modalAnimated.slideOutRight);
});
+
+ modalInstance.result.then(function(refresh) {
+ if (refresh) self.init();
+ }, function() {});
};
});
diff --git a/src/js/controllers/buyAmazon.js b/src/js/controllers/buyAmazon.js
index a4e2da7b8..074fe04af 100644
--- a/src/js/controllers/buyAmazon.js
+++ b/src/js/controllers/buyAmazon.js
@@ -45,11 +45,12 @@ angular.module('copayApp.controllers').controller('buyAmazonController',
});
} catch (e) {
$log.debug(e);
- };
+ };
};
$scope.openWalletsModal = function(wallets) {
self.error = null;
+ self.errorInfo = null;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.type = 'SELL';
$scope.wallets = wallets;
@@ -104,6 +105,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController',
this.createTx = function() {
self.error = null;
+ self.errorInfo = null;
var currency_code = configService.getSync().amazon.testnet ? window.amazon_sandbox_currency_code : window.amazon_currency_code;
var dataSrc = {
@@ -178,6 +180,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController',
self.loading = null;
if (err) {
self.error = err;
+ self.errorInfo = gift;
return;
}
self.giftCard = giftCard;
diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js
index b32411a49..d904a5ef8 100644
--- a/src/js/services/amazonService.js
+++ b/src/js/services/amazonService.js
@@ -43,6 +43,52 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo
return kSigning;
}
+
+ var _getHeaders = function(data, method, endpoint, amz_target) {
+ var content_type = 'application/json';
+ var accept = 'application/json';
+ var amz_date = moment.utc().format('YYYYMMDD[T]HHmmss[Z]');
+ var date_stamp = moment.utc().format('YYYYMMDD');
+ var canonical_querystring = '';
+
+ /************* TASK 1: CREATE A CANONICAL REQUEST *************/
+
+ var canonical_headers =
+ 'accept:' + accept + '\n' +
+ 'content-type:' + content_type + '\n' +
+ 'host:' + credentials.AMAZON_ENDPOINT.replace('https://', '') + '\n' +
+ 'x-amz-date:' + amz_date + '\n' +
+ 'x-amz-target:' + amz_target + '\n';
+
+ var signed_headers = 'accept;content-type;host;x-amz-date;x-amz-target';
+ data = JSON.stringify(data);
+ var payload_hash = CryptoJS.SHA256(data).toString(CryptoJS.enc.Hex);
+ var canonical_request = method + '\n' + endpoint + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;
+
+ /************* TASK 2: CREATE THE STRING TO SIGN *************/
+
+ var algorithm = 'AWS4-HMAC-SHA256';
+ var credential_scope = date_stamp + '/' + credentials.AMAZON_REGION + '/' + credentials.AMAZON_SERVICE_NAME + '/' + 'aws4_request';
+ var hashed_canonical_request = CryptoJS.SHA256(canonical_request).toString(CryptoJS.enc.Hex);
+ var string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashed_canonical_request;
+
+ /************* TASK 3: CALCULATE THE SIGNATURE *************/
+
+ var signing_key = _getSignatureKey();
+ var signature = CryptoJS.HmacSHA256(string_to_sign, signing_key).toString(CryptoJS.enc.Hex)
+ var authorization_header = algorithm + ' ' + 'Credential=' + credentials.AMAZON_ACCESS_KEY + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature;
+
+ /************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************/
+
+ return {
+ 'Content-Type': content_type,
+ 'Accept': accept,
+ 'X-Amz-Date': amz_date,
+ 'X-Amz-Target': amz_target,
+ 'Authorization': authorization_header
+ };
+ };
+
var _getBitPay = function(endpoint) {
return {
method: 'GET',
@@ -125,7 +171,7 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo
root.createGiftCard = function(dataSrc, cb) {
var sandbox = credentials.AMAZON_SANDBOX ? 'T' : 'P'; // T: test - P: production
var now = moment().unix();
- var requestId = credentials.AMAZON_PARTNER_ID + sandbox + now;
+ var requestId = dataSrc.creationRequestId || credentials.AMAZON_PARTNER_ID + sandbox + now;
var data = {
'creationRequestId': requestId,
@@ -136,66 +182,55 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo
}
};
- var content_type = 'application/json';
- var accept = 'application/json';
- var amz_date = moment.utc().format('YYYYMMDD[T]HHmmss[Z]');
- var date_stamp = moment.utc().format('YYYYMMDD');
+ var method = 'POST';
+ var endpoint = '/CreateGiftCard';
var amz_target = 'com.amazonaws.agcod.AGCODService.CreateGiftCard';
- var canonical_querystring = '';
- /************* TASK 1: CREATE A CANONICAL REQUEST *************/
-
- var canonical_headers =
- 'accept:' + accept + '\n' +
- 'content-type:' + content_type + '\n' +
- 'host:' + credentials.AMAZON_ENDPOINT.replace('https://', '') + '\n' +
- 'x-amz-date:' + amz_date + '\n' +
- 'x-amz-target:' + amz_target + '\n';
-
- var signed_headers = 'accept;content-type;host;x-amz-date;x-amz-target';
- data = JSON.stringify(data);
- var payload_hash = CryptoJS.SHA256(data).toString(CryptoJS.enc.Hex);
- var canonical_request = 'POST' + '\n' + '/CreateGiftCard' + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;
-
- /************* TASK 2: CREATE THE STRING TO SIGN *************/
-
- var algorithm = 'AWS4-HMAC-SHA256';
- var credential_scope = date_stamp + '/' + credentials.AMAZON_REGION + '/' + credentials.AMAZON_SERVICE_NAME + '/' + 'aws4_request';
- var hashed_canonical_request = CryptoJS.SHA256(canonical_request).toString(CryptoJS.enc.Hex);
- var string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashed_canonical_request;
-
- /************* TASK 3: CALCULATE THE SIGNATURE *************/
-
- var signing_key = _getSignatureKey();
- var signature = CryptoJS.HmacSHA256(string_to_sign, signing_key).toString(CryptoJS.enc.Hex)
- var authorization_header = algorithm + ' ' + 'Credential=' + credentials.AMAZON_ACCESS_KEY + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature;
-
- /************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************/
-
- var headers = {
- 'Content-Type': content_type,
- 'Accept': accept,
- 'X-Amz-Date': amz_date,
- 'X-Amz-Target': amz_target,
- 'Authorization': authorization_header
- };
+ var headers = _getHeaders(data, method, endpoint, amz_target);
$http({
- 'method': 'POST',
- 'url': credentials.AMAZON_ENDPOINT + '/CreateGiftCard',
- 'data': data,
+ 'method': method,
+ 'url': credentials.AMAZON_ENDPOINT + endpoint,
+ 'data': JSON.stringify(data),
'headers': headers
}).then(function(data) {
- $log.info('Amazon Create Gift Card: SUCCESS');
+ $log.info('Amazon.com Gift Card Create/Update: SUCCESS');
var newData = data.data;
newData['bitpayInvoiceId'] = dataSrc.bitpayInvoiceId;
newData['bitpayInvoiceUrl'] = dataSrc.bitpayInvoiceUrl;
- newData['date'] = now;
+ newData['date'] = dataSrc.date || now;
root.saveGiftCard(newData, null, function(err) {
return cb(null, newData);
});
}, function(data) {
- $log.error('Amazon Create Gift Card: ERROR ' + data.statusText);
+ $log.error('Amazon.com Gift Card Create/Update: ERROR ' + data.statusText);
+ return cb(data.statusText);
+ });
+ };
+
+ root.cancelGiftCard = function(dataSrc, cb) {
+ var data = {
+ 'creationRequestId': dataSrc.creationRequestId,
+ 'partnerId': credentials.AMAZON_PARTNER_ID,
+ 'gcId': dataSrc.gcId,
+ };
+
+ var method = 'POST';
+ var endpoint = '/CancelGiftCard';
+ var amz_target = 'com.amazonaws.agcod.AGCODService.CancelGiftCard';
+
+ var headers = _getHeaders(data, method, endpoint, amz_target);
+
+ $http({
+ 'method': method,
+ 'url': credentials.AMAZON_ENDPOINT + endpoint,
+ 'data': JSON.stringify(data),
+ 'headers': headers
+ }).then(function(data) {
+ $log.info('Amazon.com Gift Card Cancel: SUCCESS');
+ return cb(null, data.data);
+ }, function(data) {
+ $log.error('Amazon.com Gift Card Cancel: ERROR ' + data.statusText);
return cb(data.statusText);
});
};