/*
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 {
AmountJson,
AmountLike,
Amounts,
ConfirmPayResult,
ConfirmPayResultDone,
ConfirmPayResultType,
ContractTerms,
i18n,
NotificationType,
PreparePayResult,
PreparePayResultType,
} from "@gnu-taler/taler-util";
import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorTalerOperation } from "../components/ErrorTalerOperation";
import { LogoHeader } from "../components/LogoHeader";
import { Part } from "../components/Part";
import { QR } from "../components/QR";
import {
ButtonSuccess,
ErrorBox,
LinkSuccess,
SuccessBox,
WalletAction,
WarningBox,
} from "../components/styled";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import * as wxApi from "../wxApi";
interface Props {
talerPayUri?: string;
goToWalletManualWithdraw: (currency?: string) => void;
goBack: () => void;
}
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,
goToWalletManualWithdraw,
}: Props): VNode {
const [payStatus, setPayStatus] = useState(
undefined,
);
const [payResult, setPayResult] = useState(
undefined,
);
const [payErrMsg, setPayErrMsg] = useState<
OperationFailedError | string | undefined
>(undefined);
const balance = useAsyncAsHook(wxApi.getBalance, [
NotificationType.CoinWithdrawn,
]);
const balanceWithoutError = balance?.hasError
? []
: balance?.response.balances || [];
const foundBalance = balanceWithoutError.find(
(b) =>
payStatus &&
Amounts.parseOrThrow(b.available).currency ===
Amounts.parseOrThrow(payStatus?.amountRaw).currency,
);
const foundAmount = foundBalance
? Amounts.parseOrThrow(foundBalance.available)
: undefined;
// We use a string here so that dependency tracking for useEffect works properly
const foundAmountStr = foundAmount
? Amounts.stringify(foundAmount)
: undefined;
useEffect(() => {
if (!talerPayUri) return;
const doFetch = async (): Promise => {
try {
const p = await wxApi.preparePay(talerPayUri);
setPayStatus(p);
} catch (e) {
console.log("Got error while trying to pay", e);
if (e instanceof OperationFailedError) {
setPayErrMsg(e);
}
if (e instanceof Error) {
setPayErrMsg(e.message);
}
}
};
doFetch();
}, [talerPayUri, foundAmountStr]);
if (!talerPayUri) {
return missing pay uri;
}
if (!payStatus) {
if (payErrMsg instanceof OperationFailedError) {
return (
{i18n.str`Digital cash payment`}
);
}
if (payErrMsg) {
return (
{i18n.str`Digital cash payment`}
Could not get the payment information for this order
)}
);
}
function ButtonsSection(): VNode {
if (payResult) {
if (payResult.type === ConfirmPayResultType.Pending) {
return (
Processing...
);
}
return ;
}
if (payStatus.status === PreparePayResultType.PaymentPossible) {
return (
{i18n.str`Pay`} {amountToString(payStatus.amountEffective)}
);
}
if (payStatus.status === PreparePayResultType.InsufficientBalance) {
return (
{balance ? (
Your balance of {amountToString(balance)} is not enough to pay
for this purchase
) : (
Your balance is not enough to pay for this purchase.
)}
{i18n.str`Withdraw digital cash`}
);
}
if (payStatus.status === PreparePayResultType.AlreadyConfirmed) {
return (
{payStatus.paid && contractTerms.fulfillment_message && (
)}
{!payStatus.paid && }
);
}
return ;
}
return (
{!payResult.contractTerms.fulfillment_message
? "You will now be sent back to the merchant you came from."
: payResult.contractTerms.fulfillment_message}