Starting to integrate BIP70 payment protocol into new send flow.
This commit is contained in:
parent
d7fabc3642
commit
fb4bc1563c
5 changed files with 120 additions and 88 deletions
|
|
@ -2179,7 +2179,7 @@ msgid "Payment details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: www/views/modals/paypro.html:6
|
#: www/views/modals/paypro.html:6
|
||||||
msgid "Payment request"
|
msgid "Payment Request"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: www/views/mercadoLibreCards.html:22
|
#: www/views/mercadoLibreCards.html:22
|
||||||
|
|
@ -3761,3 +3761,7 @@ msgstr ""
|
||||||
#: www/views/review.html:69
|
#: www/views/review.html:69
|
||||||
msgid "Less than 1 cent"
|
msgid "Less than 1 cent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/js/services/incomingData.js:129
|
||||||
|
msgid "This invoice is no longer accepting payments"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -26,8 +26,8 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
|
||||||
$scope.coin = $scope.params.coin; // Contacts have a coin embedded
|
$scope.coin = $scope.params.coin; // Contacts have a coin embedded
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.params.amount) { // There is an amount, so presume that it a payment request
|
if ($scope.params.amount) { // There is an amount, so presume that it is a payment request
|
||||||
$scope.sendFlowTitle = gettextCatalog.getString('Payment request');
|
$scope.sendFlowTitle = gettextCatalog.getString('Payment Request');
|
||||||
$scope.specificAmount = $scope.specificAlternativeAmount = '';
|
$scope.specificAmount = $scope.specificAlternativeAmount = '';
|
||||||
$scope.requestAmount = (($state.params.amount) * (1 / config.unitToSatoshi)).toFixed(config.unitDecimals);
|
$scope.requestAmount = (($state.params.amount) * (1 / config.unitToSatoshi)).toFixed(config.unitDecimals);
|
||||||
$scope.isPaymentRequest = true;
|
$scope.isPaymentRequest = true;
|
||||||
|
|
@ -54,16 +54,9 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.thirdParty) {
|
if ($scope.thirdParty) {
|
||||||
|
|
||||||
// Third party services specific logic
|
// Third party services specific logic
|
||||||
|
handleThirdPartyIfBip70PaymentProtocol();
|
||||||
if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
|
handleThirdPartyIfShapeshift();
|
||||||
if ($scope.coin === 'bch') {
|
|
||||||
$scope.coin = 'btc';
|
|
||||||
} else {
|
|
||||||
$scope.coin = 'bch';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$scope.coin || $scope.coin === 'bch') { // if no specific coin is set or coin is set to bch
|
if (!$scope.coin || $scope.coin === 'bch') { // if no specific coin is set or coin is set to bch
|
||||||
|
|
@ -87,6 +80,26 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleThirdPartyIfBip70PaymentProtocol() {
|
||||||
|
if ($scope.thirdParty.id === 'bip70PaymentProtocol') {
|
||||||
|
$scope.coin = $scope.thirdParty.coin;
|
||||||
|
$scope.requestAmount = $scope.thirdParty.details.
|
||||||
|
console.log('paypro details:', $scope.thirdParty.details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleThirdPartyIfShapeshift() {
|
||||||
|
if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
|
||||||
|
if ($scope.coin === 'bch') {
|
||||||
|
$scope.coin = 'btc';
|
||||||
|
} else {
|
||||||
|
$scope.coin = 'bch';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$scope.useWallet = function(wallet) {
|
$scope.useWallet = function(wallet) {
|
||||||
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
|
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
|
||||||
$scope.params['fromWalletId'] = wallet.id;
|
$scope.params['fromWalletId'] = wallet.id;
|
||||||
|
|
|
||||||
|
|
@ -121,9 +121,14 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
var coin = data.indexOf('bitcoincash') >= 0 ? 'bch' : 'btc';
|
var coin = data.indexOf('bitcoincash') >= 0 ? 'bch' : 'btc';
|
||||||
data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, ''));
|
data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, ''));
|
||||||
if (coin == 'bch') {
|
if (coin == 'bch') {
|
||||||
payproService.getPayProDetailsViaHttp(data, function(err, details) {
|
payproService.getPayProDetailsViaHttp(data, function onGetPayProDetailsViaHttp(err, details) {
|
||||||
if (err) {
|
if (err) {
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), err)
|
var message = err.toString();
|
||||||
|
if (typeof err.data === 'string') {
|
||||||
|
// i.e. 'This invoice is no longer accepting payments'
|
||||||
|
message = gettextCatalog.getString(err.data);
|
||||||
|
}
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), message)
|
||||||
} else {
|
} else {
|
||||||
handlePayPro(createBchPayProObject(details), coin);
|
handlePayPro(createBchPayProObject(details), coin);
|
||||||
}
|
}
|
||||||
|
|
@ -415,12 +420,15 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePayPro(payProDetails, coin) {
|
function handlePayPro(payProDetails, coin) {
|
||||||
|
var thirdPartyData = {
|
||||||
|
id: 'bip70PaymentProtocol',
|
||||||
|
coin: coin,
|
||||||
|
details: payProDetails
|
||||||
|
};
|
||||||
var stateParams = {
|
var stateParams = {
|
||||||
amount: payProDetails.amount,
|
amount: payProDetails.amount,
|
||||||
toAddress: payProDetails.toAddress,
|
toAddr: payProDetails.toAddress,
|
||||||
description: payProDetails.memo,
|
thirdParty: JSON.stringify(thirdPartyData)
|
||||||
paypro: payProDetails,
|
|
||||||
coin: coin,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// fee
|
// fee
|
||||||
|
|
@ -434,7 +442,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$state.transitionTo('tabs.send.confirm', stateParams);
|
$state.transitionTo('tabs.send.origin', stateParams);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
76
src/js/services/paypro.service.js
Normal file
76
src/js/services/paypro.service.js
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('copayApp.services')
|
||||||
|
.factory('payproService', payproService);
|
||||||
|
|
||||||
|
function payproService(gettextCatalog, $http, $log, ongoingProcess, platformInfo, profileService) {
|
||||||
|
|
||||||
|
var service = {
|
||||||
|
getPayProDetails: getPayProDetails,
|
||||||
|
getPayProDetailsViaHttp: getPayProDetailsViaHttp,
|
||||||
|
broadcastBchTx: broadcastBchTx
|
||||||
|
};
|
||||||
|
|
||||||
|
return service;
|
||||||
|
|
||||||
|
function getPayProDetails(uri, coin, cb, disableLoader) {
|
||||||
|
if (!cb) cb = function() {};
|
||||||
|
|
||||||
|
var wallet = profileService.getWallets({
|
||||||
|
onlyComplete: true,
|
||||||
|
coin: coin
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (!wallet) return cb();
|
||||||
|
|
||||||
|
if (platformInfo.isChromeApp) {
|
||||||
|
return cb(gettextCatalog.getString('Payment Protocol not supported on Chrome App'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$log.debug('Fetch PayPro Request...', uri);
|
||||||
|
|
||||||
|
if (!disableLoader) ongoingProcess.set('fetchingPayPro', true);
|
||||||
|
|
||||||
|
wallet.fetchPayPro({
|
||||||
|
payProUrl: uri,
|
||||||
|
}, function(err, paypro) {
|
||||||
|
if (!disableLoader) ongoingProcess.set('fetchingPayPro', false);
|
||||||
|
if (err) return cb(gettextCatalog.getString('Could Not Fetch Payment: Check if it is still valid'));
|
||||||
|
else if (!paypro.verified) {
|
||||||
|
$log.warn('Failed to verify payment protocol signatures');
|
||||||
|
return cb(gettextCatalog.getString('Payment Protocol Invalid'));
|
||||||
|
}
|
||||||
|
return cb(null, paypro);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPayProDetailsViaHttp(uri, cb) {
|
||||||
|
var config = {
|
||||||
|
headers: {'Accept': 'application/payment-request'}
|
||||||
|
};
|
||||||
|
$http.get(uri, config).then(function onGetPayProDetailsSuccess(response) {
|
||||||
|
return cb(null, response.data);
|
||||||
|
}, function onGetPayProDetailsError(error) {
|
||||||
|
return cb(error, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function broadcastBchTx(signedTxp, cb) {
|
||||||
|
var config = {
|
||||||
|
headers: {'Content-Type': 'application/payment'}
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
currency: 'BCH',
|
||||||
|
transactions: [signedTxp.raw]
|
||||||
|
};
|
||||||
|
|
||||||
|
$http.post(signedTxp.payProUrl, data, config).then(function(response) {
|
||||||
|
signedTxp.response = response.data;
|
||||||
|
return cb(null, signedTxp);
|
||||||
|
}, function(error) {
|
||||||
|
return cb(error.data, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('copayApp.services').factory('payproService',
|
|
||||||
function(profileService, platformInfo, gettextCatalog, ongoingProcess, $log, $http) {
|
|
||||||
|
|
||||||
var ret = {};
|
|
||||||
|
|
||||||
ret.getPayProDetails = function(uri, coin, cb, disableLoader) {
|
|
||||||
if (!cb) cb = function() {};
|
|
||||||
|
|
||||||
var wallet = profileService.getWallets({
|
|
||||||
onlyComplete: true,
|
|
||||||
coin: coin
|
|
||||||
})[0];
|
|
||||||
|
|
||||||
if (!wallet) return cb();
|
|
||||||
|
|
||||||
if (platformInfo.isChromeApp) {
|
|
||||||
return cb(gettextCatalog.getString('Payment Protocol not supported on Chrome App'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$log.debug('Fetch PayPro Request...', uri);
|
|
||||||
|
|
||||||
if (!disableLoader) ongoingProcess.set('fetchingPayPro', true);
|
|
||||||
|
|
||||||
wallet.fetchPayPro({
|
|
||||||
payProUrl: uri,
|
|
||||||
}, function(err, paypro) {
|
|
||||||
if (!disableLoader) ongoingProcess.set('fetchingPayPro', false);
|
|
||||||
if (err) return cb(gettextCatalog.getString('Could Not Fetch Payment: Check if it is still valid'));
|
|
||||||
else if (!paypro.verified) {
|
|
||||||
$log.warn('Failed to verify payment protocol signatures');
|
|
||||||
return cb(gettextCatalog.getString('Payment Protocol Invalid'));
|
|
||||||
}
|
|
||||||
return cb(null, paypro);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ret.getPayProDetailsViaHttp = function(uri, cb) {
|
|
||||||
var config = {
|
|
||||||
headers: {'Accept': 'application/payment-request'}
|
|
||||||
};
|
|
||||||
$http.get(uri, config).then(function(response) {
|
|
||||||
return cb(null, response.data);
|
|
||||||
}, function(error) {
|
|
||||||
return cb(error, null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.broadcastBchTx = function(signedTxp, cb) {
|
|
||||||
var config = {
|
|
||||||
headers: {'Content-Type': 'application/payment'}
|
|
||||||
};
|
|
||||||
|
|
||||||
var data = {
|
|
||||||
currency: 'BCH',
|
|
||||||
transactions: [signedTxp.raw]
|
|
||||||
};
|
|
||||||
|
|
||||||
$http.post(signedTxp.payProUrl, data, config).then(function(response) {
|
|
||||||
signedTxp.response = response.data;
|
|
||||||
return cb(null, signedTxp);
|
|
||||||
}, function(error) {
|
|
||||||
return cb(error.data, null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
});
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue