better error report / retry prompt for failed payments
This commit is contained in:
parent
8697efd2c8
commit
24181bdf20
@ -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,
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user