Leave sending the payment blob to the merchant.

This commit is contained in:
Florian Dold 2016-04-06 02:06:57 +02:00
parent 3877ace7dd
commit d5fc7ee42d
6 changed files with 90 additions and 75 deletions

View File

@ -90,6 +90,7 @@ namespace TalerNotify {
callback_url: URI(e.detail.callback_url)
.absoluteTo(document.location.href),
bank_url: document.location.href,
wt_types: JSON.stringify(e.detail.wt_types),
};
let uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
document.location.href = uri.query(params).href();
@ -157,20 +158,17 @@ namespace TalerNotify {
});
});
// Should be: taler-request-payment, taler-result-payment
addHandler('taler-execute-payment', function(e: CustomEvent) {
console.log("got taler-execute-payment in content page");
if (!e.detail.pay_url) {
console.log("field 'pay_url' missing in taler-execute-payment event");
return;
}
const payUrl = e.detail.pay_url;
addHandler("taler-execute-contract", function(e: CustomEvent) {
console.log("got taler-execute-contract in content page");
const msg = {
type: "execute-payment",
detail: {
H_contract: e.detail.H_contract,
},
};
chrome.runtime.sendMessage(msg, (resp) => {
console.log("got resp");
console.dir(resp);
@ -190,25 +188,13 @@ namespace TalerNotify {
throw Error("contract missing");
}
console.log("Making request to ", payUrl);
let r = new XMLHttpRequest();
r.open('post', payUrl);
r.send(JSON.stringify(resp.payReq));
r.onload = () => {
switch (r.status) {
case 200:
console.log("going to", contract.fulfillment_url);
// TODO: Is this the right thing? Does the reload
// TODO: override setting location.href?
window.location.href = subst(contract.fulfillment_url,
e.detail.H_contract);
window.location.reload(true);
break;
default:
console.log("Unexpected status code for $pay_url:", r.status);
break;
let evt = new CustomEvent("taler-notify-payment", {
detail: {
contract: resp.contract,
payment: resp.payReq,
}
};
});
document.dispatchEvent(evt);
});
});
}

View File

@ -103,8 +103,13 @@ export interface IExchangeInfo {
denoms: Denomination[];
}
export interface WireInfo {
[type: string]: any;
}
export interface ReserveCreationInfo {
exchangeInfo: IExchangeInfo;
wireInfo: WireInfo;
selectedDenoms: Denomination[];
withdrawFee: AmountJson;
overhead: AmountJson;

View File

@ -21,7 +21,7 @@
* @author Florian Dold
*/
import {AmountJson, CreateReserveResponse, IExchangeInfo, Denomination, Notifier} from "./types";
import {AmountJson, CreateReserveResponse, IExchangeInfo, Denomination, Notifier, WireInfo} from "./types";
import {HttpResponse, RequestException} from "./http";
import {Query} from "./query";
import {Checkable} from "./checkable";
@ -184,7 +184,6 @@ export class ConfirmReserveRequest {
}
@Checkable.Class
export class Offer {
@Checkable.Value(Contract)
@ -346,12 +345,15 @@ export class Wallet {
* but only if the sum the coins' remaining value exceeds the payment amount.
*/
private getPossibleExchangeCoins(paymentAmount: AmountJson,
depositFeeLimit: AmountJson,
allowedExchanges: ExchangeHandle[]): Promise<ExchangeCoins> {
depositFeeLimit: AmountJson,
allowedExchanges: ExchangeHandle[]): Promise<ExchangeCoins> {
// Mapping from exchange base URL to list of coins together with their
// denomination
let m: ExchangeCoins = {};
let x: number
function storeExchangeCoin(mc, url) {
let exchange: IExchangeInfo = mc[0];
console.log("got coin for exchange", url);
@ -501,8 +503,8 @@ export class Wallet {
console.log("executing confirmPay");
return Promise.resolve().then(() => {
return this.getPossibleExchangeCoins(offer.contract.amount,
offer.contract.max_fee,
offer.contract.exchanges)
offer.contract.max_fee,
offer.contract.exchanges)
}).then((mcs) => {
if (Object.keys(mcs).length == 0) {
console.log("not confirming payment, insufficient coins");
@ -746,7 +748,8 @@ export class Wallet {
* Update the information about a reserve that is stored in the wallet
* by quering the reserve's exchange.
*/
private updateReserve(reservePub: string, exchange: ExchangeInfo): Promise<Reserve> {
private updateReserve(reservePub: string,
exchange: ExchangeInfo): Promise<Reserve> {
return Query(this.db)
.get("reserves", reservePub)
.then((reserve) => {
@ -781,29 +784,47 @@ export class Wallet {
}
getWireInfo(baseUrl: string): Promise<WireInfo> {
baseUrl = canonicalizeBaseUrl(baseUrl);
let reqUrl = URI("wire").absoluteTo(baseUrl);
return this.http.get(reqUrl).then((resp: HttpResponse) => {
if (resp.status != 200) {
throw Error("/wire request failed");
}
let wiJson = JSON.parse(resp.responseText);
if (!wiJson) {
throw Error("/wire response malformed")
}
return wiJson;
});
}
getReserveCreationInfo(baseUrl: string,
amount: AmountJson): Promise<ReserveCreationInfo> {
return this.updateExchangeFromUrl(baseUrl)
.then((exchangeInfo: IExchangeInfo) => {
let selectedDenoms = getWithdrawDenomList(amount,
exchangeInfo.denoms);
let p = this.updateExchangeFromUrl(baseUrl);
return p.then((exchangeInfo: IExchangeInfo) => {
let selectedDenoms = getWithdrawDenomList(amount, exchangeInfo.denoms);
let acc = Amounts.getZero(amount.currency);
for (let d of selectedDenoms) {
acc = Amounts.add(acc, d.fee_withdraw).amount;
}
let actualCoinCost = selectedDenoms
.map((d: Denomination) => Amounts.add(d.value,
d.fee_withdraw).amount)
.reduce((a, b) => Amounts.add(a, b).amount);
return this.getWireInfo(baseUrl).then((wireInfo) => {
let ret: ReserveCreationInfo = {
exchangeInfo,
selectedDenoms,
wireInfo,
withdrawFee: acc,
overhead: Amounts.sub(amount, actualCoinCost).amount,
};
return ret;
});
let acc = Amounts.getZero(amount.currency);
for (let d of selectedDenoms) {
acc = Amounts.add(acc, d.fee_withdraw).amount;
}
let actualCoinCost = selectedDenoms
.map((d: Denomination) => Amounts.add(d.value,
d.fee_withdraw).amount)
.reduce((a, b) => Amounts.add(a, b).amount);
let ret: ReserveCreationInfo = {
exchangeInfo,
selectedDenoms,
withdrawFee: acc,
overhead: Amounts.sub(amount, actualCoinCost).amount,
};
return ret;
});
});
}
@ -834,12 +855,12 @@ export class Wallet {
}
return exchangeInfo.mergeKeys(exchangeKeysJson, this.cryptoApi)
.then(() => {
return Query(this.db)
.put("exchanges", exchangeInfo)
.finish()
.then(() => exchangeInfo);
});
.then(() => {
return Query(this.db)
.put("exchanges", exchangeInfo)
.finish()
.then(() => exchangeInfo);
});
});
});

View File

@ -74,12 +74,17 @@ class Controller {
private request: XMLHttpRequest;
amount: AmountJson;
callbackUrl: string;
wtTypes: string[];
detailCollapsed = m.prop<boolean>(true);
constructor(initialExchangeUrl: string, amount: AmountJson, callbackUrl: string) {
constructor(initialExchangeUrl: string,
amount: AmountJson,
callbackUrl: string,
wt_types: string[]) {
console.log("creating main controller");
this.amount = amount;
this.callbackUrl = callbackUrl;
this.wtTypes = wt_types;
this.timer = new DelayTimer(800, () => this.update());
this.url(initialExchangeUrl);
this.update();
@ -125,7 +130,6 @@ class Controller {
doUpdate();
console.log("got update");
}
@ -139,15 +143,21 @@ class Controller {
}
}
confirmReserve(exchange: string, amount: AmountJson, callback_url: string) {
confirmReserve(rci: ReserveCreationInfo,
exchange: string,
amount: AmountJson,
callback_url: string) {
const d = {exchange, amount};
const cb = (rawResp) => {
if (!rawResp) {
throw Error("empty response");
}
// FIXME: filter out types that bank/exchange don't have in common
let wire_details = rci.wireInfo;
if (!rawResp.error) {
const resp = CreateReserveResponse.checked(rawResp);
let q = {
let q: {[name: string]: string|number} = {
wire_details: JSON.stringify(wire_details),
exchange: resp.exchange,
reserve_pub: resp.reservePub,
amount_value: amount.value,
@ -195,7 +205,8 @@ function view(ctrl: Controller) {
});
mx("button", {
onclick: () => ctrl.confirmReserve(ctrl.url(),
onclick: () => ctrl.confirmReserve(ctrl.reserveCreationInfo,
ctrl.url(),
ctrl.amount,
ctrl.callbackUrl),
disabled: !ctrl.isValidExchange
@ -264,15 +275,6 @@ function renderReserveCreationDetails(rci: ReserveCreationInfo) {
}
interface ExchangeProbeResult {
keyInfo?: any;
}
function probeExchange(exchangeBaseUrl: string): Promise<ExchangeProbeResult> {
throw Error("not implemented");
}
function getSuggestedExchange(currency: string): Promise<string> {
// TODO: make this request go to the wallet backend
// Right now, this is a stub.
@ -297,10 +299,11 @@ export function main() {
const amount = AmountJson.checked(JSON.parse(query.amount));
const callback_url = query.callback_url;
const bank_url = query.bank_url;
const wt_types = JSON.parse(query.wt_types);
getSuggestedExchange(amount.currency)
.then((suggestedExchangeUrl) => {
const controller = () => new Controller(suggestedExchangeUrl, amount, callback_url);
const controller = () => new Controller(suggestedExchangeUrl, amount, callback_url, wt_types);
var ExchangeSelection = {controller, view};
m.mount(document.getElementById("exchange-selection"), ExchangeSelection);
})

View File

@ -11,8 +11,8 @@
<script src="../lib/vendor/lodash.core.min.js"></script>
<script src="../lib/vendor/system-csp-production.src.js"></script>
<script src="../lib/vendor/jed.js"></script>
<script src="../lib/i18n.js"></script>
<script src="../i18n/strings.js"></script>
<script src="../lib/i18n.js"></script>
<script src="../lib/module-trampoline.js"></script>
</head>

View File

@ -136,7 +136,7 @@ namespace WalletBalance {
{config: openInExtension},
i18n`help`);
return i18n.parts`You have no balance to show. Need some ${helpLink}? getting started?`;
return i18n.parts`You have no balance to show. Need some ${helpLink} getting started?`;
}
}