diff options
| author | Florian Dold <florian.dold@gmail.com> | 2018-01-22 01:12:08 +0100 | 
|---|---|---|
| committer | Florian Dold <florian.dold@gmail.com> | 2018-01-22 01:12:08 +0100 | 
| commit | ae177549a5818e2698253ef17a11b1effbd66fdb (patch) | |
| tree | 7ac7765d2af595b1d22367740d88a397b6b9868a /src/webex | |
| parent | 1671d9a508b803af31762bcd9508e70eb40e7b48 (diff) | |
implement flicker-free refunds
Diffstat (limited to 'src/webex')
| -rw-r--r-- | src/webex/messages.ts | 4 | ||||
| -rw-r--r-- | src/webex/pages/refund.tsx | 33 | ||||
| -rw-r--r-- | src/webex/wxApi.ts | 7 | ||||
| -rw-r--r-- | src/webex/wxBackend.ts | 22 | 
4 files changed, 57 insertions, 9 deletions
| 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<RefundStatusViewProps, RefundStat    }    render(): JSX.Element { +    if (!this.props.contractTermsHash && !this.props.refundUrl) { +      return ( +        <div id="main"> +          <span>Error: Neither contract terms hash nor refund url given.</span> +        </div> +      ); +    }      const purchase = this.state.purchase;      if (!purchase) { +      let message;        if (this.state.gotResult) { -        return <span>No purchase with contract terms hash {this.props.contractTermsHash} found</span>; +        message = <span>No purchase with contract terms hash {this.props.contractTermsHash} found</span>;        } else { -        return <span>...</span>; +        message = <span>...</span>;        } +      return <div id="main">{message}</div>;      }      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<RefundStatusViewProps, RefundStat    }    async update() { -    const purchase = await wxApi.getPurchase(this.props.contractTermsHash); +    let contractTermsHash = this.state.contractTermsHash; +    if (!contractTermsHash) { +      const refundUrl = this.props.refundUrl; +      if (!refundUrl) { +        console.error("neither contractTermsHash nor refundUrl is given"); +        return; +      } +      contractTermsHash = await wxApi.acceptRefund(refundUrl); +    } +    const purchase = await wxApi.getPurchase(contractTermsHash);      console.log("got purchase", purchase);      const refundsDone = Object.keys(purchase.refundsDone).map((x) => 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(<RefundStatusView contractTermsHash={contractTermsHash} />, container); +  const contractTermsHash = query.contractTermsHash; +  const refundUrl = query.refundUrl; +  ReactDOM.render(<RefundStatusView contractTermsHash={contractTermsHash} refundUrl={refundUrl} />, 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<void> {  export function downloadProposal(url: string): Promise<number> {    return callBackend("download-proposal", { url });  } + +/** + * Download a refund and accept it. + */ +export function acceptRefund(refundUrl: string): Promise<string> { +  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<string    }    if (fields.refund_url) {      console.log("processing refund"); -    const hc = await w.acceptRefund(fields.refund_url); -    return chrome.extension.getURL(`/src/webex/pages/refund.html?contractTermsHash=${hc}`); +    const uri = new URI(chrome.extension.getURL("/src/webex/pages/refund.html")); +    return uri.query({ refundUrl: fields.refund_url }).href();    }    if (fields.tip) {      const uri = new URI(chrome.extension.getURL("/src/webex/pages/tip.html")); @@ -507,10 +509,24 @@ function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[], url: stri      return { redirectUrl: uri.href() };    } +  // Synchronous fast path for refund +  if (fields.refund_url) { +    console.log("processing refund"); +    const uri = new URI(chrome.extension.getURL("/src/webex/pages/refund.html")); +    uri.query({ refundUrl: fields.refund_url }); +    return { redirectUrl: uri.href }; +  } +    // We need to do some asynchronous operation, we can't directly redirect    talerPay(fields, url, tabId).then((nextUrl) => {      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", +      });      }    }); | 
