access refunds correctly

This commit is contained in:
Florian Dold 2018-01-18 01:37:30 +01:00
parent d4c2f6f6f9
commit 82d9c2a7cd
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
11 changed files with 76 additions and 33 deletions

View File

@ -782,6 +782,8 @@ export interface PurchaseRecord {
* Set to 0 if no refund was made on the purchase. * Set to 0 if no refund was made on the purchase.
*/ */
timestamp_refund: number; timestamp_refund: number;
lastSessionSig: string | undefined;
} }
@ -889,6 +891,7 @@ export namespace Stores {
keyPath: "id", keyPath: "id",
}); });
} }
urlIndex = new Index<string, ProposalDownloadRecord>(this, "urlIndex", "url");
timestampIndex = new Index<string, ProposalDownloadRecord>(this, "timestampIndex", "timestamp"); timestampIndex = new Index<string, ProposalDownloadRecord>(this, "timestampIndex", "timestamp");
} }

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:" msgid "Exchanges in the wallet:"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:175 #: src/webex/pages/confirm-contract.tsx:188
#, c-format #, c-format
msgid "You have insufficient funds of the requested currency in your wallet." msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "" msgstr ""
#. tslint:disable-next-line:max-line-length #. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:177 #: src/webex/pages/confirm-contract.tsx:190
#, c-format #, c-format
msgid "" msgid ""
"You do not have any funds from an exchange that is accepted by this " "You do not have any funds from an exchange that is accepted by this "
@ -56,12 +56,12 @@ msgid ""
"wallet." "wallet."
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:236 #: src/webex/pages/confirm-contract.tsx:249
#, c-format #, c-format
msgid "The merchant%1$s offers you to purchase:\n" msgid "The merchant%1$s offers you to purchase:\n"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:257 #: src/webex/pages/confirm-contract.tsx:270
#, fuzzy, c-format #, fuzzy, c-format
msgid "Confirm payment" msgid "Confirm payment"
msgstr "Bezahlung bestätigen" msgstr "Bezahlung bestätigen"

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:" msgid "Exchanges in the wallet:"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:175 #: src/webex/pages/confirm-contract.tsx:188
#, c-format #, c-format
msgid "You have insufficient funds of the requested currency in your wallet." msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "" msgstr ""
#. tslint:disable-next-line:max-line-length #. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:177 #: src/webex/pages/confirm-contract.tsx:190
#, c-format #, c-format
msgid "" msgid ""
"You do not have any funds from an exchange that is accepted by this " "You do not have any funds from an exchange that is accepted by this "
@ -56,12 +56,12 @@ msgid ""
"wallet." "wallet."
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:236 #: src/webex/pages/confirm-contract.tsx:249
#, c-format #, c-format
msgid "The merchant%1$s offers you to purchase:\n" msgid "The merchant%1$s offers you to purchase:\n"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:257 #: src/webex/pages/confirm-contract.tsx:270
#, c-format #, c-format
msgid "Confirm payment" msgid "Confirm payment"
msgstr "" msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:" msgid "Exchanges in the wallet:"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:175 #: src/webex/pages/confirm-contract.tsx:188
#, c-format #, c-format
msgid "You have insufficient funds of the requested currency in your wallet." msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "" msgstr ""
#. tslint:disable-next-line:max-line-length #. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:177 #: src/webex/pages/confirm-contract.tsx:190
#, c-format #, c-format
msgid "" msgid ""
"You do not have any funds from an exchange that is accepted by this " "You do not have any funds from an exchange that is accepted by this "
@ -56,12 +56,12 @@ msgid ""
"wallet." "wallet."
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:236 #: src/webex/pages/confirm-contract.tsx:249
#, c-format #, c-format
msgid "The merchant%1$s offers you to purchase:\n" msgid "The merchant%1$s offers you to purchase:\n"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:257 #: src/webex/pages/confirm-contract.tsx:270
#, c-format #, c-format
msgid "Confirm payment" msgid "Confirm payment"
msgstr "" msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:" msgid "Exchanges in the wallet:"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:175 #: src/webex/pages/confirm-contract.tsx:188
#, c-format #, c-format
msgid "You have insufficient funds of the requested currency in your wallet." msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "" msgstr ""
#. tslint:disable-next-line:max-line-length #. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:177 #: src/webex/pages/confirm-contract.tsx:190
#, c-format #, c-format
msgid "" msgid ""
"You do not have any funds from an exchange that is accepted by this " "You do not have any funds from an exchange that is accepted by this "
@ -56,12 +56,12 @@ msgid ""
"wallet." "wallet."
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:236 #: src/webex/pages/confirm-contract.tsx:249
#, c-format #, c-format
msgid "The merchant%1$s offers you to purchase:\n" msgid "The merchant%1$s offers you to purchase:\n"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:257 #: src/webex/pages/confirm-contract.tsx:270
#, c-format #, c-format
msgid "Confirm payment" msgid "Confirm payment"
msgstr "" msgstr ""

