Starting to integrate BIP70 payment protocol into new send flow.

This commit is contained in:
Brendon Duncan 2018-08-06 12:04:14 +12:00
commit fb4bc1563c
5 changed files with 120 additions and 88 deletions

View file

@ -2179,7 +2179,7 @@ msgid "Payment details"
msgstr ""
#: www/views/modals/paypro.html:6
msgid "Payment request"
msgid "Payment Request"
msgstr ""
#: www/views/mercadoLibreCards.html:22
@ -3761,3 +3761,7 @@ msgstr ""
#: www/views/review.html:69
msgid "Less than 1 cent"
msgstr ""
#: src/js/services/incomingData.js:129
msgid "This invoice is no longer accepting payments"
msgstr ""

View file

@ -26,8 +26,8 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
$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
$scope.sendFlowTitle = gettextCatalog.getString('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.specificAmount = $scope.specificAlternativeAmount = '';
$scope.requestAmount = (($state.params.amount) * (1 / config.unitToSatoshi)).toFixed(config.unitDecimals);
$scope.isPaymentRequest = true;
@ -54,16 +54,9 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu
}
if ($scope.thirdParty) {
// Third party services specific logic
if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
if ($scope.coin === 'bch') {
$scope.coin = 'btc';
} else {
$scope.coin = 'bch';
}
}
handleThirdPartyIfBip70PaymentProtocol();
handleThirdPartyIfShapeshift();
}
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) {
if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from
$scope.params['fromWalletId'] = wallet.id;

View file

@ -121,9 +121,14 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
var coin = data.indexOf('bitcoincash') >= 0 ? 'bch' : 'btc';
data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, ''));
if (coin == 'bch') {
payproService.getPayProDetailsViaHttp(data, function(err, details) {
payproService.getPayProDetailsViaHttp(data, function onGetPayProDetailsViaHttp(err, details) {
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 {
handlePayPro(createBchPayProObject(details), coin);
}
@ -415,12 +420,15 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
}
function handlePayPro(payProDetails, coin) {
var thirdPartyData = {
id: 'bip70PaymentProtocol',
coin: coin,
details: payProDetails
};
var stateParams = {
amount: payProDetails.amount,
toAddress: payProDetails.toAddress,
description: payProDetails.memo,
paypro: payProDetails,
coin: coin,
toAddr: payProDetails.toAddress,
thirdParty: JSON.stringify(thirdPartyData)
};
// fee
@ -434,7 +442,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
'notify': $state.current.name == 'tabs.send' ? false : true
}).then(function() {
$timeout(function() {
$state.transitionTo('tabs.send.confirm', stateParams);
$state.transitionTo('tabs.send.origin', stateParams);
});
});
}

View 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);
});
}
}

View file

@ -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;
});