/* 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 */ /** * Page shown to the user to confirm entering * a contract. */ /** * Imports. */ import * as i18n from "../i18n"; import { renderAmount, ProgressButton } from "../renderHtml"; import * as wxApi from "../wxApi"; import React, { useState, useEffect } from "react"; import { Amounts, AmountJson, PreparePayResult, PreparePayResultType, ContractTerms, codecForContractTerms, ConfirmPayResultType, } from "taler-wallet-core"; function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element { const [payStatus, setPayStatus] = useState(); const [payErrMsg, setPayErrMsg] = useState(""); const [numTries, setNumTries] = useState(0); const [loading, setLoading] = useState(false); let amountEffective: AmountJson | undefined = undefined; useEffect(() => { const doFetch = async (): Promise => { const p = await wxApi.preparePay(talerPayUri); setPayStatus(p); }; doFetch(); }, [numTries, talerPayUri]); if (!payStatus) { return Loading payment information ...; } let insufficientBalance = false; if (payStatus.status == PreparePayResultType.InsufficientBalance) { insufficientBalance = true; } if (payStatus.status === PreparePayResultType.PaymentPossible) { amountEffective = Amounts.parseOrThrow(payStatus.amountEffective); } if ( payStatus.status === PreparePayResultType.AlreadyConfirmed && numTries === 0 ) { return ( You have already paid for this article. Click{" "} here to view it again. ); } let contractTerms: ContractTerms; try { contractTerms = codecForContractTerms().decode(payStatus.contractTerms); } catch (e) { // This should never happen, as the wallet is supposed to check the contract terms // before storing them. console.error(e); console.log("raw contract terms were", payStatus.contractTerms); return Invalid contract terms.; } if (!contractTerms) { return ( Error: did not get contract terms from merchant or wallet backend. ); } let merchantName: React.ReactElement; if (contractTerms.merchant && contractTerms.merchant.name) { merchantName = {contractTerms.merchant.name}; } else { merchantName = (pub: {contractTerms.merchant_pub}); } const amount = ( {renderAmount(Amounts.parseOrThrow(contractTerms.amount))} ); const doPayment = async (): Promise => { if (payStatus.status !== "payment-possible") { throw Error(`invalid state: ${payStatus.status}`); } const proposalId = payStatus.proposalId; setNumTries(numTries + 1); try { setLoading(true); const res = await wxApi.confirmPay(proposalId, undefined); if (res.type !== ConfirmPayResultType.Done) { throw Error("payment pending"); } document.location.href = res.nextUrl; } catch (e) { console.error(e); setPayErrMsg(e.message); } }; return (

The merchant {merchantName} offers you to purchase:

{contractTerms.summary}
{amountEffective ? ( The total price is {amount} (plus {renderAmount(amountEffective)} fees). ) : ( The total price is {amount}. )}

{insufficientBalance ? (

Unable to pay: Your balance is insufficient.

) : null} {payErrMsg ? (

Payment failed: {payErrMsg}

) : (
doPayment()} > {i18n.str`Confirm payment`}
)}
); } export function createPayPage(): JSX.Element { const url = new URL(document.location.href); const talerPayUri = url.searchParams.get("talerPayUri"); if (!talerPayUri) { throw Error("invalid parameter"); } return ; }