View File

@ -42,13 +42,13 @@ msgstr ""
msgid "Exchanges in the wallet:" msgid "Exchanges in the wallet:"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:175 #: src/webex/pages/confirm-contract.tsx:188
#, c-format #, c-format
msgid "You have insufficient funds of the requested currency in your wallet." msgid "You have insufficient funds of the requested currency in your wallet."
msgstr "" msgstr ""
#. tslint:disable-next-line:max-line-length #. tslint:disable-next-line:max-line-length
#: src/webex/pages/confirm-contract.tsx:177 #: src/webex/pages/confirm-contract.tsx:190
#, c-format #, c-format
msgid "" msgid ""
"You do not have any funds from an exchange that is accepted by this " "You do not have any funds from an exchange that is accepted by this "
@ -56,12 +56,12 @@ msgid ""
"wallet." "wallet."
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:236 #: src/webex/pages/confirm-contract.tsx:249
#, c-format #, c-format
msgid "The merchant%1$s offers you to purchase:\n" msgid "The merchant%1$s offers you to purchase:\n"
msgstr "" msgstr ""
#: src/webex/pages/confirm-contract.tsx:257 #: src/webex/pages/confirm-contract.tsx:270
#, c-format #, c-format
msgid "Confirm payment" msgid "Confirm payment"
msgstr "" msgstr ""

View File

