diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-08-29 23:12:55 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-08-29 23:12:55 +0200 |
commit | defbf625bdef0f8a666b72b8ce99de5e01af6b91 (patch) | |
tree | 1bfe7c1ae0b56721d764893f62aca17271a20dbd /src/webex/pages/pay.tsx | |
parent | 1390175a9afc53948dd1d6f8a2f88e51c1bf53cc (diff) | |
download | wallet-core-defbf625bdef0f8a666b72b8ce99de5e01af6b91.tar.xz |
url-based pay/withdraw, use react hooks
Diffstat (limited to 'src/webex/pages/pay.tsx')
-rw-r--r-- | src/webex/pages/pay.tsx | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx new file mode 100644 index 000000000..d929426c4 --- /dev/null +++ b/src/webex/pages/pay.tsx @@ -0,0 +1,173 @@ +/* + This file is part of TALER + (C) 2015 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * Page shown to the user to confirm entering + * a contract. + */ + +/** + * Imports. + */ +import * as i18n from "../../i18n"; + +import { runOnceWhenReady } from "./common"; + +import { ExchangeRecord, ProposalDownloadRecord } from "../../dbTypes"; +import { ContractTerms } from "../../talerTypes"; +import { CheckPayResult, PreparePayResult } from "../../walletTypes"; + +import { renderAmount } from "../renderHtml"; +import * as wxApi from "../wxApi"; + +import React, { useState, useEffect } from "react"; +import * as ReactDOM from "react-dom"; +import URI = require("urijs"); +import { WalletApiError } from "../wxApi"; + +import * as Amounts from "../../amounts"; + +function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) { + const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(); + const [payErrMsg, setPayErrMsg] = useState<string | undefined>(""); + const [numTries, setNumTries] = useState(0); + let totalFees: Amounts.AmountJson | undefined = undefined; + + useEffect(() => { + const doFetch = async () => { + const p = await wxApi.preparePay(talerPayUri); + setPayStatus(p); + }; + doFetch(); + }); + + if (!payStatus) { + return <span>Loading payment information ...</span>; + } + + if (payStatus.status === "error") { + return <span>Error: {payStatus.error}</span>; + } + + if (payStatus.status === "payment-possible") { + totalFees = payStatus.totalFees; + } + + if (payStatus.status === "paid" && numTries === 0) { + return ( + <span> + You have already paid for this article. Click{" "} + <a href={payStatus.nextUrl}>here</a> to view it again. + </span> + ); + } + + const contractTerms = payStatus.contractTerms; + + if (!contractTerms) { + return ( + <span> + Error: did not get contract terms from merchant or wallet backend. + </span> + ); + } + + let merchantName: React.ReactElement; + if (contractTerms.merchant && contractTerms.merchant.name) { + merchantName = <strong>{contractTerms.merchant.name}</strong>; + } else { + merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>; + } + + const amount = ( + <strong>{renderAmount(Amounts.parseOrThrow(contractTerms.amount))}</strong> + ); + + const doPayment = async () => { + setNumTries(numTries + 1); + try { + const res = await wxApi.confirmPay(payStatus!.proposalId!, undefined); + document.location.href = res.nextUrl; + } catch (e) { + console.error(e); + setPayErrMsg(e.message); + } + }; + + return ( + <div> + <p> + <i18n.Translate wrap="p"> + The merchant <span>{merchantName}</span> offers you to purchase: + </i18n.Translate> + <div style={{ textAlign: "center" }}> + <strong>{contractTerms.summary}</strong> + </div> + {totalFees ? ( + <i18n.Translate wrap="p"> + The total price is <span>{amount} </span> + (plus <span>{renderAmount(totalFees)}</span> fees). + </i18n.Translate> + ) : ( + <i18n.Translate wrap="p"> + The total price is <span>{amount}</span>. + </i18n.Translate> + )} + </p> + + {payErrMsg ? ( + <div> + <p>Payment failed: {payErrMsg}</p> + <button + className="pure-button button-success" + onClick={() => doPayment()} + > + {i18n.str`Retry`} + </button> + </div> + ) : ( + <div> + <button + className="pure-button button-success" + onClick={() => doPayment()} + > + {i18n.str`Confirm payment`} + </button> + </div> + )} + </div> + ); +} + +runOnceWhenReady(() => { + try { + const url = new URI(document.location.href); + const query: any = URI.parseQuery(url.query()); + + let talerPayUri = query.talerPayUri; + + ReactDOM.render( + <TalerPayDialog talerPayUri={talerPayUri} />, + document.getElementById("contract")!, + ); + } catch (e) { + ReactDOM.render( + <span>Fatal error: {e.message}</span>, + document.getElementById("contract")!, + ); + console.error(e); + } +}); |