/* 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 { useState, useEffect } from "preact/hooks"; import { ConfirmPayResultDone, getJsonI18n, i18n } from "@gnu-taler/taler-util"; import { PreparePayResult, ConfirmPayResult, AmountJson, PreparePayResultType, Amounts, ContractTerms, ConfirmPayResultType, } from "@gnu-taler/taler-util"; import { JSX, VNode, h } from "preact"; interface Props { talerPayUri?: string } export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) { const fulfillmentUrl = payStatus.contractTerms.fulfillment_url; let message; if (fulfillmentUrl) { message = ( You have already paid for this article. Click{" "} here to view it again. ); } else { message = You have already paid for this article:{" "} {payStatus.contractTerms.fulfillment_message ?? "no message given"} ; } return

GNU Taler Wallet

{message}
} const doPayment = async (payStatus: PreparePayResult): Promise => { if (payStatus.status !== "payment-possible") { throw Error(`invalid state: ${payStatus.status}`); } const proposalId = payStatus.proposalId; const res = await wxApi.confirmPay(proposalId, undefined); if (res.type !== ConfirmPayResultType.Done) { throw Error("payment pending"); } const fu = res.contractTerms.fulfillment_url; if (fu) { document.location.href = fu; } return res; }; export function PayPage({ talerPayUri }: Props): JSX.Element { const [payStatus, setPayStatus] = useState(undefined); const [payResult, setPayResult] = useState(undefined); const [payErrMsg, setPayErrMsg] = useState(""); useEffect(() => { if (!talerPayUri) return; const doFetch = async (): Promise => { const p = await wxApi.preparePay(talerPayUri); setPayStatus(p); }; doFetch(); }, [talerPayUri]); if (!talerPayUri) { return missing pay uri } if (!payStatus) { return Loading payment information ...; } if (payResult && payResult.type === ConfirmPayResultType.Done) { if (payResult.contractTerms.fulfillment_message) { const obj = { fulfillment_message: payResult.contractTerms.fulfillment_message, fulfillment_message_i18n: payResult.contractTerms.fulfillment_message_i18n, }; const msg = getJsonI18n(obj, "fulfillment_message"); return (

Payment succeeded.

{msg}

); } else { return Redirecting ...; } } const onClick = async () => { try { const res = await doPayment(payStatus) setPayResult(res); } catch (e) { console.error(e); if (e instanceof Error) { setPayErrMsg(e.message); } } } return ; } export interface PaymentRequestViewProps { payStatus: PreparePayResult; onClick: () => void; payErrMsg?: string; } export function PaymentRequestView({ payStatus, onClick, payErrMsg }: PaymentRequestViewProps) { let totalFees: AmountJson | undefined = undefined; let insufficientBalance = false; const [loading, setLoading] = useState(false); const contractTerms: ContractTerms = payStatus.contractTerms; if ( payStatus.status === PreparePayResultType.AlreadyConfirmed ) { return } if (!contractTerms) { return ( Error: did not get contract terms from merchant or wallet backend. ); } if (payStatus.status == PreparePayResultType.InsufficientBalance) { insufficientBalance = true; } if (payStatus.status === PreparePayResultType.PaymentPossible) { const amountRaw = Amounts.parseOrThrow(payStatus.amountRaw); const amountEffective: AmountJson = Amounts.parseOrThrow( payStatus.amountEffective, ); totalFees = Amounts.sub(amountEffective, amountRaw).amount; } let merchantName: VNode; if (contractTerms.merchant && contractTerms.merchant.name) { merchantName = {contractTerms.merchant.name}; } else { merchantName = (pub: {contractTerms.merchant_pub}); } const amount = ( {renderAmount(Amounts.parseOrThrow(contractTerms.amount))} ); return

GNU Taler Wallet

The merchant {merchantName} offers you to purchase:

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

{insufficientBalance ? (

Unable to pay: Your balance is insufficient.

) : null} {payErrMsg ? (

Payment failed: {payErrMsg}

) : (
{i18n.str`Confirm payment`}
)}
}