@ -685,6 +685,7 @@ export class QueryRoot {
put<T>(store: Store<T>, val: T, keyName?: string): QueryRoot { put<T>(store: Store<T>, val: T, keyName?: string): QueryRoot {
this.checkFinished(); this.checkFinished();
const doPut = (tx: IDBTransaction) => { const doPut = (tx: IDBTransaction) => {
console.log("put into", store.name, "value", val);
const req = tx.objectStore(store.name).put(val); const req = tx.objectStore(store.name).put(val);
if (keyName) { if (keyName) {
req.onsuccess = () => { req.onsuccess = () => {

View File

@ -312,6 +312,7 @@ export class Wallet {
private processPreCoinThrottle: {[url: string]: number} = {}; private processPreCoinThrottle: {[url: string]: number} = {};
private timerGroup: TimerGroup; private timerGroup: TimerGroup;
private speculativePayData: SpeculativePayData | undefined; private speculativePayData: SpeculativePayData | undefined;
private cachedNextUrl: { [fulfillmentUrl: string]: string } = {};
/** /**
* Set of identifiers for running operations. * Set of identifiers for running operations.
@ -650,6 +651,7 @@ export class Wallet {
contractTerms: proposal.contractTerms, contractTerms: proposal.contractTerms,
contractTermsHash: proposal.contractTermsHash, contractTermsHash: proposal.contractTermsHash,
finished: false, finished: false,
lastSessionSig: undefined,
merchantSig: proposal.merchantSig, merchantSig: proposal.merchantSig,
payReq, payReq,
refundsDone: {}, refundsDone: {},
@ -673,13 +675,19 @@ export class Wallet {
* Returns an id for it to retrieve it later. * Returns an id for it to retrieve it later.
*/ */
async downloadProposal(url: string): Promise<number> { async downloadProposal(url: string): Promise<number> {
const oldProposal = await this.q().getIndexed(Stores.proposals.urlIndex, url);
if (oldProposal) {
return oldProposal.id!;
}
const { priv, pub } = await this.cryptoApi.createEddsaKeypair(); const { priv, pub } = await this.cryptoApi.createEddsaKeypair();
const parsed_url = new URI(url); const parsed_url = new URI(url);
url = parsed_url.setQuery({ nonce: pub }).href(); const urlWithNonce = parsed_url.setQuery({ nonce: pub }).href();
console.log("downloading contract from '" + url + "'"); console.log("downloading contract from '" + urlWithNonce + "'");
let resp; let resp;
try { try {
resp = await axios.get(url, { validateStatus: (s) => s === 200 }); resp = await axios.get(urlWithNonce, { validateStatus: (s) => s === 200 });
} catch (e) { } catch (e) {
console.log("contract download failed", e); console.log("contract download failed", e);
throw e; throw e;
@ -707,7 +715,7 @@ export class Wallet {
return id; return id;
} }
async submitPay(purchase: PurchaseRecord, sessionId: string | undefined): Promise<ConfirmPayResult> { private async submitPay(purchase: PurchaseRecord, sessionId: string | undefined): Promise<ConfirmPayResult> {
let resp; let resp;
const payReq = { ...purchase.payReq, session_id: sessionId }; const payReq = { ...purchase.payReq, session_id: sessionId };
try { try {
@ -724,13 +732,17 @@ export class Wallet {
} }
const merchantResp = resp.data; const merchantResp = resp.data;
console.log("got success from pay_url"); console.log("got success from pay_url");
await this.paymentSucceeded(purchase.contractTermsHash, merchantResp.sig);
const fu = new URI(purchase.contractTerms.fulfillment_url); const fu = new URI(purchase.contractTerms.fulfillment_url);
fu.addSearch("order_id", purchase.contractTerms.order_id); fu.addSearch("order_id", purchase.contractTerms.order_id);
if (merchantResp.session_sig) { if (merchantResp.session_sig) {
fu.addSearch("session_sig", merchantResp.session_sig); fu.addSearch("session_sig", merchantResp.session_sig);
purchase.lastSessionSig = merchantResp.session_sig;
console.log("updating session sig", purchase);
await this.q().put(Stores.purchases, purchase).finish();
} }
await this.paymentSucceeded(purchase.contractTermsHash, merchantResp.sig);
const nextUrl = fu.href(); const nextUrl = fu.href();
this.cachedNextUrl[purchase.contractTerms.fulfillment_url] = nextUrl;
return { nextUrl }; return { nextUrl };
} }
@ -887,6 +899,7 @@ export class Wallet {
contractTerms: t.contractTerms, contractTerms: t.contractTerms,
contractTermsHash: t.contractTermsHash, contractTermsHash: t.contractTermsHash,
found: true, found: true,
lastSessionSig: t.lastSessionSig,
payReq: t.payReq, payReq: t.payReq,
}; };
} }
@ -911,6 +924,7 @@ export class Wallet {
contractTerms: t.contractTerms, contractTerms: t.contractTerms,
contractTermsHash: t.contractTermsHash, contractTermsHash: t.contractTermsHash,
found: true, found: true,
lastSessionSig: t.lastSessionSig,
payReq: t.payReq, payReq: t.payReq,
}; };
} }
@ -1075,7 +1089,7 @@ export class Wallet {
id: hash(senderWire), id: hash(senderWire),
senderWire, senderWire,
}; };
await this.q().put(Stores.senderWires, rec); await this.q().put(Stores.senderWires, rec).finish();
} }
await this.updateExchangeUsedTime(req.exchange); await this.updateExchangeUsedTime(req.exchange);
@ -2259,10 +2273,10 @@ export class Wallet {
} }
async paymentSucceeded(contractTermsHash: string, merchantSig: string): Promise<any> { private async paymentSucceeded(contractTermsHash: string, merchantSig: string): Promise<any> {
const doPaymentSucceeded = async() => { const doPaymentSucceeded = async() => {
const t = await this.q().get<PurchaseRecord>(Stores.purchases, const t = await this.q().get<PurchaseRecord>(Stores.purchases,
contractTermsHash); contractTermsHash);
if (!t) { if (!t) {
console.error("contract not found"); console.error("contract not found");
return; return;
@ -2560,7 +2574,7 @@ export class Wallet {
} }
// FIXME: validate schema // FIXME: validate schema
const refundPermissions = resp.data; const refundPermissions = resp.data.refund_permissions;
if (!refundPermissions.length) { if (!refundPermissions.length) {
console.warn("got empty refund list"); console.warn("got empty refund list");
@ -2871,8 +2885,14 @@ export class Wallet {
} }
/**
* Synchronously get the paid URL for a resource from the plain fulfillment
* URL. Returns undefined if the fulfillment URL is not a resource that was
* payed for, or if it is not cached anymore. Use the asynchronous
* queryPaymentByFulfillmentUrl to avoid false negatives.
*/
getNextUrlFromResourceUrl(resourceUrl: string): string | undefined { getNextUrlFromResourceUrl(resourceUrl: string): string | undefined {
return; return this.cachedNextUrl[resourceUrl];
} }
/** /**

View File

@ -105,6 +105,7 @@ interface ContractPromptProps {
proposalId?: number; proposalId?: number;
contractUrl?: string; contractUrl?: string;
sessionId?: string; sessionId?: string;
resourceUrl?: string;
} }
interface ContractPromptState { interface ContractPromptState {
@ -146,6 +147,18 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
} }
async update() { async update() {
if (this.props.resourceUrl) {
const p = await wxApi.queryPaymentByFulfillmentUrl(this.props.resourceUrl);
console.log("query for resource url", this.props.resourceUrl, "result", p);
if (p.found) {
const nextUrl = new URI(p.contractTerms.fulfillment_url);
nextUrl.addSearch("order_id", p.contractTerms.order_id);
if (p.lastSessionSig) {
nextUrl.addSearch("session_sig", p.lastSessionSig);
}
location.href = nextUrl.href();
}
}
let proposalId = this.props.proposalId; let proposalId = this.props.proposalId;
if (proposalId === undefined) { if (proposalId === undefined) {
if (this.props.contractUrl === undefined) { if (this.props.contractUrl === undefined) {
@ -285,7 +298,9 @@ document.addEventListener("DOMContentLoaded", () => {
const sessionId = query.sessionId; const sessionId = query.sessionId;
const contractUrl = query.contractUrl; const contractUrl = query.contractUrl;
const resourceUrl = query.resourceUrl;
ReactDOM.render( ReactDOM.render(
<ContractPrompt {...{ proposalId, contractUrl, sessionId }}/>, <ContractPrompt {...{ proposalId, contractUrl, sessionId, resourceUrl }}/>,
document.getElementById("contract")!); document.getElementById("contract")!);
}); });

View File

@ -238,7 +238,7 @@ export function confirmReserve(reservePub: string): Promise<void> {
/** /**
* Query for a payment by fulfillment URL. * Query for a payment by fulfillment URL.
*/ */
export function queryPayment(url: string): Promise<QueryPaymentResult> { export function queryPaymentByFulfillmentUrl(url: string): Promise<QueryPaymentResult> {
return callBackend("query-payment", { url }); return callBackend("query-payment", { url });
} }

View File

@ -416,11 +416,12 @@ async function talerPay(fields: any, url: string, tabId: number): Promise<string
if (p.lastSessionSig) { if (p.lastSessionSig) {
nextUrl.addSearch("session_sig", p.lastSessionSig); nextUrl.addSearch("session_sig", p.lastSessionSig);
} }
return url; return nextUrl.href();
}; };
if (fields.resource_url) { if (fields.resource_url) {
const p = await w.queryPaymentByFulfillmentUrl(fields.resource_url); const p = await w.queryPaymentByFulfillmentUrl(fields.resource_url);
console.log("query for resource url", fields.resource_url, "result", p);
if (p.found) { if (p.found) {
return goToPayment(p); return goToPayment(p);
} }
@ -519,6 +520,9 @@ function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[], url: stri
if (fields.session_id) { if (fields.session_id) {
uri.addSearch("sessionId", fields.session_id); uri.addSearch("sessionId", fields.session_id);
} }
if (fields.resource_url) {
uri.addSearch("resourceUrl", fields.resource_url);
}
return { redirectUrl: uri.href() }; return { redirectUrl: uri.href() };
} }