better error report / retry prompt for failed payments

This commit is contained in:
Florian Dold 2017-08-27 04:19:11 +02:00
parent 8697efd2c8
commit 24181bdf20
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
4 changed files with 79 additions and 41 deletions

View File

@ -120,6 +120,7 @@ async function handlePaymentResponse(maybeFoundResponse: QueryPaymentResult) {
// Gives the user the option to retry / abort and refresh // Gives the user the option to retry / abort and refresh
wxApi.logAndDisplayError({ wxApi.logAndDisplayError({
name: "pay-post-failed", name: "pay-post-failed",
contractTerms: walletResp.contractTerms,
message: e.message, message: e.message,
response: e.response, response: e.response,
}); });

View File

@ -41,7 +41,7 @@ import {
getReserveCreationInfo, getReserveCreationInfo,
} from "../wxApi"; } from "../wxApi";
import {renderAmount} from "../renderHtml"; import {Collapsible, renderAmount} from "../renderHtml";
import * as React from "react"; import * as React from "react";
import * as ReactDOM from "react-dom"; import * as ReactDOM from "react-dom";
@ -80,40 +80,6 @@ class EventTrigger {
} }
interface CollapsibleState {
collapsed: boolean;
}
interface CollapsibleProps {
initiallyCollapsed: boolean;
title: string;
}
class Collapsible extends React.Component<CollapsibleProps, CollapsibleState> {
constructor(props: CollapsibleProps) {
super(props);
this.state = { collapsed: props.initiallyCollapsed };
}
render() {
const doOpen = (e: any) => {
this.setState({collapsed: false});
e.preventDefault();
};
const doClose = (e: any) => {
this.setState({collapsed: true});
e.preventDefault();
};
if (this.state.collapsed) {
return <h2><a className="opener opener-collapsed" href="#" onClick={doOpen}>{this.props.title}</a></h2>;
}
return (
<div>
<h2><a className="opener opener-open" href="#" onClick={doClose}>{this.props.title}</a></h2>
{this.props.children}
</div>
);
}
}
function renderAuditorDetails(rci: ReserveCreationInfo|null) { function renderAuditorDetails(rci: ReserveCreationInfo|null) {
console.log("rci", rci); console.log("rci", rci);

View File

@ -29,6 +29,8 @@ import URI = require("urijs");
import * as wxApi from "../wxApi"; import * as wxApi from "../wxApi";
import { Collapsible } from "../renderHtml";
interface ErrorProps { interface ErrorProps {
report: any; report: any;
} }
@ -38,7 +40,7 @@ class ErrorView extends React.Component<ErrorProps, { }> {
const report = this.props.report; const report = this.props.report;
if (!report) { if (!report) {
return ( return (
<div> <div id="main">
<h1>Error Report Not Found</h1> <h1>Error Report Not Found</h1>
<p>This page is supposed to display an error reported by the GNU Taler wallet, <p>This page is supposed to display an error reported by the GNU Taler wallet,
but the corresponding error report can't be found.</p> but the corresponding error report can't be found.</p>
@ -46,15 +48,47 @@ class ErrorView extends React.Component<ErrorProps, { }> {
</div> </div>
); );
} }
switch (report.name) { try {
default: switch (report.name) {
case "pay-post-failed": {
const summary = report.contractTerms.summary || report.contractTerms.order_id;
return (
<div id="main">
<h1>Failed to send payment</h1>
<p>Failed to send payment for <strong>{summary}</strong> to merchant <strong>{report.contractTerms.merchant.name}</strong>.</p>
<p>You can <a href={report.contractTerms.fulfillment_url}>retry</a> the payment. If this problem persists,
please contact the mechant with the error details below.</p>
<Collapsible initiallyCollapsed={true} title="Error Details">
<pre>
{JSON.stringify(report, null, " ")}
</pre>
</Collapsible>
</div>
);
}
default:
return (
<div id="main">
<h1>Unknown Error</h1>
The GNU Taler wallet reported an unknown error. Here are the details:
<pre>
{JSON.stringify(report, null, " ")}
</pre>
</div>
);
}
} catch (e) {
return ( return (
<div> <div id="main">
<h1>Unknown Error</h1> <h1>Error</h1>
The GNU Taler wallet reported an unknown error. Here are the details: The GNU Taler wallet reported an error. Here are the details:
<pre> <pre>
{JSON.stringify(report, null, " ")} {JSON.stringify(report, null, " ")}
</pre> </pre>
A detailed error report could not be generated:
<pre>
{e.toString()}
</pre>
</div> </div>
); );
} }

View File

@ -91,3 +91,40 @@ export function abbrev(s: string, n: number = 5) {
</span> </span>
); );
} }
interface CollapsibleState {
collapsed: boolean;
}
interface CollapsibleProps {
initiallyCollapsed: boolean;
title: string;
}
export class Collapsible extends React.Component<CollapsibleProps, CollapsibleState> {
constructor(props: CollapsibleProps) {
super(props);
this.state = { collapsed: props.initiallyCollapsed };
}
render() {
const doOpen = (e: any) => {
this.setState({collapsed: false});
e.preventDefault();
};
const doClose = (e: any) => {
this.setState({collapsed: true});
e.preventDefault();
};
if (this.state.collapsed) {
return <h2><a className="opener opener-collapsed" href="#" onClick={doOpen}>{this.props.title}</a></h2>;
}
return (
<div>
<h2><a className="opener opener-open" href="#" onClick={doClose}>{this.props.title}</a></h2>
{this.props.children}
</div>
);
}
}