From ae177549a5818e2698253ef17a11b1effbd66fdb Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 22 Jan 2018 01:12:08 +0100 Subject: [PATCH] implement flicker-free refunds --- src/wallet.ts | 8 ++++++-- src/webex/messages.ts | 4 ++++ src/webex/pages/refund.tsx | 33 +++++++++++++++++++++++++++------ src/webex/wxApi.ts | 7 +++++++ src/webex/wxBackend.ts | 22 +++++++++++++++++++--- 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/wallet.ts b/src/wallet.ts index 9498fe820..01db8c612 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -2532,6 +2532,10 @@ export class Wallet { } } + /** + * Accept a refund, return the contract hash for the contract + * that was involved in the refund. + */ async acceptRefund(refundUrl: string): Promise { console.log("processing refund"); let resp; @@ -2598,7 +2602,8 @@ export class Wallet { return refundPermissions[0].h_contract_terms; } - async submitRefunds(contractTermsHash: string): Promise { + + private async submitRefunds(contractTermsHash: string): Promise { const purchase = await this.q().get(Stores.purchases, contractTermsHash); if (!purchase) { console.error("not submitting refunds, contract terms not found:", contractTermsHash); @@ -2644,7 +2649,6 @@ export class Wallet { return c; }; - await this.q() .mutate(Stores.purchases, contractTermsHash, transformPurchase) .mutate(Stores.coins, perm.coin_pub, transformCoin) diff --git a/src/webex/messages.ts b/src/webex/messages.ts index e1bd6f12c..2219cdf1d 100644 --- a/src/webex/messages.ts +++ b/src/webex/messages.ts @@ -195,6 +195,10 @@ export interface MessageMap { request: { contractTermsHash: string, sessionId: string | undefined }; response: void; }; + "accept-refund": { + request: { refundUrl: string } + response: string; + }; } /** diff --git a/src/webex/pages/refund.tsx b/src/webex/pages/refund.tsx index 3e82f3667..8164eb664 100644 --- a/src/webex/pages/refund.tsx +++ b/src/webex/pages/refund.tsx @@ -35,10 +35,12 @@ import { AmountDisplay } from "../renderHtml"; import * as wxApi from "../wxApi"; interface RefundStatusViewProps { - contractTermsHash: string; + contractTermsHash?: string; + refundUrl?: string; } interface RefundStatusViewState { + contractTermsHash?: string; purchase?: dbTypes.PurchaseRecord; refundFees?: AmountJson; gotResult: boolean; @@ -102,13 +104,22 @@ class RefundStatusView extends React.Component + Error: Neither contract terms hash nor refund url given. + + ); + } const purchase = this.state.purchase; if (!purchase) { + let message; if (this.state.gotResult) { - return No purchase with contract terms hash {this.props.contractTermsHash} found; + message = No purchase with contract terms hash {this.props.contractTermsHash} found; } else { - return ...; + message = ...; } + return
{message}
; } const merchantName = purchase.contractTerms.merchant.name || "(unknown)"; const summary = purchase.contractTerms.summary || purchase.contractTerms.order_id; @@ -128,7 +139,16 @@ class RefundStatusView extends React.Component purchase.refundsDone[x]); const refundFees = await wxApi.getFullRefundFees( {refundPermissions: refundsDone }); @@ -147,8 +167,9 @@ async function main() { return; } - const contractTermsHash = query.contractTermsHash || "(none)"; - ReactDOM.render(, container); + const contractTermsHash = query.contractTermsHash; + const refundUrl = query.refundUrl; + ReactDOM.render(, container); } document.addEventListener("DOMContentLoaded", () => main()); diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts index 566f45265..8a7bf8250 100644 --- a/src/webex/wxApi.ts +++ b/src/webex/wxApi.ts @@ -363,3 +363,10 @@ export function talerPay(msg: any): Promise { export function downloadProposal(url: string): Promise { return callBackend("download-proposal", { url }); } + +/** + * Download a refund and accept it. + */ +export function acceptRefund(refundUrl: string): Promise { + return callBackend("accept-refund", { refundUrl }); +} diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts index 26b8ff2cf..98b543d28 100644 --- a/src/webex/wxBackend.ts +++ b/src/webex/wxBackend.ts @@ -292,6 +292,8 @@ function handleMessage(sender: MessageSender, } case "get-full-refund-fees": return needsWallet().getFullRefundFees(detail.refundPermissions); + case "accept-refund": + return needsWallet().acceptRefund(detail.refundUrl); case "get-tip-status": { const tipToken = TipToken.checked(detail.tipToken); return needsWallet().getTipStatus(tipToken); @@ -430,8 +432,8 @@ async function talerPay(fields: any, url: string, tabId: number): Promise { if (nextUrl) { - chrome.tabs.update(tabId, { url: nextUrl }); + // We use chrome.tabs.executeScript instead of chrome.tabs.update + // because the latter is buggy when it does not execute in the same + // (micro-?)task as the header callback. + chrome.tabs.executeScript({ + code: `document.location.href = decodeURIComponent("${encodeURI(nextUrl)}");`, + runAt: "document_start", + }); } });